[PATCH] ssh: use shlex to parse command line

Alexis S. L. Carvalho alexis at cecm.usp.br
Sun Sep 9 13:55:30 CDT 2007


Thus spake Patrick Mézard:
> Steve Borho a écrit :
> >... which looks pretty good.  It seems os.popen3() is successfully
> >parsing the ssh command name, but the rest of the argument parsing
> >(probably a function of the windows shell) is broken.
> 
> What about the attached patch (against crew-stable) ?
> 
> Tests pass under windows and macosx but they do not exercize it very 
> much and it's hard to build one not looking too kludgy. I think quoting 
> all arguments should be harmless under unix but I may be wrong.
> 

One alternative that wouldn't require shlex would be to just add some
util.quotecommand function that adds the extra quotes on windows.  From
the user POV, he'd use the same syntax from the [hooks] section (i.e.
system-specific quoting instead of shlex quoting).  Somthing like this:

> # HG changeset patch
> # User Steve Borho <steve at borho.org>
> # Date 1189111299 18000
> # Node ID 6446a528e29d6a01ee45b356aaaa763721298a3e
> # Parent  ed6df6b1c29af317bf130c65bb51c09989a809d0
> ssh: use shlex to parse command line
> 
> diff --git a/mercurial/sshrepo.py b/mercurial/sshrepo.py
> --- a/mercurial/sshrepo.py
> +++ b/mercurial/sshrepo.py
> @@ -8,7 +8,7 @@ from node import *
>  from node import *
>  from remoterepo import *
>  from i18n import _
> -import hg, os, re, stat, util
> +import hg, os, re, stat, util, shlex
>  
>  class sshrepository(remoterepository):
>      def __init__(self, ui, path, create=0):
> @@ -33,7 +33,7 @@ class sshrepository(remoterepository):
>          if create:
>              cmd = '%s %s "%s init %s"'
>              cmd = cmd % (sshcmd, args, remotecmd, self.path)
> -
> +            cmd = util.shellcommand(shlex.split(cmd))
>              ui.note('running %s\n' % cmd)
>              res = os.system(cmd)

Just using util.system (without any extra quoting) would be enough
here.

>              if res != 0:
> @@ -51,6 +51,7 @@ class sshrepository(remoterepository):
>          cmd = '%s %s "%s -R %s serve --stdio"'
>          cmd = cmd % (sshcmd, args, remotecmd, self.path)
>  
> +        cmd = util.shellcommand(shlex.split(cmd))

cmd = util.quotecommand(cmd)

>          ui.note('running %s\n' % cmd)
>          self.pipeo, self.pipei, self.pipee = os.popen3(cmd, 'b')
>  
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -953,6 +953,12 @@ if os.name == 'nt':
>              _quotere = re.compile(r'(\\*)("|\\$)')
>          return '"%s"' % _quotere.sub(r'\1\1\\\2', s)
>  
> +    def shellcommand(args):
> +        """Build a command string suitable for os.popen* calls."""
> +        # The extra quotes are needed because popen* runs the command
> +        # through the current COMSPEC. cmd.exe suppress enclosing quotes.
> +        return '"' + ' '.join([shellquote(arg) for arg in args]) + '"'
> +

def quotecommand(cmd):
    return '"' + cmd + '"'

>      def explain_exit(code):
>          return _("exited with status %d") % code, code
>  
> @@ -1105,6 +1111,9 @@ else:
>              return '"%s"' % s
>          else:
>              return "'%s'" % s.replace("'", "'\\''")
> +
> +    def shellcommand(args):
> +        return ' '.join([shellquote(arg) for arg in args])

def quotecommand(cmd):
    return cmd

Alexis


More information about the Mercurial-devel mailing list