~ubuntu-branches/ubuntu/intrepid/git-core/intrepid-updates

« back to all changes in this revision

Viewing changes to contrib/hg-to-git/hg-to-git.py

  • Committer: Package Import Robot
  • Author(s): Gerrit Pape
  • Date: 2007-04-22 13:31:05 UTC
  • mfrom: (1.1.14)
  • Revision ID: package-import@ubuntu.com-20070422133105-tkmhz328g2p0epz1
Tags: 1:1.5.1.2-1
* new upstream point release.
* debian/changelog.upstream: upstream changes taken from mailing list
  announcement.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
 
 
3
""" hg-to-svn.py - A Mercurial to GIT converter
 
4
 
 
5
    Copyright (C)2007 Stelian Pop <stelian@popies.net>
 
6
 
 
7
    This program is free software; you can redistribute it and/or modify
 
8
    it under the terms of the GNU General Public License as published by
 
9
    the Free Software Foundation; either version 2, or (at your option)
 
10
    any later version.
 
11
 
 
12
    This program is distributed in the hope that it will be useful,
 
13
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
    GNU General Public License for more details.
 
16
 
 
17
    You should have received a copy of the GNU General Public License
 
18
    along with this program; if not, write to the Free Software
 
19
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
"""
 
21
 
 
22
import os, os.path, sys
 
23
import tempfile, popen2, pickle, getopt
 
24
import re
 
25
 
 
26
# Maps hg version -> git version
 
27
hgvers = {}
 
28
# List of children for each hg revision
 
29
hgchildren = {}
 
30
# Current branch for each hg revision
 
31
hgbranch = {}
 
32
 
 
33
#------------------------------------------------------------------------------
 
34
 
 
35
def usage():
 
36
 
 
37
        print """\
 
38
%s: [OPTIONS] <hgprj>
 
39
 
 
40
options:
 
41
    -s, --gitstate=FILE: name of the state to be saved/read
 
42
                         for incrementals
 
43
 
 
44
required:
 
45
    hgprj:  name of the HG project to import (directory)
 
46
""" % sys.argv[0]
 
47
 
 
48
#------------------------------------------------------------------------------
 
49
 
 
50
def getgitenv(user, date):
 
51
    env = ''
 
52
    elems = re.compile('(.*?)\s+<(.*)>').match(user)
 
53
    if elems:
 
54
        env += 'export GIT_AUTHOR_NAME="%s" ;' % elems.group(1)
 
55
        env += 'export GIT_COMMITER_NAME="%s" ;' % elems.group(1)
 
56
        env += 'export GIT_AUTHOR_EMAIL="%s" ;' % elems.group(2)
 
57
        env += 'export GIT_COMMITER_EMAIL="%s" ;' % elems.group(2)
 
58
    else:
 
59
        env += 'export GIT_AUTHOR_NAME="%s" ;' % user
 
60
        env += 'export GIT_COMMITER_NAME="%s" ;' % user
 
61
        env += 'export GIT_AUTHOR_EMAIL= ;'
 
62
        env += 'export GIT_COMMITER_EMAIL= ;'
 
63
 
 
64
    env += 'export GIT_AUTHOR_DATE="%s" ;' % date
 
65
    env += 'export GIT_COMMITTER_DATE="%s" ;' % date
 
66
    return env
 
67
 
 
68
#------------------------------------------------------------------------------
 
69
 
 
70
state = ''
 
71
 
 
72
try:
 
73
    opts, args = getopt.getopt(sys.argv[1:], 's:t:', ['gitstate=', 'tempdir='])
 
74
    for o, a in opts:
 
75
        if o in ('-s', '--gitstate'):
 
76
            state = a
 
77
            state = os.path.abspath(state)
 
78
 
 
79
    if len(args) != 1:
 
80
        raise('params')
 
81
except:
 
82
    usage()
 
83
    sys.exit(1)
 
84
 
 
85
hgprj = args[0]
 
86
os.chdir(hgprj)
 
87
 
 
88
if state:
 
89
    if os.path.exists(state):
 
90
        print 'State does exist, reading'
 
91
        f = open(state, 'r')
 
92
        hgvers = pickle.load(f)
 
93
    else:
 
94
        print 'State does not exist, first run'
 
95
 
 
96
tip = os.popen('hg tip | head -1 | cut -f 2 -d :').read().strip()
 
97
print 'tip is', tip
 
98
 
 
99
# Calculate the branches
 
100
print 'analysing the branches...'
 
101
hgchildren["0"] = ()
 
102
hgbranch["0"] = "master"
 
103
for cset in range(1, int(tip) + 1):
 
104
    hgchildren[str(cset)] = ()
 
105
    prnts = os.popen('hg log -r %d | grep ^parent: | cut -f 2 -d :' % cset).readlines()
 
106
    if len(prnts) > 0:
 
107
        parent = prnts[0].strip()
 
108
    else:
 
109
        parent = str(cset - 1)
 
110
    hgchildren[parent] += ( str(cset), )
 
111
    if len(prnts) > 1:
 
112
        mparent = prnts[1].strip()
 
113
        hgchildren[mparent] += ( str(cset), )
 
114
    else:
 
115
        mparent = None
 
116
 
 
117
    if mparent:
 
118
        # For merge changesets, take either one, preferably the 'master' branch
 
119
        if hgbranch[mparent] == 'master':
 
