source: trunk/scripts/git-migration/git-migrate @ 1895

Last change on this file since 1895 was 1895, checked in by broder, 16 years ago

Use a full repo path so we can expand to include trunk/scripts later.

  • Property svn:executable set to *
File size: 4.8 KB
Line 
1#!/usr/bin/python
2
3import os
4import sys
5import subprocess
6import shutil
7
8def tagBase(pkg):
9    p = subprocess.Popen(['git', 'tag',
10                          '-l',
11                          'base'],
12                         cwd='%s.git' % pkg,
13                         stdout=subprocess.PIPE)
14    p.wait()
15    if p.stdout.read().strip() != '':
16        return
17   
18    p = subprocess.Popen(['git', 'rev-list',
19                          '--reverse',
20                          'master'],
21                         cwd='%s.git' % pkg,
22                         stdout=subprocess.PIPE)
23    p.wait()
24    base = p.stdout.read().split()[0]
25   
26    subprocess.check_call(['git', 'tag',
27                           'base',
28                           base],
29                          cwd='%s.git' % pkg)
30
31def clonePackage(base, pkg):
32    path = '%s/%s' % (base, pkg)
33    pkg = os.path.basename(pkg)
34   
35    if not os.path.isdir('%s.git' % pkg):
36        if os.path.isdir(pkg):
37            shutil.rmtree(pkg)
38        # Use --no-follow-parent because we're going to handle that with
39        # grafts.
40        subprocess.check_call(['git', 'svn', 'clone',
41                               '--no-follow-parent',
42                               '-Aauthors',
43                               '-q',
44                               '--no-metadata',
45                               '%s' % path],
46                              stdout=subprocess.PIPE)
47       
48        # Then make the repository bare, because git-svn can't do this
49        shutil.move('%s/.git' % pkg, '%s.git' % pkg)
50        shutil.rmtree(pkg)
51        subprocess.check_call(['git', 'config', 'core.bare', 'true'],
52                              cwd='%s.git' % pkg)
53       
54    # Some of these repos have a rev where everything was deleted
55    # as a result of the move. We don't want that rev to exist.
56    p = subprocess.Popen(['git', 'ls-tree', 'HEAD'],
57                         cwd='%s.git' % pkg,
58                         stdout=subprocess.PIPE)
59    p.wait()
60    if len(p.stdout.read()) == 0:
61        subprocess.check_call(['git', 'reset', '--soft', 'HEAD^'],
62                              cwd='%s.git' % pkg)
63   
64    tagBase(pkg)
65
66def cloneAllPackages(base):
67    for pkg in open('package-list'):
68        clonePackage(base, pkg.strip())
69
70def mergeHistory(old_pkg, new_pkg, n):
71    n = int(n)
72   
73    subprocess.check_call(['git', 'push',
74                           '../%s.git' % new_pkg,
75                           'master:refs/heads/%s' % old_pkg],
76                          cwd='%s.git' % old_pkg)
77   
78    # Find the merge commit
79    if n == 0:
80        p = subprocess.Popen(['git', 'rev-parse',
81                              'base'],
82                             cwd='%s.git' % new_pkg,
83                             stdout=subprocess.PIPE)
84    else:
85        p = subprocess.Popen(['git', 'rev-list',
86                              '--reverse',
87                              '--boundary',
88                              '--skip=%s' % (n - 1),
89                              'base..master'],
90                             cwd='%s.git' % new_pkg,
91                             stdout=subprocess.PIPE)
92    p.wait()
93    new_rev = p.stdout.read().split()[0].strip('-')
94   
95    # Find any other parents of the merge commit
96    p = subprocess.Popen(['git', 'log',
97                          '-1',
98                          '--pretty=format:%P',
99                          new_rev],
100                         cwd='%s.git' % new_pkg,
101                         stdout=subprocess.PIPE)
102    p.wait()
103    parents = p.stdout.read().split()
104   
105    # Find the additional parent we're adding
106    p = subprocess.Popen(['git', 'rev-parse',
107                          old_pkg],
108                         cwd='%s.git' % new_pkg,
109                         stdout=subprocess.PIPE)
110    p.wait()
111    parents.append(p.stdout.read().strip())
112   
113    # Write out the grafts file
114    f = open('%s.git/info/grafts' % new_pkg, 'a')
115    print >>f, '%s %s' % (new_rev, ' '.join(parents))
116    f.close()
117   
118    # Run filter-branch
119    subprocess.call(['git', 'filter-branch',
120                     '--tag-name-filter', 'cat',
121                     '--',
122                     '--all'],
123                    cwd='%s.git' % new_pkg)
124   
125    subprocess.call(['git', 'branch',
126                     '-D',
127                     old_pkg],
128                    cwd='%s.git' % new_pkg)
129    shutil.rmtree('%s.git/refs/original' % new_pkg, True)
130
131def mergeHistories():
132    merges = []
133    for line in open('merges'):
134        line = line.strip()
135        if line == '' or line[0] == '#':
136            continue
137       
138        merges.append(line.split())
139   
140    for merge in merges:
141        mergeHistory(*merge)
142   
143    for merge in merges:
144        shutil.rmtree('%s.git' % merge[0])
145
146if __name__ == '__main__':
147    try:
148        base = sys.argv[1]
149    except:
150        base = 'svn://invirt.mit.edu/trunk'
151   
152    cloneAllPackages(base)
153    mergeHistories()
Note: See TracBrowser for help on using the repository browser.