Listes de modifications

Il est très courant pour un développeur d'avoir à effectuer, en même temps, des modifications multiples n'ayant rien à voir entre elles sur une portion de code donnée. Ce n'est pas nécessairement la preuve d'une mauvaise gestion de son temps, ni d'une forme de masochisme numérique. Un ingénieur de développement repère souvent des bogues annexes lorsqu'il travaille sur un morceau de code particulier. Ou alors c'est une fois rendu à mi-chemin d'un changement important qu'il prend conscience que la solution qu'il a choisie serait mieux propagée sous la forme de plusieurs unités logiques plus petites, ces unités pouvant se recouper, affecter des fichiers différents d'un même module ou même toucher à des lignes différentes d'un même fichier.

Plusieurs méthodes sont à disposition des développeurs pour gérer ces ensembles de modifications. Certains développeurs utilisent des copies de travail séparées, du même dépôt, pour y conserver les progrès faits pour chaque changement. D'autres développeurs choisissent de créer au sein du dépôt des branches fonctionnelles à durée de vie très courte et d'utiliser une unique copie de travail qu'ils feront pointer selon les besoins du moment vers une branche de ce type ou vers une autre. Enfin, d'autres développeurs utilisent les outils diff et patch pour sauvegarder et restaurer des changements non propagés sur les fichiers touchés par les modifications. Chacune de ces méthodes a des avantages et des inconvénients et, en général, le détail des changements à effectuer influence fortement le choix de la méthode utilisée pour les distinguer.

Subversion 1.5 a introduit une nouvelle fonctionnalité, les listes de modifications, qui vient s'ajouter aux méthodes mentionnées ci-dessus. Les listes de modifications sont en gros des étiquettes arbitraires (une au plus par fichier pour l'instant) attachées à des fichiers de la copie de travail dans le seul but de regrouper plusieurs fichiers ensemble. Les utilisateurs de bon nombre de logiciels fournis par Google sont déjà habitués à ce concept. Dans Gmail, vous associez des étiquettes arbitraires à des e-mails et plusieurs e-mails peuvent être considérés comme faisant partie du même groupe s'ils partagent une étiquette donnée. Dès lors, ne voir qu'un groupe d'e-mails portant la même étiquette n'est plus qu'un simple jeu d'affichage. De nombreux autres sites web 2.0 possèdent des mécanismes similaires. Prenez par exemple les « tags » (« étiquette » en anglais) utilisés sur des sites comme YouTube ou Flickr, les « catégories » utilisées pour regrouper les articles de blogs, etc. Aujourd'hui les gens ont compris que l'organisation des données est essentielle et la façon dont ces données sont organisées doit être flexible. Le vieux paradigme des répertoires et des fichiers est bien trop rigide pour certaines applications.

Cette fonctionnalité de Subversion vous permet de créer des listes de modifications en étiquetant les fichiers que vous voulez inclure, de supprimer ces étiquettes et de limiter le rayon d'action des sous-commandes aux seuls fichiers qui portent l'étiquette donnée. Dans ce paragraphe, nous allons voir en détails comment accomplir ces actions.

Création et modification d'une liste de modifications

Vous pouvez créer, modifier et supprimer des listes de modifications en utilisant la commande svn changelist. Plus précisément, vous pouvez utiliser cette commande pour activer ou désactiver l'association d'une liste de modifications avec un fichier donné de la copie de travail. La création d'une liste de modifications a lieu la première fois que vous étiquetez un fichier avec ce nom de liste ; elle n'est supprimée que quand vous effacez l'étiquette du dernier fichier qui la portait. Examinons un cas concret pour illustrer ces notions.

Harry est en train de corriger des bogues dans le module de logique mathématique de l'application « calculatrice ». Son travail l'amène à modifier deux fichiers :

$ svn status
M      entier.c
M      ops-math.c
$

En testant son correctif, Harry s'aperçoit que ses modifications lui indiquent qu'un bogue collatéral existe au sein de la logique de l'interface utilisateur, située dans le fichier bouton.c. Harry décide alors qu'il va aussi corriger ce bogue, dans une propagation séparée de ses propres correctifs mathématiques. Dans une copie de travail de petite taille, ne contenant qu'une poignée de fichiers, et pour juste quelques modifications logiques, Harry pourrait probablement gérer mentalement ces deux ensembles logiques de modifications sans le moindre problème. Mais aujourd'hui il a décidé qu'il allait utiliser les listes de modifications de Subversion, pour faire une faveur aux auteurs de ce livre.

