Annexe R. Le travail en groupe avec Subversion

1. Qu'est-ce que Subversion ?
2. Installer et utiliser un client Subversion
3. Monter un serveur Subversion

1. Qu'est-ce que Subversion ?

Subversion (alias SVN) est un logiciel libre basé sur une architecture client-serveur qui permet de travailler à plusieurs et en même temps sur les mêmes fichiers. En effet, Subversion dispose d'un mécanisme intelligent de fusion des modifications apportées sur des fichiers texte. C'est un outil très utilisé pour le développement de logiciels, mais il peut également être utilisé pour gérer des sites Web, écrire des rapports en LaTeX, etc... d'une manière générale pour tout ce qui implique de travailler à plusieurs sur les mêmes fichiers textes. Il a pour but de remplaçer le logiciel CVS, qui assurait la même tâche, mais souffrait de certaines limitations dues à la conception trop ancienne de son architecture (ces limitations sont expliquées sur la page principale du site Web de Subversion).

Les paragraphes suivants vous donnent un aperçu des possibilités de Subversion et de sa mise en place. Pour plus d'informations, il existe une documentation très complète (mais en anglais) disponible à l'adresse suivante : http://svnbook.red-bean.com/.

2. Installer et utiliser un client Subversion

2.1. Installer le paquet

Le client et le serveur Subversion sont contenus dans le paquet subversion :

# aptitude install subversion

2.2. Utiliser le client Subversion

Récupérer les fichiers sur le serveur

Tout d'abord, il faut récupérer les fichiers du dépôt Subversion. Imaginons que vous ayez créé un dépôt SVN appelé projet1 sur la machine server.exemple.org, accessible à l'utilisateur toto (comme expliqué dans la section suivante Monter un serveur Subversion). Pour ce faire, on utilise la commande svn co (co étant un raccourci pour checkout) comme ceci :

% svn co svn://toto@server.exemple.org/svn/projet1

Cela va créer un répertoire appelé projet1 dans le répertoire courant, qui contiendra la version la plus récente des fichiers du dépôt projet1. Il est également possible de télécharger des versions particulières ou uniquement certains fichiers d'un dépôt. Par exemple, les commandes :

% svn co svn://toto@server.exemple.org/svn/projet1 -r35
% svn co svn://toto@server.exemple.org/svn/projet1 --revision {'2006-12-25 00:00'}
% svn co svn://toto@server.exemple.org/svn/projet1/trunk

téléchargeront respectivement :

  • la révision 35 de projet1,

  • la révision en cours le 25 décembre 2006 à minuit de projet1,

  • uniquement le répertoire trunk de projet1.

Se synchroniser avec le serveur

Si vous êtes plusieurs à travailler sur un même projet, il est fort possible que certains fichiers soient modifiés par d'autres contributeurs. La version disponible sur le serveur a donc changé, mais pas celle qui est présente sur votre ordinateur. Pour synchroniser vos fichiers avec ceux du serveur, il faut utiliser la commande svn up (avec up pour update). Par exemple, pour mettre à jour le répertoire trunk, il faut taper la commande :

% svn up trunk

De façon similaire à la commande svn co, on peut demander à SVN de se synchroniser avec la version 35, etc... On peut également demander à revenir à la version précédant la version en cours grâce à l'option --revision PREV.

Manipuler les fichiers