120
            hgbranch[str(cset)] = 'master'
 
121
        else:
 
122
            hgbranch[str(cset)] = hgbranch[parent]
 
123
    else:
 
124
        # Normal changesets
 
125
        # For first children, take the parent branch, for the others create a new branch
 
126
        if hgchildren[parent][0] == str(cset):
 
127
            hgbranch[str(cset)] = hgbranch[parent]
 
128
        else:
 
129
            hgbranch[str(cset)] = "branch-" + str(cset)
 
130
 
 
131
if not hgvers.has_key("0"):
 
132
    print 'creating repository'
 
133
    os.system('git-init-db')
 
134
 
 
135
# loop through every hg changeset
 
136
for cset in range(int(tip) + 1):
 
137
 
 
138
    # incremental, already seen
 
139
    if hgvers.has_key(str(cset)):
 
140
        continue
 
141
 
 
142
    # get info
 
143
    prnts = os.popen('hg log -r %d | grep ^parent: | cut -f 2 -d :' % cset).readlines()
 
144
    if len(prnts) > 0:
 
145
        parent = prnts[0].strip()
 
146
    else:
 
147
        parent = str(cset - 1)
 
148
    if len(prnts) > 1:
 
149
        mparent = prnts[1].strip()
 
150
    else:
 
151
        mparent = None
 
152
 
 
153
    (fdcomment, filecomment) = tempfile.mkstemp()
 
154
    csetcomment = os.popen('hg log -r %d -v | grep -v ^changeset: | grep -v ^parent: | grep -v ^user: | grep -v ^date | grep -v ^files: | grep -v ^description: | grep -v ^tag:' % cset).read().strip()
 
155
    os.write(fdcomment, csetcomment)
 
156
    os.close(fdcomment)
 
157
 
 
158
    date = os.popen('hg log -r %d | grep ^date: | cut -f 2- -d :' % cset).read().strip()
 
159
 
 
160
    tag = os.popen('hg log -r %d | grep ^tag: | cut -f 2- -d :' % cset).read().strip()
 
161
 
 
162
    user = os.popen('hg log -r %d | grep ^user: | cut -f 2- -d :' % cset).read().strip()
 
163
 
 
164
    print '-----------------------------------------'
 
165
    print 'cset:', cset
 
166
    print 'branch:', hgbranch[str(cset)]
 
167
    print 'user:', user
 
168
    print 'date:', date
 
169
    print 'comment:', csetcomment
 
170
    print 'parent:', parent
 
171
    if mparent:
 
172
        print 'mparent:', mparent
 
173
    if tag:
 
174
        print 'tag:', tag
 
175
    print '-----------------------------------------'
 
176
 
 
177
    # checkout the parent if necessary
 
178
    if cset != 0:
 
179
        if hgbranch[str(cset)] == "branch-" + str(cset):
 
180
            print 'creating new branch', hgbranch[str(cset)]
 
181
            os.system('git-checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent]))
 
182
        else:
 
183
            print 'checking out branch', hgbranch[str(cset)]
 
184
            os.system('git-checkout %s' % hgbranch[str(cset)])
 
185
 
 
186
    # merge
 
187
    if mparent:
 
188
        if hgbranch[parent] == hgbranch[str(cset)]:
 
189
            otherbranch = hgbranch[mparent]
 
190
        else:
 
191
            otherbranch = hgbranch[parent]
 
192
        print 'merging', otherbranch, 'into', hgbranch[str(cset)]
 
193
        os.system(getgitenv(user, date) + 'git-merge --no-commit -s ours "" %s %s' % (hgbranch[str(cset)], otherbranch))
 
194
 
 
195
    # remove everything except .git and .hg directories
 
196
    os.system('find . \( -path "./.hg" -o -path "./.git" \) -prune -o ! -name "." -print | xargs rm -rf')
 
197
 
 
198
    # repopulate with checkouted files
 
199
    os.system('hg update -C %d' % cset)
 
200
 
 
201
    # add new files
 
202
    os.system('git-ls-files -x .hg --others | git-update-index --add --stdin')
 
203
    # delete removed files
 
204
    os.system('git-ls-files -x .hg --deleted | git-update-index --remove --stdin')
 
205
 
 
206
    # commit
 
207
    os.system(getgitenv(user, date) + 'git-commit -a -F %s' % filecomment)
 
208
    os.unlink(filecomment)
 
209
 
 
210
    # tag
 
211
    if tag and tag != 'tip':
 
212
        os.system(getgitenv(user, date) + 'git-tag %s' % tag)
 
213
 
 
214
    # delete branch if not used anymore...
 
215
    if mparent and len(hgchildren[str(cset)]):
 
216
        print "Deleting unused branch:", otherbranch
 
217
        os.system('git-branch -d %s' % otherbranch)
 
218
 
 
219
    # retrieve and record the version
 
220
    vvv = os.popen('git-show | head -1').read()
 
221
    vvv = vvv[vvv.index(' ') + 1 : ].strip()
 
222
    print 'record', cset, '->', vvv
 
223
    hgvers[str(cset)] = vvv
 
224
 
 
225
os.system('git-repack -a -d')
 
226
 
 
227
# write the state for incrementals
 
228
if state:
 
229
    print 'Writing state'
 
230
    f = open(state, 'w')
 
231
    pickle.dump(hgvers, f)
 
232
 
 
233
# vim: et ts=8 sw=4 sts=4