bin/unfuck-hggit-mapfile @ b0566e3d38e6

spa ce
author Steve Losh <steve@stevelosh.com>
date Mon, 07 Dec 2015 15:48:10 +0000
parents dab975004291
children 4ad9d3c4ebbe
#!/usr/bin/env python

from __future__ import print_function
import collections
import sys
import subprocess
import pprint

hg_dir = sys.argv[1]
git_dir = sys.argv[2]

nodetempl = "--template={node}\\n"
prettytempl = '--pretty=format:%H'

def log(msg):
    sys.stderr.write(str(msg) + '\n')
    sys.stderr.flush()

def die(msg):
    sys.stderr.write(msg + '\n')
    sys.exit(1)

def hg(*args):
    l = ["hg", "--repository", "./" + hg_dir] + list(args)
    return subprocess.check_output(l).strip()

def git(*args):
    l = ["git", "-C", "./" + git_dir] + list(args)
    return subprocess.check_output(l).strip()

def find_hg_root_revision():
    rev = hg('log', '-r', 'roots(all())', nodetempl).split()
    if len(rev) != 1:
        die("Can't determine a single hg root revision.")
    return rev[0]

def find_git_root_revision():
    rev = git('log', '--max-parents=0', prettytempl).split()
    if len(rev) != 1:
        die("Can't determine a single git root revision.")
    return rev[0]

def find_git_children_mapping():
    result = collections.defaultdict(list)
    for l in git('rev-list', '--all', '--parents').split('\n'):
        parts = l.split()
        for parent in parts[1:]:
            result[parent].append(parts[0])
    return result

def find_hg_children(rev):
    return hg('log', '-r', 'children(%s)' % rev, nodetempl).split()

def get_hg_desc(rev):
    return hg('log', '-r', rev, '--template={desc}')

def get_git_desc(rev):
    return git('log', '--format=%B', '-n', '1', rev)

hg_root = find_hg_root_revision()
git_root = find_git_root_revision()
git_children_map = find_git_children_mapping()

# hg -> git
mapping = {hg_root: git_root}
todo = [hg_root]

n = 0
while todo:
    log(n)
    n += 1
    h = todo.pop()
    g = mapping[h]
    hg_children = find_hg_children(h)
    git_children = git_children_map[g]

    if len(hg_children) == len(git_children) == 1:
        if hg_children[0] not in mapping:
            mapping[hg_children[0]] = git_children[0]
            todo.append(hg_children[0])
    else:
        log("Multiple children, attempting to differentiate")
        for hg_child in hg_children:
            hg_desc = get_hg_desc(hg_child)
            matching = [
                git_child for git_child in git_children
                if hg_desc.startswith(get_git_desc(git_child))
            ]
            if len(matching) == 1:
                log("Found a match based on message for %s" % hg_child)
                if hg_child not in mapping:
                    mapping[hg_child] = matching[0]
                    todo.append(hg_child)
            else:
                log("no match found...")


for h, g in mapping.items():
    print(g, h)