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 les définitions 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 « Manipulation des 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-répertoires 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érieure à 1.5 utilisent un format de définitions externes qui est un tableau sur plusieurs lignes composées de sous-répertoires (relativement au répertoire 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
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

Quand quelqu'un extrait une copie de travail du répertoire 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-répertoire 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 piquets de révision. L'exemple précédent sur les références externes donne avec Subversion 1.5 :

$ svn propget svn:externals calc
      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 piquets de révision (décrite en détail dans la section intitulée « Piquets de révisions et révisions opérationnelles »), il peut aussi être écrit comme ceci :

$ svn propget svn:externals calc
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 répertoire racine appelé mon-projet pour lequel nous avons défini des références externes dans un sous-répertoire (mon-projet/un-rep) vers la dernière révision d'un autre sous-répertoire (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

Récupération de la référence externe dans 'nouveau-projet/un-rep/sous-rep'
svn: Le dépôt http://svn.exemple.com/projets/mon-projet/rep-externe n'existe pas

$

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://, seront 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.

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
^/sons                             tierce-partie/sons
/themes@148                        tierce-partie/themes
//svn.exemple.com/outils-themes@21 tierce-partie/themes/outils

Le support des références externes dans Subversion demeure imparfait. Une définition de référence externe ne peut pointer que vers des répertoires et non vers des fichiers. Par ailleurs, le sous-répertoire local dans la définition ne peut pas contenir d'indicateur de répertoire père (..) ; ainsi, ../../themes/mon-theme est interdit. Et peut-être encore plus dommage, les copies de travail créées par la définition de références externes sont toujours déconnectées de la copie de travail primaire (celle dans laquelle la propriété svn:externals est définie sur le répertoire suivi en versions). Et Subversion ne peut fonctionner pleinement que sur des copies de travail d'un seul tenant. Ainsi, si vous voulez propager des changements que vous avez effectués sur une ou plusieurs de ces copies de travail externes, vous devez lancez svn commit explicitement sur ces copies de travail — effectuer une propagation sur la copie de travail primaire ne traite pas récursivement les copies de travail externes.

Nous avons déjà mentionné certains défauts de l'ancien format de svn:externals et comment la version 1.5 de Subversion les corrige. Mais faites attention, en utilisant les nouveaux formats, à ne pas pénaliser accidentellement des utilisateurs qui accèdent à votre dépôt avec de vieux clients Subversion. Alors que les clients Subversion 1.5 supportent toujours le format original des définitions de références externes, les vieux clients ne sont pas capables d'analyser le nouveau format.

En plus des commandes svn checkout, svn update, svn switch et svn export qui gèrent effectivement les sous-répertoires disjoints (ou déconnectés) où sont extraites les références externes, la commande svn status reconnaît également les définitions de références externes. Elle affiche un code de statut X pour les sous-répertoires externes disjoints et parcourt ces sous-répertoires pour afficher le statut des éléments externes eux-mêmes. Vous pouvez passer l'option --ignore-externals à n'importe laquelle de ces commandes pour désactiver le traitement des définitions de références externes.