Rev 4841: (bialix) Change the commandline parser to be even closer to the plain in file:///home/pqm/archives/thelove/bzr/2.1/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue May 18 22:18:20 BST 2010


At file:///home/pqm/archives/thelove/bzr/2.1/

------------------------------------------------------------
revno: 4841 [merge]
revision-id: pqm at pqm.ubuntu.com-20100518211815-qtbvq8qj4gg0v7c8
parent: pqm at pqm.ubuntu.com-20100506084624-ii9nk3id2c5210us
parent: bialix at ukr.net-20100512161942-coa5f76tyjiheu02
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: 2.1
timestamp: Tue 2010-05-18 22:18:15 +0100
message:
  (bialix) Change the commandline parser to be even closer to the plain
  	win32 one.
modified:
  bzrlib/tests/test_win32utils.py test_win32utils.py-20070713181630-8xsrjymd3e8mgw23-108
  bzrlib/win32utils.py           win32console.py-20051021033308-123c6c929d04973d
=== modified file 'bzrlib/tests/test_win32utils.py'
--- a/bzrlib/tests/test_win32utils.py	2010-02-17 17:11:16 +0000
+++ b/bzrlib/tests/test_win32utils.py	2010-05-12 16:19:42 +0000
@@ -345,9 +345,29 @@
         self.assertAsTokens([(True, u'foo"bar')], u'"foo\\"bar"')
 
     def test_double_escape(self):
-        self.assertAsTokens([(True, u'foo\\bar')], u'"foo\\\\bar"')
+        self.assertAsTokens([(True, u'foo\\\\bar')], u'"foo\\\\bar"')
         self.assertAsTokens([(False, u'foo\\\\bar')], u"foo\\\\bar")
 
+    def test_n_backslashes_handling(self):
+        # https://bugs.launchpad.net/bzr/+bug/528944
+        # actually we care about the doubled backslashes when they're
+        # represents UNC paths.
+        # But in fact there is too much weird corner cases
+        # (see https://bugs.launchpad.net/tortoisebzr/+bug/569050)
+        # so to reproduce every bit of windows command-line handling
+        # could be not worth of efforts?
+        self.requireFeature(BackslashDirSeparatorFeature)
+        self.assertAsTokens([(True, r'\\host\path')], r'"\\host\path"')
+        self.assertAsTokens([(False, r'\\host\path')], r'\\host\path')
+        # handling of " after the 2n and 2n+1 backslashes
+        # inside and outside the quoted string
+        self.assertAsTokens([(True, r'\\'), (False, r'*.py')], r'"\\\\" *.py')
+        self.assertAsTokens([(True, r'\\" *.py')], r'"\\\\\" *.py"')
+        self.assertAsTokens([(True, r'\\ *.py')], r'\\\\" *.py"')
+        self.assertAsTokens([(False, r'\\"'), (False, r'*.py')],
+                            r'\\\\\" *.py')
+        self.assertAsTokens([(True, u'\\\\')], u'"\\\\')
+
 
 class Test_CommandLineToArgv(tests.TestCaseInTempDir):
 

=== modified file 'bzrlib/win32utils.py'
--- a/bzrlib/win32utils.py	2010-02-17 17:11:16 +0000
+++ b/bzrlib/win32utils.py	2010-05-12 16:19:42 +0000
@@ -536,70 +536,49 @@
         # self._quote_match = re.compile(u'[\'"]').match
         self._escape_match = lambda x: None # Never matches
         self._escape = '\\'
-        # State can be
-        #   ' ' - after whitespace, starting a new token
-        #   'a' - after text, currently working on a token
-        #   '"' - after ", currently in a "-delimited quoted section
-        #   "\" - after '\', checking the next char
-        self._state = ' '
         self._token = [] # Current token being parsed
 
     def _get_token(self):
         # Were there quote chars as part of this token?
-        quoted = False
-        quoted_state = None
+        quoted = None   # state:
+                        #  None - the string is not quoted
+                        #  empty string ('') - there was quoted substring
+                        #  double quote (") - we're inside quoted chunk
+        number_of_backslashes = 0
         for nextchar in self._input_iter:
-            if self._state == ' ':
-                if self._whitespace_match(nextchar):
-                    # if self._token: return token
-                    continue
-                elif nextchar in self._quote_chars:
-                    self._state = nextchar # quoted state
-                elif self._word_match(nextchar):
-                    self._token.append(nextchar)
-                    self._state = 'a'
-                else:
-                    raise AssertionError('wtttf?')
-            elif self._state in self._quote_chars:
-                quoted = True
-                if nextchar == self._state: # End of quote
-                    self._state = 'a' # posix allows 'foo'bar to translate to
-                                      # foobar
-                elif self._state == '"' and nextchar == self._escape:
-                    quoted_state = self._state
-                    self._state = nextchar
-                else:
-                    self._token.append(nextchar)
-            elif self._state == self._escape:
-                if nextchar == '\\':
-                    self._token.append('\\')
-                elif nextchar == '"':
-                    self._token.append(nextchar)
-                else:
-                    self._token.append('\\' + nextchar)
-                self._state = quoted_state
-            elif self._state == 'a':
-                if self._whitespace_match(nextchar):
-                    if self._token:
-                        break # emit this token
+            if self._whitespace_match(nextchar):
+                if quoted:
+                    self._token.append(nextchar)
+                elif self._token:
+                    break
+            elif nextchar == '\\':
+                number_of_backslashes += 1
+            elif nextchar in self._quote_chars:
+                if number_of_backslashes:
+                    self._token.append('\\'*(number_of_backslashes/2))
+                    if number_of_backslashes % 2:
+                        self._token.append('"')
                     else:
-                        continue # no token to emit
-                elif nextchar in self._quote_chars:
-                    # Start a new quoted section
-                    self._state = nextchar
-                # escape?
-                elif (self._word_match(nextchar)
-                      or nextchar in self._quote_chars
-                      # or whitespace_split?
-                      ):
-                    self._token.append(nextchar)
+                        if quoted:
+                            quoted = ''
+                        else:
+                            quoted = nextchar
+                    number_of_backslashes = 0
+                elif nextchar == quoted:
+                    # end of quoted string
+                    quoted = ''
                 else:
-                    raise AssertionError('state == "a", char: %r'
-                                         % (nextchar,))
+                    quoted = nextchar
             else:
-                raise AssertionError('unknown state: %r' % (self._state,))
+                if number_of_backslashes:
+                    self._token.append('\\'*number_of_backslashes)
+                    number_of_backslashes = 0
+                self._token.append(nextchar)
+        if number_of_backslashes > 0:
+            self._token.append('\\'*number_of_backslashes)
         result = ''.join(self._token)
         self._token = []
+        quoted = quoted is not None
         if not quoted and result == '':
             result = None
         return quoted, result




More information about the bazaar-commits mailing list