Rev 26: Support copying Author tags. in http://bzr.arbash-meinel.com/plugins/git

John Arbash Meinel john at arbash-meinel.com
Fri Nov 9 17:50:19 GMT 2007


At http://bzr.arbash-meinel.com/plugins/git

------------------------------------------------------------
revno: 26
revision-id:john at arbash-meinel.com-20071109175015-3o8m8icoz8lcpeih
parent: john at arbash-meinel.com-20071109165902-13hctijmgzkt9io5
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: git
timestamp: Fri 2007-11-09 12:50:15 -0500
message:
  Support copying Author tags.
modified:
  gitlib/git_repository.py       git_repository.py-20071108234408-ygidvy5hviixghsd-2
  tests/test_git_repository.py   test_git_repository.-20071108234408-ygidvy5hviixghsd-5
-------------- next part --------------
=== modified file 'gitlib/git_repository.py'
--- a/gitlib/git_repository.py	2007-11-09 04:53:15 +0000
+++ b/gitlib/git_repository.py	2007-11-09 17:50:15 +0000
@@ -19,6 +19,8 @@
 from bzrlib import (
     deprecated_graph,
     repository,
+    revision,
+    trace,
     urlutils,
     )
 
@@ -44,7 +46,7 @@
         else:
             git_revisions = None
         for lines in self._git.ancestor_lines(git_revisions):
-            yield self.parse_rev(lines)
+            yield self._parse_rev(lines)
 
     def is_shared(self):
         return True
@@ -78,9 +80,10 @@
     def get_revision(self, revision_id):
         if revision_id in self._revision_cache:
             return self._revision_cache[revision_id]
