1. Takafumi Arakaki
  2. hg-uniquify-closed-branch


hg-uniquify-closed-branch / hucb.py

#!/usr/bin/env python

Uniquify branches in Mercurial repository to prepare for `hg-fast-export`.

import subprocess

def command(cmds, *args, **kwds):
    cmds = list(a for a in cmds if a)  # exclude empty string
    proc = subprocess.Popen(
        cmds, *args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwds)
    ret = proc.wait()
    stdout = proc.stdout.read()
    if ret != 0:
        print stdout
        import sys
    return stdout

def hg_heads(sep, *args):
    return command(
        ['hg', 'heads', '--template', sep.join(['{branch}', '{node}\n'])]
        + list(args))

def hg_branch(revision, name):
    command(['hg', 'update', revision])
    command(['hg', 'branch', name])
    date = command(['hg', 'log', '--rev', revision,
                    '--template', '{date|hgdate}'])
    (ts, tz) = date.split(' ', 1)
    newts = int(ts) + 1
    newdate = '{0} {1}'.format(newts, tz)
        ['hg', 'commit', '--date', newdate, '--message',
         "(HUCB)\n\nAdd new branch '{0}' to uniquify heads.".format(name)])

def append_branch(branch_heads, heads, sep):
    """Parse strings in `heads` and add them to `branch_heads`."""
    for head in heads:
        (branch, node) = head.split(sep, 1)
        branch_heads.setdefault(branch, [])

def sort_branches(branch_heads):
    """Make sure 'default' branch comes first (for cosmetic reason)."""
    brancheset = set(branch_heads)
    if 'default' in brancheset:
        return ['default'] + list(brancheset)
        return list(brancheset)

def hucb(dry_run, sep, branch_temp):
    heads_active = hg_heads(sep).splitlines()
    heads_all = hg_heads(sep, '--closed').splitlines()
    heads_closed = set(heads_all) - set(heads_active)

    branch_heads = {}
    append_branch(branch_heads, heads_active, sep)
    append_branch(branch_heads, heads_closed, sep)

    i = 0
    for br in sort_branches(branch_heads):
        heads = branch_heads[br]
        for node in heads[1:]:
            newbranch = branch_temp.format(i=i)
            print 'node:{node} | branch: {branch} -> {newbranch}'.format(
                node=node, branch=br, newbranch=newbranch)
            if not dry_run:
                hg_branch(node, newbranch)
            i += 1

def main():
    from argparse import ArgumentParser
    parser = ArgumentParser(description=__doc__)
    parser.add_argument('--dry-run', '-n', default=False, action='store_true')
    parser.add_argument('--sep', default='#',
                        help='A character to be used to parse '
                        'branch and node name.  Use a character '
                        'which is not part of your branch names.')
    parser.add_argument('--branch-temp', default='br{i:02d}',
                        help='branch name template (default: %(default)s)')
    args = parser.parse_args()

if __name__ == '__main__':