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.

Définition de références externes

Parfois il peut être utile de construire une copie de travail issue de différentes extractions. Par exemple, vous pouvez avoir envie d'avoir différents sous-répertoires provenant de différents endroits du dépôt ou même carrément de différents dépôts. Vous pouvez arriver à un tel enchevêtrement manuellement, en utilisant svn checkout, pour créer le genre de structure voulu pour votre copie de travail. Mais si cette configuration est importante pour tous les utilisateurs de votre dépôt, chacun doit effectuer les mêmes opérations d'extraction que vous.

Heureusement, Subversion supporte la définition de références externes. Une définition de référence externe est une association entre un répertoire local et une URL (et idéalement un numéro de révision particulier) pour un répertoire suivi en versions. Dans Subversion, vous déclarez les définitions de références externes dans des groupes en utilisant la propriété svn:externals. Vous pouvez créer et modifier cette propriété en utilisant svn propset ou svn propedit (voir la section intitulée « Manipuler les propriétés »). Elle peut être définie sur tous les répertoires suivis en versions et sa valeur décrit à la fois l'URL du dépôt externe et le répertoire côté client dans lequel est extrait cette URL.

L'un des attraits de la propriété svn:externals est qu'une fois qu'elle est définie pour un répertoire suivi en versions, chaque utilisateur qui extrait une copie de travail de ce répertoire bénéficie des définitions de références externes. En d'autres termes, une fois qu'un utilisateur a fait l'effort de définir la structure de la copie de travail imbriquée, tout le monde en bénéficie automatiquement : Subversion, lors de l'extraction de la copie de travail originale, extraie également les copies de travail externes.

[Avertissement] Avertissement

Les sous-dossiers cibles des définitions de références externes ne doivent pas déjà exister sur votre système ou sur le systèmes des autres utilisateurs : Subversion les crée lors de l'extraction des copies de travail externes.

Vous bénéficiez avec les définitions de références externes de tous les avantages liés aux propriétés Subversion. Les définitions sont suivies en versions. Si vous avez besoin de changer une définition de référence externe, vous pouvez le faire à l'aide des sous-commandes classiques sur les propriétés. Quand vous propagez des modifications relatives à la propriété svn:externals, Subversion synchronise les éléments extraits par rapport à la définition de références externes modifiée dès que vous lancez svn update. Tous ceux qui mettent à jour leur copie de travail reçoivent vos modifications concernant les définitions de références externes.

[Astuce] Astuce

Comme la valeur de la propriété svn:externals est constituée de plusieurs lignes, nous vous recommandons fortement d'utiliser svn propedit plutôt que svn propset.

Les versions de Subversion antérieures à 1.5 utilisent un format de définitions externes qui est un tableau sur plusieurs lignes composées de sous-dossiers (relativement au dossier suivi en versions sur lequel est définie la propriété), d'indicateurs de révision optionnels et l'URL, absolue et complètement qualifiée, du dépôt Subversion. Par exemple :

$ svn propget svn:externals calc
# Ressources suivies en versions ailleurs
tierce-partie/sons                 http://svn.exemple.com/depot/sons
tierce-partie/themes -r148         http://svn.exemple.com/projet-themes
tierce-partie/themes/outils -r21   http://svn.exemple.com/outils-themes
$

