Le VCSSubversion s'est
largement imposé comme la référence en matière de VCS centralisé,
c'est-à-dire reposant sur un dépôt unique de
données. Contrairement à son prédécesseur CVS,
Subversion permet, par exemple, de déplacer facilement un fichier ou un
répertoire à l'intérieur du dépôt, sans perdre l'historique. Mais ce
déplacement n'est pas possible entre dépôts différents. Il existe une
manipulation pour le faire mais elle nécessite quelques efforts.
Pour Subversion, le monde se réduit à un
dépôt à la fois. Si on a un dépôt B
(https://svn.nic.fr/ReD-AFNIC/Etudes dans
l'exemple ci-dessous) et qu'on souhaite y importer des fichiers venus d'un dépôt
A
(svn+ssh://bortzmeyer@foobar.example.com/home/bortzmeyer/AFNIC-Subversion
dans l'exemple ci-dessous), en gardant leur historique (donc, sans
utiliser les fonctions d'importation classiques), la simple copie ne
marche pas :
% svn copy svn+ssh://bortzmeyer@foobar.example.com/home/bortzmeyer/AFNIC-Subversion \
https://svn.nic.fr/ReD-AFNIC/Etudes
svn: Source and dest appear not to be in the same repository (src: 'svn+ssh://bortzmeyer@foobar.example.com/home/bortzmeyer/AFNIC-Subversion'; dst: ' https://svn.nic.fr/ReD-AFNIC/Etudes')
La manipulation exacte est possible mais plus complexe. Il faut :
Copier le dépôt A sous forme d'un fichier texte. Il faut opérer
sur le serveur (on accède directement aux fichiers) avec la commande
svnadmin : svnadmin dump
/home/bortzmeyer/AFNIC-Subversion > svn.dumpFiltrer le fichier texte de dump avec la
commande svndumpfilter pour ne garder que le
sous-arbre qui nous intéresse. Attention, le chemin à donner en
paramètre est un chemin absolu dans le dépôt (ici, on garde trois
sous-arbres, anycast, EPP et
dDOS-February-2007). La commande utilisée est
svndumpfilter
include /RD/anycast /RD/EPP /RD/dDOS-February-2007 < svn.dump >
svn-filtered.dumpSelon l'arborescence utilisée dans l'ancien et dans le nouveau
dépôt, il peut être nécessaire d'éditer le fichier de
dump pour changer les noms des répertoires (les champs
Node-path et, s'il y eu des copies, par exemple des branches, les champs Node-copyfrom-path). Par exemple, si le fichier
dump contient Node-path:
IETF/Behave/tests-socket, et qu'on charge ce fichier dans
le répertoire /ReD-AFNIC, le fichier résultant
sera en /ReD-AFNIC/IETF/Behave/tests-socket. Ce changement peut se faire avec la fonction
de rechercher / remplacer d'un éditeur
ordinaire (les fichiers de dump de Subversion sont
de simples fichiers texte) ou bien avec un outil comme
sed ou perl.De même, il peut être nécessaire de créer le répertoire où sera
accroché le sous-arbre copié. Cette création peut se faire via une
copie de travail (mkdir puis svn
commit) ou bien directement dans le dépôt avec
svn mkdir URL.Copier le fichier résultant du filtrage sur le nouveau serveur
(là encore, il faut pouvoir accéder aux fichiers) avec
svnadmin : svnadmin load --parent-dir
/ReD-AFNIC /home/Subversion-Repository <
svn-filtered.dump. L'option
--parent-dir permet d'indiquer à quel endroit on
accroche le sous-arbre. Cette commande peut échouer partiellement et il est donc prudent de la tenter d'abord sur une copie du dépôt.Les deux commandes svnadmin nécessitent
d'avoir les droits pour accéder aux fichiers du dépôt Subversion, en
lecture pour la première étape et en écriture pour la seconde. Par
exemple, si le dépôt final n'est accessible qu'en
HTTP et que les données sont propriétaires de
l'utilisateur sous le nom duquel tourne le serveur HTTP (cet
utilisateur est www-data par défaut sur une
Debian), il faudra exécuter la commande sous
l'identité de www-data par exemple avec
sudo : sudo -u www-data svnadmin load ....
Si svnadmin load échoue avec un message du genre :
<<< Started new transaction, based on original revision 4
svnadmin: File not found: transaction '92-1', path '/ReD-AFNIC/Etudes/two'
* adding path : ReD-AFNIC/Etudes/two ... %
c'est qu'un répertoire manque. Il faut, comme indiqué ci-dessus, changer les noms dans le fichier de dump ou bien créer le répertoire. C'est le point le plus délicat de la manipulation.
Une fois copié l'ancien dépôt, il est prudent de faire un
svn delete sur cet ancien dépôt, pour éviter de
continuer à l'utiliser par accident.
Quelques avertissements, enfin :
Si des fusions ou d'autres opérations qui dépendent du numéro de
révision sont présentes dans l'ancien dépôt, elles ne seront pas
forcément copiées correctement.Les numéros des révisions ne sont pas conservés (puisqu'ils sont
uniques par dépôt), mais les dates le sont. Résultat, l'ordre des
révisions dans le nouveau dépôt n'est plus l'ordre chronologique.Bref, pour résumer, cette manipulation n'est pas idéale. Avec
Subversion, il vaut mieux réfléchir avant de mettre les fichiers dans
des dépôts séparés, copier entre dépôts restera toujours un pis-aller !
Merci beaucoup à Kevin Grover pour ses explications détaillées sur
la manipulation à faire, merci aussi à Les Mikesell pour des détails
utiles. Je signale aussi le court article « Moving
a Folder Across SVN Repositories ».
Blair Zajac me suggère qu'on peut aussi utiliser la propriété
svn:externals de Subversion pour « copier »
l'ancien dépôt sans réellement le fusionner (pas tout à fait ce dont
j'avais besoin mais cette technique peut être utile dans d'autres cas).
Pour tester différentes idées, j'ai écrit un script shell qui réalise cette
manipulation sur des dépôts « bidons ».