-        raw = self._git.rev_list([gitrevid_from_bzr(revision_id)], max_count=1,
+        git_id = ids.convert_revision_id_bzr_to_git(revision_id)
+        raw = self._git.rev_list([git_id], max_count=1,
                                  header=True)
-        return self.parse_rev(raw)
+        return self._parse_rev(raw)
 
     def has_revision(self, revision_id):
         try:
@@ -93,7 +96,7 @@
     def get_revisions(self, revisions):
         return [self.get_revision(r) for r in revisions]
 
-    def parse_rev(self, raw):
+    def _parse_rev(self, raw):
         # first field is the rev itself.
         # then its 'field value'
         # until the EOF??
@@ -101,33 +104,50 @@
         log = []
         in_log = False
         committer = None
-        revision_id = bzrrevid_from_git(raw[0][:-1])
-        for field in raw[1:]:
-            #if field.startswith('author '):
-            #    committer = field[7:]
-            if field.startswith('parent '):
-                parents.append(bzrrevid_from_git(field.split()[1]))
-            elif field.startswith('committer '):
-                commit_fields = field.split()
-                if committer is None:
-                    committer = ' '.join(commit_fields[1:-3])
-                timestamp = commit_fields[-2]
-                timezone = commit_fields[-1]
-            elif field.startswith('tree '):
-                tree_id = field.split()[1]
-            elif in_log:
-                log.append(field[4:])
-            elif field == '\n':
-                in_log = True
+        revision_id = ids.convert_revision_id_git_to_bzr(raw[0][:-1])
+        author = None
+        author_ts = None
+        author_tz = None
+
+        for idx in xrange(1, len(raw)):
+            field = raw[idx]
+            if field == '\n':
+                break # We follow with the commit message
+            key, value = field.split(' ', 1)
+            value = value[:-1] # Remove the newline
+            if key == 'parent':
+                parents.append(ids.convert_revision_id_git_to_bzr(value))
+            elif key == 'committer':
+                assert committer is None
+                committer, timestamp, timezone = value.rsplit(' ', 2)
+            elif key == 'tree':
+                tree_id = value
+            elif key == 'author':
+                assert author is None
+                author, author_ts, author_tz = value.rsplit(' ', 2)
+            else:
+                trace.mutter('Unknown key: %r', field)
+
+        for idx in xrange(idx+1, len(raw)): # The rest is the log
+            # rev-list inserts 4 space characters for each line of the log
+            # message
+            # cat-file does not ... ?
+            log.append(raw[idx][4:])
 
         log = ''.join(log)
-        result = Revision(revision_id)
+        result = revision.Revision(revision_id)
         result.parent_ids = parents
-        result.message = log
+        result.message = log.decode('utf-8')
         result.inventory_sha1 = ""
-        result.timezone = timezone and int(timezone)
+        result.timezone = int(timezone[:3]) * 3600 + int(timezone[-2:])
         result.timestamp = float(timestamp)
         result.committer = committer
+        if author and committer != author:
+            result.properties['author'] = author
+        if ((author_tz and author_tz != timezone)
+            or (author_ts and author_ts != timestamp)):
+            result.properties['author-timestamp'] = '%s %s' % (author_ts,
+                                                               author_tz)
         result.properties['git-tree-id'] = tree_id
         return result
 
@@ -139,9 +159,9 @@
         return GitRevisionTree(self, revision_id)
 
     def get_inventory(self, revision_id):
-        revision = self.get_revision(revision_id)
+        rev = self.get_revision(revision_id)
         inventory = GitInventory(revision_id)
-        tree_id = revision.properties['git-tree-id']
+        tree_id = rev.properties['git-tree-id']
         type_map = {'blob': 'file', 'tree': 'directory' }
         def get_inventory(tree_id, prefix):
             for perms, type, obj_id, name in self._git.get_inventory(tree_id):
@@ -200,7 +220,7 @@
 
 class GitEntry(object):
 
-    def __init__(self, path, kind, revision, text_sha1=None, executable=False,
+    def __init__(self, path, kind, revision_id, text_sha1=None, executable=False,
                  text_size=None):
         self.path = path
         self.file_id = path
@@ -211,7 +231,7 @@
             self.parent_id = None
         else:
             self.parent_id = osutils.dirname(path)
-        self.revision = revision
+        self.revision = revision_id
         self.symlink_target = None
         self.text_sha1 = text_sha1
         self.text_size = None

=== modified file 'tests/test_git_repository.py'
--- a/tests/test_git_repository.py	2007-11-09 15:53:24 +0000
+++ b/tests/test_git_repository.py	2007-11-09 17:50:15 +0000
@@ -16,6 +16,7 @@
 
 """Tests for interfacing with a Git Repository"""
 
+from cStringIO import StringIO
 import subprocess
 
 from bzrlib import repository
@@ -80,3 +81,85 @@
         self.assertEqual(graph, repo.get_revision_graph(bzr_revisions[0]))
         self.assertEqual({bzr_revisions[3]:[]},
                          repo.get_revision_graph(bzr_revisions[3]))
+
+    def test_get_revision_no_parents(self):
+        tests.run_git('init')
+        builder = tests.GitBranchBuilder()
+        commit1_handle = builder.commit('Joe Foo <joe at foo.com>',
+                                        u'message\nf\xb5\n',
+                                        timestamp=1194586400, timezone='-0200',
+                                       )
+        mapping = builder.finish()
+        commit1_id = mapping[commit1_handle]
+
+        bzr_revision_id = ids.convert_revision_id_git_to_bzr(commit1_id)
+        repo = repository.Repository.open('.')
+        rev = repo.get_revision(bzr_revision_id)
+        self.assertEqual([], rev.parent_ids)
+        self.assertEqual(bzr_revision_id, rev.revision_id)
+        self.assertEqual('Joe Foo <joe at foo.com>', rev.committer)
+        self.assertEqual(u'message\nf\xb5\n', rev.message)
+        self.failIf('author' in rev.properties)
+        self.assertIsNot(None, rev.properties['git-tree-id'])
+        self.assertEqual(1194586400, rev.timestamp)
+        self.assertEqual(-2*3600, rev.timezone)
+
+    def test_get_revision_merged(self):
+        tests.run_git('init')
+        builder = tests.GitBranchBuilder()
+        commit1_handle = builder.commit('Joe Foo <joe at foo.com>', u'one')
+        commit2_handle = builder.commit('Joe Foo <joe at foo.com>', u'two')
+        commit3_handle = builder.commit('Jerry Bar <jerry at foo.com>', u'three',
+                                        base=commit1_handle)
+        # XXX: For some reason git fast-import breaks if you base commit3 and
+        #      merge commit2, something about unknown type 0
+        commit4_handle = builder.commit('Jerry Bar <jerry at bar.com>', u'Merging',
+                                        timestamp=1194586400, timezone='-0200',
+                                        base=commit2_handle,
+                                        merge=[commit3_handle],)
+        mapping = builder.finish()
+        commit1_id = mapping[commit1_handle]
+        commit2_id = mapping[commit2_handle]
+        commit3_id = mapping[commit3_handle]
+        commit4_id = mapping[commit4_handle]
+
+        conv_g2b = ids.convert_revision_id_git_to_bzr
+        bzr_revision_id = conv_g2b(commit4_id)
+        parents = [conv_g2b(commit2_id), conv_g2b(commit3_id)]
+
+        repo = repository.Repository.open('.')
+        rev = repo.get_revision(bzr_revision_id)
+        self.assertEqual(parents, rev.parent_ids)
+        self.assertEqual(bzr_revision_id, rev.revision_id)
+        self.assertEqual('Jerry Bar <jerry at bar.com>', rev.committer)
+        self.assertEqual(u'Merging\n', rev.message)
+        self.failIf('author' in rev.properties)
+        self.assertIsNot(None, rev.properties['git-tree-id'])
+        self.assertEqual(1194586400, rev.timestamp)
+        self.assertEqual(-2*3600, rev.timezone)
+
+    def test_get_revision_author(self):
+        tests.run_git('init')
+        builder = tests.GitBranchBuilder()
+        commit1_handle = builder.commit('Joe Foo <joe at foo.com>',
+                                        u'message\nf\xb5\n',
+                                        timestamp=1194586400, timezone='-0200',
+                                        author='Jerry Bar <jerry at bar.com>',
+                                        author_ts=1194586300, author_tz='+0400',
+                                       )
+        mapping = builder.finish()
+        commit1_id = mapping[commit1_handle]
+
+        bzr_revision_id = ids.convert_revision_id_git_to_bzr(commit1_id)
+        repo = repository.Repository.open('.')
+        rev = repo.get_revision(bzr_revision_id)
+        self.assertEqual([], rev.parent_ids)
+        self.assertEqual(bzr_revision_id, rev.revision_id)
+        self.assertEqual('Joe Foo <joe at foo.com>', rev.committer)
+        self.assertEqual(u'message\nf\xb5\n', rev.message)
+        self.assertEqual('Jerry Bar <jerry at bar.com>', rev.properties['author'])
+        self.assertIsNot(None, rev.properties['git-tree-id'])
+        self.assertEqual(1194586400, rev.timestamp)
+        self.assertEqual(-2*3600, rev.timezone)
+        self.assertEqual('1194586300 +0400',
+                         rev.properties['author-timestamp'])



More information about the bazaar-commits mailing list