Dans l'exemple précédent, trois définitions externes sont définies. La première est « libre », elle fait référence à la révision HEAD de sa cible. Les deux autres ont des révisions spécifiques déclarées. L'exemple montre aussi que les lignes qui commencent par un croisillon (#) sont considérées comme des commentaires et ignorées dans l'analyse des définitions externes.

Quand quelqu'un extrait une copie de travail du dossier calc décrit dans l'exemple ci-dessus, Subversion extrait également les éléments trouvés dans les définitions de références externes.

$ svn checkout http://svn.exemple.com/depot/calc
A  calc
A  calc/Makefile
A  calc/entier.c
A  calc/bouton.c
Révision 148 extraite.

Récupération de la référence externe dans 'calc/tierce-partie/sons'
A  calc/tierce-partie/sons/ding.ogg
A  calc/tierce-partie/sons/dong.ogg
A  calc/tierce-partie/sons/clang.ogg
…
A  calc/tierce-partie/sons/bang.ogg
A  calc/tierce-partie/sons/twang.ogg
Révision 14 extraite.

Récupération de la référence externe dans 'calc/tierce-partie/themes'
…

À partir de la version 1.5 de Subversion, un nouveau format de la propriété svn:externals est supporté. Les références externes sont toujours multi-lignes mais l'ordre et le format des différentes informations ont changé. La nouvelle syntaxe ressemble plus à l'ordre des arguments que vous passez à la commande svn checkout : l'indicateur optionnel de révision est placé en premier, puis l'URL du dépôt Subversion externe et, enfin, le sous-dossier local relatif. Notez cependant que cette fois-ci nous n'avons pas indiqué « URL absolue et complètement qualifiée » pour le dépôt externe. En effet, le nouveau format accepte les URL relatives et les URL avec des révisions pivots. L'exemple précédent sur les références externes donne avec Subversion 1.5 :

$ svn propget svn:externals calc
# Ressources suivies en versions ailleurs
      http://svn.exemple.com/depot/sons     tierce-partie/sons
-r148 http://svn.exemple.com/projet-themes  tierce-partie/themes
-r21  http://svn.exemple.com/outils-themes  tierce-partie/themes/outils
$

En utilisant la syntaxe avec les révisions pivots (décrite en détail dans la section intitulée « Révisions pivots et révisions opérationnelles »), il peut aussi être écrit comme ceci :

$ svn propget svn:externals calc
# Ressources suivies en versions ailleurs
http://svn.exemple.com/depot/sons         tierce-partie/sons
http://svn.exemple.com/projet-themes@148  tierce-partie/themes
http://svn.exemple.com/outils-themes@21   tierce-partie/themes/outils
$
[Astuce] Astuce

Il est particulièrement conseillé d'utiliser des numéros de révision explicites dans toutes vos références externes. Ainsi, vous conservez la possibilité de décider quand rapatrier une nouvelle version de vos informations externes et quelle version exacte rapatrier. En plus de vous éviter la surprise de recevoir des changements effectués sur des dépôts tiers dont vous n'avez pas la maîtrise, l'utilisation de numéros de révisions explicites signifie aussi que, si vous revenez à une version de travail antérieure, vos références externes reviendront elles aussi dans l'état où elles étaient au moment de cette version antérieure. Cela signifie aussi que les copies de travail externes sont actualisées pour refléter leur état au moment de la révision antérieure. Pour des projets logiciels, cela peut faire la différence entre la réussite et l'échec de la compilation d'une version antérieure d'un code source complexe.

Pour la plupart des dépôts, les trois formats de références externes ont le même effet au final. Ils apportent tous les mêmes avantages. Malheureusement, ils possèdent aussi les mêmes inconvénients. Puisque les références indiquées utilisent des URL absolues, déplacer ou copier un répertoire auquel elles sont rattachées n'affecte pas ce qui est extrait en externe (alors qu'une référence relative est, bien évidemment, déplacée avec le répertoire). Cela peut vous induire en erreur, voire être assez frustrant, dans certaines situations. Par exemple, imaginons un dossier racine appelé mon-projet pour lequel nous avons défini des références externes dans un sous-dossier (mon-projet/un-rep) vers la dernière révision d'un autre sous-dossier (mon-projet/rep-externe).

$ svn checkout http://svn.exemple.com/projets .
A    mon-projet
A    mon-projet/un-rep
A    mon-projet/rep-externe
…
Récupération de la référence externe dans 'mon-projet/un-rep/sous-rep'
Référence externe actualisée à la révision 11.

Actualisé à la révision 11.
$ svn propget svn:externals mon-projet/un-rep
sous-rep http://svn.exemple.com/projets/mon-projet/rep-externe

$

Maintenant utilisez la commande svn move pour renommer le répertoire mon-projet. À ce moment là, vos définitions de références externes pointent toujours vers un chemin sous le répertoire mon-projet, même si ce répertoire n'existe plus.

 
$ svn move -q mon-projet nouveau-projet
$ svn commit -m "Renommé mon-projet en nouveau-projet."
Suppression    mon-projet
Ajout          nouveau-projet

Révision 12 propagée.
$ svn update
Mise à jour de '.' :
svn: warning: W200000: Erreur dans la récupération de la référence externe dans 'nouveau-projet/un-rep/sous-rep'
svn: warning: W170000: Le dépôt http://svn.exemple.com/projets/mon-projet/rep-externe n'existe pas
À la révision 12.
$

De plus, les URL absolues utilisées par les références externes peuvent causer des problèmes pour les dépôts accessibles via plusieurs types d'URL. Par exemple, si votre serveur Subversion est configuré pour autoriser tout le monde à consulter le dépôt via http:// ou https://, mais que les opérations de propagation doivent être effectuées uniquement via https://, vous vous retrouvez bien embêté. Si vos références externes pointent vers une URL de type http://, vous ne pouvez pas effectuer de propagation depuis les copies de travail créées via ces références externes. D'un autre côté, si vous utilisez la forme https:// pour les URL, ceux qui voudront effectuer des consultations via http://, parce que leur client ne sait pas traiter le https://, sont incapables de récupérer les éléments externes. Soyez conscient également que si vous avez besoin de déplacer toute votre copie de travail (avec svn switch et l'option --relocate), les références externes ne seront pas mises à jour en conséquence.

