This text is a work in progress—highly subject to change—and may not accurately describe any released version of the Apache™ Subversion® software. Bookmarking or otherwise referring others to this page is probably not such a smart idea. Please visit http://www.svnbook.com/ for stable versions of this book.

Répertoires clairsemés

Par défaut, la plupart des opérations Subversion sur des dossiers agissent de manière récursive. Par exemple, svn checkout crée une copie de travail avec tous les fichiers et dossiers de la zone spécifiée du dépôt, en descendant récursivement dans l'arborescence du dépôt pour en copier la structure complète sur votre disque local. Subversion 1.5 introduit une nouvelle fonctionnalité appelée répertoires clairsemés (ou extractions superficielles) qui permet d'obtenir facilement une copie de travail (ou une simple portion d'une copie de travail) moins profonde que via la récursion complète, avec la possibilité de n'extraire que plus tard les dossiers et les fichiers ignorés auparavant.

Par exemple, imaginons un dépôt dont l'arborescence des fichiers et dossiers est constituée des noms des membres d'une famille et de leurs animaux de compagnie (c'est assurément un exemple bizarre, mais soit). Un svn checkout standard nous donne une copie de travail de l'ensemble de l'arborescence :

$ svn checkout file:///var/svn/depot maman
A    maman/fils
A    maman/fils/petit-fils
A    maman/fille
A    maman/fille/petite-fille1
A    maman/fille/petite-fille1/lapinou1.txt
A    maman/fille/petite-fille1/lapinou2.txt
A    maman/fille/petite-fille2
A    maman/fille/poissonou.txt
A    maman/minou1.txt
A    maman/toutou1.txt
Révision 1 extraite.
$

Maintenant, extrayons la même arborescence, mais cette fois en demandant à Subversion de nous donner uniquement le dossier racine sans les enfants :

$ svn checkout file:///var/svn/depot maman-vide --depth empty
Révision 1 extraite.
$

Remarquez que nous avons ajouté l'option --depth à la commande svn checkout originale. Cette option existe pour de nombreuses sous-commandes Subversion et est similaire aux options --non-recursive (-N) et --recursive (-R). En fait, elle combine, améliore, remplace et, à terme, rend obsolète ces deux options plus anciennes. Déjà, elle permet à l'utilisateur de spécifier le niveau de profondeur de la récursion de façon plus précise, en ajoutant des niveaux auparavant non supportés (ou supportés de manière peu satisfaisante). Voici les valeurs de niveau de profondeur de récursion que vous pouvez ajouter à vos requêtes Subversion :

--depth empty

Inclut uniquement la cible immédiate de l'opération, sans aucun fichier ou dossier fils.

--depth files

Inclut la cible immédiate de l'opération et tous les fichiers fils immédiats.

--depth immediates

Inclut la cible immédiate de l'opération et tous ses sous-dossiers et fils immédiats. Les dossiers fils seront eux-mêmes vides.

--depth infinity

Inclut la cible immédiate, les fichiers et dossiers fils, les fils des fils et ainsi de suite de façon à réaliser une récursion complète.

Bien sûr, la simple combinaison de deux options existantes en une seule ne constitue pas une nouvelle fonctionnalité méritant une section complète de ce livre. Heureusement, il y a plus à en dire. Ce concept de profondeur de récursion ne s'applique pas uniquement aux opérations réalisées avec le client Subversion mais il s'étend aussi à la description de la copie de travail elle-même, en tant que niveau associé de manière permanente par la copie de travail à chaque élément. La force de ce concept est cette permanence. La copie de travail se rappelle le niveau de profondeur que vous avez choisi pour chaque élément qui la compose, jusqu'à ce que vous en changiez. Par défaut, les commandes Subversion agissent sur les éléments présents dans la copie de travail, indépendamment de leur niveau de récursion propre.

[Astuce] Astuce

Vous pouvez vérifier le niveau de profondeur d'une copie de travail en utilisant la commande svn info. Si le niveau de récursion n'est pas infini, svn info affiche une ligne indiquant le niveau de profondeur :

$ svn info maman-immediats | grep '^Profondeur :'
Profondeur : immédiates
$

Ces premiers exemples comportaient des extractions avec un niveau infini de profondeur (la valeur par défaut de svn checkout) ou avec un niveau nul. Voyons maintenant des exemples avec d'autres valeurs de niveau de profondeur :

$ svn checkout file:///var/svn/depot maman-fichiers --depth files
A    maman-fichiers/minou1.txt
A    maman-fichiers/toutou1.txt
Révision 1 extraite.
$ svn checkout file:///var/svn/depot maman-immediats --depth immediates
A    maman-immediats/fils
A    maman-immediats/fille
A    maman-immediats/minou1.txt
A    maman-immediats/toutou1.txt
Révision 1 extraite.
$

Comme indiqué, chacun de ces deux niveaux se situe quelque part entre la cible toute simple et la récursion complète.

Nous avons utilisé la commande svn checkout pour nos exemples, mais l'option --depth est également accessible depuis beaucoup d'autres commandes Subversion. Pour ces autres commandes, spécifier un niveau de profondeur de la récursion est une manière de limiter le rayon d'action d'une opération à un niveau, à l'instar des vieilles options --non-recursive (-N) et --recursive (-R). Cela veut dire que lorsque vous travaillez sur une copie de travail d'un certain niveau et que vous faites une opération sur un niveau plus faible, l'opération est limitée à ce niveau faible. En fait, on peut généraliser ce raisonnement : pour une copie de travail d'un niveau de profondeur de récursion arbitraire (éventuellement hétérogène) et pour une commande Subversion comportant un niveau de profondeur, la commande conserve le niveau de récursion associé aux éléments de la copie de travail tout en limitant le rayon d'action de l'opération au niveau demandé (ou celui par défaut).

En plus de l'option --depth, les sous-commandes svn update et svn switch acceptent une deuxième option relative au niveau de profondeur de la récursion : --set-depth. C'est cette option qui vous permet de changer le niveau de profondeur de la récursion associé à un élément d'une copie de travail. Regardez ce qui se passe après avoir extrait notre niveau zéro puis graduellement augmenté le niveau de profondeur de la récursion en utilisant la commande svn update --set-depth NOUVELLE-PROFONDEUR CIBLE:

$ svn update --set-depth files maman-vide
A    maman-vide/minou1.txt
A    maman-vide/toutou1.txt
Actualisé à la révision 1. 
$ svn update --set-depth immediates maman-vide
A    maman-vide/fils
A    maman-vide/fille
Actualisé à la révision 1.
$ svn update --set-depth infinity maman-vide
A    maman-vide/fils/petit-fils
A    maman-vide/fille/petite-fille1
A    maman-vide/fille/petite-fille1/lapinou1.txt
A    maman-vide/fille/petite-fille1/lapinou2.txt
A    maman-vide/fille/petite-fille2
A    maman-vide/fille/poissonou1.txt
Actualisé à la révision 1.
$

Au fur et à mesure que nous avons augmenté le niveau de profondeur de la récursion, le dépôt a complété progressivement notre arborescence.

Dans notre exemple, nous n'avons agi que sur la racine de notre copie de travail, en changeant la valeur du niveau associé de profondeur de la récursion. Mais nous pouvons aussi changer de façon indépendante le niveau associé de profondeur de la récursion à chaque sous-dossier de la copie de travail. Une utilisation minutieuse de cette option nous permet de récupérer uniquement certaines portions de la copie de travail, en laissant de côté toutes les autres portions (d'où le nom « clairsemé » de la fonctionnalité). Voici un exemple montrant comment construire une portion d'une branche de notre arbre généalogique, activer la récursion totale sur une autre branche et élaguer le reste (qui ne sera donc pas sur notre disque dur).

$ rm -rf maman-vide
$ svn checkout file:///var/svn/depot maman-vide --depth empty
Révision 1 extraite.
$ svn update --set-depth empty maman-vide/fils
A    maman-vide/fils
Actualisé à la révision 1.
$ svn update --set-depth empty maman-vide/fille
A    maman-vide/fille
Actualisé à la révision 1.
$ svn update --set-depth infinity maman-vide/fille/petite-fille1
A    maman-vide/fille/petite-fille1
A    maman-vide/fille/petite-fille1/lapinou1.txt
A    maman-vide/fille/petite-fille1/lapinou2.txt
Actualisé à la révision 1.
$

Heureusement, même avec différents niveaux de récursion définis au sein d'une même copie de travail, les actions sur la copie de travail ne s'en trouvent pas plus compliquées. Vous pouvez toujours effectuer des modifications et les propager, revenir en arrière ou afficher les modifications locales de votre copie de travail sans spécifier d'option particulière (y compris --depth et --set-depth) aux dites commandes. Même svn update fonctionne normalement quand on ne lui fournit pas de niveau de récursion spécifique : elle met à jour les cibles de la copie de travail qui sont présentes en tenant compte des niveaux de récursion qui leur sont associés.

Vous devez vous demander : « Bien. Mais quand aurais-je besoin d'utiliser ça ? » Un cas classique est lié à une architecture du dépôt particulière : lorsque de nombreux projets et modules logiciels liés cohabitent au même niveau dans un dépôt (trunk/projet1, trunk/projet2, trunk/projet3, etc.). Dans de tels scénarios, il est probable que seuls quelques projets vous intéressent personnellement, sans doute pas plus d'un projet principal et de quelques autres modules dont il dépend. Vous pouvez extraire une copie de travail pour chacune de ces arborescences, mais ces copies de travail sont séparées et, par conséquent, il peut être fastidieux d'effectuer des opérations sur plusieurs ou sur l'ensemble des copies de travail en même temps. L'autre solution est d'utiliser la fonctionnalité de répertoires clairsemés, en construisant une seule copie de travail qui ne contient que les modules qui vous intéressent. Vous partez d'une extraction du dossier parent commun aux différents projets avec un niveau zéro de profondeur de récursion (empty-depth), puis vous mettez à jour avec un niveau infini de récursion les éléments que vous voulez récupérer, comme nous l'avons fait dans l'exemple précédent. Voyez ça comme un système d'inclusion optionnelle des éléments qui peuplent la copie de travail.

L'implémentation des extractions superficielles de Subversion 1.5 était relativement bonne mais elle ne permettait pas de diminuer le niveau de profondeur de récursion d'un élément de la copie de travail. Subversion 1.6 pallie ce problème. Par exemple, si vous lancez svn update --set-depth empty sur une copie de travail de niveau de récursion infini, vous ne conserverez que le dossier sommital[27]. Subversion 1.6 introduit également une autre valeur de profondeur de récursion pour l'option --set-depth : exclude. En indiquant --set-depth exclude à svn update, la cible de la mise à jour sera entièrement supprimée de la copie de travail, le dossier cible lui-même étant lui aussi supprimé. C'est utile lorsqu'il y a davantage d'éléments de la copie de travail que vous voulez garder par rapport à ce que vous voulez supprimer.

Considérons un dossier avec des centaines de sous-dossiers, dont un que vous ne voulez pas voir dans votre copie de travail. En utilisant une approche « additive » des dossiers clairsemés, vous pourriez l'extraire avec un niveau de profondeur nul, puis explicitement augmenter (en utilisant svn update --set-depth infinity) le niveau de profondeur pour tous les autres sous-dossiers.

$ svn checkout http://svn.exemple.com/depot/plein-de-repertoires --depth empty
…
$ svn update --set-depth infinity plein-de-repertoires/rep-voulu-1
…
$ svn update --set-depth infinity plein-de-repertoires/rep-voulu-2
…
$ svn update --set-depth infinity plein-de-repertoires/rep-voulu-3
…
### etc., etc.

C'est peut-être un peu fastidieux, d'autant que vous n'avez pas les « souches » de ces dossiers dans votre copie de travail pour les manipuler. Une telle copie de travail aurait de plus une caractéristique que vous ne soupçonnez pas ou ne voulez pas : si quelqu'un d'autre crée un sous-dossier dans le dossier racine, vous ne le recevrez pas lors de vos mises à jour.

À partir de Subversion 1.6, vous pouvez adopter une approche différente. En premier lieu, faites une extraction du dossier en entier. Ensuite, lancez svn update --set-depth exclude sur le dossier que vous ne voulez pas voir.

$ svn checkout http://svn.exemple.com/depot/plein-de-repertoires
…
$ svn update --set-depth exclude plein-de-repertoires/j-en-veux-pas
D         plein-de-repertoires/j-en-veux-pas
$

Cette approche laisse votre copie de travail avec le même contenu que la première approche, mais si un sous-dossier est créé au niveau du dossier racine, il apparaîtra lors de la mise à jour de votre copie de travail. L'inconvénient de cette approche est que vous devez extraire tout le sous-dossier que vous ne voulez pas garder afin de pouvoir dire à Subversion que vous n'en voulez pas. Il n'est pas impossible que ce sous-dossier soit trop gros pour votre disque dur (ce qui pourrait expliquer, après tout, que vous n'en voulez pas dans votre copie de travail).

