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