Subversion 1.5 franchit un grand pas dans la résolution de ces soucis. Comme indiqué précédemment, les URL utilisées dans le nouveau format des définitions des références externes peuvent être relatives. Par ailleurs, Subversion autorise une syntaxe magique pour spécifier plusieurs types d'URL relatives.

../

Relative à l'URL du répertoire sur lequel la propriété svn:externals est définie.

^/

Relative à la racine du dépôt pour lequel la propriété svn:externals est suivie en versions.

//

Relative au type d'URL du répertoire sur lequel la propriété svn:externals est définie.

/

Relative à l'URL du serveur sur lequel la propriété svn:externals est suivie en versions.

^/../NOM-DÉPÔT

Relative à un dépôt frère sous le même emplacement SVNParentPath-que le dépôt dans laquelle la référence svn:externals est définie.

Donc, considérons pour la quatrième fois la définition de nos références externes de l'exemple précédent et utilisons la nouvelle syntaxe de différentes manière. Nous obtenons :

$ svn propget svn:externals calc
# Ressources suivies en versions ailleurs
^/sons                             tierce-partie/sons
/themes@148                        tierce-partie/themes
//svn.exemple.com/outils-themes@21 tierce-partie/themes/outils
$

Subversion 1.6 apporta deux nouvelles améliorations aux définitions de références externes. D'abord, il ajouta un mécanisme d'échappement et mise entre guillemets à la syntaxe afin de traiter correctement des chemins de copies de travail externes contenant des espaces. Cela posait auparavant des problèmes car l'espace est un délimiteur de champs dans les définitions de références externes. Maintenant, vous n'avez qu'à entourer la spécification du chemin entre des guillemets doubles (") ou échapper les caractères qui posent problème dans le chemin avec la barre oblique inversée (\). Bien sûr, si l'URL de la référence externe comporte des espaces, vous devrez utiliser l'encodage standard des URI pour les représenter.

$ svn propget svn:externals paint 
http://svn.site-tiers.fr/depot/Mon%20projet "Mon projet"
http://svn.site-tiers.fr/depot/%22Avec%20des%20guillemets%22 \"Avec\ des\ guillemets\"
$

Subversion 1.6 introduit également le support pour la définition de références externes de fichiers. Les définitions de références externes de fichiers sont configurées de la même manière que les répertoires externes et apparaissent comme des fichiers suivis en versions dans la copie de travail.

Par exemple, supposons que vous ayez le fichier /trunk/couleurs_vélo/bleu.html dans votre dépôt et que vous souhaitiez que ce fichier, tel qu'il était dans la révision 40, apparaisse dans votre copie de travail de /trunk/www/ comme le fichier vert.html.

La définition de référence externe nécessaire pour obtenir ce résultat devrait vous être familière maintenant :

$ svn propget svn:externals www/
^/trunk/couleurs_vélo/bleu.html@40 vert.html
$ svn update
Mise à jour de '.' :

Récupération de la référence externe dans 'www' :
E    www/vert.html
Référence externe à la révision 40.

À la révision 103.
$ svn status
    X   www/vert.html
$

Comme vous pouvez le voir dans l'exemple ci-dessus, Subversion annote les fichiers externes avec la lettre E quand ils sont rappatriés vers la copie de travail et avec la lettre X lors de l'affichage de l'état de la copie de travail.

[Avertissement] Avertissement

Alors que les définitions de références externes pour un répertoire peuvent placer le répertoire à n'importe quelle profondeur et créer les répertoires intermédiaires manquants, les définitions de fichiers externes doivent être placées dans une copie de travail qui a déjà fait l'objet d'une extraction.

Lorsque vous examinez un fichier externe à l'aide de la commande svn info, vous pouvez voir l'URL et la révision qui sont à l'origine du fichier.

$ svn info www/vert.html
Chemin : www/vert.html
Nom : green.html
Chemin racine de la copie de travail : /home/harry/projects/my-project
URL : http://svn.example.com/projects/my-project/trunk/bikeshed/blue.html
Relative URL: ^/trunk/bikeshed/blue.html
Racine du dépôt : http://svn.example.com/projects/my-project
UUID du dépôt : b2a368dc-7564-11de-bb2b-113435390e17
Révision: 40
Type de nœud : fichier
Tâche programmée : normale
Auteur de la dernière modification : harry
Révision de la dernière modification : 40
Date de la dernière modification : 2009-07-20 20:38:20 +0100 (lun. 20 juil. 2009)
Texte mis à jour : 2009-07-20 23:22:36 +0100 (lun. 20 juil. 2009)
Somme de contrôle : 01a58b04617b92492d99662c3837b33b
$

Parce que les fichier externes sont traités dans la copie de travail comme des fichiers suivis en versions, ils peuvent être modifiés et même propagés s'ils font référence à un fichier à la révision HEAD. Les modifications propagées sont répercutées dans le fichier externe comme dans le fichier référencé. Cependant, dans notre exemple, nous avons pointé vers un fichier à une révision antérieure, c'est pourquoi une tentative de propagation du fichier externe échoue :

