Fix some more corner cases with file ids.
authorJelmer Vernooij <jelmer@samba.org>
Mon, 23 Jul 2007 20:18:26 +0000 (22:18 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Mon, 23 Jul 2007 20:18:26 +0000 (22:18 +0200)
branchprops.py
commit.py
repository.py
tests/test_branch.py
tests/test_branchprops.py
tests/test_commit.py
tests/test_fetch.py
tests/test_repos.py
workingtree.py

index c4fe5fdc5614b7d5dc44a0b52c0f0912ec900c32..acce1753e32047797c4043db991551863a9108e0 100644 (file)
@@ -82,6 +82,24 @@ class BranchPropertyList:
             return props[name]
         return default
 
+    def touches_property(self, path, revnum, name):
+        """Check whether a property was modified in a revision."""
+        assert isinstance(path, str)
+        assert isinstance(revnum, int)
+        assert isinstance(name, str)
+        # If the path this property is set on didn't change, then 
+        # the property can't have changed.
+        if not self.log.touches_path(path, revnum):
+            return ""
+
+        current = self.get_property(path, revnum, name, None)
+        (prev_path, prev_revnum) = self.log.get_previous(path, revnum)
+        if prev_path is None and prev_revnum == -1:
+            return (current is not None)
+        previous = self.get_property(prev_path.encode("utf-8"), 
+                                     prev_revnum, name, None)
+        return (previous != current)
+
     def get_property_diff(self, path, revnum, name):
         """Returns the new lines that were added to a particular property."""
         assert isinstance(path, str)
index 9772b747eafdd55045d4238ee1a2de8386a73308..7e9fb27fa035f51c6fea058cf8f1f85367bfc208 100644 (file)
--- a/commit.py
+++ b/commit.py
@@ -72,6 +72,7 @@ class SvnCommitBuilder(RootCommitBuilder):
         self._svnprops = {}
         self._svnprops[SVN_PROP_BZR_REVISION_INFO] = generate_revision_metadata(
             timestamp, timezone, committer, revprops)
+        self._svnprops[SVN_PROP_BZR_FILEIDS] = ""
 
         # Gather information about revision on top of which the commit is 
         # happening
@@ -206,35 +207,34 @@ class SvnCommitBuilder(RootCommitBuilder):
             if not (child_ie.kind in ('file', 'symlink')):
                 continue
 
+            new_child_path = self.new_inventory.id2path(child_ie.file_id)
             # add them if they didn't exist in old_inv 
             if not child_ie.file_id in self.old_inv:
-                mutter('adding %s %r' % (child_ie.kind, self.new_inventory.id2path(child_ie.file_id)))
-
+                mutter('adding %s %r' % (child_ie.kind, new_child_path))
+                self._record_file_id(child_ie, new_child_path)
                 child_baton = self.editor.add_file(
-                    urlutils.join(
-                        self.branch.get_branch_path(), 
-                        self.new_inventory.id2path(child_ie.file_id)),
-                           baton, None, -1, self.pool)
+                    urlutils.join(self.branch.get_branch_path(), 
+                                  new_child_path), baton, None, -1, self.pool)
 
 
             # copy if they existed at different location
-            elif self.old_inv.id2path(child_ie.file_id) != self.new_inventory.id2path(child_ie.file_id):
+            elif self.old_inv.id2path(child_ie.file_id) != new_child_path:
                 mutter('copy %s %r -> %r' % (child_ie.kind, 
                                   self.old_inv.id2path(child_ie.file_id), 
-                                  self.new_inventory.id2path(child_ie.file_id)))
-
+                                  new_child_path))
+                self._record_file_id(child_ie, new_child_path)
                 child_baton = self.editor.add_file(
-                    urlutils.join(self.branch.get_branch_path(), self.new_inventory.id2path(child_ie.file_id)), baton, 
+                    urlutils.join(self.branch.get_branch_path(), new_child_path), baton, 
                     urlutils.join(self.repository.transport.svn_url, self.base_path, self.old_inv.id2path(child_ie.file_id)),
                     self.base_revnum, self.pool)
 
             # open if they existed at the same location
             elif child_ie.revision is None:
