Patchwork D9238: errors: add config that lets user get more detailed exit codes

login
register
mail settings
Submitter phabricator
Date Oct. 22, 2020, 4:08 p.m.
Message ID <differential-rev-PHID-DREV-cqxq54brv3iw7jnutbrz-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47506/
State Superseded
Headers show

Comments

phabricator - Oct. 22, 2020, 4:08 p.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This adds an experimental config that lets the user get more detailed
  exit codes. For example, there will be a specific error code for
  input/user errors. This is part of
  https://www.mercurial-scm.org/wiki/ErrorCategoriesPlan. I've made the
  config part of tweakdefaults.
  
  I've made the config enabled by default in tests. My reasoning is that
  we want to see that each specific error case gives the right exit code
  and we don't want to duplicate all error cases in the entire test
  suite. The logic for the current exit codes is quite simple, so I'm
  not too worried about regressions there. I've added a test case
  specifically for the "legacy" exit codes.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9238

AFFECTED FILES
  mercurial/configitems.py
  mercurial/scmutil.py
  mercurial/ui.py
  tests/run-tests.py
  tests/test-basic.t
  tests/test-commandserver.t
  tests/test-legacy-exit-code.t

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-legacy-exit-code.t b/tests/test-legacy-exit-code.t
new file mode 100644
--- /dev/null
+++ b/tests/test-legacy-exit-code.t
@@ -0,0 +1,35 @@ 
+Tests that the exit code is as expected when ui.detailed-exit-code is *not*
+enabled.
+
+  $ hg init
+  $ echo a > a
+Expect exit code 0 on success
+  $ hg ci -Aqm initial
+
+  $ hg co nonexistent
+  abort: unknown revision 'nonexistent'!
+  [255]
+
+  $ hg co 'none()'
+  abort: empty revision set
+  [255]
+
+  $ hg co 'invalid('
+  hg: parse error at 8: not a prefix: end
+  (invalid(
+           ^ here)
+  [255]
+
+  $ hg co 'invalid('
+  hg: parse error at 8: not a prefix: end
+  (invalid(
+           ^ here)
+  [255]
+
+  $ hg continue
+  abort: no operation in progress
+  [255]
+
+  $ hg st --config a=b
+  abort: malformed --config option: 'a=b' (use --config section.name=value)
+  [255]
diff --git a/tests/test-commandserver.t b/tests/test-commandserver.t
--- a/tests/test-commandserver.t
+++ b/tests/test-commandserver.t
@@ -211,6 +211,7 @@ 
   lfs.usercache=$TESTTMP/.cache/lfs
   ui.slash=True
   ui.interactive=False
+  ui.detailed-exit-code=True
   ui.merge=internal:merge
   ui.mergemarkers=detailed
   ui.foo=bar
@@ -222,6 +223,7 @@ 
   *** runcommand -R foo showconfig ui defaults
   ui.slash=True
   ui.interactive=False
+  ui.detailed-exit-code=True
   ui.merge=internal:merge
   ui.mergemarkers=detailed
   ui.nontty=true
diff --git a/tests/test-basic.t b/tests/test-basic.t
--- a/tests/test-basic.t
+++ b/tests/test-basic.t
@@ -9,6 +9,7 @@ 
   lfs.usercache=$TESTTMP/.cache/lfs
   ui.slash=True
   ui.interactive=False
+  ui.detailed-exit-code=True
   ui.merge=internal:merge
   ui.mergemarkers=detailed
   ui.promptecho=True
diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -1439,6 +1439,7 @@ 
             hgrc.write(b'[ui]\n')
             hgrc.write(b'slash = True\n')
             hgrc.write(b'interactive = False\n')
+            hgrc.write(b'detailed-exit-code = True\n')
             hgrc.write(b'merge = internal:merge\n')
             hgrc.write(b'mergemarkers = detailed\n')
             hgrc.write(b'promptecho = True\n')
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -60,6 +60,8 @@ 
 # The config knobs that will be altered (if unset) by ui.tweakdefaults.
 tweakrc = b"""
 [ui]
+# Gives detailed exit codes for input/user errors, config errors, etc.
+detailed-exit-code = True
 # The rollback command is dangerous. As a rule, don't use it.
 rollback = False
 # Make `hg status` report copy information
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -148,6 +148,8 @@ 
     return func() if no exception happens. otherwise do some error handling
     and return an exit code accordingly. does not handle all exceptions.
     """
+    want_detailed_exit_code = ui.configbool(b'ui', b'detailed-exit-code')
+    exit_code = -1
     try:
         try:
             return func()
@@ -216,6 +218,9 @@ 
     except error.WdirUnsupported:
         ui.error(_(b"abort: working directory revision cannot be specified\n"))
     except error.Abort as inst:
+        if want_detailed_exit_code:
+            # TODO: set exit_code for different errors here
+            pass
         ui.error(_(b"abort: %s\n") % inst.message)
         if inst.hint:
             ui.error(_(b"(%s)\n") % inst.hint)
@@ -265,7 +270,7 @@ 
         # Just in case catch this and and pass exit code to caller.
         return inst.code
 
-    return -1
+    return exit_code
 
 
 def checknewlabel(repo, lbl, kind):
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -1270,6 +1270,9 @@ 
     b'ui', b'editor', default=dynamicdefault,
 )
 coreconfigitem(
+    b'ui', b'detailed-exit-code', default=False, experimental=True,
+)
+coreconfigitem(
     b'ui', b'fallbackencoding', default=None,
 )
 coreconfigitem(