Support commits in heavy checkouts.
authorJelmer Vernooij <jelmer@samba.org>
Fri, 18 May 2007 18:01:27 +0000 (19:01 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Fri, 18 May 2007 18:01:27 +0000 (19:01 +0100)
NEWS
__init__.py
commit.py
fetch.py
format.py
tests/test_commit.py

diff --git a/NEWS b/NEWS
index ea0852f5a4f8f9352b89c8da9045a23860bdf441..a3f3852e3ec20917a18ad986d68f7bbc55da87c5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,10 @@ bzr-svn 0.4  UNRELEASED
    * Remove branches when they are being replaced. Fixes DivergedBranches 
      error when using svn-import (#81908).
 
+   * Support true push (#80612).
+
+   * Support commits in heavy checkouts (#79330).
+
   IMPROVEMENTS
 
   PERFORMANCE
index e136b5d3833b72537c5012248b727c569d095bb0..3f0280823db94b1d8394c81ad49d6badfad1d99a 100644 (file)
@@ -97,7 +97,8 @@ from bzrlib.bzrdir import BzrDirFormat
 
 from bzrlib.repository import InterRepository
 
-from fetch import InterSvnRepository
+from fetch import InterFromSvnRepository
+from commit import InterToSvnRepository
 
 BzrDirFormat.register_control_format(format.SvnFormat)
 
@@ -106,7 +107,8 @@ _subr_version = svn.core.svn_subr_version()
 
 BzrDirFormat.register_control_format(checkout.SvnWorkingTreeDirFormat)
 
-InterRepository.register_optimiser(InterSvnRepository)
+InterRepository.register_optimiser(InterFromSvnRepository)
+InterRepository.register_optimiser(InterToSvnRepository)
 
 from bzrlib.branch import Branch
 from bzrlib.commands import Command, register_command, display_command, Option
index cc9c7075808c5300779b4f9aaa148036aaf1389e..f2fc88cb745bab66fe632c082b57d99cfe89804b 100644 (file)
--- a/commit.py
+++ b/commit.py
@@ -22,13 +22,15 @@ from bzrlib.branch import Branch
 from bzrlib.errors import InvalidRevisionId, DivergedBranches
 from bzrlib.inventory import Inventory
 import bzrlib.osutils as osutils
-from bzrlib.repository import RootCommitBuilder
+from bzrlib.repository import RootCommitBuilder, InterRepository
+from bzrlib.revision import NULL_REVISION
 from bzrlib.trace import mutter
 
 from repository import (SVN_PROP_BZR_MERGE, SVN_PROP_BZR_FILEIDS,
                         SVN_PROP_SVK_MERGE, SVN_PROP_BZR_REVISION_INFO, 
                         SVN_PROP_BZR_REVISION_ID, revision_id_to_svk_feature,
-                        generate_revision_metadata)
+                        generate_revision_metadata, SvnRepositoryFormat, 
+                        SvnRepository)
 from revids import escape_svn_path
 
 import os
@@ -505,3 +507,63 @@ def push(target, source, revision_id):
             raise DivergedBranches(source, target)
         raise
 
+class InterToSvnRepository(InterRepository):
+    """Any to Subversion repository actions."""
+
+    _matching_repo_format = SvnRepositoryFormat()
+
+    @staticmethod
+    def _get_repo_format_to_test():
+        return None
+
+    def copy_content(self, revision_id=None, basis=None, pb=None):
+        """See InterRepository.copy_content."""
+        assert revision_id is not None, "fetching all revisions not supported"
+        # Go back over the LHS parent until we reach a revid we know
+        todo = []
+        while not self.target.has_revision(revision_id):
+            todo.append(revision_id)
+            revision_id = self.source.revision_parents(revision_id)[0]
+            if revision_id == NULL_REVISION:
+                raise "Unrelated repositories."
+        todo.reverse()
+        mutter("pushing %r into svn" % todo)
+        while len(todo) > 0:
+            revision_id = todo.pop()
+
+            rev = self.source.get_revision(revision_id)
+            inv = self.source.get_inventory(revision_id)
+
+            mutter('pushing %r' % (revision_id))
+
+            old_tree = self.source.revision_tree(revision_id)
+            parent_revid = self.source.revision_parents(revision_id)[0]
+            new_tree = self.source.revision_tree(parent_revid)
+
+            (bp, _) = self.target.lookup_revision_id(parent_revid)
+            target_branch = Branch.open("%s/%s" % (self.target.base, bp))
+
+            builder = SvnCommitBuilder(self.target, target_branch, 
+                               rev.parent_ids,
+                               target_branch.get_config(),
+                               rev.timestamp,
+                               rev.timezone,
+                               rev.committer,
+                               rev.properties, 
+                               revision_id,
+                               new_tree.inventory)
+                         
+            delta = new_tree.changes_from(old_tree)
+            builder.new_inventory = inv
+            replay_delta(builder, delta, old_tree)
+            builder.commit(rev.message)
+
+    def fetch(self, revision_id=None, pb=None):
+        """Fetch revisions. """
+        self.copy_content(revision_id=revision_id, pb=pb)
+
+    @staticmethod
+    def is_compatible(source, target):
+        """Be compatible with SvnRepository."""
+        return isinstance(target, SvnRepository)
index 32b4fea06e0f19f141bbfcdeef0f3cc2ee099c80..929a79d3dd4a64aacda84679e73c17cdce0f1202 100644 (file)
--- a/fetch.py
+++ b/fetch.py
@@ -314,7 +314,7 @@ class RevisionBuildEditor(svn.delta.Editor):
                                      self.file_stream, self.pool)
 
 
-class InterSvnRepository(InterRepository):
+class InterFromSvnRepository(InterRepository):
     """Svn to any repository actions."""
 
     _matching_repo_format = SvnRepositoryFormat()
@@ -467,6 +467,7 @@ class InterSvnRepository(InterRepository):
     @staticmethod
     def is_compatible(source, target):
         """Be compatible with SvnRepository."""
+        mutter("Checking from %r %r" % (source, target))
         # FIXME: Also check target uses VersionedFile
         return isinstance(source, SvnRepository)
 
index 2d77785d9c6c971e82506bd6e583c76032755d2a..c01dc1eb32f3eff3f398d2ea634e6bab836b6434 100644 (file)
--- a/format.py
+++ b/format.py
@@ -24,7 +24,6 @@ from bzrlib.transport.local import LocalTransport
 from svn.core import SubversionException
 import svn.core, svn.repos
 
-from branch import SvnBranch
 from repository import SvnRepository
 from scheme import BranchingScheme
 from transport import SvnRaTransport, bzr_to_svn_url, get_svn_ra_transport
@@ -124,6 +123,7 @@ class SvnRemoteAccess(BzrDir):
 
     def create_branch(self):
         """See BzrDir.create_branch()."""
+        from branch import SvnBranch
         repos = self.open_repository()
         # TODO: Check if there are any revisions in this repository 
         # yet if it is the top-level one
@@ -133,6 +133,7 @@ class SvnRemoteAccess(BzrDir):
 
     def open_branch(self, unsupported=True):
         """See BzrDir.open_branch()."""
+        from branch import SvnBranch
 
         if not self.scheme.is_branch(self.branch_path) and \
            not self.scheme.is_tag(self.branch_path):
index 63bac9266fe2a289de2d1d1bd5228ac90bcea03f..3589ddbf61e9f180ba4efa777c0b13c7b67c501b 100644 (file)
@@ -383,4 +383,6 @@ class HeavyWeightCheckoutTests(TestCaseWithSubversionRepository):
         local_dir.open_branch().bind(master_branch)
         self.build_tree({'b/file': 'data'})
         wt.add('file')
-        wt.commit(message="Commit from Bzr")
+        revid = wt.commit(message="Commit from Bzr")
+        master_branch = Branch.open(repos_url)
+        self.assertEquals(revid, master_branch.last_revision())