Rev 357: Store file id maps when committing to Subversion. Fixes #54738. in http://people.samba.org/bzr/jelmer/bzr-svn/bzr.dev

Jelmer Vernooij jelmer at samba.org
Mon Jan 1 22:19:50 GMT 2007


------------------------------------------------------------
revno: 357
revision-id: jelmer at samba.org-20070101221853-z74gmy058bm6z1j0
parent: jelmer at samba.org-20070101214906-cw23w5x9ytcf1ia0
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: main
timestamp: Mon 2007-01-01 23:18:53 +0100
message:
  Store file id maps when committing to Subversion. Fixes #54738.
modified:
  NEWS                           news-20061231030336-h9fhq245ie0de8bs-1
  commit.py                      commit.py-20060607190346-qvq128wgfubhhgm2-1
  fetch.py                       fetch.py-20060625004942-x2lfaib8ra707a8p-1
  fileids.py                     fileids.py-20060714013623-u5iiyqqnko11grcf-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
=== modified file 'NEWS'
--- a/NEWS	2007-01-01 17:36:22 +0000
+++ b/NEWS	2007-01-01 22:18:53 +0000
@@ -32,6 +32,8 @@
 
    * Don't try to import files as branches.
 
+   * Store file id map when committing to Subversion. (#54738)
+
   IMPROVEMENTS
 
    * Implemented SvnRepository.all_revision_ids().

=== modified file 'commit.py'
--- a/commit.py	2007-01-01 21:49:06 +0000
+++ b/commit.py	2007-01-01 22:18:53 +0000
@@ -21,19 +21,18 @@
                            DivergedBranches)
 from bzrlib.inventory import Inventory, ROOT_ID
 import bzrlib.osutils as osutils
-from bzrlib.repository import CommitBuilder
+from bzrlib.repository import RootCommitBuilder
 from bzrlib.trace import mutter, warning
 
-from repository import (SvnRepository, SVN_PROP_BZR_MERGE, SVN_PROP_SVK_MERGE, 
-                       SVN_PROP_BZR_REVPROP_PREFIX, revision_id_to_svk_feature)
+from repository import (SvnRepository, SVN_PROP_BZR_MERGE, SVN_PROP_BZR_FILEIDS,
+                        SVN_PROP_SVK_MERGE, SVN_PROP_BZR_REVPROP_PREFIX, 
+                        revision_id_to_svk_feature, escape_svn_path)
 
 import os
 
-class SvnCommitBuilder(CommitBuilder):
+class SvnCommitBuilder(RootCommitBuilder):
     """Commit Builder implementation wrapped around svn_delta_editor. """
 
-    record_root_entry = True 
-
     def __init__(self, repository, branch, parents, config, revprops):
         """Instantiate a new SvnCommitBuilder.
 
@@ -332,6 +331,44 @@
 
         return revid
 
+    def record_entry_contents(self, ie, parent_invs, path, tree):
+        """Record the content of ie from tree into the commit if needed.
+
+        Side effect: sets ie.revision when unchanged
+
+        :param ie: An inventory entry present in the commit.
+        :param parent_invs: The inventories of the parent revisions of the
+            commit.
+        :param path: The path the entry is at in the tree.
+        :param tree: The tree which contains this entry and should be used to 
+        obtain content.
+        """
+        assert self.new_inventory.root is not None or ie.parent_id is None
+        self.new_inventory.add(ie)
+
+        # ie.revision is always None if the InventoryEntry is considered
+        # for committing. ie.snapshot will record the correct revision 
+        # which may be the sole parent if it is untouched.
+        mutter('recording %s' % ie.file_id)
+        if ie.revision is not None:
+            return
+
+        # 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, "%\t\n"), ie.file_id)
+
+        previous_entries = ie.find_previous_heads(
+            parent_invs,
+            self.repository.weave_store,
+            self.repository.get_transaction())
+
+        # we are creating a new revision for ie in the history store
+        # and inventory.
+        ie.snapshot(self._new_revision_id, path, previous_entries, tree, self)
+
 
 def push_as_merged(target, source, revision_id):
     rev = source.repository.get_revision(revision_id)

=== modified file 'fetch.py'
--- a/fetch.py	2007-01-01 21:49:06 +0000
+++ b/fetch.py	2007-01-01 22:18:53 +0000
@@ -346,8 +346,9 @@
                     parent_inv = prev_inv
 
                 changes = self.source._log.get_revision_paths(revnum, branch)
+                renames = self.source.revision_fileid_renames(revid)
                 id_map = self.source.transform_fileid_map(self.source.uuid, 
-                                            revnum, branch, changes)
+                                            revnum, branch, changes, renames)
 
                 editor = RevisionBuildEditor(self.source, self.target, branch, 
                                              parent_inv, revid, 

=== modified file 'fileids.py'
--- a/fileids.py	2006-12-30 17:43:09 +0000
+++ b/fileids.py	2007-01-01 22:18:53 +0000
@@ -118,7 +118,7 @@
         return map
 
     def apply_changes(self, uuid, revnum, branch, global_changes, 
-                      find_children=None):
+                      renames, find_children=None):
         """Change file id map to incorporate specified changes.
 
         :param uuid: UUID of repository changes happen in
@@ -141,8 +141,10 @@
         return self._apply_changes(lambda x: generate_file_id(revid, x), 
                                    changes, get_children)
 