-                mutter('open %s %r' % (child_ie.kind, 
-                                 self.new_inventory.id2path(child_ie.file_id)))
+                mutter('open %s %r' % (child_ie.kind, new_child_path))
 
                 child_baton = self.editor.open_file(
-                    urlutils.join(self.branch.get_branch_path(), self.new_inventory.id2path(child_ie.file_id)), 
+                    urlutils.join(self.branch.get_branch_path(), 
+                        new_child_path), 
                     baton, self.base_revnum, self.pool)
 
             else:
@@ -281,30 +281,32 @@ class SvnCommitBuilder(RootCommitBuilder):
             if child_ie.kind != 'directory':
                 continue
 
+            new_child_path = self.new_inventory.id2path(child_ie.file_id)
             # add them if they didn't exist in old_inv 
             if not child_ie.file_id in self.old_inv:
                 mutter('adding dir %r' % child_ie.name)
+                self._record_file_id(child_ie, new_child_path)
                 child_baton = self.editor.add_directory(
-                           urlutils.join(self.branch.get_branch_path(), self.new_inventory.id2path(child_ie.file_id)),
-                           baton, None, -1, self.pool)
+                    urlutils.join(self.branch.get_branch_path(), 
+                                  new_child_path), baton, None, -1, self.pool)
 
             # copy if they existed at different location
-            elif self.old_inv.id2path(child_ie.file_id) != self.new_inventory.id2path(child_ie.file_id):
-                mutter('copy dir %r -> %r' % (self.old_inv.id2path(child_ie.file_id), 
-                                         self.new_inventory.id2path(child_ie.file_id)))
+            elif self.old_inv.id2path(child_ie.file_id) != new_child_path:
+                old_child_path = self.old_inv.id2path(child_ie.file_id)
+                mutter('copy dir %r -> %r' % (old_child_path, new_child_path))
+                self._record_file_id(child_ie, new_child_path)
                 child_baton = self.editor.add_directory(
-                           urlutils.join(self.branch.get_branch_path(), self.new_inventory.id2path(child_ie.file_id)),
-                           baton, 
-                           urlutils.join(self.repository.transport.svn_url, self.base_path, self.old_inv.id2path(child_ie.file_id)),
-                           self.base_revnum, self.pool)
+                    urlutils.join(self.branch.get_branch_path(), new_child_path),
+                    baton, 
+                    urlutils.join(self.repository.transport.svn_url, self.base_path, old_child_path), self.base_revnum, self.pool)
 
             # open if they existed at the same location and 
             # the directory was touched
             elif self.new_inventory[child_ie.file_id].revision is None:
-                mutter('open dir %r' % self.new_inventory.id2path(child_ie.file_id))
+                mutter('open dir %r' % new_child_path)
 
                 child_baton = self.editor.open_directory(
-                        urlutils.join(self.branch.get_branch_path(), self.new_inventory.id2path(child_ie.file_id)), 
+                        urlutils.join(self.branch.get_branch_path(), new_child_path), 
                         baton, self.base_revnum, self.pool)
             else:
                 assert child_ie.file_id not in self.modified_dirs
@@ -312,8 +314,7 @@ class SvnCommitBuilder(RootCommitBuilder):
 
             # Handle this directory
             if child_ie.file_id in self.modified_dirs:
-                self._dir_process(self.new_inventory.id2path(child_ie.file_id), 
-                        child_ie.file_id, child_baton)
+                self._dir_process(new_child_path, child_ie.file_id, child_baton)
 
             self.editor.close_directory(child_baton, self.pool)
 
@@ -429,12 +430,8 @@ class SvnCommitBuilder(RootCommitBuilder):
         return revid
 
     def _record_file_id(self, ie, path):
