Fix RefsContainer.add_if_new to support dangling symrefs.
authorDave Borowitz <dborowitz@google.com>
Wed, 28 Apr 2010 19:36:22 +0000 (12:36 -0700)
committerDave Borowitz <dborowitz@google.com>
Wed, 12 May 2010 16:40:21 +0000 (09:40 -0700)
Change-Id: I411b60135c3374fefd03701db4bb0dc5d0644164

dulwich/repo.py
dulwich/tests/test_repository.py

index fc57690858ee1e4e6d4c29aecfb1f3580a61031e..61d905ec7f202fa0dcf37af6732967f55b4fe8b0 100644 (file)
@@ -126,7 +126,7 @@ class RefsContainer(object):
         :param name: Name of the ref to set
         :param other: Name of the ref to point at
         """
-        self[name] = SYMREF + other + '\n'
+        self[name] = SYMREF + other
 
     def get_packed_refs(self):
         """Get contents of the packed-refs file.
@@ -566,9 +566,23 @@ class DiskRefsContainer(RefsContainer):
         return True
 
     def add_if_new(self, name, ref):
-        """Add a new reference only if it does not already exist."""
-        self._check_refname(name)
-        filename = self.refpath(name)
+        """Add a new reference only if it does not already exist.
+
+        This method follows symrefs, and only ensures that the last ref in the
+        chain does not exist.
+
+        :param name: The refname to set.
+        :param ref: The new sha the refname will refer to.
+        :return: True if the add was successful, False otherwise.
+        """
+        try:
+            realname, contents = self._follow(name)
+            if contents is not None:
+                return False
+        except KeyError:
+            realname = name
+        self._check_refname(realname)
+        filename = self.refpath(realname)
         ensure_dir_exists(os.path.dirname(filename))
         f = GitFile(filename, 'wb')
         try:
index a195fa348176b9597da1f3ea80be2963aa802f57..69bc3e150b6647d72cf22b8d41d6c89ee9945aa4 100644 (file)
@@ -549,6 +549,25 @@ class DiskRefsContainerTests(RefsContainerTests, unittest.TestCase):
         self.assertEqual('df6800012397fb85c56e7418dd4eb9405dee075c',
                          self._refs['refs/tags/refs-0.1'])
 
+    def test_add_if_new_symbolic(self):
+        # Use an empty repo instead of the default.
+        tear_down_repo(self._repo)
+        repo_dir = os.path.join(tempfile.mkdtemp(), 'test')
+        os.makedirs(repo_dir)
+        self._repo = Repo.init(repo_dir)
+        refs = self._repo.refs
+
+        nines = '9' * 40
+        self.assertEqual('ref: refs/heads/master', refs.read_ref('HEAD'))
+        self.assertFalse('refs/heads/master' in refs)
+        self.assertTrue(refs.add_if_new('HEAD', nines))
+        self.assertEqual('ref: refs/heads/master', refs.read_ref('HEAD'))
+        self.assertEqual(nines, refs['HEAD'])
+        self.assertEqual(nines, refs['refs/heads/master'])
+        self.assertFalse(refs.add_if_new('HEAD', '1' * 40))
+        self.assertEqual(nines, refs['HEAD'])
+        self.assertEqual(nines, refs['refs/heads/master'])
+
     def test_follow(self):
         self.assertEquals(
           ('refs/heads/master', '42d06bd4b77fed026b154d16493e5deab78f02ec'),