Domanda

Sto cercando di ottenere il numero/id di revisione mercuriale (è un hash, non un numero) a livello di codice in Python.

Il motivo è che voglio aggiungerlo ai file css/js sul nostro sito Web in questo modo:

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

In modo che ogni volta che viene apportata una modifica al foglio di stile, otterrà un nuovo URL e non utilizzerà più la vecchia versione memorizzata nella cache.

O se sai dove trovare una buona documentazione per il mercurial modulo Python, anche questo sarebbe utile.Non riesco a trovarlo da nessuna parte.

La mia soluzione

Ho finito per utilizzare subprocess semplicemente per eseguire un comando che ottiene il nodo hg.Ho scelto questa soluzione perché non è garantito che l'API rimanga la stessa, ma probabilmente l'interfaccia bash:

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()

esempio utilizzare:

> path_to_file = "/home/jim/workspace/lgr/pinax/projects/lgr/site_media/base.css"
> get_hg_rev(path_to_file)
'0ed525cf38a7b7f4f1321763d964a39327db97c4'
È stato utile?

Soluzione

E 'vero non c'è API ufficiali, ma si può avere un'idea di best practice leggendo altre estensioni, in particolare quelli in bundle con hg. Per questo particolare problema, vorrei fare qualcosa di simile:

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())

Aggiorna Ad un certo punto l'ordine dei parametri è cambiato, ora è come questo:

   repo = hg.repository(ui.ui(), '/path/to/repo/root' )

Altri suggerimenti

questa documentazione ?
Si noti che, come dichiarato in quella pagina, non v'è alcuna ufficiale API, perché riservano comunque il diritto di modificare in qualsiasi momento. Ma si può vedere l'elenco delle modifiche negli ultimi versioni, non è molto ampia.

Un aggiornato, più pulito versione sottoprocesso (usa .check_output(), aggiunto in Python 2.7 / 3.1) che uso nelle mie impostazioni Django file per un controllo di distribuzione grezza end-to-end (I discarica in un commento HTML):

import subprocess

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

Si poteva avvolgerlo in un try se non vuoi un po 'strano incidente di percorso per evitare l'avvio:

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 Exception:  # don't use bare 'except', mis-catches Ctrl-C and more
    # should never have to deal with a hangup 
    HG_REV = "???"

Se stai usando Python 2, vuoi usare hglib.

Non so cosa usare se stai usando Python 3, mi dispiace.Probabilmente hgapi.

Contenuto di questa risposta

  • Le API di Mercurial
  • Come usare hglib
  • Perché hglib è la scelta migliore per gli utenti di Python 2
  • Se stai scrivendo un hook, quell'interfaccia interna scoraggiata è terribilmente conveniente

Le API di Mercurial

Mercurial ha due API ufficiali.

  1. Il server dei comandi Mercurial.Puoi parlarci da Python 2 usando il file hglib (wiki, PyPI), gestito dal team Mercurial.
  2. L'interfaccia della riga di comando di Mercurial.Puoi parlarci tramite subprocess, O hgapi, o qualcosa del genere.

Come usare hglib

Installazione:

pip install python-hglib

Utilizzo:

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

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

Ulteriori informazioni sull'utilizzo su pagina wiki di hglib.

Perché hglib è la scelta migliore per gli utenti di Python 2

Perché è gestito dal team Mercurial ed è ciò che il team Mercurial consiglia per l'interfacciamento con Mercurial.

Dal wiki di Mercurial, la seguente dichiarazione sull'interfacciamento con Mercurial:

Per la stragrande maggioranza del codice di terze parti, l'approccio migliore è utilizzare l'API pubblicata, documentata e stabile di Mercurial:l'interfaccia della riga di comando.In alternativa, utilizzare il CommandServer o le librerie che si basano su di esso per ottenere un'interfaccia veloce, stabile e indipendente dalla lingua.

Dalla pagina del server dei comandi:

[Il server dei comandi consente] ad applicazioni e librerie di terze parti di comunicare con Mercurial tramite una pipe che elimina il sovraccarico di avvio per comando.Le librerie possono quindi incapsulare la generazione e l'analisi dei comandi per presentare a questi comandi un'API adatta al linguaggio.

L'interfaccia Python per il server dei comandi Mercurial, come detto, è hglib.

A proposito, il sovraccarico per comando dell'interfaccia della riga di comando non è uno scherzo.Una volta ho creato una suite di test molto piccola (solo circa 5 test) che utilizzava hg attraverso subprocess per creare, commit per commit, una manciata di repository con ad es.unire le situazioni.Durante tutto il progetto, la durata di esecuzione della suite è rimasta compresa tra 5 e 30 secondi, con quasi tutto il tempo trascorso nel file hg chiamate.

Se stai scrivendo un hook, quell'interfaccia interna scoraggiata è terribilmente conveniente

La firma di una funzione hook Python è così:

# 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 E repo fanno parte dei suddetti scoraggiati non ufficiali API interna.Il fatto che siano proprio lì negli argomenti della tua funzione li rende terribilmente comodi da usare, come in questo esempio di a preupdate hook che non consente unioni tra determinati rami.

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.

Se il tuo codice hook non è così importante e non lo pubblichi, potresti scegliere di utilizzare l'API interna non ufficiale scoraggiata.Se il tuo hook fa parte di un'estensione che stai pubblicando, è meglio utilizzarlo hglib.

FWIW per evitare il recupero di tale valore in ogni pagina / vista render, ho solo la mia implementazione metterlo nel file settings.py. Allora posso riferimento settings.REVISION senza tutto il sovraccarico di accesso mercuriali e / o un altro processo. Ti capita mai di avere questo cambiamento valore w / o ricaricare il vostro server?

Ho voluto fare la stessa cosa il PO voleva fare, ottenere hg id -i da uno script (get punta revisione dell'intero repository, non di un singolo file in quella dei pronti contro termine), ma non volevo usare popen, ed il codice brendan mi ha iniziato, ma non era quello che volevo.

Così ho scritto questo ... commenti / critiche di benvenuto. Questo diventa il rev punta in esadecimale come una stringa.

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")
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top