-        # Make sure that ie.file_id exists in the map
-        if not ie.file_id in self.old_inv:
-            if not self._svnprops.has_key(SVN_PROP_BZR_FILEIDS):
-                self._svnprops[SVN_PROP_BZR_FILEIDS] = ""
-            mutter('adding fileid mapping %s -> %s' % (path, ie.file_id))
-            self._svnprops[SVN_PROP_BZR_FILEIDS] += "%s\t%s\n" % (escape_svn_path(path), ie.file_id)
+        mutter('adding fileid mapping %s -> %s' % (path, ie.file_id))
+        self._svnprops[SVN_PROP_BZR_FILEIDS] += "%s\t%s\n" % (escape_svn_path(path), ie.file_id)
 
     def record_entry_contents(self, ie, parent_invs, path, tree):
         """Record the content of ie from tree into the commit if needed.
@@ -457,8 +454,6 @@ class SvnCommitBuilder(RootCommitBuilder):
         if ie.revision is not None:
             return
 
-        self._record_file_id(ie, path)
-
         previous_entries = ie.find_previous_heads(parent_invs, 
             self.repository.weave_store, self.repository.get_transaction())
 
@@ -478,7 +473,6 @@ def replay_delta(builder, old_tree, new_tree):
     def touch_id(id):
         ie = builder.new_inventory[id]
         path = builder.new_inventory.id2path(id)
-        builder._record_file_id(ie, path)
 
         id = ie.file_id
         while builder.new_inventory[id].parent_id is not None:
index 101f5b67369f23cd7d0521bf2f20022737869401..bb6622952051d691167a48b6d90725d4ed84d5af 100644 (file)
@@ -386,9 +386,16 @@ class SvnRepository(Repository):
         :return: dictionary with paths as keys, file ids as values
         """
         (path, revnum, scheme) = self.lookup_revision_id(revid)
+        # Only consider bzr:file-ids if this is a bzr revision
+        if not self.branchprop_list.touches_property(path, revnum, 
+                SVN_PROP_BZR_REVISION_INFO):
+            return {}
+        fileids = self.branchprop_list.get_property(path, revnum, 
+                                                    SVN_PROP_BZR_FILEIDS)
+        if fileids is None:
+            return {}
         ret = {}
-        for line in self.branchprop_list.get_property_diff(path, revnum, 
-                SVN_PROP_BZR_FILEIDS).splitlines():
+        for line in fileids.splitlines():
             (path, key) = line.split("\t", 2)
             ret[path] = osutils.safe_file_id(key)
         return ret
index 606c84694a692152d5c502d1829c8ce1530a23eb..4a0cc057b2daaa7e39d69a9cce51bd1fbc68bb0d 100644 (file)
@@ -49,7 +49,7 @@ class WorkingSubversionBranch(TestCaseWithSubversionRepository):
         self.client_add("dc/trunk")
         self.client_commit("dc", "Add branch")
         branch = Branch.open(repos_url+"/trunk")
-        self.assertEqual("/trunk", branch.get_branch_path())
+        self.assertEqual("trunk", branch.get_branch_path())
 
     def test_open_nonexistant(self):
         repos_url = self.make_client("a", "dc")
index 846748a168fdc3656e86e8f670cb2aecf79a5741..efcb4092359e79787d3050595b2b752fc29feb2e 100644 (file)
@@ -115,6 +115,20 @@ class TestBranchProps(TestCaseWithSubversionRepository):
         bp = BranchPropertyList(logwalk, self.db)
         self.assertEqual("data2\n", bp.get_property_diff("", 2, "myprop"))
 
+    def test_touches_property(self):
+        repos_url = self.make_client('d', 'dc')
+        self.client_set_prop("dc", "myprop", "data\n")
+        self.client_commit("dc", "My Message")
+        self.client_set_prop("dc", "myprop", "data\ndata2\n")
+        self.client_commit("dc", "My Message")
+
+        logwalk = LogWalker(transport=SvnRaTransport(repos_url))
+
+        bp = BranchPropertyList(logwalk, self.db)
+        self.assertTrue(bp.touches_property("", 2, "myprop"))
+        self.assertTrue(bp.touches_property("", 1, "myprop"))
+        self.assertFalse(bp.touches_property("", 1, "nonexistant-property"))
+
     def test_get_property_diff_ignore_origchange(self):
         repos_url = self.make_client('d', 'dc')
         self.client_set_prop("dc", "myprop", "foodata\n")
index ed1bbe6cbb90476a12b9f67881703bc7791f8a1a..08f4ac6352e8aacb4c3409f8d72cec951618359a 100644 (file)
@@ -145,7 +145,6 @@ class TestNativeCommit(TestCaseWithSubversionRepository):
         self.assertEquals(1, paths["/bar"].copyfrom_rev)
         self.assertEquals("bar\t%s\n" % oldid, 
                           self.client_get_prop(repos_url, "bzr:file-ids", 2))
-                          
 
     def test_commit_rename_file_from_directory(self):
         repos_url = self.make_client('d', 'dc')
