Merge 0.4.
[jelmer/subvertpy.git] / __init__.py
index 6ddd9cadc556459ea386431f84326dc66edbc9cf..01114e40488e520f887e043cf622f7f927532b87 100644 (file)
 Support for Subversion branches
 """
 import bzrlib
-from bzrlib.bzrdir import BzrDirFormat
+from bzrlib.bzrdir import BzrDirFormat, format_registry
 from bzrlib.commands import Command, register_command, display_command, Option
 from bzrlib.help_topics import topic_registry
-from bzrlib.lazy_import import lazy_import
-from bzrlib.trace import warning, mutter
+from bzrlib.revisionspec import SPEC_TYPES
+from bzrlib.trace import warning
 from bzrlib.transport import register_lazy_transport, register_transport_proto
-from bzrlib.repository import InterRepository
-from bzrlib.workingtree import WorkingTreeFormat
 
-lazy_import(globals(), """
-import branch
-import commit
-import fetch 
 import format
-import workingtree
-""")
+import revspec
 
 # versions ending in 'exp' mean experimental mappings
 # versions ending in 'dev' mean development version
-__version__ = '0.4.0exp'
-COMPATIBLE_BZR_VERSIONS = [(0, 19)]
+# versions ending in 'final' mean release (well tested, etc)
+version_info = (0, 4, 7, 'dev', 0)
+
+if version_info[3] == 'final':
+    version_string = '%d.%d.%d' % version_info[:3]
+else:
+    version_string = '%d.%d.%d%s%d' % version_info
+__version__ = version_string
+
+COMPATIBLE_BZR_VERSIONS = [(0, 93), (1, 0), (1, 1)]
 
 def check_bzrlib_version(desired):
     """Check that bzrlib is compatible.
@@ -53,21 +54,19 @@ def check_bzrlib_version(desired):
         ((bzrlib_version[0], bzrlib_version[1]-1) in desired and 
          bzrlib.version_info[3] == 'dev')):
         return
+    from bzrlib.errors import BzrError
     if bzrlib_version < desired[0]:
-        warning('Installed bzr version %s is too old to be used with bzr-svn'
-                ' %s.' % (bzrlib.__version__, __version__))
-        # Not using BzrNewError, because it may not exist.
-        raise Exception, ('Version mismatch', desired)
+        raise BzrError('Installed bzr version %s is too old to be used with bzr-svn, at least %s.%s required' % (bzrlib.__version__, desired[0][0], desired[0][1]))
     else:
         warning('bzr-svn is not up to date with installed bzr version %s.'
                 ' \nThere should be a newer version of bzr-svn available.' 
                 % (bzrlib.__version__))
         if not (bzrlib_version[0], bzrlib_version[1]-1) in desired:
-            raise Exception, 'Version mismatch'
+            raise BzrError('Version mismatch')
 
 def check_bzrsvn_version():
     """Warn about use of experimental mappings."""
-    if __version__.endswith("exp"):
+    if version_info[3] == "exp":
         warning('version of bzr-svn is experimental; output may change between revisions')
 
 def check_subversion_version():
@@ -106,15 +105,15 @@ topic_registry.register_lazy('svn-branching-schemes',
                              'bzrlib.plugins.svn.scheme',
                              'help_schemes', 'Subversion branching schemes')
 
-BzrDirFormat.register_control_format(format.SvnFormat)
-BzrDirFormat.register_control_format(workingtree.SvnWorkingTreeDirFormat)
-
-bzrlib.branch.BranchFormat.register_format(branch.SvnBranchFormat())
-bzrlib.repository.format_registry.register_lazy(
-        "Subversion Repository Format",
-        "bzrlib.plugins.svn.repository",
-        "SvnRepositoryFormat")
-WorkingTreeFormat.register_format(workingtree.SvnWorkingTreeFormat())
+BzrDirFormat.register_control_format(format.SvnRemoteFormat)
+BzrDirFormat.register_control_format(format.SvnWorkingTreeDirFormat)
+format_registry.register("subversion", format.SvnRemoteFormat, 
+                         "Subversion repository. ", 
+                         native=False)
+format_registry.register("subversion-wc", format.SvnWorkingTreeDirFormat, 
+                         "Subversion working copy. ", 
+                         native=False, hidden=True)
+SPEC_TYPES.append(revspec.RevisionSpec_svn)
 
 versions_checked = False
 def lazy_check_versions():
