[PATCH 6 of 6] convert: pass startrev to sources as an optimization hint

Patrick Mezard pmezard at gmail.com
Tue Jan 1 17:03:16 CST 2008


# HG changeset patch
# User Patrick Mezard <pmezard at gmail.com>
# Date 1199228284 -3600
# Node ID 8ea6e30f0970063b3c4eb2d6d3e91215a16b6214
# Parent  788a3da824f18f7669aee3c65cd4fc0132a3d97e
convert: pass startrev to sources as an optimization hint

diff --git a/hgext/convert/common.py b/hgext/convert/common.py
--- a/hgext/convert/common.py
+++ b/hgext/convert/common.py
@@ -40,9 +40,14 @@ class converter_source(object):
 class converter_source(object):
     """Conversion source interface"""
 
-    def __init__(self, ui, path=None, rev=None):
+    def __init__(self, ui, path=None, rev=None, startrev=None):
         """Initialize conversion source (or raise NoRepo("message")
-        exception if path is not a valid repository)"""
+        exception if path is not a valid repository)
+
+        If startrev is not None, the conversion operates on startrev descendants.
+        It can be used to optimize revisions retrieval but must not change 
+        the source output.
+        """
         self.ui = ui
         self.path = path
         self.rev = rev
diff --git a/hgext/convert/convcmd.py b/hgext/convert/convcmd.py
--- a/hgext/convert/convcmd.py
+++ b/hgext/convert/convcmd.py
@@ -31,12 +31,12 @@ sink_converters = [
     ('svn', svn_sink),
     ]
 
-def convertsource(ui, path, type, rev):
+def convertsource(ui, path, type, rev, startrev):
     exceptions = []
     for name, source in source_converters:
         try:
             if not type or name == type:
-                return source(ui, path, rev)
+                return source(ui, path, rev, startrev)
         except NoRepo, inst:
             exceptions.append(inst)
     if not ui.quiet:
@@ -287,16 +287,16 @@ def convert(ui, src, dest=None, revmapfi
     destc = convertsink(ui, dest, opts.get('dest_type'))
 
     try:
+        startrev = opts.get('startrev')
         srcc = convertsource(ui, src, opts.get('source_type'),
-                             opts.get('rev'))
+                             opts.get('rev'), startrev)
     except Exception:
         for path in destc.created:
             shutil.rmtree(path, True)
         raise
 
-    if opts.get('startrev'):
-        srcc = revstart.startrev_source(ui, srcc, 
-                                           opts.get('startrev'))
+    if startrev:
+        srcc = revstart.startrev_source(ui, srcc, startrev)
 
     fmap = opts.get('filemap')
     if fmap:
diff --git a/hgext/convert/cvs.py b/hgext/convert/cvs.py
--- a/hgext/convert/cvs.py
+++ b/hgext/convert/cvs.py
@@ -7,8 +7,9 @@ from common import NoRepo, commit, conve
 from common import NoRepo, commit, converter_source, checktool
 
 class convert_cvs(converter_source):
-    def __init__(self, ui, path, rev=None):
-        super(convert_cvs, self).__init__(ui, path, rev=rev)
+    def __init__(self, ui, path, rev=None, startrev=None):
+        super(convert_cvs, self).__init__(ui, path, rev=rev, 
+                                          startrev=startrev)
 
         cvs = os.path.join(path, "CVS")
         if not os.path.exists(cvs):
diff --git a/hgext/convert/darcs.py b/hgext/convert/darcs.py
--- a/hgext/convert/darcs.py
+++ b/hgext/convert/darcs.py
@@ -18,8 +18,8 @@ except ImportError:
 
 
 class darcs_source(converter_source, commandline):
-    def __init__(self, ui, path, rev=None):
-        converter_source.__init__(self, ui, path, rev=rev)
+    def __init__(self, ui, path, rev=None, startrev=None):
+        converter_source.__init__(self, ui, path, rev=rev, startrev=startrev)
         commandline.__init__(self, ui, 'darcs')
 
         # check for _darcs, ElementTree, _darcs/inventory so that we can
diff --git a/hgext/convert/git.py b/hgext/convert/git.py
--- a/hgext/convert/git.py
+++ b/hgext/convert/git.py
@@ -24,8 +24,9 @@ class convert_git(converter_source):
         def gitcmd(self, s):
             return util.popen('GIT_DIR=%s %s' % (self.path, s))
 
-    def __init__(self, ui, path, rev=None):
-        super(convert_git, self).__init__(ui, path, rev=rev)
+    def __init__(self, ui, path, rev=None, startrev=None):
+        super(convert_git, self).__init__(ui, path, rev=rev, 
+                                          startrev=startrev)
 
         if os.path.isdir(path + "/.git"):
             path += "/.git"
diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py
--- a/hgext/convert/hg.py
+++ b/hgext/convert/hg.py
@@ -185,8 +185,8 @@ class mercurial_sink(converter_sink):
         self.filemapmode = active
 
 class mercurial_source(converter_source):
-    def __init__(self, ui, path, rev=None):
-        converter_source.__init__(self, ui, path, rev)
+    def __init__(self, ui, path, rev=None, startrev=None):
+        converter_source.__init__(self, ui, path, rev, startrev=startrev)
         self.saverev = ui.configbool('convert', 'hg.saverev', True)
         try:
             self.repo = hg.repository(self.ui, path)
diff --git a/hgext/convert/revstart.py b/hgext/convert/revstart.py
--- a/hgext/convert/revstart.py
+++ b/hgext/convert/revstart.py
@@ -17,7 +17,7 @@ class startrev_source(converter_source):
     before any operations making use of source revisions.
     """
     def __init__(self, ui, baseconverter, startrev):