-    def get_map(self, uuid, revnum, branch):
+    def get_map(self, uuid, revnum, branch, renames_cb=None):
         """Make sure the map is up to date until revnum."""
+        if renames_cb is None:
+            renames_cb = lambda x: {}
         # First, find the last cached map
         todo = []
         next_parent_revs = []
@@ -178,9 +180,15 @@
                     yield self.repos.scheme.unprefix(p)[1]
 
             parent_revs = next_parent_revs
+
+            renames = renames_cb(revid)
+
+            def new_file_id(x):
+                if renames.has_key(x):
+                    return renames[x]
+                return generate_file_id(revid, x)
             
-            revmap = self._apply_changes(lambda x: generate_file_id(revid, x), 
-                                         changes, find_children)
+            revmap = self._apply_changes(new_file_id, changes, find_children)
             for p in changes:
                 if changes[p][0] == 'M':
                     revmap[p] = map[p][0]

=== modified file 'repository.py'
--- a/repository.py	2007-01-01 21:49:06 +0000
+++ b/repository.py	2007-01-01 22:18:53 +0000
@@ -21,10 +21,11 @@
                            NoSuchRevision, NotBranchError, 
                            UninitializableFormat)
 from bzrlib.graph import Graph
-from bzrlib.inventory import Inventory, ROOT_ID
+from bzrlib.inventory import Inventory
 from bzrlib.lockable_files import LockableFiles, TransportLock
 import bzrlib.osutils as osutils
 from bzrlib.repository import Repository, RepositoryFormat
+from bzrlib.revisiontree import RevisionTree
 from bzrlib.revision import Revision, NULL_REVISION
 from bzrlib.transport import Transport
 from bzrlib.trace import mutter
@@ -55,9 +56,9 @@
 SVN_REVPROP_BZR_SIGNATURE = 'bzr:gpg-signature'
 
 
-_unsafe = "%/-\t "
-def escape_svn_path(id):
-    r = [((c in _unsafe) and ('%%%02x' % ord(c)) or c)
+def escape_svn_path(id, unsafe="%/-\t \n"):
+    assert "%" in unsafe
+    r = [((c in unsafe) and ('%%%02x' % ord(c)) or c)
          for c in id]
     return ''.join(r)
 
@@ -255,10 +256,12 @@
         return self.revision_tree(revision_id).inventory
 
     def get_fileid_map(self, revnum, path):
-        return self.fileid_map.get_map(self.uuid, revnum, path)
+        return self.fileid_map.get_map(self.uuid, revnum, path,
+                                       self.revision_fileid_renames)
 
-    def transform_fileid_map(self, uuid, revnum, branch, changes):
-        return self.fileid_map.apply_changes(uuid, revnum, branch, changes)
+    def transform_fileid_map(self, uuid, revnum, branch, changes, renames):
+        return self.fileid_map.apply_changes(uuid, revnum, branch, changes, 
+                                             renames)
 
     def path_to_file_id(self, revnum, path):
         """Generate a bzr file id from a Subversion file name. 
@@ -270,6 +273,10 @@
         assert isinstance(revnum, int) and revnum >= 0
         assert isinstance(path, basestring)
 
+        if revnum == 0:
+            from fileids import generate_svn_file_id
+            return (generate_svn_file_id(self.uuid, 0, "", ""), NULL_REVISION)
+
         (bp, rp) = self.scheme.unprefix(path)
 
         try:
@@ -341,10 +348,18 @@
             revision_id = NULL_REVISION
 
         if revision_id == NULL_REVISION:
-            inventory = Inventory(ROOT_ID)
+            inventory = Inventory()
+            inventory.revision_id = revision_id
+            return RevisionTree(self, inventory, revision_id)
 
         return SvnRevisionTree(self, revision_id, inventory)
 
+    def revision_fileid_renames(self, revid):
+        (path, revnum) = self.parse_revision_id(revid)
+        items = self.branchprop_list.get_property_diff(path, revnum, 
+                                  SVN_PROP_BZR_FILEIDS).splitlines()
+        return dict(map(lambda x: x.split("\t"), items))
+
     def _mainline_revision_parent(self, path, revnum):
         assert isinstance(path, basestring)
         assert isinstance(revnum, int)

=== modified file 'tests/test_commit.py'
--- a/tests/test_commit.py	2007-01-01 21:49:06 +0000
+++ b/tests/test_commit.py	2007-01-01 22:18:53 +0000
@@ -159,7 +159,7 @@
         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.assertEqual("file\t%s\n" % wt.inventory.path2id("file"), 
                 self.client_get_prop(self.repos_url, "bzr:file-ids", 1))
 
     def test_commit_fileids_added(self):

=== modified file 'tests/test_fileids.py'
--- a/tests/test_fileids.py	2007-01-01 21:49:06 +0000
+++ b/tests/test_fileids.py	2007-01-01 22:18:53 +0000
@@ -214,7 +214,8 @@
                  ("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])
+        self.assertEqual("svn-v%d:1 at uuid-" % MAPPING_VERSION, map["foo"][1])
+        self.assertEqual("svn-v%d:1 at uuid-" % MAPPING_VERSION, map["foo/bla"][1])
 
     def test_usemap(self):
         map = self.apply_mappings(




More information about the bazaar-commits mailing list