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.
L'interface entre Subversion et les outils de comparaison (de deux
ou trois fichiers) remonte à l'époque où Subversion, pour afficher les
différences de manière contextuelle, utilisait directement la suite
d'outils GNU de comparaison, plus précisément les utilitaires
diff et diff3. Pour obtenir le
comportement désiré par Subversion, l'appel à ces programmes se faisait
avec une ribambelle d'options et de paramètres dont la plupart étaient
spécifiques à ces utilitaires. Plus tard, Subversion s'est doté de sa
propre bibliothèque de comparaison et, afin de conserver la possibilité
de choisir, les options --diff-cmd
et
--diff3-cmd
ont été ajoutées au client texte
interactif pour que les utilisateurs allergiques à la nouvelle
bibliothèque puissent indiquer facilement leur souhait de se servir des
utilitaires GNU diff et diff3. Si ces options étaient utilisées,
Subversion ignorait purement et simplement sa bibliothèque interne de
comparaison et appelait alors ces programmes externes, avec leurs
listes d'arguments longue comme un jour sans pain et leurs autres
spécificités. Les choses sont restées en l'état.
Il n'a pas fallu longtemps pour que les adeptes de Subversion comprennent que si l'on pouvait utiliser les utilitaires GNU diff et diff3 situés à un endroit précis du disque, on pouvait alors aussi profiter de ce mécanisme pour utiliser d'autres outils de comparaison. Après tout, Subversion ne vérifiait pas que les programmes qu'il lançait faisaient bien partie de la suite des outils GNU de comparaison. Mais la seule chose que l'on peut configurer dans l'utilisation de programmes externes est leur emplacement sur le disque ; pas les options, ni l'ordre des paramètres, ni le reste. Subversion continue à envoyer toutes les options des utilitaires GNU à votre programme de comparaison, indépendamment du fait que votre programme en tienne compte ou non. Et c'est là que la plupart des utilisateurs ne comprennent pas la logique de la chose.
Note | |
---|---|
La décision de lancer une comparaison entre deux ou trois
fichiers dans le cadre d'une opération Subversion est entièrement du
ressort de Subversion et est conditionnée, en autres, au fait que les
fichiers soient lisibles par un humain comme indiqué par leur
propriété |
Bien plus tard, Subversion 1.5 introduisit la résolution
interactive des conflits (décrite dans la section intitulée « Résolution des conflits »). L'une des options proposées à
l'utilisateur est de lancer un outil de fusion externe. Si cette action
est choisie, Subversion consultera l'option
merge-tool-cmd
de la zone de configuration des
exécutables, susceptible de contenir le nom d'un outil externe de
fusion. S'il en trouve un, il lancera cet outil.
Note | |
---|---|
Bien que l'objectif soit globalement le même entre les outils qui comparent trois fichiers et les outils de fusion (trouver une un découpage des fichiers de manière à ce que les modifications soient clairement séparées sans se perturber), Subversion met en œuvre chacune de ces options à des moments différents et pour des raisons différentes. Le moteur de comparaison pour trois fichiers ou son pendant externe sont utilisés lorsqu'une interaction avec l'utilisateur n'est pas requise. En fait, de tels outils induisent des délais significatifs qui peuvent produire des erreurs dans certaines opérations de Subversion. C'est l'outil de fusion externe qui a vocation à être utilisé de manière interactive. |
Maintenant, bien que l'interface entre Subversion et un outil de fusion externe soit nettement moins compliquée que celle entre Subversion et les outils diff et diff3, la probabilité de trouver un tel outil dont les conventions d'appel sont exactement les mêmes que Subversion sont très faibles. La clé pour utiliser des outils externes de différenciation et de fusion avec Subversion, c'est d'encapsuler ces outils dans des scripts d'interface qui convertiront les entrées en provenance de Subversion en quelque chose d'intelligible pour votre outil, puis de convertir en retour la sortie de votre outil vers le format que Subversion attend. Les sections qui suivent couvrent les détails des attendus de Subversion.
Subversion appelle les programmes externes de comparaison avec des paramètres compatibles avec la suite d'outils de comparaison GNU et s'attend à ce que le programme renvoie un code d'erreur signifiant la réussite de la comparaison. Pour la plupart des programmes de comparaison alternatifs, seuls les sixième et septième arguments, indiquant les chemins vers les fichiers à comparer, respectivement placés à gauche et à droite, sont intéressants. Notez que Subversion lance le programme de comparaison pour chaque fichier concerné par l'opération Subversion, ce qui peut vous amener à avoir plusieurs instances simultanément si votre programme fonctionne de manière asynchrone (ou s'il est placé en arrière-plan). Enfin, Subversion s'attend à ce que votre programme retourne un code d'erreur de 1 s'il a détecté des différences ou 0 sinon. Tout autre code d'erreur est considéré comme une erreur fatale [76].
L'Exemple 7.2, « diffwrap.py » et l'Exemple 7.3, « diffwrap.bat » sont des modèles de scripts d'interface pour un outil externe de comparaison, respectivement en langage Python et en langage de script Windows.
Exemple 7.2. diffwrap.py
#!/usr/bin/env python import sys import os # Indiquez ici le chemin de votre outil de comparaison favori. DIFF = "/usr/local/bin/mon-diff-perso" # Subversion fournit les chemins voulus dans les deux derniers arguments. GAUCHE = sys.argv[-2] DROITE = sys.argv[-1] # Appelons la commande de comparaison (modifiez la ligne suivante # en accord avec votre programme de comparaison). cmd = [DIFF, '--left', GAUCHE, '--right', DROITE] os.execv(cmd[0], cmd) # Le code d'erreur renvoyé doit être : # 0 si aucune différence n'est détectée, # 1 s'il y a des différences. # Tout autre code est traité comme une erreur fatale.
Exemple 7.3. diffwrap.bat
@ECHO OFF REM Indiquez ici le chemin de votre outil de comparaison favori. SET DIFF="C:\Program Files\Super Progs\Mon Diff Perso.exe" REM Subversion fournit les chemins voulus dans les deux derniers arguments. REM Ce sont les paramètres 6 et 7 (sauf si vous utilisez svn diff -x, REM auquel cas tout est possible). SET GAUCHE=%6 SET DROITE=%7 REM Appelons la commande de comparaison (modifiez la ligne suivante REM en accord avec votre programme de comparaison). %DIFF% --left %GAUCHE% --right %DROITE% REM Le code d'erreur renvoyé doit être : REM 0 si aucune différence n'est détectée, REM 1 s'il y a des différences. REM Tout autre code est traité comme une erreur fatale.
Subversion appelle les programmes externes de comparaison de trois fichiers pour effectuer des fusions sans interaction avec l'utilisateur. Lorsqu'il est configuré pour utiliser un programme externe, il appelle ce programme avec des paramètres compatibles avec l'outil GNU diff3 et s'attend à ce que le programme externe retourne un code d'erreur correct et que le fichier résultant de l'opération de fusion soit envoyé vers la sortie standard (de façon à ce que Subversion puisse le rediriger vers le fichier suivi en versions approprié). Pour la plupart des programmes de fusion alternatifs, seuls les neuvième, dixième et onzième arguments (les chemins des fichiers qui contiennent les versions « mien », « original » et « leur » respectivement) sont intéressants. Notez que puisque Subversion utilise la sortie de votre programme de fusion, votre script d'interface ne doit pas se terminer avant que la sortie n'ait été fournie à Subversion. Quand il se termine, il doit retourner un code d'erreur de 0 si la fusion s'est correctement déroulée ou de 1 si des conflits non résolus persistent dans la sortie. Tout autre code d'erreur est considéré comme une erreur fatale.
L'Exemple 7.4, « diff3wrap.py » et l'Exemple 7.5, « diff3wrap.bat » sont des modèles pour des scripts d'interface vers un programme externe de comparaison de trois fichiers en langage Python et script Windows respectivement.
Exemple 7.4. diff3wrap.py
#!/usr/bin/env python import sys import os # Indiquez ici le chemin de votre outil de comparaison de 3 fichiers favori. DIFF3 = "/usr/local/bin/mon-diff3-favori" # Subversion fournit les chemins voulus dans les trois derniers arguments. MIEN = sys.argv[-3] VIEUX = sys.argv[-2] LEUR = sys.argv[-1] # Appelons la commande de comparaison (modifiez la ligne suivante # en accord avec votre outil). cmd = [DIFF3, '--older', VIEUX, '--mine', MIEN, '--yours', LEUR] os.execv(cmd[0], cmd) # Après avoir effectué la fusion, le script doit envoyer le # contenu du fichier résultant vers la sortie standard (stdout) # Faites le à votre convenance. # Le code d'erreur renvoyé doit être : # 0 si la fusion a bien fonctionné, # 1 s'il reste des conflits non résolus. # Tout autre code est traité comme une erreur fatale.
Exemple 7.5. diff3wrap.bat
@ECHO OFF REM Indiquez ici le chemin de votre outil de comparaison favori. SET DIFF3="C:\Program Files\Super Progs\Mon Diff3 Favori.exe" REM Subversion fournit les chemins voulus dans les trois derniers arguments. REM Ce sont les paramètres 9, 10 et 11. Mais nous n'avons accès qu'à REM neuf paramètres en même temps, nous effectuons donc deux décalages REM pour obtenir les paramètres manquants. SHIFT SHIFT SET MIEN=%7 SET VIEUX=%8 SET LEUR=%9 REM Appelons la commande de comparaison (modifiez la ligne suivante REM en accord avec votre outil). %DIFF3% --older %VIEUX% --mine %MIEN% --yours %LEUR% REM Après avoir effectué la fusion, le script doit envoyer le REM contenu du fichier résultant vers la sortie standard (stdout) REM Faites le à votre convenance. REM Le code d'erreur renvoyé doit être : REM 0 si la fusion a bien fonctionné, REM 1 s'il reste des conflits non résolus. REM Tout autre code est traité comme une erreur fatale.
Subversion peut faire appel à un outil de fusion externe dans le cadre de la résolution interactive de conflits. Il fournit alors les arguments suivants à ce programme : le chemin vers le fichier original non modifié, le chemin vers le fichier « theirs » qui contient les modifications en provenance du dépôt, le chemin vers le fichier dans lequel doivent être insérées les modifications une fois les conflits résolus et le chemin vers la copie de travail du fichier en conflit. L'outil de fusion est censé retourner un code d'erreur de 0 si la fusion s'est correctement déroulée ou de 1 si des conflits non résolus persistent dans la sortie. Tout autre code d'erreur est considéré comme une erreur fatale.
L'Exemple 7.6, « mergewrap.py » et l'Exemple 7.7, « mergewrap.bat » fournissent des modèles de scripts d'interface pour encapsuler un outil de fusion, en langage Python et script Windows respectivement.
Exemple 7.6. mergewrap.py
#!/usr/bin/env python import sys import os # Indiquez ici le chemin vers votre outil de fusion favori. MERGE = "/usr/local/bin/mon-outil-de-fusion" # Subversion fournit les chemins voulus BASE = sys.argv[1] LEUR = sys.argv[2] MIEN = sys.argv[3] FUSIONNE = sys.argv[4] COPIE_TRAVAIL = sys.argv[5] # Appelons la commande de fusion (modifiez la ligne suivante # en accord avec votre outil de fusion). cmd = [MERGE, '--base', BASE, '--mine', MIEN, '--theirs', LEUR, '--outfile', FUSIONNE] os.execv(cmd[0], cmd) # Le code d'erreur renvoyé doit être : # 0 si la fusion a bien fonctionné, # 1 s'il reste des conflits non résolus. # Tout autre code est traité comme une erreur fatale.
Exemple 7.7. mergewrap.bat
@ECHO OFF REM Indiquez ici le chemin vers votre outil de fusion favori. SET MERGE="C:\Program Files\Mes Outils Perso\Mon Outil de Fusion.exe" REM Subversion fournit les chemins voulus SET BASE=%1 SET LEUR=%2 SET MIEN=%3 SET FUSIONNE=%4 SET COPIE_TRAVAIL=%5 REM Appelons la commande de fusion (modifiez la ligne suivante REM en accord avec votre outil de fusion). %MERGE% --base %BASE% --mine %MIEN% --theirs %LEUR% --outfile %FUSIONNE% REM Le code d'erreur renvoyé doit être : REM 0 si la fusion a bien fonctionné, REM 1 s'il reste des conflits non résolus. REM Tout autre code est traité comme une erreur fatale.
[76] Le manuel du diff GNU indique : « Un code de retour valant 0 signifie qu'aucune différence n'a été trouvée, 1 signifie que des différences sont apparues, 2 indique une erreur ».