changeset 415:b17b2969861c

svnmeta: move revmap methods, make last_known_revision() more efficient
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Thu, 11 Jun 2009 10:32:32 +0200
parents 343da842dbe6
children cd6317fe70be
files hgsubversion/hg_delta_editor.py hgsubversion/maps.py hgsubversion/stupid.py hgsubversion/svnmeta.py hgsubversion/utility_commands.py hgsubversion/wrappers.py
diffstat 6 files changed, 26 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/hgsubversion/hg_delta_editor.py
+++ b/hgsubversion/hg_delta_editor.py
@@ -156,7 +156,7 @@ class HgChangeReceiver(delta.Editor):
 
         closebranches = {}
         for branch in tbdelta['branches'][1]:
-            branchedits = self.meta.branchedits(branch, rev)
+            branchedits = self.meta.revmap.branchedits(branch, rev)
             if len(branchedits) < 1:
                 # can't close a branch that never existed
                 continue
--- a/hgsubversion/maps.py
+++ b/hgsubversion/maps.py
@@ -101,11 +101,19 @@ class RevMap(dict):
     def __init__(self, repo):
         dict.__init__(self)
         self.path = os.path.join(repo.path, 'svn', 'rev_map')
+        self.seen = 0
         if os.path.isfile(self.path):
             self._load()
         else:
             self._write()
 
+    def hashes(self):
+        return dict((v, k) for (k, v) in self.iteritems())
+
+    def branchedits(self, branch, rev):
+        check = lambda x: x[0][1] == branch and x[0][0] < rev.revnum
+        return sorted(filter(check, self.iteritems()), reverse=True)
+
     def _load(self):
         f = open(self.path)
         ver = int(f.readline())
@@ -118,7 +126,9 @@ class RevMap(dict):
                 branch = None
             else:
                 branch = branch[:-1]
-            dict.__setitem__(self, (int(revnum), branch), node.bin(hash))
+            revnum = int(revnum)
+            self.seen = max(self.seen, revnum)
+            dict.__setitem__(self, (revnum, branch), node.bin(hash))
         f.close()
 
     def _write(self):
@@ -134,6 +144,7 @@ class RevMap(dict):
         f.write(str(revnum) + ' ' + node.hex(hash) + ' ' + b + '\n')
         f.flush()
         f.close()
+        self.seen = max(self.seen, revnum)
         dict.__setitem__(self, (revnum, branch), hash)
 
 
