Commits

Jun Omae committed 19576b2

1.1.2dev: merge [12019-12020] from 1.0-stable (refs #11198 #11291)

  • Participants
  • Parent commits 7b25fb2

Comments (0)

Files changed (2)

tracopt/versioncontrol/git/PyGIT.py

 
 
 _unquote_re = re.compile(r'\\(?:[abtnvfr"\\]|[0-7]{3})')
-_unquote_chars = {'a': r'\a', 'b': r'\b', 't': r'\t', 'n': r'\n', 'v': r'\v',
-                  'f': r'\f', 'r': r'\r', '"': r'\"', '\\': r'\\'}
+_unquote_chars = {'a': '\a', 'b': '\b', 't': '\t', 'n': '\n', 'v': '\v',
+                  'f': '\f', 'r': '\r', '"': '"', '\\': '\\'}
 
 
-def _unquote(path, enclosed=False):
-    def replace(match):
-        s = match.group(0)[1:]
-        if len(s) == 3:
-            return chr(int(s, 8))  # \ooo
-        return _unquote_chars[s]
-    if enclosed and path.startswith('"') and path.endswith('"'):
-        path = path[1:-1]
-    return _unquote_re.sub(replace, path)
+def _unquote(path):
+    if path.startswith('"') and path.endswith('"'):
+        def replace(match):
+            s = match.group(0)[1:]
+            if len(s) == 3:
+                return chr(int(s, 8))  # \ooo
+            return _unquote_chars[s]
+        path = _unquote_re.sub(replace, path[1:-1])
+    return path
 
 
 class GitCore(object):
 
             meta, fname = l.split('\t', 1)
             _mode, _type, _sha, _size = meta.split()
-            fname = self._fs_to_unicode(_unquote(fname))
 
             if _size == '-':
                 _size = None
             else:
                 _size = int(_size)
 
-            return _mode, _type, _sha, _size, fname
+            return _mode, _type, _sha, _size, self._fs_to_unicode(fname)
 
         return [ split_ls_tree_line(e) for e in tree if e ]
 
                     if l == '\n':
                         break
                     _, path = l.rstrip('\n').split('\t', 1)
-                    path = _unquote(path, enclosed=True)
+                    # git-log without -z option quotes each pathname
+                    path = _unquote(path)
                     while path not in change:
                         change[path] = old_sha
                         if next_path == [path]:

tracopt/versioncontrol/git/tests/PyGIT.py

         args = [self.git_bin] + list(args)
         proc = Popen(args, stdout=PIPE, stderr=PIPE, close_fds=close_fds,
                      cwd=self.repos_path)
-        proc.wait()
-        assert proc.returncode == 0, proc.stderr.read()
+        stdout, stderr = proc.communicate()
+        assert proc.returncode == 0, \
+               'git exits with %r, stdout %r, stderr %r' % (proc.returncode,
+                                                            stdout, stderr)
         return proc
 
     def _storage(self):
         # create git repository and master branch
         self._git('init', self.repos_path)
         self._git('config', 'core.quotepath', 'true')  # ticket:11198
-        self._git('config', 'user.name', u"Joé")
+        self._git('config', 'user.name', "Joé")  # passing utf-8 bytes
         self._git('config', 'user.email', "joe@example.com")
         create_file(os.path.join(self.repos_path, '.gitignore'))
         self._git('add', '.gitignore')
         args = [self.git_bin] + list(args)
         proc = Popen(args, stdout=PIPE, stderr=PIPE, close_fds=close_fds,
                      cwd=self.repos_path)
-        proc.wait()
-        assert proc.returncode == 0, proc.stderr.read()
+        stdout, stderr = proc.communicate()
+        assert proc.returncode == 0, \
+               'git exits with %r, stdout %r, stderr %r' % (proc.returncode,
+                                                            stdout, stderr)
         return proc
 
     def _storage(self):
         path = os.path.join(self.repos_path, '.git')
         return Storage(path, self.env.log, self.git_bin, 'utf-8')
 
-    def test_quotepath(self):
-        filenames = [u'control\a\b\t\n\v\f\r\x1b"\\.txt',
-                     u'unicodeáćéẃýź.txt']
-        for filename in filenames:
-            filename = filename.encode('utf-8')
-            create_file(os.path.join(self.repos_path, filename))
-            self._git('add', filename)
-        self._git('commit', '-m', 'ticket:11198',
-                  '--date', 'Wed Aug 28 23:21:27 2013 +0900')
-
-        for quotepath in ('true', 'false'):
-            storage = self._storage()
-            self._git('config', 'core.quotepath', quotepath)
-            entries = sorted(storage.ls_tree('HEAD'),
-                             key=lambda entry: entry[4])
-            self.assertEquals(3, len(entries))
-            self.assertEquals('.gitignore', entries[0][4])
-            self.assertEquals(filenames[0], entries[1][4])
-            self.assertEquals(filenames[1], entries[2][4])
-
     def test_unicode_verifyrev(self):
         storage = self._storage()
         self.assertNotEqual(None, storage.verifyrev(u'master'))
         self.assertEquals(u'täg-t10980', tags[0])
         self.assertNotEqual(None, storage.verifyrev(u'täg-t10980'))
 
-    def test_get_historian_with_unicode_path(self):
-        # regression test for #11180
-        create_file(os.path.join(self.repos_path, 'tickét.txt'))
-        self._git('add', 'tickét.txt')
-        self._git('commit', '-m', 'ticket:11180',
-                  '--date', 'Thu May 9 04:31 2013 +0900')
+    def test_ls_tree(self):
+        paths = [u'normal-path.txt',
+                 u'tickét.tx\\t',
+                 u'\a\b\t\n\v\f\r\x1b"\\.tx\\t']
+        for path in paths:
+            path_utf8 = path.encode('utf-8')
+            create_file(os.path.join(self.repos_path, path_utf8))
+            self._git('add', path_utf8)
+        self._git('commit', '-m', 'ticket:11180 and ticket:11198',
+                  '--date', 'Fri Aug 30 00:48:57 2013 +0900')
+
         storage = self._storage()
         rev = storage.head()
-        self.assertNotEqual(None, rev)
-        with storage.get_historian('HEAD', u'tickét.txt') as historian:
-            self.assertNotEqual(None, historian)
-            self.assertEquals(rev, storage.last_change('HEAD', u'tickét.txt',
-                                                       historian))
+        entries = storage.ls_tree(rev, '/')
+        self.assertEquals(4, len(entries))
+        self.assertEquals(u'\a\b\t\n\v\f\r\x1b"\\.tx\\t', entries[0][4])
+        self.assertEquals(u'.gitignore', entries[1][4])
+        self.assertEquals(u'normal-path.txt', entries[2][4])
+        self.assertEquals(u'tickét.tx\\t', entries[3][4])
+
+    def test_get_historian(self):
+        paths = [u'normal-path.txt',
+                 u'tickét.tx\\t',
+                 u'\a\b\t\n\v\f\r\x1b"\\.tx\\t']
+
+        for path in paths:
+            path_utf8 = path.encode('utf-8')
+            create_file(os.path.join(self.repos_path, path_utf8))
+            self._git('add', path_utf8)
+        self._git('commit', '-m', 'ticket:11180 and ticket:11198',
+                  '--date', 'Fri Aug 30 00:48:57 2013 +0900')
+
+        def validate(path, quotepath):
+            self._git('config', 'core.quotepath', quotepath)
+            storage = self._storage()
+            rev = storage.head()
+            with storage.get_historian('HEAD', path) as historian:
+                hrev = storage.last_change('HEAD', path, historian)
+                self.assertEquals(rev, hrev)
+
+        validate(paths[0], 'true')
+        validate(paths[0], 'false')
+        validate(paths[1], 'true')
+        validate(paths[1], 'false')
+        validate(paths[2], 'true')
+        validate(paths[2], 'false')
 
 
 #class GitPerformanceTestCase(unittest.TestCase):