Rev 356: Initial work on supporting the 'bzr:file-ids' property. in http://people.samba.org/bzr/jelmer/bzr-svn/bzr.dev

Jelmer Vernooij jelmer at samba.org
Mon Jan 1 21:50:38 GMT 2007


------------------------------------------------------------
revno: 356
revision-id: jelmer at samba.org-20070101214906-cw23w5x9ytcf1ia0
parent: jelmer at samba.org-20070101214750-ro0wz5uf2bhknx08
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: main
timestamp: Mon 2007-01-01 22:49:06 +0100
message:
  Initial work on supporting the 'bzr:file-ids' property.
modified:
  TODO                           todo-20060729211917-2kpobww0zyvvo0j2-1
  checkout.py                    workingtree.py-20060306120941-b083cb0fdd4a69de
  commit.py                      commit.py-20060607190346-qvq128wgfubhhgm2-1
  fetch.py                       fetch.py-20060625004942-x2lfaib8ra707a8p-1
  mapping.txt                    mapping.txt-20060625151311-9ghaqrm71ajq593n-1
  repository.py                  repository.py-20060306123302-1f8c5069b3fe0265
  tests/test_commit.py           test_commit.py-20060624213521-l5kcufywkh9mnilk-1
  tests/test_fileids.py          test_fileids.py-20060622131341-19gyrlgqy8yl2od5-1
  tests/test_repos.py            test_repos.py-20060508151940-ddc49a59257ca712
  tree.py                        tree.py-20060624222557-dudlwqcmkf22lt2s-1
=== modified file 'TODO'
--- a/TODO	2007-01-01 17:36:22 +0000
+++ b/TODO	2007-01-01 21:49:06 +0000
@@ -5,3 +5,4 @@
 - avoid extra connect in logwalker?
 - get rid of use of `svn ls' in logwalker
 - more efficient implementation for applying txdeltas to weaves. perhaps convert svn deltas to bzr deltas?
+- free memory!

=== modified file 'checkout.py'
--- a/checkout.py	2007-01-01 17:36:22 +0000
+++ b/checkout.py	2007-01-01 21:49:06 +0000
@@ -55,11 +55,9 @@
         self.client_ctx.log_msg_baton2 = self.log_message_func
 
         self._set_inventory(self.read_working_inventory(), dirty=False)
-        mutter('working inv: %r' % self.read_working_inventory().entries())
 
         self.base_revid = branch.repository.generate_revision_id(
                     self.base_revnum, branch.branch_path)
-        mutter('basis inv: %r' % self.basis_tree().inventory.entries())
         self.controldir = os.path.join(self.basedir, svn.wc.get_adm_dir(), 'bzr')
         try:
             os.makedirs(self.controldir)
@@ -177,7 +175,7 @@
             svn.wc.adm_close(to_wc)
 
     def read_working_inventory(self):
-        inv = Inventory(ROOT_ID)
+        inv = Inventory()
 
         def add_file_to_inv(relpath, id, revid, parent_id):
             """Add a file to the inventory."""
@@ -349,7 +347,8 @@
 
         commit_info = svn.client.commit3(specific_files, True, False, self.client_ctx)
 
-        revid = self.branch.repository.generate_revision_id(commit_info.revision, self.branch.branch_path)
+        revid = self.branch.repository.generate_revision_id(
+                commit_info.revision, self.branch.branch_path)
 
         self.base_revid = revid
         #FIXME: Use public API:

=== modified file 'commit.py'
--- a/commit.py	2007-01-01 06:17:51 +0000
+++ b/commit.py	2007-01-01 21:49:06 +0000
@@ -352,7 +352,7 @@
             continue
 
         id = ie.file_id
-        while id != ROOT_ID:
+        while inv[id].parent_id is not None:
             if inv[id].revision is None:
                 break
             inv[id].revision = None

=== modified file 'fetch.py'
--- a/fetch.py	2007-01-01 16:07:12 +0000
+++ b/fetch.py	2007-01-01 21:49:06 +0000
@@ -339,7 +339,7 @@
                 parent_revid = parents[revid]
 
                 if parent_revid is None:
-                    parent_inv = Inventory(ROOT_ID)
+                    parent_inv = Inventory()
                 elif prev_revid != parent_revid:
                     parent_inv = self.target.get_inventory(parent_revid)
                 else:
@@ -403,6 +403,5 @@
     def is_compatible(source, target):
         """Be compatible with SvnRepository."""
         # FIXME: Also check target uses VersionedFile
-        mutter('test %r' % source)
         return isinstance(source, SvnRepository)
 

=== modified file 'mapping.txt'
--- a/mapping.txt	2006-12-30 02:14:58 +0000
+++ b/mapping.txt	2007-01-01 21:49:06 +0000
@@ -71,12 +71,32 @@
 revision X and a file in revision Y are the same without traversing over all 
 the revisions between X and Y.
 
-Fileids are generated by concatenating a revision id and the path of the file
-from the revision it was added or was copied from another file.
-
-Since / is forbidden in revision ids, the '/', '-', '%' and all whitespace
+File ids use the following syntax:
+
+svn-v<MAPPING_VERSION>:<REVNO>@<UUID>-<BRANCHPATH>-<PATH>
+
+Since / is forbidden in file ids, the '/', '-', '%' and all whitespace
 characters are urlencoded.
 
+Alternatively, these file ids can be mapped to more specific file ids. Such 
+a map should be stored in the `bzr:file-ids' property that is set on the 
+branch path.
+
+The bzr:file-ids property should contain a list of mappings. Entries are 
+separated by newlines. The path in the branch and new file-id are separated 
+by a tab.
+
+Given, the path, the revision the mapping was added, the repository uuid 
+and the path the property is set on the (the branch path), the original 
+file id can be determined.  
+
+Tabs, newlines and percent signs in path will be urlencoded.
+
+Neither the original nor the target file id may occur more than once. 
+
+The entries are sorted by revnum (highest revnum last). Within a specific 
+revnum, the order is not specified.
+
 File id mappings can only change if something about the metadata of a file changed: it 
 is in no way related to the contents of that file.
 