Harry commence par créer une première liste de modifications et y associe les deux premiers fichiers qu'il a déjà modifié. Pour ce faire, il utilise la commande svn changelist afin d'associer le même nom arbitraire de liste de modifications aux deux fichiers :

$ svn changelist correctifs-maths entier.c ops-math.c
Le chemin 'entier.c' fait maintenant partie de la liste de changement 'correctifs-maths'.
Le chemin 'ops-math.c' fait maintenant partie de la liste de changement 'correctifs-maths'.
$ svn status

--- Liste de changements 'correctifs-maths' :
M      entier.c
M      ops-math.c
$

Comme vous pouvez le constater, le résultat de svn status reflète bien ce nouvel ensemble.

Harry se lance alors dans la correction du problème d'interface graphique collatéral. Puisqu'il sait quel fichier il va modifier, il associe également ce chemin à une liste de modifications. Mais malencontreusement Harry associe ce troisième fichier à la même liste de modifications que les deux premiers :

$ svn changelist correctifs-maths bouton.c
Le chemin 'bouton.c' fait maintenant partie de la liste de changement 'correctifs-maths'.
$ svn status

--- Liste de changements 'correctifs-maths' :
       bouton.c
M      entier.c
M      ops-math.c
$

Par chance, Harry prend conscience de son erreur. Deux options se présentent alors à lui. Il peut supprimer l'association de bouton.c avec la liste de modifications, puis lui associer un nouveau nom de liste de modifications :

$ svn changelist --remove bouton.c
Le chemin 'bouton.c' n'est plus associé à une liste de changements.
$ svn changelist correctifs-graphiques bouton.c
Le chemin 'bouton.c' fait maintenant partie de la liste de changement 'correctifs-graphiques'.
$

Ou alors il peut sauter l'étape de suppression et juste associer un nouveau nom de liste de modifications à bouton.c. Dans ce cas, Subversion signale à Harry que bouton.c va être supprimé de la première liste de modifications :

$ svn changelist correctifs-graphiques bouton.c
svn:  avertissement : Retrait de 'bouton.c' de la liste de changements (changelist) 'correctifs-maths'.
Le chemin 'bouton.c' fait maintenant partie de la liste de changement 'correctifs-graphiques'.
$ svn status

--- Liste de changements 'correctifs-graphiques' :
       bouton.c

--- Liste de changements 'correctifs-maths' :
M      entier.c
M      ops-maths.c
$

Harry dispose donc à présent de deux listes de modifications distinctes dans sa copie de travail et svn status présente ses résultats en les regroupant par liste de modifications. Notez que bien qu'Harry n'ait pas encore modifié bouton.c, celui-ci est quand même mentionné par svn status car une liste de modifications lui est associée. Les listes de modifications peuvent être associées, ou enlevées, aux fichiers à tout moment, indépendamment du fait que ces fichiers contiennent des modifications locales ou pas.

Harry règle maintenant le problème de l'interface graphique dans bouton.c.

$ svn status

--- Liste de changements 'correctifs-graphiques':
M      bouton.c

--- Liste de changements 'correctifs-maths':
M      entier.c
M      ops-math.c
$

Listes de modifications : des filtres pour vos opérations

Le regroupement visuel qu'Harry constate en sortie de svn status, comme indiqué précédemment, est intéressant d'un point de vue esthétique, mais pas vraiment utile. La commande status n'est qu'une des commandes qu'il est susceptible de lancer sur sa copie de travail. Heureusement, bon nombre des autres opérations de Subversion sont capables d'agir sur les listes de modifications grâce à l'option --changelist.

Quand l'option --changelist est présente, les commandes Subversion limitent leur champ d'action aux fichiers auxquels est associé le nom de liste de modifications donné. Si Harry veut voir quels changements il a effectué sur les fichiers de sa liste correctifs-maths, il peut lister explicitement les fichiers faisant partie de cette liste de modifications avec la commande svn diff.

$ svn diff entier.c ops-math.c
Index: entier.c
===================================================================
--- entier.c	(révision 1157)
+++ entier.c	(copie de travail)
…
Index: ops-math.c
===================================================================
--- ops-math.c	(révision 1157)
+++ ops-math.c	(copie de travail)
…
$

