Scripting Mercurial avec python

j'essaie d'obtenir le numéro de révision mercurial/id (c'est un hash et non un nombre) programmatiquement en python.

La raison est que je veux ajouter à la css/js fichiers sur notre site web comme ceci:

<link rel="stylesheet" href="example.css?{% mercurial_revision "example.css" %}" />

de sorte que chaque fois qu'une modification est apportée à la feuille de style, elle obtiendra une nouvelle url et n'utilisera plus l'ancienne version mise en cache.

OR si vous savez où trouver de la bonne documentation pour l'mercurial python module, qui serait également utile. Je n'arrive pas à le trouver n'importe où.

Ma Solution

j'ai fini par utiliser subprocess pour lancer une commande qui obtient le noeud hg. J'ai choisi cette solution parce que l'api n'est pas garantie de rester la même, mais l'interface bash va probablement:

import subprocess

def get_hg_rev(file_path):
    pipe = subprocess.Popen(
        ["hg", "log", "-l", "1", "--template", "{node}", file_path],
        stdout=subprocess.PIPE
        )
    return pipe.stdout.read()

exemple d'utilisation:

> path_to_file = "/home/jim/workspace/lgr/pinax/projects/lgr/site_media/base.css"
> get_hg_rev(path_to_file)
'0ed525cf38a7b7f4f1321763d964a39327db97c4'
28
demandé sur Mogsdad 2009-07-20 17:08:01

7 réponses

il est vrai qu'il n'y a pas D'API officielle, mais vous pouvez vous faire une idée des meilleures pratiques en lisant d'autres extensions, en particulier celles qui sont liées à hg. Pour ce problème particulier, je voudrais faire quelque chose comme ceci:

from mercurial import ui, hg
from mercurial.node import hex

repo = hg.repository('/path/to/repo/root', ui.ui())
fctx = repo.filectx('/path/to/file', 'tip')
hexnode = hex(fctx.node())

mise à Jour à un moment donné l'ordre des paramètres a changé, MAINTENANT c'est comme ceci:

   repo = hg.repository(ui.ui(), '/path/to/repo/root' )
14
répondu brendan 2012-11-26 15:43:09

voulez-vous dire cette documentation?

Notez que, comme indiqué dans cette page, il n'y a pas de officiel API, car ils se réservent le droit de le modifier à tout moment. Mais vous pouvez voir la liste des changements dans les dernières versions, il n'est pas très étendue.

8
répondu Roberto Liffredo 2016-10-28 07:53:11

une version mise à jour, plus propre du sous-processus (utilise .check_output(), ajouté en Python 2.7 / 3.1) que j'utilise dans mon fichier de configuration Django pour un contrôle brut de déploiement de bout en bout (je le renverse dans un commentaire HTML):

import subprocess

HG_REV = subprocess.check_output(['hg', 'id', '--id']).strip()

Vous pourriez l'envelopper dans un try si vous ne voulez pas quelque étrange hoquet pour éviter de démarrage:

try:
    HG_REV = subprocess.check_output(['hg', 'id', '--id']).strip()
except OSError:
    HG_REV = "? (Couldn't find HG)"
except subprocess.CalledProcessError as e:
    HG_REV = "? (Error {})".format(e.returncode)
except:
    # should never have to deal with a hangup 
    HG_REV = "???"
4
répondu Nick T 2014-02-24 22:50:00
3
répondu dfa 2009-07-20 13:14:48

Si vous utilisez Python 2, vous souhaitez utiliser hglib.

Je ne sais pas quoi utiliser si vous utilisez Python 3, désolé. Probablement hgapi.

contenu de cette réponse

  • Mercurial Api
  • comment utiliser hglib
  • pourquoi hglib est le meilleur choix pour les utilisateurs de Python 2
  • si vous écrivez un crochet, cette interface interne découragée est affreusement pratique

Mercurial Api

Mercurial a deux API officielles.

  1. le serveur de commandes Mercurial. Vous pouvez lui parler depuis Python 2 en utilisant le hglib ( wiki, PyPI), qui est maintenu par L'équipe Mercurial.
  2. interface en ligne de commande de Mercurial. Vous pouvez lui parler via subprocess, ou hgapi, ou somesuch.

Comment pour utiliser hglib

Installation:

pip install python-hglib

Utilisation:

import hglib
client = hglib.open("/path/to/repo")

commit = client.log("tip")
print commit.author

plus d'informations sur l'utilisation du hglib wiki page.

pourquoi hglib est le meilleur choix pour les utilisateurs de Python 2

Parce qu'il est maintenu par l'Mercurial équipe, et c'est ce que l'Mercurial équipe recommander pour l'interfaçage avec Mercurial.

à Partir de Mercurial wiki, la déclaration suivante sur l'interfaçage avec Mercurial:

pour la grande majorité du code tiers, la meilleure approche est d'utiliser L'API publiée, documentée et stable de Mercurial: l'interface en ligne de commande. Alternativement, utilisez le CommandServer ou les bibliothèques qui sont basées sur elle pour obtenir une interface rapide, stable, neutre du point de vue de la langue.

à Partir de l'invite du serveur de la page:

[le serveur de commande permet] des applications et des bibliothèques tierces pour communiquer avec Mercurial au-dessus d'un tuyau qui élimine le démarreur per-command overhead. Les bibliothèques peuvent alors encapsuler la génération de commandes et la parsing pour présenter une API de langue appropriée à ces commandes.

l'interface Python vers le serveur de commandes Mercurial, comme dit, est hglib.

La par commande frais généraux de l'interface de ligne de commande n'est pas une blague, par la manière. J'ai une fois construit une très petite suite de test (seulement environ 5 tests) qui a utilisé hg via subprocess pour créer, commit by commit, une poignée de repos avec par exemple des situations de fusion. Tout au long du projet, le fonctionnement de la suite est resté entre 5 et 30 secondes, avec presque tout le temps passé dans le hg appels.

si vous écrivez un crochet, cette interface interne découragée est terriblement commode

la signature D'une fonction Python hook est comme suit:

# In the hgrc:
# [hooks]
# preupdate.my_hook = python:/path/to/file.py:my_hook

def my_hook(
    ui, repo, hooktype, 
    ... hook-specific args, find them in `hg help config` ..., 
    **kwargs)

ui et repo font partie de ladite découragé non officiel API interne. Le fait qu'ils sont là, dans votre fonction args rend très pratique à utiliser, comme dans cet exemple de preupdate crochet qui empêche les fusions entre certaines branches.

def check_if_merge_is_allowed(ui, repo, hooktype, parent1, parent2, **kwargs):
    from_ = repo[parent2].branch()
    to_ = repo[parent1].branch()
    ...
    # return True if the hook fails and the merge should not proceed.

si votre code crochet n'est pas si important, et que vous ne le publiez pas, vous pouvez choisir d'utiliser l'API interne non officielle découragée. Si votre crochet fait partie d'une extension que vous publiez, utilisez plutôt hglib.

3
répondu Esteis 2015-03-01 23:12:55

FWIW pour éviter de récupérer cette valeur sur chaque page / rendu de vue, j'ai juste mon deploy le mettre dans le settings.py fichier. Ensuite, je peux de référence settings.REVISION sans tous les frais généraux d'accès à mercurial et / ou un autre processus. Vous arrive-t-il de modifier cette valeur en rechargeant votre serveur?

1
répondu Ry4an Brase 2012-11-26 16:28:54

j'ai voulu faire la même chose que l'OP voulait faire, get hg id -i à partir d'un script (obtenir la dernière révision de l'ensemble du RÉFÉRENTIEL, non pas d'un seul FICHIER dans ce repo) mais je n'ai pas envie d'utiliser popen, et le code de

alors j'ai écrit ceci... Commentaires / critiques bienvenus. Cela obtient le tip rev en hex comme une ficelle.

from mercurial import ui, hg, revlog
# from mercurial.node import hex  # should I have used this?

def getrepohex(reporoot):
    repo = hg.repository(ui.ui(), reporoot)
    revs = repo.revs('tip')
    if len(revs)==1:
      return str(repo.changectx(revs[0]))
    else:
      raise Exception("Internal failure in getrepohex")
0
répondu Warren P 2012-11-26 16:08:18