@@ -149,6 +169,5 @@
 
 Revision 1 was the original version of this document.
 
-Revision 2 uses real file ids for the tree root rather than the hardcoded 
-"TREE_ROOT" and enforces UTF-8-valid characters for everything except file 
+Revision 2 enforces UTF-8-valid characters for everything except file 
 contents.

=== modified file 'repository.py'
--- a/repository.py	2007-01-01 06:17:51 +0000
+++ b/repository.py	2007-01-01 21:49:06 +0000
@@ -50,6 +50,7 @@
 REVISION_ID_PREFIX = "svn-v%d:" % MAPPING_VERSION
 SVN_PROP_BZR_MERGE = 'bzr:merge'
 SVN_PROP_SVK_MERGE = 'svk:merge'
+SVN_PROP_BZR_FILEIDS = 'bzr:file-ids'
 SVN_PROP_BZR_REVPROP_PREFIX = 'bzr:revprop:'
 SVN_REVPROP_BZR_SIGNATURE = 'bzr:gpg-signature'
 

=== modified file 'tests/test_commit.py'
--- a/tests/test_commit.py	2006-12-31 20:57:48 +0000
+++ b/tests/test_commit.py	2007-01-01 21:49:06 +0000
@@ -14,8 +14,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-from bzrlib.branch import BranchReferenceFormat
-from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
+from bzrlib.branch import Branch, BranchReferenceFormat
+from bzrlib.bzrdir import BzrDir, BzrDirFormat
 from bzrlib.errors import DivergedBranches
 from bzrlib.inventory import Inventory
 from bzrlib.workingtree import WorkingTree
@@ -23,6 +23,7 @@
 import os
 import format
 import checkout
+import svn.core
 from repository import MAPPING_VERSION
 from tests import TestCaseWithSubversionRepository
 
@@ -90,7 +91,7 @@
         self.repos_url = self.make_repository('d')
         source = BzrDir.open("svn+"+self.repos_url)
         os.mkdir('dc')
-        self.checkout = BzrDirMetaFormat1().initialize('dc')
+        self.checkout = BzrDirFormat.get_default_format().initialize('dc')
         BranchReferenceFormat().initialize(self.checkout, source.open_branch())
 
     def test_simple_commit(self):
@@ -142,6 +143,8 @@
         wt.commit(message="data")
         wt.add('foo')
         wt.add('foo/bla')
