diff svncommands.py @ 246:074f27c68818

Move rebuildmeta into svncommands.
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Wed, 08 Apr 2009 18:49:44 +0200
parents 28d0ee605308
children 1272e87546ed
line wrap: on
line diff
--- a/svncommands.py
+++ b/svncommands.py
@@ -1,4 +1,5 @@
 import os
+import cPickle as pickle
 
 from mercurial import hg
 from mercurial import node
@@ -211,3 +212,120 @@ def diff(ui, repo, hg_repo_path, **opts)
                                                   }))
     ui.write(cmdutil.filterdiff(''.join(it), base_rev))
 diff = util.register_subcommand('diff')(diff)
+
+
+def rebuildmeta(ui, repo, hg_repo_path, args, **opts):
+    """rebuild hgsubversion metadata using values stored in revisions
+    """
+    if len(args) != 1:
+        raise hgutil.Abort('You must pass the svn URI used to create this repo.')
+    uuid = None
+    url = args[0].rstrip('/')
+    user = opts.get('username', hgutil.getuser())
+    passwd = opts.get('password', '')
+    svn = svnwrap.SubversionRepo(url, user, passwd)
+    subdir = svn.subdir
+    svnmetadir = os.path.join(repo.path, 'svn')
+    if not os.path.exists(svnmetadir):
+        os.makedirs(svnmetadir)
+
+    revmap = open(os.path.join(svnmetadir, 'rev_map'), 'w')
+    revmap.write('1\n')
+    last_rev = -1
+    branchinfo = {}
+    noderevnums = {}
+    for rev in repo:
+        ctx = repo[rev]
+        convinfo = ctx.extra().get('convert_revision', None)
+        if convinfo:
+            assert convinfo.startswith('svn:')
+            revpath, revision = convinfo[40:].split('@')
+            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 uuid is None:
+                uuid = convinfo[4:40]
+                assert uuid == svn.uuid, 'UUIDs did not match!'
+                urlfile = open(os.path.join(svnmetadir, 'url'), 'w')
+                urlfile.write(url)
+                urlfile.close()
+                uuidfile = open(os.path.join(svnmetadir, 'uuid'), 'w')
+                uuidfile.write(uuid)
+                uuidfile.close()
+            commitpath = revpath[len(subdir)+1:]
+            if commitpath.startswith('branches'):
+                commitpath = commitpath[len('branches/'):]
+            elif commitpath == 'trunk':
+                commitpath = ''
+            else:
+                assert False, 'Unhandled case in rebuildmeta'
+            revmap.write('%s %s %s\n' % (revision,
+                                         node.hex(ctx.node()),
+                                         commitpath))
+            revision = int(revision)
+            noderevnums[ctx.node()] = revision
+            if revision > last_rev:
+                last_rev = revision
+            branch = ctx.branch()
+            if branch == 'default':
+                branch = None
+            if branch not in branchinfo:
+                parent = ctx.parents()[0]
+                if (parent.node() in noderevnums
+                    and parent.branch() != ctx.branch()):
+                    parentbranch = parent.branch()
+                    if parentbranch == 'default':
+                        parentbranch = None
+                else:
+                    parentbranch = None
+                branchinfo[branch] = (parentbranch,
+                                      noderevnums.get(parent.node(), 0),
+                                      revision)
+            for c in ctx.children():
+                if c.branch() == 'closed-branches':
+                    if branch in branchinfo:
+                        del branchinfo[branch]
+    branchinfofile = open(os.path.join(svnmetadir, 'branch_info'), 'w')
+    pickle.dump(branchinfo, branchinfofile)
+    branchinfofile.close()
+
+    # now handle tags
+    tagsinfo = {}
+    realtags = svn.tags
+    tagsleft = realtags.items()
+    while tagsleft:
+        tag, tagparent = tagsleft.pop(0)
+        source, rev = tagparent
+        if source.startswith('tags/'):
+            src = source[len('tags/'):]
+            if src in tagsinfo:
+                tagsinfo[tag] = tagsinfo[src]
+            elif src in realtags:
+                if (realtags[src][1] <= last_rev
+                    or realtags[src][0].startswith('tags/')):
+                    tagsleft.append(src)
+            else:
+                older_tags = svn.tags_at_rev(rev)
+                newsrc, newrev = older_tags[src]
+                tagsleft.append((tag, (newsrc, newrev)))
+            continue
+        else:
+            # determine the branch
+            assert not source.startswith('tags/'), "Tags can't be tags of other tags."
+            if source.startswith('branches/'):
+                source = source[len('branches/'):]
+            elif source == 'trunk':
+                source = None
+            else:
+                source = '../' + source
+        if rev <= last_rev and (source or 'default') in repo.branchtags():
+            tagsinfo[tag] = source, rev
+
+    tagsinfofile = open(os.path.join(svnmetadir, 'tag_info'), 'w')
+    pickle.dump(tagsinfo, tagsinfofile)
+    tagsinfofile.close()
+rebuildmeta = util.register_subcommand('rebuildmeta')(rebuildmeta)
+rebuildmeta = util.command_needs_no_url(rebuildmeta)