Rev 440: True push works, with some limits. in file:///home/jelmer/bzr-svn/customrevids/

Jelmer Vernooij jelmer at samba.org
Fri May 18 13:22:58 BST 2007


At file:///home/jelmer/bzr-svn/customrevids/

------------------------------------------------------------
revno: 440
revision-id: jelmer at samba.org-20070518122257-v826cvviwuo5xq8b
parent: jelmer at samba.org-20070518110606-ghip0jetjq210xdg
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: customrevids
timestamp: Fri 2007-05-18 13:22:57 +0100
message:
  True push works, with some limits.
modified:
  BRANCH.TODO                    branch.todo-20070516183134-f9xjfbsv6x6u6x2t-1
  branch.py                      svnbranch.py-20051017135706-11c749eb0dab04a7
  commit.py                      commit.py-20060607190346-qvq128wgfubhhgm2-1
  repository.py                  repository.py-20060306123302-1f8c5069b3fe0265
  tests/test_commit.py           test_commit.py-20060624213521-l5kcufywkh9mnilk-1
  tests/test_push.py             test_push.py-20070201165715-g2ievcdfqi33wqsy-1
  tests/test_repos.py            test_repos.py-20060508151940-ddc49a59257ca712
  tree.py                        tree.py-20060624222557-dudlwqcmkf22lt2s-1
=== modified file 'BRANCH.TODO'
--- a/BRANCH.TODO	2007-05-18 02:01:15 +0000
+++ b/BRANCH.TODO	2007-05-18 12:22:57 +0000
@@ -1,3 +1,6 @@
-- keep revision ids when doing true pushes
 - add tests to make sure a revision is still 100% the same after being pushed 
   to subversion
+ still not kept:
+ - timestamp
+ - timezone
+ - committer

=== modified file 'branch.py'
--- a/branch.py	2007-05-17 19:04:30 +0000
+++ b/branch.py	2007-05-18 12:22:57 +0000
@@ -24,7 +24,7 @@
 
 import svn.client, svn.core
 
-from commit import push_as_merged
+from commit import push
 from repository import SvnRepository
 from transport import bzr_to_svn_url, svn_config
 
@@ -226,7 +226,7 @@
         else:
             for rev_id in self.missing_revisions(other, stop_revision):
                 mutter('pushing %r to Svn branch' % rev_id)
-                push_as_merged(self, other, rev_id)
+                push(self, other, rev_id)
 
     # The remote server handles all this for us
     def lock_write(self):

=== modified file 'commit.py'
--- a/commit.py	2007-05-18 11:06:06 +0000
+++ b/commit.py	2007-05-18 12:22:57 +0000
@@ -84,10 +84,15 @@
                 self._svnprops[SVN_PROP_SVK_MERGE] = old + new
 
         if revision_id is not None:
-            extra = "%s\n" % revision_id
-            if not self._svnprops.has_key(SVN_PROP_BZR_REVISION_ID):
-                self._svnprops[SVN_PROP_BZR_REVISION_ID] = ""
-            self._svnprops[SVN_PROP_BZR_REVISION_ID] += extra
+            if branch.last_revision():
+                (bp, revnum) = repository.lookup_revision_id(branch.last_revision())
+                old = repository.branchprop_list.get_property(bp, revnum, 
+                            SVN_PROP_BZR_REVISION_ID, "")
+            else:
+                old = ""
+
+            self._svnprops[SVN_PROP_BZR_REVISION_ID] = old + \
+                    "%s\n" % revision_id
 
         # At least one of the parents has to be the last revision on the 
         # mainline in # Subversion.
@@ -384,6 +389,28 @@
         ie.snapshot(self._new_revision_id, path, previous_entries, tree, self)
 
 
