Hi Simon, On Tue, Jan 10, 2017 at 07:53:48PM +0000, Simon McVittie wrote: > I'm currently using git-buildpackage with a custom --builder command > (vectis, https://github.com/smcv/vectis) that among other things accepts > a command-line option of the form: > > --extra-repository='deb [trusted=yes] http://localhost/path suite > component' > > With git-buildpackage, I have to backslash-escape the spaces: > > --extra-repository='deb\ [trusted=yes]\ ...' > > or it will treat "--extra-repository=deb", "[trusted=yes]", etc. as > separate command-line arguments for vectis. This is because > gbp.command_wrappers.Command(..., shell=True) just joins the command > to the arguments with " ".join() rather than doing proper shell quoting. > That's correct for the --builder as currently documented, but not for > its arguments. > > It would be easy to run into this with debuild if you're using something > like gbp buildpackage --set-envvar=DEBFULLNAME="Simon McVittie" > (a debuild option) or gbp buildpackage --check-command="lintian -Ii" > (a dpkg-buildpackage option).
Thanks for the detailed description. Interesting that this went unnoticed for so long. I've added a test so we hopefully don't regress there. > > Doing proper shell quoting in Python 3 is trival (shlex.quote, which > I use a lot in vectis) but Python 2 doesn't have that function. However, > there is another way to get the --builder interpreted as a shell > one-liner and still pass it arguments: you can invoke > > ["sh", "-c", ('%s "$@"' % builder), "sh"] + arguments I went for using pipes.quote which is python2's equivalent of shlex.quote and fixed up buildpackage-rpm as well so we're consistent. Decided to leave quoting to the caller rather than doing it in Command itself to be consistent between shell=True and cases where command itself is already a script with arguments from e.g. gbp.conf like hooks. Cheers, -- Guido > > with shell=False, and it will do the right thing. The first "sh" in > that monster is argv[0] for the subprocess, and the second is $0 for > the shell one-liner. > > I attach a possible patch. > > S > From a088aef91ffa9de60c6d7ac3278360ce0ee571e1 Mon Sep 17 00:00:00 2001 > From: Simon McVittie <s...@debian.org> > Date: Tue, 10 Jan 2017 19:49:08 +0000 > Subject: [PATCH] buildpackage: don't treat dpkg arguments as shell input > > If one of gbp buildpackage's command-line arguments (after processing > by the calling shell if applicable) includes spaces or shell > metacharacters, it's unexpected to subject it to a layer of shell > interpretation. Conversely, the builder option is documented to be > a shell command and so must go through one layer of shell > interpretation. > > This makes an invocation like > > gbp buildpackage --check-command="lintian -Ii" > > work the way it was presumably intended. > --- > gbp/scripts/buildpackage.py | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/gbp/scripts/buildpackage.py b/gbp/scripts/buildpackage.py > index 6524f01..c7ad903 100755 > --- a/gbp/scripts/buildpackage.py > +++ b/gbp/scripts/buildpackage.py > @@ -727,7 +727,11 @@ def main(argv): > )(dir=build_dir) > > # Finally build the package: > - RunAtCommand(options.builder, dpkg_args, shell=True, > + RunAtCommand('sh', > + ['-c', options.builder + ' "$@"', > + 'sh'] + # $0 for the shell one-liner > + dpkg_args, # $@ for the shell one-liner > + shell=False, # we start the shell explicitly > extra_env=Hook.md(build_env, > {'GBP_BUILD_DIR': build_dir}) > )(dir=build_dir) > -- > 2.11.0 >