$ svn status 
M   X   www/vert.html
$ svn commit -m "change la couleur" www/vert.html
Envoi        www/vert.html
svn: E155011: Échec de la propagation (commit), détails :
svn: E155011: Fichier '/trunk/couleurs_vélo/bleu.html' obsolète
$

Gardez cela à l'esprit quand vous définissez des références vers des fichiers externes. Si vous avez besoin de pointer vers une révision particulière d'un fichier, vous ne pourrez pas modifier ce fichier externe. Si vous voulez pouvoir modifier le fichier externe, vous ne pouvez pas spécifier une révision autre que HEAD, ce qui est implicite si aucune révision n'est spécifiée.

Malheureusement, le support des références externes de Subversion reste largement perfectible. Les fichiers et les répertoires externes possèdent leur lot d'inconvénients. Quel que soit le type de référence externe, le sous-répertoire local faisant partie de la définition ne peut pas contenir d'indicateurs vers le répertoire parent « .. » (par exemple ../../skins/perso). Les fichiers externes ne peuvent pas faire référence à des fichiers d'autres dépôts. L'URL d'un fichier externe doit toujours être dans le même dépôt que sa cible. Aussi, les fichiers externes ne peuvent pas être déplacés ou effacés. C'est la propriété svn:externals qui doit être modifiée à la place. Cependant, les fichiers externes peuvent être copiés.

Ce qui est peut-être le plus ennuyeux, c'est que les copies de travail créées via le support de définition de références externes sont toujours déconnectées de la copie de travail primaire (sur laquelle le répertoire suivi en versions possède la propriété svn:externals). Et Subversion continue à fonctionner seulement sur des copies de travail conjointes. Ainsi, par exemple, si vous voulez propager des modifications que vous avez faites sur une ou plus de ces copies de travail externes, vous devez lancer svn commit explicitement sur ces copies de travail (la propagation sur la copie de travail initiale ne se répercute pas sur les copies externes).

Nous avons déjà mentionné quelques inconvénients de l'ancienne syntaxe svn:externals et comment la nouvelle syntaxe des versions plus récentes que Subversion 1.5 résolvent ce problème. Mais soyez vigilant lorsque vous utilisez cette nouvelle syntaxe de ne pas introduire de nouveaux problèmes par inadvertance. Par exemple, alors que les nouveaux clients sont capables de reconnaitre et prendre en charge l'ancienne syntaxe de défintion des références externes, les clients pré-1.5 ne peuvent pas analyser correctement la nouvelle syntaxe. Si vous changez vos définitions de références externes au nouveau format, vous forcez tous ceux qui utilisent ces références externes à effectivement mettre à niveau leur client Subversion vers une version capable de lire ce format. De même, soyez attentif à ne pas naïvement déplacer la portion -rNNN de la définition (l'ancien format utilise cette révision comme pivot, mais le nouveau format l'utilise comme révision opérationnelle avec une révision pivot à HEAD, sauf mention contraire  lisez la section intitulée « Révisions pivots et révisions opérationnelles » pour une explication complète de cette distinction).

[Avertissement] Avertissement

Les copies de travail externes sont toujours des copies de travail totalement auto-suffisantes. Vous pouvez effectuez les opérations que vous effectueriez sur toute autre copie de travail. Cela peut s'avérer très utile, vous permettant d'examiner une copie de travail externe indépendamment de toute copie de travail primaire dont la propriété svn:externals a causé l'instanciation. Faites attention, cependant, à ne pas modifier par mégarde votre copie de travail externe par des modifications subtiles qui peuvent engendrer des problèmes. Par exemple, bien que des définitions de références externes peuvent spécifier que la copie de travail externe pointe vers un numéro de révision particulier, si vous lancez la commande svn update directement sur la copie de travail externe, Subversion s'exécutera et votre copie de travail sera maintenant désynchronisée de la déclaration dans la copie de travail primaire. Utiliser svn switch pour faire pointer directement la copie de travail externe vers une nouvelle URL engendre le même type de problème si le contenu de la copie de travail primaire s'attend à un contenu particulier de la copie de travail externe.

Tout comme les commandes svn checkout, svn update, svn switch et svn export qui gèrent les sous-répertoires disjoints (ou déconnectés) depuis lesquels les références externes sont extraites, la commande svn status reconnait les définitions de références externes. Elle affiche un statut sous le code X pour les sous-répertoires externes disjoints, puis explore récursivement ces sous-répertoires pour afficher le statut des éléments externes eux-mêmes. Vous pouvez spécifier l'option --ignore-externals à n'importe laquelle de ces sous-commandes pour désactiver le traitement des définitions des références externes.