Friday, January 02, 2009

Create a mercurial mirror of an svn branch

#hgsvnsync.py
#
#Create a mercurial mirror of a branch in an svn repository
#This scripts requires that the commands svn and hg be present
#in the path.
#
#Usage:
#To create a new mirror
# python hgsvnsync.py init svn_url mirror_location
#
#To update the mirror
# python hgsvnsync.py update mirror_location
#
# Changes
# 23-Jan-2009 Updated to working version.

import commands
import re
import os

hgignore= """syntax: regexp
[.]svn/
[.]hgignore
[.]commitmessage"""


def getRevisions(svn_url, frm=1):
    s = commands.getoutput('svn -r%s:HEAD log %s' % (frm, svn_url))
    return re.findall('------------------------------------------------------------------------\n'+
            'r(\d+) [|] \w+ [|] ', s)

def createFile(filename, content):
    f = file(filename, 'w')
    f.write(content)
    f.close()

def init(svn_url, dest):
    commands.getoutput('svn co -r1 %s %s' % (svn_url, dest))
    commands.getoutput('hg init %s' % dest)
    createFile(os.path.join(dest, '.hgignore'), hgignore)

def parseLog(log):
    (rev, commiter, date, lines) =  re.search(
        '------------------------------------------------------------------------\n'+
        'r(\d+) [|] (\w+) [|] ([^(]+)[^|]+[|] (\d+) line[s]?\n', log).groups()
    message = "%s\n\nSvn Revision %s" % ( 
                "\n".join(log.split('\n')[3:(3+int(lines))]),rev)
    return (rev, commiter, date, message)
    
def parseInfo(info):
    return dict(re.findall("(\w+): (.*)", info))

def commitRevs(svn_url, dest, frm):
    revs = getRevisions(svn_url, frm)[1:]
    for rev in revs:
        print "Commiting revision %s" % rev
        commands.getoutput('svn update -r%s %s' % (rev, dest))
        logMsg = commands.getoutput('svn log -rCOMMITTED %s' % dest)
        (rev, commiter, date, message) = parseLog(logMsg)
        commitmessagepath = os.path.join(dest, '.commitmessage')
        createFile(commitmessagepath, message)
        commands.getoutput("hg commit -A -l %s -d '%s' -u %s %s" % 
                            (commitmessagepath, date, commiter, dest))

def main():
    import sys
    if sys.argv[1]=='init':
        svn_url = sys.argv[2]
        dest = sys.argv[3]
        init(svn_url, dest)
        commitRevs(svn_url, dest, 1)
    elif sys.argv[1]=='update':
        dest = sys.argv[2]
        info = parseInfo(commands.getoutput('svn info %s' % dest))
        rev = info['Revision']
        svn_url = info['URL']
        commitRevs(svn_url, dest, rev)

if __name__ == '__main__':
    main()
    

0 Comments:

Post a Comment

<< Home