@@ -125,8 +124,18 @@ def lazy_check_versions():
     check_bzrlib_version(COMPATIBLE_BZR_VERSIONS)
     check_bzrsvn_version()
 
-InterRepository.register_optimiser(fetch.InterFromSvnRepository)
-InterRepository.register_optimiser(commit.InterToSvnRepository)
+optimizers_registered = False
+def lazy_register_optimizers():
+    global optimizers_registered
+    if optimizers_registered:
+        return
+    from bzrlib.repository import InterRepository
+    import commit
+    import fetch
+    optimizers_registered = True
+    InterRepository.register_optimiser(fetch.InterFromSvnRepository)
+    InterRepository.register_optimiser(commit.InterToSvnRepository)
+
 
 def get_scheme(schemename):
     """Parse scheme identifier and return a branching scheme."""
@@ -160,24 +169,24 @@ class cmd_svn_import(Command):
     @display_command
     def run(self, from_location, to_location=None, trees=False, 
             standalone=False, scheme=None, all=False, prefix=None):
-        from bzrlib.errors import NoRepositoryPresent
+        from bzrlib.errors import BzrCommandError, NoRepositoryPresent
         from bzrlib.bzrdir import BzrDir
-        from bzrlib.trace import info
         from convert import convert_repository
+        from repository import SvnRepository
         import os
-        from scheme import TrunkBranchingScheme
 
         if to_location is None:
             to_location = os.path.basename(from_location.rstrip("/\\"))
 
         if all:
+            # All implies shared repository 
+            # (otherwise there is no repository to store revisions in)
             standalone = False
 
         if os.path.isfile(from_location):
             from convert import load_dumpfile
             import tempfile
             tmp_repos = tempfile.mkdtemp(prefix='bzr-svn-dump-')
-            mutter('loading dumpfile %r to %r' % (from_location, tmp_repos))
             load_dumpfile(from_location, tmp_repos)
             from_location = tmp_repos
         else:
@@ -187,10 +196,13 @@ class cmd_svn_import(Command):
         try:
             from_repos = from_dir.open_repository()
         except NoRepositoryPresent, e:
-            from bzrlib.errors import BzrCommandError
             raise BzrCommandError("No Repository found at %s. "
                 "For individual branches, use 'bzr branch'." % from_location)
 
+        if not isinstance(from_repos, SvnRepository):
+            raise BzrCommandError(
+                    "Not a Subversion repository: %s" % from_location)
+
         def filter_branch((branch_path, revnum, exists)):
             if prefix is not None and not branch_path.startswith(prefix):
                 return False
@@ -217,10 +229,11 @@ class cmd_svn_upgrade(Command):
 
     @display_command
     def run(self, from_repository=None, verbose=False):
-        from upgrade import upgrade_branch
+        from upgrade import upgrade_branch, upgrade_workingtree
         from bzrlib.branch import Branch
         from bzrlib.errors import NoWorkingTree, BzrCommandError
         from bzrlib.repository import Repository
+        from bzrlib.trace import info
         from bzrlib.workingtree import WorkingTree
         try:
             wt_to = WorkingTree.open(".")
@@ -243,38 +256,133 @@ class cmd_svn_upgrade(Command):
         else:
             from_repository = Repository.open(from_repository)
 
-        upgrade_branch(branch_to, from_repository, allow_changes=True, 
-                       verbose=verbose)
+        if wt_to is not None:
+            renames = upgrade_workingtree(wt_to, from_repository, 
+                                          allow_changes=True, verbose=verbose)
+        else:
+            renames = upgrade_branch(branch_to, from_repository, 
+                                     allow_changes=True, verbose=verbose)
+
+        if renames == {}:
+            info("Nothing to do.")
 
         if wt_to is not None:
             wt_to.set_last_revision(branch_to.last_revision())
 
 register_command(cmd_svn_upgrade)
 
-class cmd_svn_push_new(Command):
-    """Create a new branch in Subversion.
+class cmd_svn_push(Command):
+    """Push revisions to Subversion, creating a new branch if necessary.
+
+    The behaviour of this command is the same as that of "bzr push", except 
+    that it also creates new branches.
     
