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.

Utilisation des outils externes de comparaison et de fusion

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] 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é svn:mime-type. Cela signifie, par exemple, que même si vous avez le plus formidable outil de l'univers, capable de comparer et fusionner des documents Microsoft Word, il ne sera jamais appelé par Subversion tant que le type MIME des documents Word suivis en versions indiquera qu'ils ne sont pas lisibles par un humain (tel que application/msword). Heureusement, vous pouvez passer l'option --force à svn diff pour court-circuiter la vérification du type MIME et ainsi forcer à calculer les différences. Pour plus d'informations sur la configuration des types MIME, voir la section intitulée « Type de contenu des fichiers »

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] 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.

Programmes externes de comparaison

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.

Programmes externes de comparaison de trois fichiers

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.

Outils de fusion externes

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 ».