Queues


h1 12/17/2008 01:43:00 AM

La suite du billet précédent...

Initialement, je me suis mis à Mercurial dans l'idée de mieux gérer mes projets, à commencer par Savonet. J'ai commencé par tester Mercurial sur un projet en solo, où j'utilise des ropes annotées (oui, c'est une réponse lapidaire à un billet précédent) pour écrire proprement un éditeur de texte qui supporte bien l'analyse lexicale et syntaxique du texte (oui, c'est bed). Cela m'avait plu, et inspiré les remarques du précédent billet.

Maintenant, quel interêt a Mercurial pour un projet comme Savonet? Nous avons actuellement un écosystème assez bien foutu autour de notre SVN, dont nous sommes globalement contents. Pas de vrai besoin de décentralisation, ni de super gestion des branches. Les apports de Mercurial seraient en fait: le commit local, les queues de patchs. Je ne parlerai que des queues de patchs car elles permettent grosso modo d'émuler le commit local de toutes façons.

Dans Mercurial, un patch est une modification (révision, changeset...) modifiable. Imaginez faire quelques commits, puis vouloir en fusionner deux ou en modifier un. C'est quelque chose de risqué: si quelqun a déja vos modifications et que vous les modifiez, c'est très dur de se resynchroniser. Mais si les modifications sont restées locales, tout va bien. Et ça peut être très pratique pour éviter de se retrouver avec un historique SVN plein de modifications type "Typo", "Oops, I didn't mean to commit that file" ou encore "Remove debug code" et autres "Fixed the fix".

Les patchs sont gérées dans une queue, d'où l'appellation mercurial queue (MQ). C'est à dire qu'on va avoir une queue de modifications en attente, qu'on peut appliquer à son dépôt, ou annuler de façon très pratique. Par exemple, on va avoir un patch avec du code de debug, un patch avec un correctif, et on peut rapidement enlever l'un ou l'autre pour tester si le correctif a bien l'effet voulu, avec plus ou moins d'informations affichées. Une fois qu'on a un patch bien propre, on peut le transformer en révision normale et la partager avec le monde. Si on a envie de passer à autre chose, on met le patch en attente. Avant, pour faire ça, j'avais plusieurs copies du dépôt Savonet: une pour bosser le système de type, une pour bosser sur le smart cross, etc.

Travailler avec MQ est très intuitif et très pratique. Je me suis donc demandé comment l'utiliser pour Savonet, pour espérer avoir un jour des logs un peu plus lisibles.

J'ai testé hgsubversion pour convertir le dépôt SVN de savonet en Mercurial. Bien qu'expérimentale, cette extension marche bien, et surtout bien plus rapidement que l'import SVN actuellement officiellement inclus dans Mercurial. On obtient un dépôt Mercurial avec tout l'historique SVN, et on peut échanger de nouvelles révisions avec le dépôt SVN. J'ai ainsi pu élaborer un patch, puis le commiter sur le SVN. Par contre, il semble inutile de vouloir partager le dépôt Mercurial et mélanger le versioning Mercurial et SVN, ça pète assez vite. En plus, on perd quelques trucs propres au SVN dans Savonet: l'inclusion de la révision SVN dans la version, et les liens external.

Une autre possibilité est de rester à SVN mais d'utiliser MQ par dessus. Cela implique encore de mélanger le versioning SVN et Mercurial: si on fait une mise a jour SVN, il faut la propager à la main dans le dépôt Mercurial, avant de ré-appliquer éventuellement les patches en queue. Je n'ai pas encore essayé, mais je ne suis pas très optimiste.

Enfin, on peut utiliser les outils de gestion de patches qui ont inspiré MQ, notamment quilt. Je me disais qu'il n'y avait pas tant que ça à perdre, mais ils ne mentent pas dans Mercurial: l'intégration des queues dans Mercurial même fait toute la différence. Il est beaucoup plus pénible de bosser avec quilt: par exemple, il n'a aucun moyen de savoir qu'un fichier est modifié par rapport à sa version SVN, et donc de passer cette modification locale dans un patch. On peut bricoler deux trois trucs, et arriver à ses fins, mais ça reste peu confortable. Au fond, quilt ne m'inspire pas trop, c'est assez rugueux à l'usage, pis... c'est codé en shell.