-    This command is experimental and will be removed in the future.
+    This command is experimental and will be removed in the future when all 
+    functionality is included in "bzr push".
     """
-    takes_args = ['location']
-    takes_options = ['revision']
+    takes_args = ['location?']
+    takes_options = ['revision', 'remember']
 
-    def run(self, location, revision=None):
+    def run(self, location=None, revision=None, remember=False):
         from bzrlib.bzrdir import BzrDir
         from bzrlib.branch import Branch
+        from bzrlib.errors import NotBranchError, BzrCommandError
+        from bzrlib import urlutils
+
+        source_branch = Branch.open_containing(".")[0]
+        stored_loc = source_branch.get_push_location()
+        if location is None:
+            if stored_loc is None:
+                raise BzrCommandError("No push location known or specified.")
+            else:
+                display_url = urlutils.unescape_for_display(stored_loc,
+                        self.outf.encoding)
+                self.outf.write("Using saved location: %s\n" % display_url)
+                location = stored_loc
+
         bzrdir = BzrDir.open(location)
-        branch = Branch.open(".")
         if revision is not None:
             if len(revision) > 1:
-                raise errors.BzrCommandError(
-                    'bzr svn-push-new --revision takes exactly one revision' 
+                raise BzrCommandError(
+                    'bzr svn-push --revision takes exactly one revision' 
                     ' identifier')
-            revision_id = revision[0].in_history(branch).rev_id
+            revision_id = revision[0].in_history(source_branch).rev_id
         else:
             revision_id = None
-        bzrdir.import_branch(branch, revision_id)
+        try:
+            target_branch = bzrdir.open_branch()
+            target_branch.pull(source_branch, revision_id)
+        except NotBranchError:
+            target_branch = bzrdir.import_branch(source_branch, revision_id)
+        # We successfully created the target, remember it
+        if source_branch.get_push_location() is None or remember:
+            source_branch.set_push_location(target_branch.base)
+
+register_command(cmd_svn_push)
+
+
+class cmd_svn_branching_scheme(Command):
+    """Show or change the branching scheme for a Subversion repository.
+
+    See 'bzr help svn-branching-schemes' for details.
+    """
+    takes_args = ['location?']
+    takes_options = [
+        Option('set', help="Change the branching scheme. "),
+        Option('repository-wide', 
+            help="Act on repository-wide setting rather than local.")
+        ]
+
+    def run(self, location=".", set=False, repository_wide=False):
+        from bzrlib.errors import BzrCommandError
+        from bzrlib.msgeditor import edit_commit_message
+        from bzrlib.repository import Repository
+        from bzrlib.trace import info
+        from repository import SvnRepository
+        from scheme import scheme_from_branch_list
+        def scheme_str(scheme):
+            if scheme is None:
+                return ""
+            return "".join(map(lambda x: x+"\n", scheme.to_lines()))
+        repos = Repository.open(location)
+        if not isinstance(repos, SvnRepository):
+            raise BzrCommandError("Not a Subversion repository: %s" % location)
+        if repository_wide:
+            scheme = repos._get_property_scheme()
+        else:
+            scheme = repos.get_scheme()
+        if set:
+            schemestr = edit_commit_message("", 
+                                            start_message=scheme_str(scheme))
+            scheme = scheme_from_branch_list(
+                map(lambda x:x.strip("\n"), schemestr.splitlines()))
+            if repository_wide:
+                repos.set_property_scheme(scheme)
+            else:
+                repos.set_branching_scheme(scheme, mandatory=True)
+        elif scheme is not None:
+            info(scheme_str(scheme))
+
 
-register_command(cmd_svn_push_new)
+register_command(cmd_svn_branching_scheme)
+
+
+class cmd_svn_set_revprops(Command):
+    """Migrate Bazaar metadata to Subversion revision properties.
+
+    This requires that you have permission to change the 
+    revision properties on the repository.
+
+    To change these permissions, edit the hooks/pre-revprop-change 
+    file in the Subversion repository.
+    """
+    takes_args = ['location']
+
+    def run(self, location="."):
+        raise NotImplementedError(self.run)
+
+
+register_command(cmd_svn_set_revprops)
 
 
 def test_suite():
@@ -284,6 +392,7 @@ def test_suite():
     suite.addTest(tests.test_suite())
     return suite
 
+
 if __name__ == '__main__':
     print ("This is a Bazaar plugin. Copy this directory to ~/.bazaar/plugins "
           "to use it.\n")