1. Dan Villiom Podlaski Christiansen
  2. hgsubversion-queue

Source

hgsubversion-queue / allow-multi-rebuildmeta.diff

# HG changeset patch
# User Dan Villiom Podlaski Christiansen <dan@cabo.dk>
# Date 1323817677 -3600
# Node ID bfba4f40b62cdcde7a9cd7895b2942eab57fb750
# Parent  7ac002d36732a3cf80f0f92cea432ef583a19ed5
rebuildmeta: handle revisions from other repositories gracefully

Previously, such revisions would cause 'hg svn rebuildmeta' to fail
with an assertion error. If the error was suppressed by running hg
under 'python -O' (which is common on Windows), all revisions from
Subversion would be added to the rev_map.

After this change, rebuildmeta will silently skip revisions which
belong to another Subversion repository or use another subdirectory
within the same repository.

diff --git a/hgsubversion/svncommands.py b/hgsubversion/svncommands.py
--- a/hgsubversion/svncommands.py
+++ b/hgsubversion/svncommands.py
@@ -116,6 +116,11 @@ def rebuildmeta(ui, repo, args, **opts):
     if not os.path.exists(svnmetadir):
         os.makedirs(svnmetadir)
 
+    if subdir and subdir[0] != '/':
+        subdir = '/' + subdir
+    if subdir and subdir[-1] == '/':
+        subdir = subdir[:-1]
+
     lastpulled = open(os.path.join(svnmetadir, 'lastpulled'), 'wb')
     revmap = open(os.path.join(svnmetadir, 'rev_map'), 'w')
     revmap.write('1\n')
@@ -134,10 +139,29 @@ def rebuildmeta(ui, repo, args, **opts):
 
     numrevs = len(repo)
 
+    uuidfile = open(os.path.join(svnmetadir, 'uuid'), 'w')
+    uuidfile.write(svn.uuid)
+    uuidfile.close()
+
     subdirfile = open(os.path.join(svnmetadir, 'subdir'), 'w')
     subdirfile.write(subdir.strip('/'))
     subdirfile.close()
 
+    def splitconvinfo(convinfo):
+        uuid = convinfo[4:40]
+        revpath, revision = convinfo[40:].split('@')
+        return uuid, revpath, revision
+
+    def isinrepo(ctx):
+        convinfo = ctx.extra().get('convert_revision', None)
+
+        if not convinfo or not convinfo.startswith('svn:'):
+            return False
+
+        uuid, revpath, revision = splitconvinfo(convinfo)
+
+        return uuid == svn.uuid and revpath.startswith(subdir)
+
     # ctx.children() visits all revisions in the repository after ctx. Calling
     # it would make us use O(revisions^2) time, so we perform an extra traversal
     # of the repository instead. During this traversal, we find all converted
@@ -146,6 +170,10 @@ def rebuildmeta(ui, repo, args, **opts):
     for rev in repo:
         util.progress(ui, 'prepare', rev, total=numrevs)
         ctx = repo[rev]
+
+        if not isinrepo(ctx):
+            continue
+
         extra = ctx.extra()
         convinfo = extra.get('convert_revision', None)
         if not convinfo:
@@ -169,9 +197,11 @@ def rebuildmeta(ui, repo, args, **opts):
     for rev in repo:
         util.progress(ui, 'rebuild', rev, total=numrevs)
         ctx = repo[rev]
+        if not isinrepo(ctx):
+            ui.debug('skipping %s:%s\n' % (ctx.rev(), node.short(ctx.node())))
+            continue
+        ui.debug('inspecting %s:%s\n' % (ctx.rev(), node.short(ctx.node())))
         convinfo = ctx.extra().get('convert_revision', None)
-        if not convinfo:
-            continue
         if '.hgtags' in ctx.files():
             parent = ctx.parents()[0]
             parentdata = ''
@@ -193,15 +223,11 @@ def rebuildmeta(ui, repo, args, **opts):
                 tagrev = max(tagged, tagging)
                 tags[tag] = node.bin(ha), tagrev
 
-        # check that the conversion metadata matches expectations
-        assert convinfo.startswith('svn:')
-        revpath, revision = convinfo[40:].split('@')
+        uuid, revpath, revision = splitconvinfo(convinfo)
         if subdir and subdir[0] != '/':
             subdir = '/' + subdir
         if subdir and subdir[-1] == '/':
             subdir = subdir[:-1]
-        assert revpath.startswith(subdir), ('That does not look like the '
-                                            'right location in the repo.')
 
         if layout is None:
             if (subdir or '/') == revpath:
@@ -215,14 +241,6 @@ def rebuildmeta(ui, repo, args, **opts):
             assert (subdir or '/') == revpath, ('Possible layout detection'
                                                 ' defect in replay')
 
-        # write repository uuid if required
-        if uuid is None:
-            uuid = convinfo[4:40]
-            assert uuid == svn.uuid, 'UUIDs did not match!'
-            uuidfile = open(os.path.join(svnmetadir, 'uuid'), 'w')
-            uuidfile.write(uuid)
-            uuidfile.close()
-
         # don't reflect closed branches
         if (ctx.extra().get('close') and not ctx.files() or
             ctx.parents()[0].node() in skipped):