Subversion a ceci d'extrêmement pratique qu'il permet de garder un historique des modifications apportées aux fichiers du dépôt. Imaginons que votre dépôt contienne un fichier truc.txt. Un jour, ce fichier devient inutile et vous décidez de le supprimer, mais parallèlement, vous avez besoin de créer un fichier truc.txt n'ayant rien à voir dans un autre répertoire. Comment SVN peut-il savoir si vous avez juste déplacé et modifié le fichier truc.txt ou si vous l'avez supprimé puis vous avez créé un fichier du même nom ailleurs (auquel cas, le diff des deux fichiers n'a aucun sens...). ? C'est pour cela que SVN a ses propres commandes pour déplacer, renommer... des fichiers à la place des commandes habituelles. Voyons les principales :

  • svn list : liste les fichiers présents dans le répertoire courant,

  • svn add mon_fichier : ajoute le fichier mon_fichier au dépôt,

  • svn remove mon_fichier : supprime le fichier mon_fichier du dépôt,

  • svn move mon_fichier1 dossier/mon_fichier2  : déplace le fichier mon_fichier1 dans le répertoire dossier et le renomme en mon_fichier2,

  • svn copy mon_fichier1 dossier/mon_fichier2  : copie le fichier mon_fichier1 dans le répertoire dossier et le renomme en mon_fichier2.

Pour connaître l'ensemble des commandes disponibles, tapez :

% svn help

dans une console. Et pour obtenir la liste des options disponibles pour la commande ma_commande, tapez :

% svn help ma_commande

Voir les modifications apportées et commiter

Avant de commiter (envoyer les modifications que l'on a apportées sur le serveur), il peut être utile de vérifier les fichiers que l'on a modifiés ainsi que les modification que l'on y a apportées. Pour cela, SVN fournit également de nombreuses commandes :

  • svn status : liste les fichiers qui ont été modifiés depuis le dernier svn up. On peut connaître la nature des modifications apportées grâce au flag se trouvant juste avant le nom du fichier. Par exemple, « M » sigifie modifié, « A » ajouté, « D » supprimé, « ? » fichier créé mais non ajouté...

  • svn diff mon_fichier : affiche le diff entre le fichier mon_fichier et sa version courante (celle du dépôt),

  • svn log mon_fichier : affiche l'historique des modifications du fichier mon_fichier,

  • svn cleanup : annule toutes vos modifications de façon à retourner au même état que lors de votre dernier svn up.

Une fois que l'on est bien sûr des modifications que l'on a apportées, on peut commiter grâce à la commande :

% svn commit

SVN vous demandera alors de décrire les modifications que vous avez apportées. Ce sont ces mêmes lignes que vous verrez ultérieurement en faisant un svn log.

[Avertissement] Avertissement

ATTENTION : Faites bien attention à mettre à jour les fichiers que vous avez modifiés avant de commiter (commande svn up), sinon vous risquez d'annuler les modifications qu'un autre utilisateur a effectuées !

[Note] Note

Ceci n'est qu'un rapide aperçu de l'utilisation de Subversion. SVN est bien plus puissant, et vous pourrez trouver la documentation de référence (en anglais) ici .

3. Monter un serveur Subversion

Créer un repository SVN pour un premier projet

Je vais vous guider pas-à-pas pour la création d'un répository SVN pour un projet d'exemple appelé projet1.

Commençez par créer un groupe svn-projet1 associé au répository, qui permettra une bonne gestion des droits d'accès au répository :

# addgroup --system svn-projet1

Ensuite, créez le répository SVN (situé dans le répertoire /usr/local/svn/projet1 dans notre exemple, mais nous créerons aussi un lien symbolique /svn/ qui servira de raccourci) et donnez-lui les bonnes permissions :

# mkdir /usr/local/svn
# ln -s /usr/local/svn /svn
# svnadmin create --fs-type fsfs /usr/local/svn/projet1
# chgrp -R svn-projet1 /usr/local/svn/projet1
# chmod -R g+w /usr/local/svn/projet1

Donner l'accès aux utilisateurs du système via SSH

[Note] Note

Cette section requiert qu'un serveur SSH soit installé sur le système. Pour plus d'informations sur ce sujet, cf L'accès à distance par SSH.

Pour donner un accès au SVN à l'utilisateur toto qui a un compte sur le système, il suffit alors de le rajouter dans le groupe svn-projet1 :

# adduser toto svn-projet1

L'utilisateur toto peut alors se connecter au SVN par SSH :

% svn co svn+ssh://toto@server.exemple.org/svn/projet1

serveur.exemple.org est le nom DNS du serveur. À l'exécution de la commande, il vous demandera votre mot de passe système (ou votre pass-phrase si vous avez mis en place des clés SSH protégées par mot de passe).

Donner l'accès à des utilisateurs extérieurs

Pour donner accès au SVN à des utilisateurs qui n'ont pas de compte sur le système, il faut passer par inetd : toute connexion sur le port SVN (port 3690, cf. /etc/services) déclenchera le lancement de svnserve en tant qu'utilisateur svnowner.

Créez l'utilisateur svnowner et donnez-lui les droits sur le répository SVN :

# adduser --system --home /usr/local/svn svnowner
# chown -R svnowner /usr/local/svn/

Ajoutez la ligne suivante au fichier /etc/inetd.conf :

svn stream tcp nowait svnowner /usr/bin/svnserve svnserve -i

Dites à inetd de tenir compte de ce changement :

# /etc/init.d/inetd reload

Ensuite, éditez le fichier /usr/local/svn/projet1/conf/svnserve.conf. Vous allez décommenter certaines lignes pour configurer les droits d'accès à votre répository SVN ; les lignes qui commencent par trois '#' sont des commentaires (à lire !) ; les lignes qui commencent par un seul '#' sont destinées à être décommentées et personnalisées pour répondre à vos besoins.

Pour les projets OpenSource, il est courant de donner un accès en lecture seule aux utilisateurs non authentifiés. Si telle est votre motivation, mettez le paramètre anon-access à read ; sinon, pour empêcher tout accès non authentifié, mettez-le à none. Quant au paramère auth-access, il contrôle le niveau d'autorisation des utilisateurs authentifiés ; pour donner un accès en lecture et en écriture aux utilisateurs authentifiés, ce qui est probablement votre souhait, mettez-le à write. Le paramètre password-db définit l'emplacement du fichier contenant les noms d'utilisateurs et leurs mots de passe. Enfin, le paramètre realm vous permet de donner un nom long à votre répository, qui sera communiqué à la personne qui se connecte au serveur SVN.

Par exemple, pour un répository sans accès anonyme en lecture seule, le fichier svnserve.conf contiendra par exemple les lignes suivantes :

[general]
anon-access = none
auth-access = write
password-db = passwd
realm = Le projet numéro 1

Enfin, créez le fichier contenant les noms d'utilisateur et les mots de passe, que vous avez défini dans le fichier svnserve.conf. Dans notre exemple, nous avons mis la ligne password-db = passwd ; nous allons donc créer un fichier passwd dans le même répertoire que le fichier svnserve.conf, et qui ressemblera au fichier suivant si on veut avoir deux utilisateurs toto et tonton :

[users]
toto = mot_de_passe_de_toto_en_clair
tonton = mot_de_passe_de_tonton_en_clair

Enfin, assurez-vous que le fichier appartient à l'utilisateur svnowner et restreignez les droits sur ce fichier pour que tous les utilisateurs du système ne puissent pas voir les mots de passe qu'il contient :

# chown svnowner /usr/local/svn/projet1/conf/passwd
# chmod 600 /usr/local/svn/projet1/conf/passwd

L'utilisateur toto peut maintenant se connecter au serveur grâce au client SVN qu'il aura préalablement installé sur sa machine. Il lui suffira d'exécuter la commande suivante sur sa machine pour checkouter le répository :

% svn co svn://toto@server.exemple.org/svn/projet1

serveur.exemple.org est le nom DNS du serveur.

[Note] Note

L'authentification se fait par la technique du "challenge" ; le mot de passe n'est donc pas transmis sur le réseau.

La notification de commit par mail

Nous allons configurer le répository SVN pour qu'un mail soit envoyé à chaque commit ; ce mail devant contenir le nom de l'utilisateur qui a fait le commit, la liste des fichiers qu'il a modifiés, le message de commit et les modifications effectuées. Installez le paquet subversion-tools qui contient notamment un script de notification des commits par mail :

# aptitude install subversion-tools

Activez l'utilisation de ce script pour votre répository SVN :

# cd /usr/local/svn/projet1/hooks/
# mv post-commit.tmpl post-commit
# chmod 755 post-commit

Dans le fichier post-commit, vous verrez à la fin une ligne de commande qui fait appel à un script /usr/lib/subversion/hook-scripts/commit-email.pl, qui est le script de notification par mail du paquet subversion-tools. Vous pouvez améliorer l'utilisation du script en modifiant le fichier post-commit pour qu'il ressemble par exemple à ça :

REPOS="$1"
REV="$2"

AUTHOR=$(svnlook author --revision $REV $REPOS)

/usr/lib/subversion/hook-scripts/commit-email.pl "$REPOS" "$REV" --from "provenance@exemple.org" \
-s "[projet1] $AUTHOR |" destination@exemple.org

provenance@exemple.org et destination@exemple.org sont les adresses de provenance et de destination des mails de commit. Par exemple, vous pouvez mettre en adresse de provenance et de destination une mailing-liste à laquelle tous les participants du projet sont abonnés. Vous pouvez également personnaliser le flag dans le sujet du mail, qui est [projet1] dans cet exemple.

Désormais, les commits ne passeront plus inaperçus !