Rev 481: Store bzr revnum in revision-id-vX property, should make revid-to-revno lookups a lot cheaper (and not scale by the size of history). in file:///home/jelmer/bzr-svn/0.4/

Jelmer Vernooij jelmer at samba.org
Sun Jun 17 17:11:18 BST 2007


------------------------------------------------------------
revno: 481
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: 0.4
timestamp: Sun 2007-06-17 18:10:27 +0200
message:
  Store bzr revnum in revision-id-vX property, should make revid-to-revno lookups a lot cheaper (and not scale by the size of history).
modified:
  TODO
  branch.py
  checkout.py
  commit.py
  errors.py
  mapping.txt
  repository.py
  tests/test_branch.py
  tests/test_commit.py
  tests/test_errors.py
  tests/test_push.py
  tests/test_repos.py
=== modified file 'TODO'
--- a/TODO	2007-05-30 18:10:08 +0000
+++ b/TODO	2007-06-17 16:10:27 +0000
@@ -19,3 +19,4 @@
 - more blackbox tests
 - split fetch tests out of test_repos
 - what happened to WorkingTree.add() ?
+- integrate bzr:merge into bzr:revision-info or rename to bzr:merge-vXX ?

=== modified file 'branch.py'
--- a/branch.py	2007-06-17 11:40:28 +0000
+++ b/branch.py	2007-06-17 16:10:27 +0000
@@ -159,6 +159,9 @@
         last_revid = self.last_revision()
         return self.revision_id_to_revno(last_revid), last_revid
 
+    def revno(self):
+        return self.last_revision_info()[0]
+
     def revision_id_to_revno(self, revision_id):
         if revision_id is None:
             return 0

=== modified file 'checkout.py'
--- a/checkout.py	2007-06-16 23:43:38 +0000
+++ b/checkout.py	2007-06-17 16:10:27 +0000
@@ -428,7 +428,7 @@
 
         self.client_ctx.log_msg_baton2 = log_message_func
         if rev_id is not None:
-            extra = "%s\n" % rev_id
+            extra = "%d %s\n" % (self.branch.revno()+1, rev_id)
         else:
             extra = ""
         wc = self._get_wc(write_lock=True)

=== modified file 'commit.py'
--- a/commit.py	2007-06-01 13:30:34 +0000
+++ b/commit.py	2007-06-17 16:10:27 +0000
@@ -89,7 +89,8 @@
                 self._svnprops[SVN_PROP_SVK_MERGE] = old + new
 
         if revision_id is not None:
-            if branch.last_revision():
+            (previous_revno, previous_revid) = branch.last_revision_info()
+            if previous_revid is not None:
                 (bp, revnum) = repository.lookup_revision_id(branch.last_revision())
                 old = repository.branchprop_list.get_property(bp, revnum, 
                             SVN_PROP_BZR_REVISION_ID, "")
@@ -97,7 +98,7 @@
                 old = ""
 
             self._svnprops[SVN_PROP_BZR_REVISION_ID] = old + \
-                    "%s\n" % revision_id
+                    "%d %s\n" % (previous_revno+1, revision_id)
 
         # At least one of the parents has to be the last revision on the 
         # mainline in # Subversion.

=== modified file 'errors.py'
--- a/errors.py	2007-06-15 19:58:45 +0000
+++ b/errors.py	2007-06-17 16:10:27 +0000
@@ -65,3 +65,12 @@
 class LocalCommitsUnsupported(BzrError):
 
     _fmt = 'Local commits are not supported for lightweight Subversion checkouts.'
+
+
+class InvalidPropertyValue(BzrError):
+    _fmt = 'Invalid property value for Subversion property %(property)s: %(msg)s'
+
+    def __init__(self, property, msg):
+        BzrError.__init__(self)
+        self.property = property
+        self.msg = msg

=== modified file 'mapping.txt'
--- a/mapping.txt	2007-05-18 15:11:30 +0000
+++ b/mapping.txt	2007-06-17 16:10:27 +0000
@@ -76,9 +76,9 @@
 
 bzr:revision-id-v%d (where %d is the current mapping version) 
 
-to the revision id. This property should only be honored for the revision 
-in which it was set, as subversion will not erase the property 
-for subsequent commits.
+to the bzr revision number following by a space and the revision id. This o
+property should only be honored for the revision in which it was set, as 
+subversion will not erase the property for subsequent commits.
 
 A (path,revnum) tuple is valid if:
 * path is valid according to the branching scheme