Cette méthode fonctionne correctement pour un petit nombre de fichiers, mais qu'en est-il si Harry a modifié une vingtaine ou une trentaine de fichiers ? Fournir la liste de tous ces fichiers serait assez pénible. Mais puisqu'il utilise les listes de modifications, Harry peut désormais éviter de lister explicitement tous les fichiers et ne donner à la place que le nom de la liste de modifications :

$ svn diff --changelist correctifs-maths

Index: entier.c
===================================================================
--- entier.c	(révision 1157)
+++ entier.c	(copie de travail)
…
Index: ops-math.c
===================================================================
--- ops-math.c	(révision 1157)
+++ ops-math.c	(copie de travail)
…
$

Et au moment de lancer la propagation, Harry peut à nouveau se servir de l'option --changelist pour limiter le rayon d'action de la propagation aux fichiers de sa liste de modifications. Par exemple, il peut propager ses changements concernant l'interface graphique en lançant :

$ svn ci -m "Corrigé un bug de l'interface graphique découvert en travaillant sur la logique mathématique." \
      --changelist correctifs-graphiques
Envoi        bouton.c
Transmission des données .
Révision 1158 propagée.
$

En fait, la commande svn commit accepte une deuxième option liée aux listes de modifications : --keep-changelists. Normalement, l'association des listes de modifications avec les fichiers est supprimée dès que ceux-ci ont été propagés. Mais si l'option --keep-changelists est ajoutée sur la ligne de commande, les fichiers propagés (qui ne sont donc plus dans l'état modifié) restent associés aux listes de modifications en question. Dans tous les cas, propager des fichiers faisant partie d'une liste de modification laisse les autres listes de modifications intactes.

$ svn status

--- Liste de changements 'correctifs-maths':
M      entier.c
M      ops-math.c
$
[Note] Note

L'option --changelist agit comme un filtre sur les cibles des commandes Subversion et n'ajoute jamais de cible à une opération. Par exemple, lors d'une opération de propagation lancée via svn commit /chemin/vers/rep, la cible est le répertoire /chemin/vers/rep et ses fils (avec une profondeur infinie). Si ensuite vous ajoutez une option spécifiant une liste de modifications à cette commande, seuls les fichiers se trouvant sous le chemin /chemin/vers/rep et associés à cette liste de modifications sont pris en compte en tant que cibles de la propagation ; ne sont pas inclus les fichiers situés ailleurs (tels ceux sous /chemin/vers/autre-rep), quelle que soit la liste de modifications à laquelle ils appartiennent, même s'il font partie de la même copie de travail que la ou les cibles de l'opération.

Même la commande svn changelist accepte l'option --changelist. Ceci vous permet de renommer ou supprimer facilement une liste de modifications :

$ svn changelist bogues-maths --changelist correctifs-maths --depth infinity .
svn: avertissement : Retrait de 'entier.c' de la liste de changements (changelist) 'correctifs-maths'.
Le chemin 'entier.c' fait maintenant partie de la liste de changement 'bogues-maths'.
svn: avertissement : Retrait de 'ops-math.c' de la liste de changements (changelist) 'correctifs-maths'.
Le chemin 'ops-math.c' fait maintenant partie de la liste de changement 'bogues-maths'.
$ svn changelist --remove --changelist bogues-maths --depth infinity .
Le chemin 'entier.c' n'est plus associé à une liste de changements.
Le chemin 'ops-math.c' n'est plus associé à une liste de changements.
$

Enfin, vous pouvez spécifier plusieurs instances de l'option --changelist dans une même ligne de commande. Ceci limite le champ d'action de votre opération aux fichiers faisant partie de toutes les listes de modifications spécifiées.

Limitations des listes de modifications

La fonctionnalité de listes de modifications de Subversion est un outil très pratique pour créer des groupes de fichiers au sein de la copie de travail, mais elle a cependant quelques limitations. Les listes de modifications sont des objets contenus à l'intérieur d'une copie de travail, ce qui signifie que les associations entre fichiers et listes de modifications ne peuvent pas être propagées vers le dépôt, ni partagées avec d'autres utilisateurs. Les listes de modifications ne peuvent être associées qu'à des fichiers, Subversion n'offre pas cette possibilité pour les répertoires. Enfin, vous pouvez avoir au plus un nom de liste de modifications associé à un fichier donné. C'est ici que l'analogie avec les articles de blogs et les services d'étiquetage de photos en ligne part en fumée. S'il vous faut associer un fichier à plusieurs listes de modifications, vous êtes coincé.