+def replay_delta(builder, delta, old_tree):
+    for (_, ie) in builder.new_inventory.entries():
+        if not delta.touches_file_id(ie.file_id):
+            continue
+
+        id = ie.file_id
+        while builder.new_inventory[id].parent_id is not None:
+            if builder.new_inventory[id].revision is None:
+                break
+            builder.new_inventory[id].revision = None
+            if builder.new_inventory[id].kind == 'directory':
+                builder.modified_directory(id, [])
+            id = builder.new_inventory[id].parent_id
+
+        if ie.kind == 'link':
+            builder.modified_link(ie.file_id, [], ie.symlink_target)
+        elif ie.kind == 'file':
+            def get_text():
+                return old_tree.get_file_text(ie.file_id)
+            builder.modified_file_text(ie.file_id, [], get_text)
+
+
 def push_as_merged(target, source, revision_id):
     """Push a revision as merged revision.
 
@@ -422,27 +449,46 @@
                          
     delta = new_tree.changes_from(old_tree)
     builder.new_inventory = inv
-
-    for (_, ie) in inv.entries():
-        if not delta.touches_file_id(ie.file_id):
-            continue
-
-        id = ie.file_id
-        while inv[id].parent_id is not None:
-            if inv[id].revision is None:
-                break
-            inv[id].revision = None
-            if inv[id].kind == 'directory':
-                builder.modified_directory(id, [])
-            id = inv[id].parent_id
-
-        if ie.kind == 'link':
-            builder.modified_link(ie.file_id, [], ie.symlink_target)
-        elif ie.kind == 'file':
-            def get_text():
-                return old_tree.get_file_text(ie.file_id)
-            builder.modified_file_text(ie.file_id, [], get_text)
-
+    replay_delta(builder, delta, old_tree)
+
+    try:
+        return builder.commit(rev.message)
+    except SubversionException, (_, num):
+        if num == svn.core.SVN_ERR_FS_TXN_OUT_OF_DATE:
+            raise DivergedBranches(source, target)
+        raise
+
+def push(target, source, revision_id):
+    """Push a revision into Subversion.
+
+    This will do a new commit in the target branch.
+
+    :param target: Repository to push to
+    :param source: Repository to pull the revision from
+    :param revision_id: Revision id of the revision to push
+    """
+    assert isinstance(source, Branch)
+    rev = source.repository.get_revision(revision_id)
+    inv = source.repository.get_inventory(revision_id)
+
+    # revision on top of which to commit
+    assert target.last_revision() in rev.parent_ids
+
+    mutter('pushing %r' % (revision_id))
+
+    old_tree = source.repository.revision_tree(revision_id)
+    new_tree = source.repository.revision_tree(target.last_revision())
+
+    builder = SvnCommitBuilder(target.repository, target, 
+                               rev.parent_ids,
+                               target.get_config(),
+                               rev.properties, 
+                               revision_id,
+                               new_tree.inventory)
+                         
+    delta = new_tree.changes_from(old_tree)
+    builder.new_inventory = inv
+    replay_delta(builder, delta, old_tree)
     try:
         return builder.commit(rev.message)
     except SubversionException, (_, num):

=== modified file 'repository.py'
--- a/repository.py	2007-05-18 02:01:15 +0000
+++ b/repository.py	2007-05-18 12:22:57 +0000
@@ -205,7 +205,7 @@
 
         (path, revnum) = self.lookup_revision_id(revision_id)
 
-        ancestry = []
+        ancestry = [revision_id]
 
         for l in self.branchprop_list.get_property(path, revnum, 
                                     SVN_PROP_BZR_MERGE, "").splitlines():

=== modified file 'tests/test_commit.py'
--- a/tests/test_commit.py	2007-05-18 01:46:26 +0000
+++ b/tests/test_commit.py	2007-05-18 12:22:57 +0000
@@ -224,11 +224,13 @@
 
         repos = self.olddir.find_repository()
         inv = repos.get_inventory(repos.generate_revision_id(2, ""))
+        import pdb
+        pdb.set_trace()
         self.assertEqual(repos.generate_revision_id(2, ""),
                          inv[inv.path2id('foo/bla')].revision)
         self.assertTrue(wt.branch.last_revision() in 
           repos.revision_parents(repos.generate_revision_id(2, "")))
-        self.assertEqual(repos.generate_revision_id(2, ""),
+        self.assertEqual(wt.branch.last_revision(),
                         self.olddir.open_branch().last_revision())
         self.assertEqual("other data", 
             repos.revision_tree(repos.generate_revision_id(2, "")).get_file_text( inv.path2id("foo/bla")))
@@ -244,9 +246,8 @@
         repos = self.olddir.find_repository()
         inv = repos.get_inventory(repos.generate_revision_id(2, ""))
         self.assertTrue(inv.has_filename('file'))
-        self.assertTrue(wt.branch.last_revision() in 
-            repos.revision_parents(
-                repos.generate_revision_id(2, "")))
+        self.assertEqual(wt.branch.last_revision(), 
+                repos.generate_revision_id(2, ""))
         self.assertEqual(repos.generate_revision_id(2, ""),
                         self.olddir.open_branch().last_revision())
 
@@ -261,8 +262,9 @@
         repos = self.olddir.find_repository()
         inv = repos.get_inventory(repos.generate_revision_id(2, ""))
         self.assertTrue(inv.has_filename('file'))
-        self.assertTrue(wt.branch.last_revision() in 
-                         repos.revision_parents(repos.generate_revision_id(2, "")))
+        self.assertEquals(wt.branch.last_revision(), 
+                         repos.generate_revision_id(2, ""))
+
         self.assertEqual(repos.generate_revision_id(2, ""),
                         self.olddir.open_branch().last_revision())
 
@@ -296,34 +298,6 @@
             repos.get_revision(repos.generate_revision_id(2, "")).message.decode("utf-8"))
 
 
-    def test_multiple(self):
-        self.build_tree({'dc/file': 'data'})
-        wt = self.newdir.open_workingtree()
-        wt.add('file')
-        wt.commit(message="Commit from Bzr")
-
-        self.build_tree({'dc/file': 'data2', 'dc/adir': None})
-        wt.add('adir')
-        wt.commit(message="Another commit from Bzr")
-
-        self.olddir.open_branch().pull(self.newdir.open_branch())
-
-        repos = self.olddir.find_repository()
-
-        self.assertEqual(repos.generate_revision_id(3, ""), 
-                        self.olddir.open_branch().last_revision())
-
-        inv = repos.get_inventory(repos.generate_revision_id(2, ""))
-        self.assertTrue(inv.has_filename('file'))
-        self.assertFalse(inv.has_filename('adir'))
-
-        inv = repos.get_inventory(repos.generate_revision_id(3, ""))
-        self.assertTrue(inv.has_filename('file'))
-        self.assertTrue(inv.has_filename('adir'))
-
-        self.assertTrue(wt.branch.last_revision() in 
-             repos.get_ancestry(repos.generate_revision_id(3, "")))
-
 class TestPushNested(TestCaseWithSubversionRepository):
     def setUp(self):
         super(TestPushNested, self).setUp()

=== modified file 'tests/test_push.py'
--- a/tests/test_push.py	2007-05-18 11:06:06 +0000
+++ b/tests/test_push.py	2007-05-18 12:22:57 +0000
@@ -211,6 +211,10 @@
 
         self.assertEqual(self.svndir.open_branch().revision_history(),
                          self.bzrdir.open_branch().revision_history())
-        self.assertTrue(wt.branch.last_revision() in 
-             repos.get_ancestry(repos.generate_revision_id(3, "")))
+
+        self.assertEqual(wt.branch.last_revision(), 
+                repos.generate_revision_id(3, ""))
+        self.assertEqual(
+                wt.branch.repository.get_ancestry(wt.branch.last_revision()), 
+                repos.get_ancestry(wt.branch.last_revision()))
 

=== modified file 'tests/test_repos.py'
--- a/tests/test_repos.py	2007-05-18 01:46:26 +0000
+++ b/tests/test_repos.py	2007-05-18 12:22:57 +0000
@@ -456,19 +456,22 @@
         self.assertEqual([None, 
             repository.generate_revision_id(0, ""),
             repository.generate_revision_id(1, ""),
+            repository.generate_revision_id(2, ""),
+            repository.generate_revision_id(3, "")],
+                repository.get_ancestry(
+                    repository.generate_revision_id(3, "")))
+        self.assertEqual([None, 
+            repository.generate_revision_id(0, ""),
+            repository.generate_revision_id(1, ""),
             repository.generate_revision_id(2, "")],
                 repository.get_ancestry(
-                    repository.generate_revision_id(3, "")))
-        self.assertEqual([None, 
-            repository.generate_revision_id(0, ""),
-            repository.generate_revision_id(1, "")],
-                repository.get_ancestry(
                     repository.generate_revision_id(2, "")))
         self.assertEqual([None,
-                    repository.generate_revision_id(0, "")],
+                    repository.generate_revision_id(0, ""),
+                    repository.generate_revision_id(1, "")],
                 repository.get_ancestry(
                     repository.generate_revision_id(1, "")))
-        self.assertEqual([None],
+        self.assertEqual([None, repository.generate_revision_id(0, "")],
                 repository.get_ancestry(
                     repository.generate_revision_id(0, "")))
         self.assertEqual([None], repository.get_ancestry(None))
@@ -558,15 +561,17 @@
         self.build_tree({'dc/foo': "data2"})
         self.client_commit("dc", "Second Message")
         repository = Repository.open("svn+%s" % repos_url)
-        self.assertEqual([None],
+        self.assertEqual([None, repository.generate_revision_id(0, "")],
                 repository.get_ancestry(
                     repository.generate_revision_id(0, "")))
-        self.assertEqual([None, repository.generate_revision_id(0, "")],
+        self.assertEqual([None, repository.generate_revision_id(0, ""),
+            repository.generate_revision_id(1, "")],
                 repository.get_ancestry(
                     repository.generate_revision_id(1, "")))
         self.assertEqual([None, 
             repository.generate_revision_id(0, ""),
-            repository.generate_revision_id(1, "")], 
+            repository.generate_revision_id(1, ""),
+            repository.generate_revision_id(2, "")], 
                 repository.get_ancestry(
                     repository.generate_revision_id(2, "")))
 
@@ -579,16 +584,17 @@
         self.build_tree({'dc/foo': "data2"})
         self.client_commit("dc", "Second Message")
         repository = Repository.open("svn+%s" % repos_url)
-        self.assertEqual([None],
+        self.assertEqual([None, repository.generate_revision_id(0, "")],
                 repository.get_ancestry(
                     repository.generate_revision_id(0, "")))
-        self.assertEqual([None, repository.generate_revision_id(0, "")],
+        self.assertEqual([None, repository.generate_revision_id(0, ""),
+            repository.generate_revision_id(1, "")],
                 repository.get_ancestry(
                     repository.generate_revision_id(1, "")))
         self.assertEqual([None, 
             repository.generate_revision_id(0, ""),
             repository.generate_revision_id(1, ""), 
-                          "a-parent"], 
+                          "a-parent", repository.generate_revision_id(2, "")], 
                 repository.get_ancestry(
                     repository.generate_revision_id(2, "")))
 

=== modified file 'tree.py'
--- a/tree.py	2007-05-17 19:04:30 +0000
+++ b/tree.py	2007-05-18 12:22:57 +0000
@@ -98,7 +98,7 @@
     def change_dir_prop(self, id, name, value, pool):
         from repository import (SVN_PROP_BZR_MERGE, SVN_PROP_SVK_MERGE, 
                         SVN_PROP_BZR_PREFIX, SVN_PROP_BZR_REVPROP_PREFIX, 
-                        SVN_PROP_BZR_FILEIDS)
+                        SVN_PROP_BZR_FILEIDS, SVN_PROP_BZR_REVISION_ID)
 
         if name == svn.core.SVN_PROP_ENTRY_COMMITTED_REV:
             self.dir_revnum[id] = int(value)
@@ -122,6 +122,8 @@
             pass
         elif name.startswith(SVN_PROP_BZR_REVPROP_PREFIX):
             pass
+        elif name == SVN_PROP_BZR_REVISION_ID:
+            pass
         elif (name.startswith(svn.core.SVN_PROP_PREFIX) or
               name.startswith(SVN_PROP_BZR_PREFIX)):
             mutter('unsupported dir property %r' % name)




More information about the bazaar-commits mailing list