@@ -498,8 +497,15 @@ class HeavyWeightCheckoutTests(TestCaseWithSubversionRepository):
         self.build_tree({'b/file': 'data'})
         wt.add('file')
         oldid = wt.path2id("file")
-        revid = wt.commit(message="Commit from Bzr")
+        revid1 = wt.commit(message="Commit from Bzr")
+        wt.rename_one('file', 'file2')
+        revid2 = wt.commit(message="Commit from Bzr")
         master_branch = Branch.open(repos_url)
-        self.assertEquals(revid, master_branch.last_revision())
         self.assertEquals("file\t%s\n" % oldid, 
                           self.client_get_prop(repos_url, "bzr:file-ids", 1))
+        self.assertEquals("file2\t%s\n" % oldid, 
+                          self.client_get_prop(repos_url, "bzr:file-ids", 2))
+        tree1 = master_branch.repository.revision_tree(revid1)
+        tree2 = master_branch.repository.revision_tree(revid2)
+        delta = tree2.changes_from(tree1)
+        self.assertEquals(1, len(delta.renamed))
index cdaae2423db912b24d1419c66ec16befb743c69e..9f6b8feee786176268c5d0e9edd49764504def67 100644 (file)
@@ -36,6 +36,7 @@ class TestFetchWorks(TestCaseWithSubversionRepository):
         self.build_tree({'dc/test': "data"})
         self.client_add("dc/test")
         self.client_set_prop("dc", "bzr:file-ids", "test\tbla\n")
+        self.client_set_prop("dc", "bzr:revision-info", "")
         self.client_commit("dc", "Msg")
 
         oldrepos = Repository.open(repos_url)
index 29908de84370330fcab5faf3a1cb2437567d71b4..bbea386fea3f7c07250709357c259f8b31a6ec9f 100644 (file)
@@ -399,6 +399,7 @@ class TestSubversionRepositoryWorks(TestCaseWithSubversionRepository):
         repos_url = self.make_client('d', 'dc')
         self.build_tree({'dc/foo': "data"})
         self.client_add("dc/foo")
+        self.client_set_prop("dc", "bzr:revision-info", "")
         self.client_set_prop("dc", "bzr:file-ids", "foo\tsomeid\n")
         self.client_commit("dc", "My Message")
         repository = Repository.open("svn+%s" % repos_url)
@@ -852,6 +853,7 @@ class TestSubversionRepositoryWorks(TestCaseWithSubversionRepository):
         repos_url = self.make_client('d', 'dc')
         self.build_tree({'dc/test': "data"})
         self.client_add("dc/test")
+        self.client_set_prop("dc", "bzr:revision-info", "")
         self.client_set_prop("dc", "bzr:file-ids", "test\tbla\n")
         self.client_commit("dc", "Msg")
 
index fb5f4bf9e9a66ba000414a243c3c62a096b7919b..9d1f422b91faa1b4e28844568aa35a457b9fa384 100644 (file)
@@ -582,11 +582,7 @@ class SvnWorkingTree(WorkingTree):
         else:
             assert isinstance(id, str)
             new_entries[path] = id
-        committed = self.branch.repository.branchprop_list.get_property(
-                self.branch.get_branch_path(self.base_revnum), 
-                self.base_revnum, 
-                SVN_PROP_BZR_FILEIDS, "")
-        existing = committed + "".join(map(lambda (path, id): "%s\t%s\n" % (path, id), new_entries.items()))
+        existing = "".join(map(lambda (path, id): "%s\t%s\n" % (path, id), new_entries.items()))
         if existing != "":
             svn.wc.prop_set(SVN_PROP_BZR_FILEIDS, existing.encode("utf-8"), self.basedir, subwc)
         if wc is None:
@@ -597,11 +593,10 @@ class SvnWorkingTree(WorkingTree):
                 self.branch.get_branch_path(self.base_revnum), self.base_revnum, 
                 SVN_PROP_BZR_FILEIDS, "")
         existing = svn.wc.prop_get(SVN_PROP_BZR_FILEIDS, self.basedir, wc)
-        if existing is None:
+        if existing is None or committed == existing:
             return {}
-        else:
-            return dict(map(lambda x: str(x).split("\t"), 
-                existing[len(committed):].splitlines()))
+        return dict(map(lambda x: str(x).split("\t"), 
+            existing.splitlines()))
 
     def _get_bzr_revids(self):
         return self.branch.repository.branchprop_list.get_property(