--- a/hgsubversion/stupid.py
+++ b/hgsubversion/stupid.py
@@ -431,7 +431,7 @@ def fetch_branchrev(svn, hg_editor, bran
     return files, filectxfn
 
 def checkbranch(hg_editor, r, branch):
-    branchedits = hg_editor.meta.branchedits(branch, r)
+    branchedits = hg_editor.meta.revmap.branchedits(branch, r)
     if not branchedits:
         return None
     branchtip = branchedits[0][1]
--- a/hgsubversion/svnmeta.py
+++ b/hgsubversion/svnmeta.py
@@ -120,25 +120,6 @@ class SVNMeta(object):
     def authors_file(self):
         return os.path.join(self.meta_data_dir, 'authors')
 
-    def hashes(self):
-        return dict((v, k) for (k, v) in self.revmap.iteritems())
-
-    def branchedits(self, branch, rev):
-        check = lambda x: x[0][1] == branch and x[0][0] < rev.revnum
-        return sorted(filter(check, self.revmap.iteritems()), reverse=True)
-
-    def last_known_revision(self):
-        """Obtain the highest numbered -- i.e. latest -- revision known.
-
-        Currently, this function just iterates over the entire revision map
-        using the max() builtin. This may be slow for extremely large
-        repositories, but for now, it's fast enough.
-        """
-        try:
-            return max(k[0] for k in self.revmap.iterkeys())
-        except ValueError:
-            return 0
-
     def fixdate(self, date):
         if date is not None:
             date = date.replace('T', ' ').replace('Z', '').split('.')[0]
--- a/hgsubversion/utility_commands.py
+++ b/hgsubversion/utility_commands.py
@@ -19,7 +19,7 @@ def genignore(ui, repo, hg_repo_path, fo
     user, passwd = util.getuserpass(opts)
     svn = svnwrap.SubversionRepo(url, user, passwd)
     hge = hg_delta_editor.HgChangeReceiver(repo, svn.uuid)
-    hashes = hge.meta.hashes()
+    hashes = hge.meta.revmap.hashes()
     parent = cmdutil.parentrev(ui, repo, hge, hashes)
     r, br = hashes[parent.node()]
     if br == None:
@@ -47,7 +47,7 @@ def info(ui, repo, hg_repo_path, **opts)
     user, passwd = util.getuserpass(opts)
     svn = svnwrap.SubversionRepo(url, user, passwd)
     hge = hg_delta_editor.HgChangeReceiver(repo, svn.uuid)
-    hashes = hge.meta.hashes()
+    hashes = hge.meta.revmap.hashes()
     parent = cmdutil.parentrev(ui, repo, hge, hashes)
     pn = parent.node()
     if pn not in hashes:
--- a/hgsubversion/wrappers.py
+++ b/hgsubversion/wrappers.py
@@ -37,7 +37,7 @@ def parents(orig, ui, repo, *args, **opt
     if not opts.get('svn', False):
         return orig(ui, repo, *args, **opts)
     hge = hg_delta_editor.HgChangeReceiver(repo)
-    hashes = hge.meta.hashes()
+    hashes = hge.meta.revmap.hashes()
     ha = cmdutil.parentrev(ui, repo, hge, hashes)
     if ha.node() == node.nullid:
         raise hgutil.Abort('No parent svn revision!')
@@ -58,10 +58,9 @@ def incoming(orig, ui, repo, source='def
     user, passwd = util.getuserpass(opts)
     svn = svnwrap.SubversionRepo(other.svnurl, user, passwd)
     hg_editor = hg_delta_editor.HgChangeReceiver(repo)
-    start = hg_editor.meta.last_known_revision()
 
     ui.status('incoming changes from %s\n' % other.svnurl)
-    for r in svn.revisions(start=start):
+    for r in svn.revisions(start=hg_editor.meta.revmap.seen):
         ui.status('\n')
         for label, attr in revmeta:
             l1 = label + ':'
@@ -80,7 +79,8 @@ def outgoing(repo, dest=None, heads=None
     svnurl, revs, checkout = hg.parseurl(dest.svnurl, heads)
     hge = hg_delta_editor.HgChangeReceiver(repo)
     parent = repo.parents()[0].node()
-    return util.outgoing_revisions(repo.ui, repo, hge, hge.meta.hashes(), parent)
+    hashes = hge.meta.revmap.hashes()
+    return util.outgoing_revisions(repo.ui, repo, hge, hashes, parent)
 
 
 def diff(orig, ui, repo, *args, **opts):
@@ -89,7 +89,7 @@ def diff(orig, ui, repo, *args, **opts):
     if not opts.get('svn', False) or opts.get('change', None):
         return orig(ui, repo, *args, **opts)
     hge = hg_delta_editor.HgChangeReceiver(repo)
-    hashes = hge.meta.hashes()
+    hashes = hge.meta.revmap.hashes()
     if not opts.get('rev', None):
         parent = repo.parents()[0]
         o_r = util.outgoing_revisions(ui, repo, hge, hashes, parent.node())
@@ -132,7 +132,7 @@ def push(repo, dest, force, revs):
         return 1
     workingrev = repo.parents()[0]
     ui.status('searching for changes\n')
-    hashes = hge.meta.hashes()
+    hashes = hge.meta.revmap.hashes()
     outgoing = util.outgoing_revisions(ui, repo, hge, hashes, workingrev.node())
     if not (outgoing and len(outgoing)):
         ui.status('no changes found\n')
@@ -197,7 +197,7 @@ def push(repo, dest, force, revs):
                         rebasesrc = node.bin(child.extra().get('rebase_source', node.hex(node.nullid)))
         # TODO: stop constantly creating the HgChangeReceiver instances.
         hge = hg_delta_editor.HgChangeReceiver(hge.repo, svn.uuid)
-        hashes = hge.meta.hashes()
+        hashes = hge.meta.revmap.hashes()
     util.swap_out_encoding(old_encoding)
     return 0
 
@@ -237,8 +237,8 @@ def pull(repo, source, heads=[], force=F
     svn = svnwrap.SubversionRepo(svn_url, user, passwd)
     hg_editor = hg_delta_editor.HgChangeReceiver(repo, svn.uuid, svn.subdir)
 
-    start = max(hg_editor.meta.last_known_revision(), skipto_rev)
-    initializing_repo = (hg_editor.meta.last_known_revision() <= 0)
+    start = max(hg_editor.meta.revmap.seen, skipto_rev)
+    initializing_repo = hg_editor.meta.revmap.seen <= 0
     ui = repo.ui
 
     if initializing_repo and start > 0:
@@ -305,7 +305,7 @@ def rebase(orig, ui, repo, **opts):
     extrafn = opts.get('svnextrafn', extrafn2)
     sourcerev = opts.get('svnsourcerev', repo.parents()[0].node())
     hge = hg_delta_editor.HgChangeReceiver(repo)
-    hashes = hge.meta.hashes()
+    hashes = hge.meta.revmap.hashes()
     o_r = util.outgoing_revisions(ui, repo, hge, hashes, sourcerev=sourcerev)
     if not o_r:
         ui.status('Nothing to rebase!\n')