Bref, il y a encore du boulot pour pousser les développeurs Savonet à tous utiliser un gestionnaire de patches avant de passer une modif sur le SVN. La seule chose claire dans tout ça, c'est qu'on peut déja utiliser ma queue de patches, quel que soit l'outil et la méthode, c'est relativement standard: elle est publiée (sous forme de dépôt Mercurial) sur dolebrai.net. C'était d'abord une queue Mercurial mais je l'utilise désormais via quilt sur des dépôts SVN. Dans les deux cas je partage ainsi des patchs entre mon portable et le serveur: ainsi, je ne salis pas le SVN pour tester sur le serveur une modif en cours d'élaboration.

Libellés :

Gestion de code pour les nuls


h1 12/07/2008 08:02:00 PM

Les programmeurs qui travaillent en groupe ont l'habitude d'utiliser des outils pour contrôler l'évolution de leur code source. Ces outils peuvent en fait être utiles à quiconque travaille sur du texte. Par exemple, j'utilise SVN aussi bien pour développer savonet que pour rédiger des articles à plusieurs, ou ma thèse tout seul. Leur utilité est par contre grandement réduite pour des fichiers comme des images ou du son, mais aussi un document de traitement de texte: c'est un avantage quand on travaille avec LaTeX ou HTML, le document est du texte brut, contrairement aux divers Machin Office.

Un objectif clair quand on travaille à plusieurs est d'éviter les conflits. Monsieur Machin et Madame Bidule font des modifications en même temps, il faut que tout le monde puisse en profiter, si possible fusionner les modifications (si elles portent sur des morceaux de texte différents) et sinon signaler le conflit et permettre de le résoudre manuellement.

Même quand on travaille seul, ces outils sont très utiles car il permettent de suivre l'évolution d'un fichier ("Quand et pourquoi ai-je changé cette ligne?") de récupérer une version précédente, de visualiser les modifications entre plusieurs versions, et bien d'autres choses.

En ce moment, la gestion de version distribuée (DCVS) a le vent en poupe. C'est conceptuellement perturbant pour ceux qui connaissent la traditionelle gestion centralisée. Mais la décentralisation simplifie beaucoup de choses. Notamment, pour commencer à travailler avec un outil centralisé il faut (1) créer un dépôt central puis (2) obtenir une copie de travail de ce dépot. C'est souvent un peu fastidieux. Avec un outil distribué (décentralisé) les dépôts sont partout, attachés à chaque copie de travail. Créer un nouveau dépôt est une opération très naturelle et simple.

J'ai récemment commencé à utiliser Mercurial, ce qui m'a d'abord mené à l'observation ci-dessus. J'ai ensuite découvert d'autres avantages. Mais j'aimerais ici présenter à quel point il est aisé d'utiliser Mercurial pour un usage personnel. Comme pré-requis, il faut cependant savoir un petit peu utiliser le shell. Les personnes visées sont surtout celles qui n'ont jamais utilisé d'outil de gestion de code. Par la suite je présenterai peut être une utilisation plus avancée.

Créer un dépôt


Vous avez un répertoire dans lequel vous développez un projet: un livre, quelques pages, des programmes, n'importe. Pour commencer à utiliser Mercurial, qu'on appelle hg pour faire court (c'est le code de l'élément Mercure en chimie), placez vous dans ce répertoire et commandez simplement: hg init.

Cette commande initialise, dans le sous-répertoire caché .hg, une quantité d'informations dont Mercurial a l'usage. Ce sous-répertoire incarne le dépot, qui va tracer toute l'histoire de (certains de) vos fichiers, et les fichiers avec lesquels vous travaillerez comme avant constituent votre copie de travail.

Le travail comme d'habitude