+        self.assertTrue(wt.inventory.has_filename("bla"))
+        self.assertTrue(wt.inventory.has_filename("foo/bla"))
         wt.set_pending_merges(["some-ghost-revision"])
         wt.commit(message="data")
         self.assertEqual([
@@ -151,6 +154,34 @@
         self.assertEqual("some-ghost-revision\n", 
                 self.client_get_prop(self.repos_url, "bzr:merge", 2))
 
+    def test_commit_fileids(self):
+        wt = self.checkout.create_workingtree()
+        self.build_tree({'dc/file': 'data'})
+        wt.add('file')
+        wt.commit(message="Commit from Bzr")
+        self.assertEqual("\t%s\nfile\t%s\n" % (wt.inventory.root.file_id, wt.inventory.path2id("file")), 
+                self.client_get_prop(self.repos_url, "bzr:file-ids", 1))
+
+    def test_commit_fileids_added(self):
+    
+        rev = svn.core.svn_opt_revision_t()
+        rev.kind = svn.core.svn_opt_revision_head
+
+        svn.client.checkout2(self.repos_url, "db", 
+                rev, rev, True, False, self.client_ctx)
+
+        self.build_tree({'dc/file1': 'data', 'db/file2': "otherdata"})
+        self.client_add("db/file2")
+        self.client_commit("db", "amesg")
+        branch = Branch.open(self.repos_url)
+        inv = branch.repository.get_inventory(branch.last_revision())
+        wt = self.checkout.create_workingtree()
+        self.assertEqual(wt.inventory.root.file_id, inv.root.file_id)
+        wt.add('file1')
+        wt.commit(message="Commit from Bzr")
+        self.assertEqual("file1\t%s\n" % wt.inventory.path2id("file1"), 
+                self.client_get_prop(self.repos_url, "bzr:file-ids", 2))
+
     def test_commit_branchnick(self):
         wt = self.checkout.create_workingtree()
         self.build_tree({'dc/foo/bla': "data", 'dc/bla': "otherdata"})
@@ -298,3 +329,4 @@
 
         self.assertTrue(wt.branch.last_revision() in 
              repos.get_ancestry("svn-v%d:3@%s-" % (MAPPING_VERSION, repos.uuid)))
+

=== modified file 'tests/test_fileids.py'
--- a/tests/test_fileids.py	2006-12-31 20:03:11 +0000
+++ b/tests/test_fileids.py	2007-01-01 21:49:06 +0000
@@ -163,13 +163,17 @@
                          generate_file_id("svn-v2:2 at uuid-bp", dir+"filename"))
 
 class TestFileMapping(TestCase):
-    def apply_mappings(self, mappings, find_children=None):
+    def apply_mappings(self, mappings, find_children=None, renames={}):
         map = {}
         revids = mappings.keys()
         revids.sort()
         for r in revids:
-            revmap = SimpleFileIdMap._apply_changes(lambda x: generate_file_id(r, x), mappings[r], find_children)
-            map.update(dict([(x,(revmap[x],r)) for x in revmap]))
+             def new_file_id(x):
+                 if renames.has_key(r) and renames[r].has_key(x):
+                     return renames[r][x]
+                 return generate_file_id(r, x)
+             revmap = SimpleFileIdMap._apply_changes(new_file_id, mappings[r], find_children)
+             map.update(dict([(x,(revmap[x],r)) for x in revmap]))
         return map
 
     def test_simple(self):
@@ -210,4 +214,27 @@
                  ("svn-v%d:2 at uuid-" % MAPPING_VERSION): {
                                    "foo/bla": ('M', None, None)}
                 })
