2016-08-04 32 views
0

Was ist der empfohlene Ansatz zur Fehlerbehandlung in einer Mercurial-Erweiterung? Wir konnten keine Dokumente für diesen Aspekt online finden.Umgang mit Fehlern in der Mercurial-Erweiterung

Im folgenden Beispiel wird Hello world gedruckt und in einer Windows-Shell errorlevel auf 1 gesetzt.

@command('print-parents', [('','', None, '')], '') 
def printparents(ui, repo, node, **opts): 
    print "Hello world" 
    return True 

Warum ist errorlevel Satz 1? Wir haben erwartet, dass es 0 ist. Wie behandelt Python oder Mercurial in diesem Zusammenhang True und False? Wechsel zur Rückgabe False produziert errorlevel0.

Wir haben einige Beispiele von raise error.Abort(..) gesehen, aber dies gab einen sehr ausführlichen Callstack aus, der nicht notwendig ist. Eine einfache Textnachricht und korrekte errorlevel ist, was benötigt wird.

Verwendung von Windows 7 und Mercurial 3.4.1

+0

Warum gibt Ihr Befehl "True" zurück? Der Rückgabewert eines '@ -Befehls 'wird als Exit-Code und in Python' True == 1' interpretiert. –

Antwort

0

In einer @command Funktion ui.warn() verwenden, um eine Fehlermeldung anzuzeigen, dann Zurücksenden einer ganzen Zahl Wert den Beendigungscode einzustellen:

if something_is_wrong: 
    ui.warn(_('Something is wrong, please correct this')) 
    return 1 

Jedoch Die Verwendung von raise mercurial.error.Abort() ist ebenfalls in Ordnung und führt nicht zu einer Rückverfolgung, es sei denn, Sie haben ui.traceback auf True eingestellt (Standardeinstellung ist False). Die Anhebung Abort() führt normalerweise zu einer ui.warn('abort: ' + msg_from_exception) und return -1 Combo (die in einem 255 Exit-Code führt):

$ cat demo.py 
from mercurial import cmdutil, error 

cmdtable = {} 
command = cmdutil.command(cmdtable) 

@command('demo1', [], '') 
def demo1(ui, repo, *args, **opts): 
    ui.warn('Error message written directly to ui.warn') 
    return 1 

@command('demo2', [], '') 
def demo2(ui, repo, *args, **opts): 
    raise error.Abort('Error message raised with Abort') 

$ hg --config extensions.demo=`pwd`/demo.py demo1 
Error message written directly to ui.warn 
$ echo $? 
1 
$ hg --config extensions.demo=`pwd`/demo.py demo2 
abort: Error message raised with Abort 
$? 
255 
$ hg --config extensions.demo=`pwd`/demo.py --config ui.traceback=true demo2 
Traceback (most recent call last): 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 204, in _runcatch 
    return _dispatch(req) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 880, in _dispatch 
    cmdpats, cmdoptions) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure 
    return func(*(args + a), **kw) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/fastmanifest/cachemanager.py", line 318, in runcommandtrigger 
    result = orig(*args, **kwargs) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure 
    return func(*(args + a), **kw) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/fastmanifest/__init__.py", line 174, in _logonexit 
    r = orig(ui, repo, cmd, fullargs, *args) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure 
    return func(*(args + a), **kw) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/hgext/journal.py", line 79, in runcommand 
    return orig(lui, repo, cmd, fullargs, *args) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 637, in runcommand 
    ret = _runcommand(ui, options, cmd, d) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure 
    return func(*(args + a), **kw) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/hgext/pager.py", line 160, in pagecmd 
    return orig(ui, options, cmd, cmdfunc) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/extensions.py", line 210, in closure 
    return func(*(args + a), **kw) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/hgext/color.py", line 503, in colorcmd 
    return orig(ui_, opts, cmd, cmdfunc) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 1010, in _runcommand 
    return checkargs() 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 971, in checkargs 
    return cmdfunc() 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/dispatch.py", line 877, in <lambda> 
    d = lambda: util.checksignature(func)(ui, *args, **cmdoptions) 
    File "/opt/facebook/hg/lib/python2.7/site-packages/mercurial/util.py", line 1036, in check 
    return func(*args, **kwargs) 
    File "/tmp/demo/demo.py", line 13, in demo2 
    raise error.Abort('Error message raised with Abort') 
Abort: Error message raised with Abort 
abort: Error message raised with Abort 

Bitte beachte, dass ich die Zurückverfolgungs explizit aktivieren musste!

In Python, der bool Typ ist eine Unterklasse von int und True hat einen Wert von 1False und einen ganzzahligen Wert von 0. Da Mercurial @command Funktionen erwartet, um eine Ganzzahl zurückzugeben, um einen Exitcode (oder None für Exitcode 0) festzulegen, setzen Sie den Exitcode auf 1, indem Sie True zurückgeben.

Ich sehe in der Regel über das mercurial.commands Modul und die verschiedenen hgext Erweiterungen zu lernen, wie andere spezifische Probleme gelöst haben. Der hg grep Befehl zum Beispiel enthält dieses Beispiel einen Fehler von Handhabung:

try: 
    regexp = util.re.compile(pattern, reflags) 
except re.error as inst: 
    ui.warn(_("grep: invalid match pattern: %s\n") % inst) 
    return 1 

während der hg addremove Code wirft error.Abort():

try: 
    sim = float(opts.get('similarity') or 100) 
except ValueError: 
    raise error.Abort(_('similarity must be a number')) 

I error.Abort() für Kommandofehler verwenden würde, und ui.warn() plus eine Rückkehr Ganzzahl nur, wenn Sie speziell einen anderen Exit-Code als 255 benötigen.

+0

Eine sehr gute Beschreibung, danke :-) – Lars