Mercurial Scripting mit Python
Frage
Ich versuche, die Quecksilber-Revisionsnummer / id (es ist ein Hash keine Zahl) programmatisch in Python zu erhalten.
Der Grund dafür ist, dass ich es auf die css / js Dateien auf unserer Website hinzufügen möchte wie folgt:
<link rel="stylesheet" href="example.css?{% mercurial_revision "example.css" %}" />
So dass, wenn eine Änderung des Sheet gemacht wird, wird es eine neue URL bekommen und nicht mehr die alte Cache-Version verwenden.
ODER , wenn Sie wissen, wo gute Dokumentation für die Quecksilber- Python-Modul finden , die auch hilfreich sein würden. Ich kann nicht scheinen, es überall zu finden.
Meine Lösung
endete ich mit subprocess bis zu nur einen Befehl ausführen, der die hg Knoten bekommt. Ich habe mich für diese Lösung, weil die api nicht garantiert gleich bleiben, aber die Bash-Schnittstelle wird wahrscheinlich:
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()
Beispiel für die Verwendung:
> path_to_file = "/home/jim/workspace/lgr/pinax/projects/lgr/site_media/base.css"
> get_hg_rev(path_to_file)
'0ed525cf38a7b7f4f1321763d964a39327db97c4'
Lösung
Es ist wahr, es gibt keine offizielle API, aber Sie können durch das Lesen anderer Erweiterungen eine Vorstellung von Best Practices erhalten, insbesondere solche mit hg gebündelt. Für dieses spezielle Problem, würde ich so etwas tun:
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())
Aktualisieren An einem gewissen Punkt der Parameter geändert, um, jetzt ist es wie folgt aus:
repo = hg.repository(ui.ui(), '/path/to/repo/root' )
Andere Tipps
Haben Sie meinen dieser Dokumentation ?
Beachten Sie, dass, wie in dieser Seite angegeben ist, gibt es keinen offizielle API, weil sie nach wie vor das Recht vor, sie jederzeit zu ändern. Aber Sie können die Liste der Änderungen in den letzten Versionen sehen, es ist nicht sehr umfangreich ist.
Eine aktualisierter, saubere subprocess Version (verwendet .check_output()
, hinzugefügt in Python 2.7 / 3.1), die ich in meinen Django-Einstellungen verwende Datei für eine rohe End-to-End-Bereitstellung Prüfung (ich es in eine HTML-Kommentar-Dump):
import subprocess
HG_REV = subprocess.check_output(['hg', 'id', '--id']).strip()
Sie können es in einem try
wickeln, wenn beim Starten des Systems zu verhindern, nicht einige seltsame Schluckauf wollen:
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 = "???"
gibt einen Versuch das Stichwort Erweiterung
Wenn Sie Python 2 verwenden, können Sie Ich weiß nicht, was zu verwenden, wenn Sie Python verwenden 3, sorry. Wahrscheinlich Mercurial hat zwei offizielle APIs. Installation: Verbrauch: Weitere Verwendungsinformationen auf der hglib Wikiseite . Weil es durch das Mercurial-Team gehalten wird, und es ist das, was das Mercurial-Team für die Anbindung mit Mercurial empfehlen. Von Mercurial Wiki , die folgende Erklärung mit Mercurial auf Schnittstellen: Für die überwiegende Mehrheit der Dritten Code, der beste Ansatz ist Mercurial veröffentlicht wurde, dokumentiert und eine stabile API zu verwenden: die Befehlszeilenoberfläche. Alternativ können Sie die CommandServer oder die Bibliotheken, die darauf beruhen, eine schnelle, stabile, Sprache zu erhalten -neutrale Schnittstelle. Von der Befehlsserver Seite: [Der Befehlsserver ermöglicht] Anwendungen von Drittanbietern und Bibliotheken mit Mercurial über ein Rohr zu kommunizieren, der die pro-Befehl Start-up-Overhead beseitigt. Bibliotheken können dann den Befehl Generation kapseln und Parsen eine sprach entsprechende API auf diese Befehle zu präsentieren. Der Python Schnittstelle zum Mercurial Befehlsserver, wie gesagt, ist Der pro-Befehl Overhead der Befehlszeilenschnittstelle ist kein Witz, nebenbei bemerkt. Ich baute einmal eine sehr kleine Test-Suite (nur ca. 5 Tests), die Die Signatur eines Funktions Python Haken ist wie folgt: Wenn Ihr Haken Code nicht so wichtig ist, und Sie veröffentlichen es nicht, könnten Sie wählen die entmutigte inoffizielle interne API verwenden. Wenn Ihr Haken part einer Erweiterung, die Sie veröffentlichen, eine bessere Nutzung hglib
. hgapi
. Der Inhalt dieser Antwort
Mercurial APIs
hglib
( Wiki , PyPI ) Paket, das von dem Mercurial Team gehalten wird. subprocess
oder hgapi
, etc. zu jagen. Wie verwenden hglib
pip install python-hglib
import hglib
client = hglib.open("/path/to/repo")
commit = client.log("tip")
print commit.author
Warum hglib ist die beste Wahl für Python 2 Benutzer
hglib
. hg
über subprocess
zum Erstellen, begehen, zu begehen, eine Handvoll repos mit z.B. verschmelzen Situationen. Während des gesamten Projekts blieb die Laufzeit der Suite zwischen 5 bis 30 Sekunden, wobei fast alle Zeit in den hg
Anrufe ausgegeben. Wenn Sie einen Haken schreiben, die interne Schnittstelle entmutigt ist furchtbar bequem
# 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
repo
und sind ein Teil der vorher erwähnten discouraged nicht offizielle interne API . Die Tatsache, dass sie genau dort in der Funktion args sind macht sie furchtbar bequem, wie in diesem Beispiel eines preupdate
Haken zu verwenden, die Verschmelzungen zwischen bestimmten Zweigen nicht zulässt. 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.
hglib
.
FWIW zu vermeiden, diesen Wert zu holen auf jeder Seite / Ansicht machen, ich habe nur mein deploy es in die settings.py
Datei setzen. Dann kann ich settings.REVISION
ohne den ganzen Aufwand für den Zugriff auf Mercurial und / oder einen anderen Prozess verweisen. Haben Sie jemals diesen Wert ändern w / o Nachladen Ihre Server?
Ich wollte wollte die OP, das Gleiche tun hg id -i
aus einem Skript tun, zu erhalten (aktuelle Revision des gesamten REPOSITORY bekommt, nicht von einer einzigen Datei in diesem Repo), aber ich wollte nicht verwenden, popen, und die Code von brendan
hat mich begonnen, war aber nicht das, was ich wollte.
Also schrieb ich diese ... Kommentare / Kritik willkommen. Dies wird die Spitze rev in hex als String zurück.
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")