[PATCH 2 of 2] chgserver: handle ParseError during validate

Jun Wu quark at fb.com
Fri Mar 11 07:48:59 EST 2016


# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1457698875 0
#      Fri Mar 11 12:21:15 2016 +0000
# Node ID 57ce1dae166bcfcaae191e2077b0dff21f7efc42
# Parent  b39cdec1d4e8817cf096474642ad8337d218d126
chgserver: handle ParseError during validate

Currently the validate command in chgserver expects config can be loaded
without issues but that's not true if the config file is ill-formed. The
current code does not catch ParseError. The server will print a stacktrace
then abort, while the client will abort with "failed to read channel".

This patch add handler for ParseError during validate and makes getpager,
runcommand no-ops, returning the correct exit code without crashing the
server.

diff --git a/hgext/chgserver.py b/hgext/chgserver.py
--- a/hgext/chgserver.py
+++ b/hgext/chgserver.py
@@ -340,6 +340,7 @@
         self._oldios = []  # original (self.ch, ui.fp, fd) before "attachio"
         self.hashstate = hashstate
         self.baseaddress = baseaddress
+        self._exitcode = None
         if hashstate is not None:
             self.capabilities = self.capabilities.copy()
             self.capabilities['validate'] = chgcmdserver.validate
@@ -428,7 +429,16 @@
               server instead.
         """
         args = self._readlist()
-        self.ui = _renewui(self.ui, args)
+        try:
+            self.ui = _renewui(self.ui, args)
+        except error.ParseError as inst:
+            # same behavior with dispatch.py
+            dispatch._formatparse(self.ui.warn, inst)
+            if inst.hint:
+                self.ui.warn(_("(%s)\n") % inst.hint)
+            self._exitcode = -1
+            self.cresult.write('\0')
+            return
         newhash = hashstate.fromui(self.ui, self.hashstate.mtimepaths)
         insts = []
         if newhash.mtimehash != self.hashstate.mtimehash:
@@ -440,6 +450,13 @@
         _log('validate: %s\n' % insts)
         self.cresult.write('\0'.join(insts) or '\0')
 
+    def runcommand(self):
+        if self._exitcode is not None:
+            self._readlist()
+            self.cresult.write(struct.pack('>i', (self._exitcode & 255)))
+            return
+        return super(chgcmdserver, self).runcommand()
+
     def chdir(self):
         """Change current directory
 
@@ -465,6 +482,9 @@
         does not allow to write empty data.
         """
         args = self._readlist()
+        if self._exitcode is not None:
+            self.cresult.write('\0')
+            return
         try:
             cmd, _func, args, options, _cmdoptions = dispatch._parse(self.ui,
                                                                      args)
@@ -510,6 +530,7 @@
     capabilities.update({'attachio': attachio,
                          'chdir': chdir,
                          'getpager': getpager,
+                         'runcommand': runcommand,
                          'setenv': setenv,
                          'setumask': setumask})
 


More information about the Mercurial-devel mailing list