Fix bug in revid caching.
[jelmer/subvertpy.git] / __init__.py
index e98a5019da6fa0b83e0b5854fbfed529fb0909e0..ba74d16a0450b84abcc309e7970f556f3af8c476 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2006 Jelmer Vernooij <jelmer@samba.org>
+# Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@samba.org>
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -22,119 +22,166 @@ import sys
 import unittest
 import bzrlib
 
-__version__ = '0.2.0'
-required_bzr_version = (0,13)
+from bzrlib.trace import warning
+
+__version__ = '0.4.0'
+COMPATIBLE_BZR_VERSIONS = [(0, 15), (0, 16), (0, 17)]
 
 def check_bzrlib_version(desired):
     """Check that bzrlib is compatible.
 
-    If version is < desired version, assume incompatible.
-    If version == desired version, assume completely compatible
-    If version == desired version + 1, assume compatible, with deprecations
+    If version is < all compatible version, assume incompatible.
+    If version is compatible version + 1, assume compatible, with deprecations
     Otherwise, assume incompatible.
     """
-    desired_plus = (desired[0], desired[1]+1)
     bzrlib_version = bzrlib.version_info[:2]
-    if bzrlib_version == desired:
+    if bzrlib_version in desired:
         return
-    try:
-        from bzrlib.trace import warning
-    except ImportError:
-        # get the message out any way we can
-        from warnings import warn as warning
-    if bzrlib_version < desired:
+    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)
     else:
         warning('bzr-svn is not up to date with installed bzr version %s.'
-                ' \nThere should be a newer version available, e.g. %i.%i.' 
-                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
-        if bzrlib_version != desired_plus:
+                ' \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'
 
-check_bzrlib_version(required_bzr_version)
+def check_subversion_version():
+    """Check that Subversion is compatible.
+
+    """
+    import svn.delta
+    if not hasattr(svn.delta, 'svn_delta_invoke_txdelta_window_handler'):
+        warning('Installed Subversion version does not have updated Python '
+                'bindings. See the bzr-svn README for details.')
+        raise bzrlib.errors.BzrError("incompatible python subversion bindings")
+
+check_bzrlib_version(COMPATIBLE_BZR_VERSIONS)
+check_subversion_version()
 
 import branch
 import convert
-import dumpfile
 import format
 import transport
 import checkout
 
-def convert_svn_exception(unbound):
-    """Decorator that catches particular Subversion exceptions and 
-    converts them to Bazaar exceptions.
-    """
-    def convert(self, *args, **kwargs):
-        try:
-            unbound(self, *args, **kwargs)
-        except SubversionException, (msg, num):
-            if num == svn.core.SVN_ERR_RA_SVN_CONNECTION_CLOSED:
-                raise ConnectionReset(msg=msg)
-            else:
-                raise
-
-    convert.__doc__ = unbound.__doc__
-    convert.__name__ = unbound.__name__
-    return convert
-
 from bzrlib.transport import register_transport
-register_transport('svn:', transport.SvnRaTransport)
-register_transport('http:', transport.SvnRaTransport)
-register_transport('https:', transport.SvnRaTransport)
-register_transport('file:', transport.SvnRaTransport)
+register_transport('svn://', transport.SvnRaTransport)
 register_transport('svn+', transport.SvnRaTransport)
 
 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)
 
-BzrDirFormat.register_control_format(checkout.SvnWorkingTreeDirFormat)
+import svn.core
+_subr_version = svn.core.svn_subr_version()
 
-BzrDirFormat.register_control_format(dumpfile.SvnDumpFileFormat)
+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
+from bzrlib.errors import BzrCommandError
+from bzrlib.repository import Repository
+import bzrlib.urlutils as urlutils
 
-class cmd_import_svn(Command):
+
+def get_scheme(schemename):
+    """Parse scheme identifier and return a branching scheme."""
+    from scheme import BranchingScheme
+    
+    ret = BranchingScheme.find_scheme(schemename)
+    if ret is None:
+        raise BzrCommandError('No such branching scheme %r' % schemename)
+    return ret
+
+
+class cmd_svn_import(Command):
     """Convert a Subversion repository to a Bazaar repository.
     
     """
-    takes_args = ['url', 'output_dir']
+    takes_args = ['from_location', 'to_location?']
     takes_options = [Option('trees', help='Create working trees'),
-                     Option('shared', help='Create shared repository')]
+                     Option('shared', help='Create shared repository'),
+                     Option('all', 
+                         help='Convert all revisions, even those not in '
+                              'current branch history (implies --shared)'),
+                     Option('scheme', type=get_scheme,
+                         help='Branching scheme (none, trunk, or trunk-INT)')]
 
     @display_command
-    def run(self, url, output_dir, trees=False, shared=False):
+    def run(self, from_location, to_location=None, trees=False, 
+            shared=False, scheme=None, all=False):
         from convert import convert_repository
         from scheme import TrunkBranchingScheme
-        # TODO: support non-trunk branching schemes
-        convert_repository(url, output_dir, TrunkBranchingScheme(), shared, 
-                           trees)
 
+        if scheme is None:
+            scheme = TrunkBranchingScheme()
+
+        if to_location is None:
+            to_location = os.path.basename(from_location.rstrip("/\\"))
+
+        if all:
+            shared = True
+        convert_repository(from_location, to_location, scheme, shared, trees,
+                           all)
+
+
+register_command(cmd_svn_import)
+
+class cmd_svn_upgrade(Command):
+    """Upgrade the revisions mapped from Subversion in a Bazaar branch.
+    
+    This will change the revision ids of revisions whose parents 
+    were mapped from svn revisions.
+    """
+    takes_args = ['svn_repository?']
+    takes_options = [Option('allow-changes', help='Allow content changes')]
+
+    @display_command
+    def run(self, svn_repository=None, allow_changes=False):
+        from upgrade import upgrade_branch
+        
+        branch_to = Branch.open(".")
+
+        stored_loc = branch_to.get_parent()
+        if svn_repository is None:
+            if stored_loc is None:
+                raise BzrCommandError("No pull 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)
+                svn_repository = stored_loc
+
+        upgrade_branch(branch_to, Repository.open(svn_repository), 
+                       allow_changes)
+
+register_command(cmd_svn_upgrade)
 
-register_command(cmd_import_svn)
 
 def test_suite():
-    from unittest import TestSuite, TestLoader
+    from unittest import TestSuite
     import tests
-
     suite = TestSuite()
-
     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")
+    runner = unittest.TextTestRunner()
+    runner.run(test_suite())
 else:
-    sys.path.append(os.path.dirname(__file__))
-
+    sys.path.append(os.path.dirname(os.path.abspath(__file__)))