e61f380d50f332674577e5b5cdccb15df4f95c98
[invirt/scripts/git-migration.git] / git-migrate
1 #!/usr/bin/python
2
3 import os
4 import sys
5 import subprocess
6 import shutil
7
8 def clonePackage(base, pkg):
9     if not os.path.isdir('%s.git' % pkg):
10         if os.path.isdir(pkg):
11             shutil.rmtree(pkg)
12         # Use --no-follow-parent because we're going to handle that with
13         # grafts.
14         subprocess.check_call(['git', 'svn', 'clone',
15                                '--no-follow-parent',
16                                '-Aauthors',
17                                '-q',
18                                '--no-metadata',
19                                '%s/packages/%s' % (base, pkg)],
20                               stdout=subprocess.PIPE)
21         
22         # Then make the repository bare, because git-svn can't do this
23         shutil.move('%s/.git' % pkg, '%s.git' % pkg)
24         shutil.rmtree(pkg)
25         subprocess.check_call(['git', 'config', 'core.bare', 'true'],
26                               cwd='%s.git' % pkg)
27         
28     # Some of these repos have a rev where everything was deleted
29     # as a result of the move. We don't want that rev to exist.
30     p = subprocess.Popen(['git', 'ls-files'],
31                          cwd='%s.git' % pkg,
32                          stdout=subprocess.PIPE)
33     p.wait()
34     if len(p.stdout.read()) == 0:
35         subprocess.check_call(['git', 'reset', '--soft', 'HEAD^'],
36                               cwd='%s.git' % pkg)
37
38 def cloneAllPackages(base):
39     for pkg in open('package-list'):
40         clonePackage(base, pkg.strip())
41
42 def mergeHistory(old_pkg, new_pkg, n):
43     cwd = os.getcwd()
44     subprocess.check_call(['git', 'push',
45                            'file:///%s/%s.git' % (cwd, new_pkg),
46                            'master:refs/heads/%s' % old_pkg],
47                           cwd='%s.git' % new_pkg)
48     
49     graft = []
50     p = subprocess.Popen(['git', 'rev-list',
51                           '--reverse',
52                           '--skip=%s' % n,
53                           'master'],
54                          cwd='%s.git' % new_pkg,
55                          stdout=subprocess.PIPE)
56     p.wait()
57     new_rev = p.stdout.read().split()[0]
58     graft.append(new_rev)
59     
60     # If n isn't 0, then n has a parent commit already that we
61     # shouldn't forget about.
62     if n != 0:
63         p = subprocess.Popen(['git', 'rev-parse',
64                               '%s^' % new_rev],
65                              cwd='%s.git' % new_pkg,
66                              stdout=subprocess.PIPE)
67         p.wait()
68         graft.append(p.stdout.read().strip())
69     
70     # And regardless, the HEAD of old_pkg should be a parent of
71     # new_pkg
72     p = subprocess.Popen(['git', 'rev-parse',
73                           'master'],
74                          cwd='%s.git' % old_pkg,
75                          stdout=subprocess.PIPE)
76     p.wait()
77     graft.append(p.stdout.read().strip())
78     
79     f = open('%s.git/info/grafts' % new_pkg, 'a')
80     
81     print >>f, ' '.join(graft)
82
83 def mergeHistories():
84     merges = []
85     for line in open('merges'):
86         line = line.strip()
87         if line[0] == '#' or line == '':
88             continue
89         
90         merges.append(line.split())
91     
92     for merge in merges:
93         mergeHistory(*merge)
94     
95     for line in open('package-list'):
96         line = line.strip()
97         subprocess.check_call(['git', 'filter-branch',
98                                '--',
99                                '--all'],
100                               cwd='%s.git' % line)
101     
102     for merge in merges:
103         shutil.rmtree('%s.git' % merge[0])
104
105 if __name__ == '__main__':
106     try:
107         base = sys.argv[1]
108     except:
109         base = 'svn://invirt.mit.edu/trunk'
110     
111     cloneAllPackages(base)
112     mergeHistories()