-        super(startrev_source, self).__init__(ui)
+        super(startrev_source, self).__init__(ui, startrev=startrev)
         self.startrev = startrev
         self.built = False
         self.commits = {}
diff --git a/hgext/convert/subversion.py b/hgext/convert/subversion.py
--- a/hgext/convert/subversion.py
+++ b/hgext/convert/subversion.py
@@ -101,8 +101,9 @@ def debugsvnlog(ui, **opts):
 
 # SVN conversion code stolen from bzr-svn and tailor
 class svn_source(converter_source):
-    def __init__(self, ui, url, rev=None):
-        super(svn_source, self).__init__(ui, url, rev=rev)
+    def __init__(self, ui, url, rev=None, startrev=None):
+        super(svn_source, self).__init__(ui, url, rev=rev, 
+                                         startrev=startrev)
 
         try:
             SubversionException
@@ -113,6 +114,9 @@ class svn_source(converter_source):
         # Map module to the last and last but one converted revision
         # for that module.
         self.lastrevs = {}
+        # Map module to the module converted revision preceding the start
+        # revision and the start revision
+        self.startrevs = {}
 
         latest = None
         try:
@@ -143,6 +147,10 @@ class svn_source(converter_source):
         if rev:
             latest = self.revnum(self.getrevid(rev))
 
+        self.startrev = 0
+        if startrev:
+            self.startrev = self.revnum(self.getrevid(startrev))
+
         try:
             self.get_blacklist()
         except IOError, e:
@@ -161,6 +169,7 @@ class svn_source(converter_source):
 
     def setrevmap(self, revmap):
         lastrevs = {}
+        startrevs = {}
         for revid in revmap.iterkeys():
             uuid, module, revnum = self.revsplit(revid)
             if module in lastrevs:
@@ -171,8 +180,14 @@ class svn_source(converter_source):
                     lastrevs[module] = (revnum, lastnum)
             else:
                 lastrevs[module] = (0, revnum)
+            
+            if self.startrev > 0:
+                prev, start = startrevs.setdefault(module, (0, self.startrev))
+                if prev < revnum < start:
+                    startrevs[module] = (revnum, start)
 
         self.lastrevs = lastrevs
+        self.startrevs = startrevs
 
     def exists(self, path, optrev):
         try:
@@ -586,8 +601,14 @@ class svn_source(converter_source):
         self.reparent(module)
         # We assume commits are requested from children to parents,
         # so we try to fetch and cache ranges ending at revnum.
+        # 1- Try to cache down to module last converted revisions
         prevstop, stop = self.lastrevs.get(module, (0, 0))
         if stop > revnum:
+            # 2- Then try down to the module converted revision just
+            # lower than the start revision
+            prevstop, stop = self.startrevs.get(module, (0, 0))
+        if stop > revnum:
+            # 3- Fetch all revisions for this module
             prevstop, stop = 0, 0
         # Fetch down to prevstop instead of stop because the cached 
         # to_revnum revision parents are invalid


More information about the Mercurial-devel mailing list