[Note] Note

Alors qu'exclure un élément existant de la copie de travail ne fait pas partie de la commande svn update, vous avez sans doute remarqué que la sortie de svn update --set-depth exclude diffère de celle d'une mise à jour normale. Cette sortie trahit le fait que, sous le capot, l'exclusion est une opération réalisée entièrement du côté du client, à l'opposé d'une mise à jour classique.

Dans une telle situation, vous pouvez adopter une approche intermédiaire. D'abord, faites une extraction du dossier racine avec l'option --depth immediates. Puis, faites une extraction du dossier que vous ne souhaitez pas conserver avec svn update --set-depth exclude. Enfin, récupérez tous les éléments qui restent à un niveau de profondeur infini, ce qui relativement facile puisque tous sont visibles par votre interpréteur de commandes.

$ svn checkout http://svn.exemple.com/depot/plein-de-repertoires --depth immediates
…
$ svn update --set-depth exclude plein-de-repertoires/j-en-veux-pas
D         plein-de-repertoires/j-en-veux-pas
$ svn update --set-depth infinity plein-de-repertoires/*
…
$

Cette fois encore, votre copie de travail contiendra la même chose que dans les deux cas précédents. Mais maintenant, chaque fois qu'un nouveau fichier ou sous-dossier sera propagé au niveau du dossier racine, vous le recevrez (à un niveau de profondeur nul) au moment de votre mise à jour. Vous pouvez décider à ce stade ce que vous voulez faire avec ce nouvel élément : le récupérer avec un niveau de profondeur infini ou l'exclure.



[27] En toute sécurité, bien sûr. Comme dans les autres situations, Subversion laissera sur le disque tous les fichiers que vous avez modifiés ou qui ne sont pas suivis en versions.