Skip to content

hglib, la bibliothèque python pour s’interfacer avec Mercurial

14 octobre 2015

Mercurial, un système de gestion de version décentralisé, propose hglib pour pouvoir agir sur un dépôt programmatiquement depuis Python.

Hglib est compatible avec python 2 et 3 donc, à moins de faire de l’archéologie logicielle (python 2.3 et encore plus vieux), il n’y a pas de raison de s’en priver.

L’installation est triviale puisque la bibliothèque est disponible à partir de pypi (donc utilisable dans un virtualenv) ou dans votre distribution préférée (paquet python-hglib ou python3-hglib avec Debian).

Créer un dépôt

>>> import hglib
>>> depot = hglib.init(dest="/tmp/geographie")
>>> print(depot)
<hglib.client.hgclient object at 0x7f9e75dc2250>

Le résultat est équivalent à la commande :

$ hg init /tmp/geographie

Le résultat est banalement prévisible :

$ ls -la /tmp/geographie/
total 268
drwxr-xr-x  3 alice    alice     4096 oct.  13 21:07 .
drwxrwxrwt 17 root     root    262144 oct.  13 21:08 ..
drwxr-xr-x  3 alice    alice     4096 oct.  13 21:07 .hg

Accéder au dépôt

Pour ouvrir le dépôt :

>>> import hglib
>>> depot = hglib.open("/tmp/geographie")
>>> print(depot)
<hglib.client.hgclient object at 0x7f2b230a8050>

Il est possible de voir et ajouter des branches :

>>> depot.branches()
[]  #pas de branche particulière
>>> depot.branch()
'default' #'default' est la branche que Mercurial crée par défaut
>>> depot.branch("dev") #création et passage sur la branche 'dev'
'dev'
>>> depot.branch()
'dev'
>>> depot.branches()
[]
>>> depot.commit("ajout de la branche dev")
(0, 'f1c9646830e4efc57830ddd588001917c3046e5d')
>>> depot.branches()
[('dev', 0, 'f1c9646830e4')] #la branche 'dev' est maintenant visible

depot.commit() retourne un couple (numéro de révision, identifiant du nœud).
depot.branches() retourne la liste des branches, chacune avec le triplet (nom de la branche, numéro de révision, identifiant du nœud).

Ajouter des fichiers

Supposons que nous ayons un fichier listant les villes de France nommé villes.tsv et que nous décidions de l’ajouter à notre dépôt :

>>> depot.add("/tmp/geographie/villes.tsv") #équivaut à hg add /tmp/geographie/villes.tsv
True
>>> depot.status() #équivaut à hg status
[('A', 'villes.tsv')]
>>> depot.commit("ajout des villes") #équivaut à hg commit -m"ajout des villes"
(1, '815765cc96bde95ff8ca02305f798e1effc31688')
>>> depot.status()
[]

depot.status() retourne une liste des changements. Chaque changement est représenté par un couple (lettre_code, fichier). lettre_code vaut les valeurs classiques :

  • M : fichier modifié
  • A : fichier ajouté
  • R : fichier supprimé
  • etc.

Modifier des fichiers

Malheureusement, une erreur s’était glissée dans le fichier villes.tsv… Après la correction mais avant le commit :

>>> depot.diff() #le diff brut de décoffrage
'diff -r 815765cc96bd villes.tsv\n--- a/villes.tsv\tTue Oct 13 21:49:41 2015 +0200\n+++ b/villes.tsv\tTue Oct 13 22:13:12 2015 +0200\n@@ -13492,7 +13492,7 @@\n giey-sur-aujon\tGiey-sur-Aujon\n giez\tGiez\n giffaumont-champaubert\tGiffaumont-Champaubert\n-png-sur-yvette\tPng-sur-Yvette\n+gif-sur-yvette\tGif-sur-Yvette\n gigean\tGigean\n gignac-34\tGignac\n gignac-46\tGignac\n'
>>> for ligne in depot.diff().split('\n'):) #équivaut à hg diff
...  print(ligne)
... 
diff -r 815765cc96bd villes.tsv
--- a/villes.tsv	Tue Oct 13 21:49:41 2015 +0200
+++ b/villes.tsv	Tue Oct 13 22:13:37 2015 +0200
@@ -13492,7 +13492,7 @@
 giey-sur-aujon	Giey-sur-Aujon
 giez	Giez
 giffaumont-champaubert	Giffaumont-Champaubert
-png-sur-yvette	Png-sur-Yvette
+gif-sur-yvette	Gif-sur-Yvette
 gigean	Gigean
 gignac-34	Gignac
 gignac-46	Gignac

Après le commit, le diff est aussi vide qu’on peut s’y attendre :

>>> depot.commit("correction gif-sur-yvette")
(2, 'a972c3bee591b2ec549420ef6fbe36e2cc433189')
>>> depot.diff()
''

depot.diff() accepte un nom de fichier ou une plage de révisions en paramètre pour limiter les résultats.

Voir l’historique

L’équivalent de hg log est aussi disponible :

>>> import pprint # c'est juste pour la lisibilité
>>> pprint.pprint(depot.log())
[('2',
  'a972c3bee591b2ec549420ef6fbe36e2cc433189',
  'tip',
  'dev',
  'Alice <alice@pays-des-merveilles.tld>',
  'correction gif-sur-yvette',
  datetime.datetime(2015, 10, 13, 22, 21, 53)),
 ('1',
  '815765cc96bde95ff8ca02305f798e1effc31688',
  '',
  'dev',
  'Alice <alice@pays-des-merveilles.tld>',
  'ajout des villes',
  datetime.datetime(2015, 10, 13, 21, 49, 41)),
 ('0',
  'f1c9646830e4efc57830ddd588001917c3046e5d',
  '',
  'dev',
  'Alice <alice@pays-des-merveilles.tld>',
  'ajout de la branche dev',
  datetime.datetime(2015, 10, 13, 21, 18, 34))]

C’est une liste de commits. Chaque commit est un n-uplet (numéro de la révision, identifiant du nœud, tip ou pas, branche, auteur, message, date).

Créer une archive

Vu l’avancée pour l’humanité réalisée, il est temps de faire une archive du projet :

>>> depot.archive("/tmp/archive") # équivaut à hg archive /tmp/archive

Le répertoire obtenu :

$ ls -la /tmp/archive/
total 1200
drwxr-xr-x  2 alice    alice     4096 oct.  13 22:41 .
drwxrwxrwt 18 root     root    262144 oct.  13 22:41 ..
-rw-r--r--  1 alice    alice      168 oct.  13 22:41 .hg_archival.txt
-rw-r--r--  1 alice    alice   948448 oct.  13 22:41 villes.tsv

Générique de fin

Ce n’était qu’un survol des possiblités de hglib. De nombreuses possibilités n’ont pas été abordées (ouvrir un dépôt distant, depot.pull(), depot.push(), la création de .tar.gz pour les archives, etc.). La plupart des méthodes prennent des paramètres facultatifs pour en modifier le comportement.

Les cascades de cet article ont été réalisées avec Python 2.7.10, Mercurial 3.4.2 et hglib 1.7-1. Vous pouvez les reproduire chez vous, même si vous n’êtes pas un professionnel.

Aucun terminal n’a été maltraité lors de la réalisation de cet article.

From → Python

Laisser un commentaire

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :