changeset 671:7a8ddf54f012

0.6dev: Changing Windows `CommandLine.execute()` to not go through a shell. This makes execution consistent across platforms, and also fixes the quoting and escaping issues reported in #441. Also adds proper documentation for quoting and escaping.
author osimons
date Sat, 05 Sep 2009 00:20:09 +0000
parents a9d8359f4dc9
children 01cc0c8e49fb
files bitten/build/api.py bitten/build/tests/api.py doc/recipes.txt
diffstat 3 files changed, 21 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/bitten/build/api.py
+++ b/bitten/build/api.py
@@ -102,11 +102,10 @@
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE,
                         cwd=(self.cwd or None),
-                        shell=(os.name == 'nt' and True or False),
+                        shell=False,
                         universal_newlines=True,
                         env=None)
         except Exception, e:
-            # NT executes through shell and will not raise BuildError
             raise BuildError('Error executing %s: %s %s' % (args,
                                         e.__class__.__name__, str(e)))
 
--- a/bitten/build/tests/api.py
+++ b/bitten/build/tests/api.py
@@ -33,6 +33,12 @@
         fd.close()
         return filename
 
+    def test_escape_and_quote_args(self):
+        # Verify shlex.split() used by many commands to split input -> args
+        import shlex
+        self.assertEquals(['o\ne', '4 2', '"hi there"'],
+                shlex.split('o\\\ne "4 2" \\"hi\\ there\\"'))
+
     def test_single_argument(self):
         cmdline = CommandLine(sys.executable, ['-V'])
         stdout = []
@@ -141,11 +147,7 @@
         iterable = iter(cmdline.execute())
         try:
             out, err = iterable.next()
-            if os.name == 'nt':
-                # NT executes through shell and will not raise BuildError
-                self.failUnless("'doesnotexist' is not recognized" in err)
-            else:
-                self.fail("Expected BuildError")
+            self.fail("Expected BuildError")
         except BuildError, e:
             self.failUnless("Error executing ['doesnotexist']" in str(e))
 
--- a/doc/recipes.txt
+++ b/doc/recipes.txt
@@ -112,3 +112,16 @@
 +-----------+------------+
 | ``'``     | ``'`` |
 +-----------+------------+
+
+If needed, most commands use regular shell rules to split parts of the input -
+typically like ``args`` input for ``sh:exec`` command. Double-quotes
+(``"``) can be used to mark the start and end if any sub-parts contain
+whitespace, alternatively ``'\'`` can be used to escape whitespace or any other
+character that carries meaning as part of input - including double-quotes and
+backslash itself:
+
+.. code-block:: xml
+
+  <sh:exec file="echo" args="o\\ne &quot;4 2&quot; \&quot;hi\ there\&quot;"/>
+
+This will pass 3 arguments: ``o\ne`` + ``4 2`` + ``"hi there"``.
Copyright (C) 2012-2017 Edgewall Software