Ajouter des fichiers au dépôt


Mercurial ne s'occupe pas de suivre un fichier si on ne lui demande pas. Sinon, il suivrait tout un tas de fichiers temporaires, ce qui serait gênant -- dans un contexte ou on partage un dépôt, on veut aussi éviter de tracer des fichiers secrets. Pour commencer à suivre un fichier, on utilise la commande: hg add FICHIER_1 FICHIER_2 ....

Cette commande ne répond rien de spécial, elle prend note, c'est tout. Après cela, vous pouvez continuer de modifier vos fichiers comme avant.

Enregistrer une modification


Quand vous pensez avoir atteint un point critique dans votre travail, fini une partie important, ou sur le point de commencer quelque chose de délicat, ou tout simplement si vous avez envie de sauvegarder votre travail, il faut enregistrer vos modifications: hg commit.

Cette commande va vous demander de saisir un message décrivant la modification. Cela peut paraitre ennuyant mais c'est bien pratique quand on revient plus tard, pour comprendre une modification.

Il est possible de n'enregistrer les modifications que sur certains fichiers: hg commit FICHIER_1 FICHIER_2.

Supprimer un fichier


Quand on veut supprimer un fichier, il faut aussi le dire à Mercurial: hg remove FICHIER. Au prochain commit le fichier sera effacé et Mercurial arrêtera d'essayer de le suivre.

Les nouvelles possibilités


Visualiser les modifications en cours


Un premier avantage est la possibilité de visualiser rapidement les modifications apportées depuis la dernière sauvegarde (le dernier commit). Pour cela: hg diff, ou hg diff FICHIERS si on ne s'intéresse qu'à certains fichiers. Cette commande est bien pratique pour voir où on en est, vérifier que tout est propre avant d'enregistrer et de documenter une modification.

On peut aussi avoir un aperçu du statut de nos fichiers: hg stat (parfois verbeux) ou hg stat -m pour avoir la liste des fichiers modifiés.

Visualiser, visuellement


La commande diff permet aussi de voir les différences entre des versions enregistrées dans le dépot, cf. hg help diff. Il y a deux façons plus conviviales de faire cela, et plus encore. D'abord, hg view qui permet de naviguer dans la liste des révisions et permet de voir les modifications associées à chacune. Plus agréable, hg serve lance un serveur en local sur le port 8000: dans votre navigateur, à l'adresse http://localhost:8000, vous pourrez naviguer dans les révisions et les fichiers, visualiser des différences et des versions passées.

Annuler une modification


Souvent, on se rend compte d'une erreur, avec ou sans l'aide de Mercurial pour comparer aux versions précédentes. Parfois, il est facile de la corriger. Mais ce n'est pas toujours le cas, et on souhaite alors pouvoir tout simplement annuler un ensemble de modifications enregistrées. Pour cela il y a la commande revert.
  • Tout seul, hg revert --all annule les modifications non sauvergardées, et annule aussi les ajouts/suppressions de fichiers. On peut lui spécifier un ou plusieurs fichiers en particulier, au lieu de --all.
  • On peut aussi faire hg revert -r -2 [FICHIER ou --all] pour revenir à la version précédente enregistrée, -3 encore un cran avant, etc. La version -1 est la dernière version enregistrée, c'est donc équivalent à ne pas passer d'option -r. Attention, dans tous les cas on perd aussi les modifications non enregistrées.
  • Finalement on peut utiliser -r REVREV est l'entier positif désignant une version, telle qu'on peut le lire via hg view/serve/log. Par exemple la dénomination complète d'une version sera 2:26e8052bce45 mais 2 suffit pour la désigner. Même remarque qu'avant: attention, cela supprime les modifications en cours.


Fini


Il y aurait encore beaucoup à dire mais pour une utilisation simple c'est déja largement suffisant. En cas de doute au cours de votre apprentissage, n'hésitez pas à faire une copie sauvegarde de votre répertoire, le dépôt caché dedans sera sauvé aussi.

Libellés :