+        self.assertEqual("svn-v%d:2 at uuid-" % MAPPING_VERSION, map["foo"][1])
+
+    def test_usemap(self):
+        map = self.apply_mappings(
+                {("svn-v%d:1 at uuid-" % MAPPING_VERSION): {
+                                   "foo": ('A', None, None), 
+                                   "foo/bla": ('A', None, None)},
+                 ("svn-v%d:2 at uuid-" % MAPPING_VERSION): {
+                                   "foo/bla": ('M', None, None)}
+                 }, 
+                renames={("svn-v%d:1 at uuid-" % MAPPING_VERSION): {"foo": "myid"}})
+        self.assertEqual("myid", map["foo"][0])
+
+    def test_usemap_later(self):
+        map = self.apply_mappings(
+                {("svn-v%d:1 at uuid-" % MAPPING_VERSION): {
+                                   "foo": ('A', None, None), 
+                                   "foo/bla": ('A', None, None)},
+                 ("svn-v%d:2 at uuid-" % MAPPING_VERSION): {
+                                   "foo/bla": ('M', None, None)}
+                 }, 
+                renames={("svn-v%d:2 at uuid-" % MAPPING_VERSION): {"foo": "myid"}})
+        self.assertEqual("svn-v%d:1 at uuid--foo" % MAPPING_VERSION, map["foo"][0])
         self.assertEqual("svn-v%d:1 at uuid-" % MAPPING_VERSION, map["foo"][1])

=== modified file 'tests/test_repos.py'
--- a/tests/test_repos.py	2006-12-31 20:57:48 +0000
+++ b/tests/test_repos.py	2007-01-01 21:49:06 +0000
@@ -253,6 +253,17 @@
             repository.revision_parents(
                 "svn-v%d:2@%s-" % (MAPPING_VERSION, repository.uuid)))
 
+    def test_revision_fileidmap(self):
+        repos_url = self.make_client('d', 'dc')
+        self.build_tree({'dc/foo': "data"})
+        self.client_add("dc/foo")
+        self.client_set_prop("dc", "bzr:file-ids", "foo\tsomeid\n")
+        self.client_commit("dc", "My Message")
+        repository = Repository.open("svn+%s" % repos_url)
+        tree = repository.revision_tree(Branch.open(repos_url).last_revision())
+        self.assertEqual("someid", tree.inventory.path2id("foo"))
+        self.assertFalse("svn-v2:1@%s--foo" % repository.uuid in tree.inventory)
+
     def test_revision_ghost_parents(self):
         repos_url = self.make_client('d', 'dc')
         self.build_tree({'dc/foo': "data"})
@@ -477,6 +488,17 @@
         repository = Repository.open("svn+%s" % repos_url)
         self.assertTrue(repository.is_shared())
 
+    def test_revision_fileid_renames(self):
+        repos_url = self.make_client('d', 'dc')
+        self.build_tree({'dc/test': "data"})
+        self.client_add("dc/test")
+        self.client_set_prop("dc", "bzr:file-ids", "test\tbla\n")
+        self.client_commit("dc", "Msg")
+
+        repos = Repository.open(repos_url)
+        renames = repos.revision_fileid_renames("svn-v%d:1@%s-" % (MAPPING_VERSION, repos.uuid))
+        self.assertEqual({"test": "bla"}, renames)
+
     def test_fetch_trunk1(self):
         repos_url = self.make_client('d', 'dc')
         self.build_tree({'dc/proj1/trunk/file': "data"})

=== modified file 'tree.py'
--- a/tree.py	2006-12-27 04:21:19 +0000
+++ b/tree.py	2007-01-01 21:49:06 +0000
@@ -112,7 +112,7 @@
 
     def change_dir_prop(self, id, name, value, pool):
         from repository import (SVN_PROP_BZR_MERGE, SVN_PROP_SVK_MERGE, 
-                        SVN_PROP_BZR_REVPROP_PREFIX)
+                        SVN_PROP_BZR_REVPROP_PREFIX, SVN_PROP_BZR_FILEIDS)
 
         if name == svn.core.SVN_PROP_ENTRY_COMMITTED_REV:
             self.dir_revnum[id] = int(value)
@@ -122,6 +122,10 @@
             if id != ROOT_ID:
                 mutter('%r set on non-root dir!' % SVN_PROP_BZR_MERGE)
                 return
+        elif name == SVN_PROP_BZR_FILEIDS:
+            if id != self.tree.id_map[""][0]:
+                mutter('%r set on non-root dir!' % SVN_PROP_BZR_FILEIDS)
+                return
         elif name in (svn.core.SVN_PROP_ENTRY_COMMITTED_DATE,
                       svn.core.SVN_PROP_ENTRY_LAST_AUTHOR,
                       svn.core.SVN_PROP_ENTRY_LOCK_TOKEN,




More information about the bazaar-commits mailing list