Forráskód Böngészése

Allow do_commit to make dangling commits

do_commit has a lot of process that is useful for any arbitrary commit.

do_commit creates dangling commits by setting ref=None and specifying
the commit parents with merge_heads.

Signed-Off-By: Jelmer Vernooij <jelmer@samba.org>
milki 11 éve
szülő
commit
fb5d22bc3e
2 módosított fájl, 56 hozzáadás és 11 törlés
  1. 16 11
      dulwich/repo.py
  2. 40 0
      dulwich/tests/test_repository.py

+ 16 - 11
dulwich/repo.py

@@ -599,19 +599,24 @@ class BaseRepo(object):
         except KeyError:  # no hook defined, message not modified
             c.message = message
 
-        try:
-            old_head = self.refs[ref]
-            c.parents = [old_head] + merge_heads
-            self.object_store.add_object(c)
-            ok = self.refs.set_if_equals(ref, old_head, c.id)
-        except KeyError:
+        if ref is None:
+            # Create a dangling commit
             c.parents = merge_heads
             self.object_store.add_object(c)
-            ok = self.refs.add_if_new(ref, c.id)
-        if not ok:
-            # Fail if the atomic compare-and-swap failed, leaving the commit and
-            # all its objects as garbage.
-            raise CommitError("%s changed during commit" % (ref,))
+        else:
+            try:
+                old_head = self.refs[ref]
+                c.parents = [old_head] + merge_heads
+                self.object_store.add_object(c)
+                ok = self.refs.set_if_equals(ref, old_head, c.id)
+            except KeyError:
+                c.parents = merge_heads
+                self.object_store.add_object(c)
+                ok = self.refs.add_if_new(ref, c.id)
+            if not ok:
+                # Fail if the atomic compare-and-swap failed, leaving the commit and
+                # all its objects as garbage.
+                raise CommitError("%s changed during commit" % (ref,))
 
         try:
             self.hooks['post-commit'].execute()

+ 40 - 0
dulwich/tests/test_repository.py

@@ -683,6 +683,46 @@ class BuildRepoTests(TestCase):
             [self._root_commit, merge_1],
             r[commit_sha].parents)
 
+    def test_commit_dangling_commit(self):
+        r = self._repo
+
+        old_shas = set(r.object_store)
+        old_refs = r.get_refs()
+        commit_sha = r.do_commit('commit with no ref',
+             committer='Test Committer <test@nodomain.com>',
+             author='Test Author <test@nodomain.com>',
+             commit_timestamp=12395, commit_timezone=0,
+             author_timestamp=12395, author_timezone=0,
+             ref=None)
+        new_shas = set(r.object_store) - old_shas
+
+        # New sha is added, but no new refs
+        self.assertEqual(1, len(new_shas))
+        new_commit = r[new_shas.pop()]
+        self.assertEqual(r[self._root_commit].tree, new_commit.tree)
+        self.assertEqual([], r[commit_sha].parents)
+        self.assertEqual(old_refs, r.get_refs())
+
+    def test_commit_dangling_commit_with_parents(self):
+        r = self._repo
+
+        old_shas = set(r.object_store)
+        old_refs = r.get_refs()
+        commit_sha = r.do_commit('commit with no ref',
+             committer='Test Committer <test@nodomain.com>',
+             author='Test Author <test@nodomain.com>',
+             commit_timestamp=12395, commit_timezone=0,
+             author_timestamp=12395, author_timezone=0,
+             ref=None, merge_heads=[self._root_commit])
+        new_shas = set(r.object_store) - old_shas
+
+        # New sha is added, but no new refs
+        self.assertEqual(1, len(new_shas))
+        new_commit = r[new_shas.pop()]
+        self.assertEqual(r[self._root_commit].tree, new_commit.tree)
+        self.assertEqual([self._root_commit], r[commit_sha].parents)
+        self.assertEqual(old_refs, r.get_refs())
+
     def test_stage_deleted(self):
         r = self._repo
         os.remove(os.path.join(r.path, 'a'))