=== modified file 'repository.py'
--- a/repository.py	2007-06-16 23:43:38 +0000
+++ b/repository.py	2007-06-17 16:10:27 +0000
@@ -51,6 +51,20 @@
 SVN_REVPROP_BZR_SIGNATURE = 'bzr:gpg-signature'
 SVN_PROP_BZR_REVISION_ID = 'bzr:revision-id-v%d' % MAPPING_VERSION
 
+def parse_revid_property(line):
+    """Parse a (revnum, revid) tuple as set in revision id properties.
+    :param line: line to parse
+    :return: tuple with (bzr_revno, revid)
+    """
+    assert not '\n' in line
+    try:
+        (revno, revid) = line.split(' ', 1)
+    except ValueError:
+        raise errors.InvalidPropertyValue(SVN_PROP_BZR_REVISION_ID, 
+                "missing space")
+    return (int(revno), revid)
+
+
 def parse_revision_metadata(text, rev):
     """Parse a revision info text (as set in bzr:revision-info).
 
@@ -62,7 +76,8 @@
         try:
             key, value = l.split(": ", 2)
         except ValueError:
-            raise BzrError("Missing : in revision metadata")
+            raise errors.InvalidPropertyValue(SVN_PROP_BZR_REVISION_INFO, 
+                    "Missing : in revision metadata")
         if key == "committer":
             rev.committer = str(value)
         elif key == "timestamp":
@@ -72,7 +87,8 @@
         elif key[0] == "\t" and in_properties:
             rev.properties[str(key[1:])] = str(value)
         else:
-            raise BzrError("Invalid key %r" % key)
+            raise errors.InvalidPropertyValue(SVN_PROP_BZR_REVISION_INFO, 
+                    "Invalid key %r" % key)
 
 
 def generate_revision_metadata(timestamp, timezone, committer, revprops):
@@ -408,11 +424,13 @@
             return revid
 
         # Lookup the revision from the bzr:revision-id-vX property
-        revid = self.branchprop_list.get_property_diff(path, revnum, 
+        line = self.branchprop_list.get_property_diff(path, revnum, 
                 SVN_PROP_BZR_REVISION_ID).strip("\n")
         # Or generate it
-        if revid == "":
+        if line == "":
             revid = generate_svn_revision_id(self.uuid, revnum, path)
+        else:
+            (bzr_revno, revid) = parse_revid_property(line)
 
         self.revmap.insert_revid(revid, path, revnum, revnum, "undefined")
 
@@ -450,13 +468,14 @@
             # If there is no entry in the map, walk over all branches:
             for (branch, revno, exists) in self.find_branches():
                 # Look at their bzr:revision-id-vX
-                revids = self.branchprop_list.get_property(branch, revno, 
-                        SVN_PROP_BZR_REVISION_ID, "").splitlines()
+                revids = map(parse_revid_property, 
+                        self.branchprop_list.get_property(branch, revno, 
+                        SVN_PROP_BZR_REVISION_ID, "").splitlines())
 
                 # If there are any new entries that are not yet in the cache, 
                 # add them
-                for r in revids:
-                    self.revmap.insert_revid(r, branch, 0, revno, 
+                for (entry_revno, entry_revid) in revids:
+                    self.revmap.insert_revid(entry_revid, branch, 0, revno, 
                             "undefined")
 
                 if revid in revids:
@@ -469,7 +488,10 @@
         # added revid
         i = min_revnum
         for (bp, rev) in self.follow_branch(branch_path, max_revnum):
-            if self.branchprop_list.get_property_diff(bp, rev, SVN_PROP_BZR_REVISION_ID).strip("\n") == revid:
+            (entry_revno, entry_revid) = parse_revid_property(
+                 self.branchprop_list.get_property_diff(bp, rev, 
+                     SVN_PROP_BZR_REVISION_ID).strip("\n"))
+            if entry_revid == revid:
                 self.revmap.insert_revid(revid, bp, rev, rev, scheme)
                 return (bp, rev)
 

=== modified file 'tests/test_branch.py'
--- a/tests/test_branch.py	2007-06-17 11:40:28 +0000
+++ b/tests/test_branch.py	2007-06-17 16:10:27 +0000
@@ -148,11 +148,12 @@
         repos_url = self.make_client('a', 'dc')
 
         branch = Branch.open("svn+"+repos_url)
-        self.assertEqual([branch.generate_revision_id(0)], branch.revision_history())
+        self.assertEqual([branch.generate_revision_id(0)], 
+                branch.revision_history())
 
         self.build_tree({'dc/foo': "data"})
         self.client_add("dc/foo")
-        self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID, "mycommit\n")
+        self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID, "42 mycommit\n")
         self.client_commit("dc", "My Message")
         
         branch = Branch.open("svn+"+repos_url)
@@ -192,7 +193,7 @@
         self.build_tree({'dc/foo': "data"})
         self.client_add("dc/foo")
         self.client_set_prop("dc", "bzr:revision-id-v%d" % MAPPING_VERSION, 
-                            "myrevid\n")
+                            "2 myrevid\n")
         self.client_commit("dc", "My Message")
         branch = Branch.open(repos_url)
         self.assertEquals(2, branch.revision_id_to_revno("myrevid"))
@@ -202,11 +203,11 @@
         self.build_tree({'dc/foo': "data"})
         self.client_add("dc/foo")
         self.client_set_prop("dc", "bzr:revision-id-v%d" % MAPPING_VERSION, 
-                            "myrevid\n")
+                            "2 myrevid\n")
         self.client_commit("dc", "My Message")
         self.build_tree({'dc/foo': "someotherdata"})
         self.client_set_prop("dc", "bzr:revision-id-v%d" % MAPPING_VERSION, 
-                            "myrevid\nmysecondrevid\n")
+                            "2 myrevid\n3 mysecondrevid\n")
         self.client_commit("dc", "My Message")
         branch = Branch.open(repos_url)
         self.assertEquals(3, branch.revision_id_to_revno("mysecondrevid"))

=== modified file 'tests/test_commit.py'
--- a/tests/test_commit.py	2007-05-18 18:01:27 +0000
+++ b/tests/test_commit.py	2007-06-17 16:10:27 +0000
@@ -145,7 +145,7 @@
         builder.finish_inventory()
         builder.commit("foo")
 
-        self.assertEqual("my-revision-id\n", 
+        self.assertEqual("3 my-revision-id\n", 
                 self.client_get_prop("dc", "bzr:revision-id-v%d" % MAPPING_VERSION, 2))
 
     def test_commit_metadata(self):
@@ -167,7 +167,7 @@
         builder.finish_inventory()
         builder.commit("foo")
 
-        self.assertEqual("my-revision-id\n", 
+        self.assertEqual("3 my-revision-id\n", 
                 self.client_get_prop("dc", "bzr:revision-id-v%d" % MAPPING_VERSION, 2))
 
         self.assertEqual("timestamp: Thu 1970-01-01 01:15:36.000000000 +0000\ncommitter: fry\n", 

=== modified file 'tests/test_errors.py'
--- a/tests/test_errors.py	2007-06-15 19:58:45 +0000
+++ b/tests/test_errors.py	2007-06-17 16:10:27 +0000
@@ -17,7 +17,7 @@
 from bzrlib.errors import ConnectionReset, LockError, PermissionDenied
 from bzrlib.tests import TestCase
 
-from errors import convert_svn_error, convert_error
+from errors import convert_svn_error, convert_error, InvalidPropertyValue
 
 import svn.core
 from svn.core import SubversionException
@@ -56,3 +56,9 @@
             return foo+1
         self.assertEqual(2, test_nothrow(1))
 
+    def test_invalid_property_value(self):
+        error = InvalidPropertyValue("svn:foobar", "corrupt")
+
+        self.assertEqual(
+          "Invalid property value for Subversion property svn:foobar: corrupt", 
+          str(error))

=== modified file 'tests/test_push.py'
--- a/tests/test_push.py	2007-05-27 19:36:59 +0000
+++ b/tests/test_push.py	2007-06-17 16:10:27 +0000
@@ -182,7 +182,7 @@
         self.svndir.open_branch().pull(self.bzrdir.open_branch())
 
         self.client_update("sc")
-        self.assertEqual("some-rid\n", 
+        self.assertEqual("3 some-rid\n", 
                 self.client_get_prop("sc", SVN_PROP_BZR_REVISION_ID))
 
     def test_commit_check_rev_equal(self):

=== modified file 'tests/test_repos.py'
--- a/tests/test_repos.py	2007-06-16 23:43:38 +0000
+++ b/tests/test_repos.py	2007-06-17 16:10:27 +0000
@@ -29,6 +29,7 @@
 import svn.fs
 
 from convert import load_dumpfile
+from errors import InvalidPropertyValue
 from fileids import generate_svn_file_id, generate_file_id
 import format
 from scheme import TrunkBranchingScheme, NoBranchingScheme
@@ -37,7 +38,8 @@
 from tests.test_fileids import MockRepo
 from repository import (svk_feature_to_revision_id, revision_id_to_svk_feature,
                         SvnRepositoryFormat, SVN_PROP_BZR_REVISION_ID,
-                        generate_revision_metadata, parse_revision_metadata)
+                        generate_revision_metadata, parse_revision_metadata,
+                        parse_revid_property)
 from revids import (MAPPING_VERSION, escape_svn_path, unescape_svn_path,
                     parse_svn_revision_id, generate_svn_revision_id)
 
@@ -86,7 +88,7 @@
 
     def test_generate_revision_id_forced_revid(self):
         repos_url = self.make_client("a", "dc")
-        self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID, "someid\n")
+        self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID, "2 someid\n")
         self.client_commit("dc", "set id")
         repos = Repository.open(repos_url)
         revid = repos.generate_revision_id(1, "")
@@ -402,7 +404,8 @@
     def test_get_revision(self):
         repos_url = self.make_client('d', 'dc')
         repository = Repository.open("svn+%s" % repos_url)
-        self.assertRaises(NoSuchRevision, repository.get_revision, "nonexisting")
+        self.assertRaises(NoSuchRevision, repository.get_revision, 
+                "nonexisting")
         self.build_tree({'dc/foo': "data"})
         self.client_add("dc/foo")
         self.client_commit("dc", "My Message")
@@ -413,7 +416,8 @@
             repository.generate_revision_id(2, ""))
         self.assertEqual([repository.generate_revision_id(1, "")],
                 rev.parent_ids)
-        self.assertEqual(rev.revision_id, repository.generate_revision_id(2, ""))
+        self.assertEqual(rev.revision_id, 
+                repository.generate_revision_id(2, ""))
         self.assertEqual(author, rev.committer)
         self.assertIsInstance(rev.properties, dict)
 
@@ -426,7 +430,7 @@
         self.client_commit("dc", "My Message")
         self.build_tree({'dc/foo': "data2"})
         self.client_set_prop("dc", "bzr:revision-id-v%d" % MAPPING_VERSION, 
-                            "myrevid\n")
+                            "3 myrevid\n")
         (num, date, author) = self.client_commit("dc", "Second Message")
         repository = Repository.open("svn+%s" % repos_url)
         revid = generate_svn_revision_id(repository.uuid, 2, "")
@@ -608,7 +612,8 @@
     def test_get_inventory(self):
         repos_url = self.make_client('d', 'dc')
         repository = Repository.open("svn+%s" % repos_url)
-        self.assertRaises(NoSuchRevision, repository.get_inventory, "nonexisting")
+        self.assertRaises(NoSuchRevision, repository.get_inventory, 
+                "nonexisting")
         self.build_tree({'dc/foo': "data", 'dc/blah': "other data"})
         self.client_add("dc/foo")
         self.client_add("dc/blah")
@@ -666,7 +671,7 @@
         repos_url = self.make_client('d', 'dc')
         self.build_tree({'dc/bloe': None})
         self.client_add("dc/bloe")
-        self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID, "myid\n")
+        self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID, "2 myid\n")
         self.client_commit("dc", "foobar")
         repository = Repository.open("svn+%s" % repos_url)
         self.assertEqual(("", 1), repository.lookup_revision_id( 
@@ -680,7 +685,7 @@
         repos_url = self.make_client('d', 'dc')
         self.build_tree({'dc/bloe': None})
         self.client_add("dc/bloe")
-        self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID, "myid\n")
+        self.client_set_prop("dc", SVN_PROP_BZR_REVISION_ID, "2 myid\n")
         self.client_commit("dc", "foobar")
         repository = Repository.open("svn+%s" % repos_url)
         self.assertRaises(NoSuchRevision, 
@@ -2347,8 +2352,20 @@
 
     def test_parse_revision_metadata_no_colon(self):
         rev = Revision('someid')
-        self.assertRaises(BzrError, lambda: parse_revision_metadata("bla", rev))
+        self.assertRaises(InvalidPropertyValue, 
+                lambda: parse_revision_metadata("bla", rev))
 
     def test_parse_revision_metadata_invalid_name(self):
         rev = Revision('someid')
-        self.assertRaises(BzrError, lambda: parse_revision_metadata("bla: b", rev))
+        self.assertRaises(InvalidPropertyValue, 
+                lambda: parse_revision_metadata("bla: b", rev))
+
+    def test_parse_revid_property(self):
+        self.assertEquals((1, "bloe"), parse_revid_property("1 bloe"))
+
+    def test_parse_revid_property_space(self):
+        self.assertEquals((42, "bloe bla"), parse_revid_property("42 bloe bla"))
+
+    def test_parse_revid_property_invalid(self):
+        self.assertRaises(InvalidPropertyValue, 
+                lambda: parse_revid_property("blabla"))




More information about the bazaar-commits mailing list