Créez un dossier dédié au présent TP. Nous ne nommerons svn
dans la suite de l’énoncée.
Dans ce dossier, créez-en un nommé client
et un autre nommé serveur
. Dans un terminal, positionnez vous sur le dossier serveur
.
La plupart du temps, les serveurs sont abrités sur des machines différentes des clients. Dans le cadre de ce TP, nous travaillerons en local sur localhost
et “simulerons” plusieurs clients se synchronisant avec le serveur.
A ce point, la commande tree -d
devrait afficher
..
├── clients
└── serveur
Correction
$ mkdir svn
$ cd svn
$ mkdir serveur
$ mkdir clients
$ cd serveur
$ svnadmin create projet1
Vérifiez qu’un dossier projet1
a bien été créé. La commande tree -d
lancée du dossier svn
affiche quelque chose comme :
.
├── clients
├── init1
├── init2
└── serveur
└── projet1
├── conf
├── db
├── hooks
└── locks
On remarque ainsi que projet1
et projet2
– créés par svnadmin create
– contiennent des dossiers qui seront employés par SVN pour la configuration et le stockage des différentes versions du projet.
projet1/conf/passwd
pour déterminer les utilisateurs pouvant accéder à ce dépôt SVN. Saisissez les informations suivantes :[users]
usera = passa
userb = passb
Pour éditer le fichier, vous pouvez par exemple lancer la commande gedit projet1/conf/passwd
ou bien nano projet1/conf/passwd
.
Ce faisant, l’utilisateur avec le login usera
pourra accéder au dépôt avec le mot de passe passa
. Un autre utilisateur pourra également y accéder. Ces informations ne seront employées que lors d’un accès par le protocole svn://
, et pas localement (dans ce cas, ce sont les droits du système de fichiers qui régissent les accès en lecture et écriture au dépôt).
userb
et userc
y auront accès.Ainsi,
projet1/conf/svnserve.conf
et projet2/conf/svnserve.conf
en décommantant les lignes suivantes :anon-access = read
auth-access = write
password-db = passwd
$ chmod o-r projet1/conf/authz
$ chmod o-r projet1/conf/passwd
$ chmod o-r projet2/conf/authz
$ chmod o-r projet2/conf/passwd
svn
, créez deux dossiers init1
et init2
. Ces deux dossiers vont abriter les versions initiales des projets 1 et 2.La commande tree -d svn
lancée du dossier svn
devrait afficher quelque chose comme :
.
├── clients
├── init1
├── init2
└── serveur
├── projet1
└── projet2
(raccourci)
L’emplacement où sont créés init1
et inti2
est en fait indifférent. Ces dossiers ne serviront qu’à l’initialisation des dépôts.
prose.txt
avec le contenu suivant :Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus hendrerit tempus consequat. Donec ut massa vitae lacus euismod luctus. Nunc venenatis auctor leo id facilisis. Etiam et lobortis quam. Aliquam erat volutpat. Quisque non eleifend eros. Nulla mauris sem, sodales ut massa quis, consequat mattis odio. Aliquam luctus, quam nec aliquam ornare, orci metus posuere sem, non tincidunt tellus enim ac massa. Curabitur rhoncus odio non congue volutpat.
HelloWorld.java
avec le contenu suivant :class HelloWorld {
}
L’initialisation du projet 1 s’opère par l’importation du contenu de inti1
dans le dépôt SVN projet1
. Comme le dépôt est sur le système de fichiers local, on peut employer le protocole file://
.
prose.txt
) dans le dépôt projet 1
par la commande suivante, à supposer que l’on soit positionné dans le dossier svn
.svn import init1 file:///CHEMIN-VERS-SVN/svn/serveur/projet1 -m "création du projet1"
Vous devriez obtenir un message de confirmation de l’import :
Ajout init1/prose.txt
Révision 1 propagée.
svn://
pour des accès distantsSur une machine accessible par son IP, on peut utiliser un protocole spécifique à SVN en démarrant un serveur adéquat, comme on démarre Apache pour le protocole http://
.
serveur
créé plus haut soit la racine des dépôts disponibles, employez la commande suivante.& svnserve -d -r /CHEMIN-VERS-SVN/svn/serveur &
Un ps -aux | grep svnserve
permet de faire apparaître le numéro de processus et de vérifier que le démon est bien lancé.
Désormais, le serveur sera accessible de manière distante par l’adresse svn://IP/NOMDEPOT
.
init2
dans projet2
, utilisez le protocole SVN en employant la commandesvn import --username userb --password passb init2 svn://localhost/projet2 -m "création du projet2"
Ici, une identification est nécessaire. Si vous n’en saisissez pas les informations dans la ligne de commande, elles vous seront demandées.
En principe, un message de confirmation devrait apparaître.
Ajout init2/HelloWorld.java
Révision 1 propagée.
$ rm -rf init1 init2
svn
├── clients
└── serveur
├── projet1
└── projet2
Trois utilisateurs usera
, userb
et usera
ont été définis. Avec le protocole svn://
, ils peuvent accéder aux dépôts de manière distante. Dans le cadre de ce TP, nous emploierons ce protocole mais ferons tout de la même machine, en “simulant” ces trois utilisateurs.
user-a
, user-b
et user-c
dans le dossier client
.svn
├── clients
│ ├── user-a
│ ├── user-b
│ └── user-c
└── serveur
Ces dossiers pourraient tout aussi bien être n’importe où, sur des machines différentes et utilisées par des individus différents.
user-X
.Pour créer des copies de travail locales depuis le serveur, il suffit d’utiliser la commande svn checkout
en indiquant le dépôt du projet que l’on veut récupérer.
PLACEZ VOUS DU POINT DE VUE DE L’UTILISATEUR A (en sélectionnant l’onglet A).
$ svn checkout svn://localhost/projet1
Un message de confirmation apparaît :
A projet1/prose.txt
Révision 1 extraite.
L’utilisateur B peut travailler sur les deux projets et l’utilisateur C peut travailler sur le projet 2 seulement.
user-b
et user-a
.A l’issue de ces manipulations, vous devriez obtenir l’arborescence suivante :
clients
├── user-a
│ └── projet1
│ └── prose.txt
├── user-b
│ ├── projet1
│ │ └── prose.txt
│ └── projet2
│ └── HelloWorld.java
└── user-c
└── projet2
└── HelloWorld.java
Deux utilisateurs travaillent donc sur chaque projet, et modifient leurs copies locales de manière tout à fait indépendante. Il est néanmoins nécessaire de garantir une cohérence de leurs copies locales.
PLACEZ VOUS DU POINT DE VUE DE L’UTILISATEUR C (en sélectionnant l’onglet C).
HelloWorld.java
en employant par exemple la commande gedit projet2/HelloWorld.java
ou nano projet2/HelloWorld.java
. Modifiez le fichier en ébauchant une méthode main()
:class HelloWorld {
static void main() {
}
}
svn commit projet2 -m "ajout d'un main"
Un message de confirmation apparaît.
Envoi projet2/HelloWorld.java
Transmission des données .
Révision 2 propagée.
PLACEZ VOUS DU POINT DE VUE DE L’UTILISATEUR B
Le fichier HelloWorld.java
a-t-il changé ?
Mettez à jour la copie locale du projet 2 et vérifiez que le fichier a bien été mis à jour.
$ svn update projet2
vers.txt
dans le projet1
. Son contenu est :Sans ruse et sans détours, sans honte ni mensonge
Sans qu'un désir nous trompe, ou qu'un remords nous ronge
D'avoir une âme douce et mystiquement tendre
Et d'espérer, de croire et de toujours attendre
Comment roulent les cieux, et quel puissant génie
Des sphères dans leur cours entretient l'harmonie
Elle aime, et n'aime plus, et puis elle aime encore
Cent fois elle brûla mon coeur du feu qui me dévore
Quelquefois seulement quand mon âme est oppressée
Je sens en rythmes nombreux déborder ma pensée
svn commit projet1 -m "ajout d'un poème en vers"
Il n’y a aucun message de confirmation et un update du point de l’utilisateur A confirme que rien n’a changé. D’ailleurs, du point de vue de B, la commande svn status -vu projet1
indique le statut suivant pour la copie locale :
1 1 pierre projet1/prose.txt
? projet1/vers.txt
1 1 pierre projet1
État par rapport à la révision 1
Le ?
indique en fait que vers.txt
n’est pas géré par SVN.
Utilisez svn add
de manière adéquate, pour que vers.txt
soit désormais géré par SVN.
Sans commit, rien n’est transféré au dépôt. Commitez donc.
Comme vous lancez une opération d’écriture dans le dépôt, une authentification peut être requise. Le cas échéant, identifiez-vous en tant que userb
avec le mot de passe passb
, tel que défini plus haut.
PLACEZ VOUS DU POINT DE VUE DE L’UTILISATEUR A
Désormais, on a bien :
clients
├── user-a
│ └── projet1
│ ├── prose.txt
│ └── vers.txt
├── user-b
│ ├── projet1
│ │ ├── prose.txt
│ │ └── vers.txt
│ └── projet2
│ └── HelloWorld.java
└── user-c
└── projet2
└── HelloWorld.java
Pour supprimer un fichier d’un projet, il ne faut pas simplement le supprimer du système de fichiers. Comme il est géré par SVN, il est nécessaire d’utiliser une commande SVN.
prose.txt
grâce à la commande :$ svn delete projet1/prose.txt
Le fichier est supprimé localement, et le prochain commit
propagera ce changement au dépôt. On n’est pas obligé de propager chaque changement immédiatement : on attend même souvent la fin d’une journée de travail pour faire un commit
entraînant de nombreuses modifications simultanées.
vers.txt
pour que son contenu devienne moins fleur bleue :Le minuscule radiocompas du grand bateau me poursuivait
L'impératrice envieuse du dernier chlorure adorait tenir la main du caprice de femme terrible
La giboulée de la poulette m'obsédait
La fille du bibi rêvait du l'adorateur stérilisé
Comme pour la suppression, le renommage d’un fichier pris en charge par SVN se fait à l’aide de la commande svn
:
$ svn rename projet1/vers.txt projet1/poesie.txt
Le statut de la copie locale (svn status -vu projet1
) indique que plusieurs changements ont été effectués et doivent être propagés au dépôt.
A + - 2 userb projet1/poesie.txt
D 2 1 pierre projet1/prose.txt
D 2 2 userb projet1/vers.txt
2 2 userb projet1
État par rapport à la révision 2
PLACEZ VOUS DU POINT DE VUE DE L’UTILISATEUR B
$ svn update projet1
Updating 'projet1':
D projet1/vers.txt
D projet1/prose.txt
A projet1/poesie.txt
Actualisé à la révision 3.
Pour plus de commodité quand on travaille sur un seul projet, on se place souvent dans le dossier de la copie de travail du projet en question. Ainsi, exécutez des commandes cd projet2
dans les onglets des utilisateurs B et C. Les commandes SVN sont ainsi raccourcies car on n’est plus contraints de préciser le projet.
HelloWorld.java
:class HelloWorld {
static void main(String[] args) {
}
}
PLACEZ VOUS DU POINT DE VUE DE L’UTILISATEUR C
HelloWorld.java
:class HelloWorld {
static void main() {
System.out.println("Hello world");
}
}
$ svn commit -m "affichage dans le main"
PLACEZ VOUS DU POINT DE VUE DE L’UTILISATEUR B
$ svn commit -m "ajout des paramètres du main"
Envoi HelloWorld.java
Transmission des données .svn: E160028: Échec de la propagation (commit), détails :
svn: E160028: Fichier '/HelloWorld.java' obsolète
L’utilisateur B ne peut pas propager ses modifications sur le serveur, car elles avaient été opérées à partir d’une version qui n’est plus la version courante sur le serveur. Dans ce cas, il convient plutôt de mettre d’abord à jour la copie locale avec la dernière version. Cette lise à jour cherchera à préserver le travail de l’utilisateur B.
$ svn update
Updating '.':
G HelloWorld.java
Actualisé à la révision 3.
Affichez le fichier HelloWorld.java
de B. Que remarquez-vous ?
Propagez le fichier au serveur et à la copie de travail de l’utilisateur C.
Quand deux clients modifient la même ligne, en revanche, il est difficile de rassembler plusieurs versions.
Assurez-vous que les deux utilisateurs B et C disposent de la même copie de HelloWorld.java
:
class HelloWorld {
static void main(String[] args) {
System.out.println("Hello world");
}
}
HelloWorld.java
, et propagez les changements au dépôt :class HelloWorld {
static void main(String[] args) {
System.out.println("Hola mundo");
}
}
PLACEZ VOUS DU POINT DE VUE DE L’UTILISATEUR C
HelloWorld.java
, et propagez les changements au dépôt :class HelloWorld {
static void main(String[] args) {
System.out.println("Ciao mondo");
}
}
Là encore, le commit ne peut pas se faire.
Ca ne fonctionne pas (entrez p
) car c’est la même ligne qui a été modifiée et il en résulte un conflit qui doit être résolu manuellement. Pour ce faire, la copie locale voit apparaître plusieurs versions du fichier :
HelloWorld.java
avec les problèmes mis en évidenceHelloWorld.java.mine
qui est la version de la copie de travailHelloWorld.java.r4
et HelloWorld.java.r5
qui sont les versions du fichier aux deux dernières révisions du dépôt.HelloWorld.java
:class HelloWorld {
static void main(String[] args) {
System.out.println("Ciao mundo");
}
}
$ svn resolved HelloWorld.java
Après propagation, le fichier HelloWorld.java
a subi quelques modifications que l’on peut tracer grâce à la sous-commande log
.
$ svn log HelloWorld.java
Ce TP est une courte introduction à Subversion. Mais SVN prend toute sa mesure
On recommande un ouvrage gratuit par les développeurs de Subversion pour aller plus loin.
Dans le cadre de ce TP, nous avons choisi de n’aborder que la ligne de commande. En pratique, les IDE comme Eclipse intègrent subversion, de manière à proposer une interface plus conviviale et intégrée au contrôle de version des logiciels développés en équipe.