Show More
@@ -6,12 +6,24 | |||||
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | import os |
|
8 | import os | |
9 | from mercurial import util |
|
9 | from mercurial import util, config | |
10 | from mercurial.node import hex, nullid |
|
10 | from mercurial.node import hex, nullid | |
11 | from mercurial.i18n import _ |
|
11 | from mercurial.i18n import _ | |
12 |
|
12 | |||
13 | from common import NoRepo, commit, converter_source, checktool |
|
13 | from common import NoRepo, commit, converter_source, checktool | |
14 |
|
14 | |||
|
15 | class submodule(object): | |||
|
16 | def __init__(self, path, node, url): | |||
|
17 | self.path = path | |||
|
18 | self.node = node | |||
|
19 | self.url = url | |||
|
20 | ||||
|
21 | def hgsub(self): | |||
|
22 | return "%s = [git]%s" % (self.path, self.url) | |||
|
23 | ||||
|
24 | def hgsubstate(self): | |||
|
25 | return "%s %s" % (self.node, self.path) | |||
|
26 | ||||
15 | class convert_git(converter_source): |
|
27 | class convert_git(converter_source): | |
16 | # Windows does not support GIT_DIR= construct while other systems |
|
28 | # Windows does not support GIT_DIR= construct while other systems | |
17 | # cannot remove environment variable. Just assume none have |
|
29 | # cannot remove environment variable. Just assume none have | |
@@ -55,6 +67,7 class convert_git(converter_source): | |||||
55 | checktool('git', 'git') |
|
67 | checktool('git', 'git') | |
56 |
|
68 | |||
57 | self.path = path |
|
69 | self.path = path | |
|
70 | self.submodules = [] | |||
58 |
|
71 | |||
59 | def getheads(self): |
|
72 | def getheads(self): | |
60 | if not self.rev: |
|
73 | if not self.rev: | |
@@ -76,16 +89,56 class convert_git(converter_source): | |||||
76 | return data |
|
89 | return data | |
77 |
|
90 | |||
78 | def getfile(self, name, rev): |
|
91 | def getfile(self, name, rev): | |
|
92 | if name == '.hgsub': | |||
|
93 | data = '\n'.join([m.hgsub() for m in self.submoditer()]) | |||
|
94 | mode = '' | |||
|
95 | elif name == '.hgsubstate': | |||
|
96 | data = '\n'.join([m.hgsubstate() for m in self.submoditer()]) | |||
|
97 | mode = '' | |||
|
98 | else: | |||
79 | data = self.catfile(rev, "blob") |
|
99 | data = self.catfile(rev, "blob") | |
80 | mode = self.modecache[(name, rev)] |
|
100 | mode = self.modecache[(name, rev)] | |
81 | return data, mode |
|
101 | return data, mode | |
82 |
|
102 | |||
|
103 | def submoditer(self): | |||
|
104 | null = hex(nullid) | |||
|
105 | for m in sorted(self.submodules, key=lambda p: p.path): | |||
|
106 | if m.node != null: | |||
|
107 | yield m | |||
|
108 | ||||
|
109 | def parsegitmodules(self, content): | |||
|
110 | """Parse the formatted .gitmodules file, example file format: | |||
|
111 | [submodule "sub"]\n | |||
|
112 | \tpath = sub\n | |||
|
113 | \turl = git://giturl\n | |||
|
114 | """ | |||
|
115 | self.submodules = [] | |||
|
116 | c = config.config() | |||
|
117 | # Each item in .gitmodules starts with \t that cant be parsed | |||
|
118 | c.parse('.gitmodules', content.replace('\t','')) | |||
|
119 | for sec in c.sections(): | |||
|
120 | s = c[sec] | |||
|
121 | if 'url' in s and 'path' in s: | |||
|
122 | self.submodules.append(submodule(s['path'], '', s['url'])) | |||
|
123 | ||||
|
124 | def retrievegitmodules(self, version): | |||
|
125 | modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules')) | |||
|
126 | if ret: | |||
|
127 | raise util.Abort(_('cannot read submodules config file in %s') % version) | |||
|
128 | self.parsegitmodules(modules) | |||
|
129 | for m in self.submodules: | |||
|
130 | node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path)) | |||
|
131 | if ret: | |||
|
132 | continue | |||
|
133 | m.node = node.strip() | |||
|
134 | ||||
83 | def getchanges(self, version): |
|
135 | def getchanges(self, version): | |
84 | self.modecache = {} |
|
136 | self.modecache = {} | |
85 | fh = self.gitopen("git diff-tree -z --root -m -r %s" % version) |
|
137 | fh = self.gitopen("git diff-tree -z --root -m -r %s" % version) | |
86 | changes = [] |
|
138 | changes = [] | |
87 | seen = set() |
|
139 | seen = set() | |
88 | entry = None |
|
140 | entry = None | |
|
141 | subexists = False | |||
89 | for l in fh.read().split('\x00'): |
|
142 | for l in fh.read().split('\x00'): | |
90 | if not entry: |
|
143 | if not entry: | |
91 | if not l.startswith(':'): |
|
144 | if not l.startswith(':'): | |
@@ -97,15 +150,24 class convert_git(converter_source): | |||||
97 | seen.add(f) |
|
150 | seen.add(f) | |
98 | entry = entry.split() |
|
151 | entry = entry.split() | |
99 | h = entry[3] |
|
152 | h = entry[3] | |
100 | if entry[1] == '160000': |
|
|||
101 | raise util.Abort('git submodules are not supported!') |
|
|||
102 | p = (entry[1] == "100755") |
|
153 | p = (entry[1] == "100755") | |
103 | s = (entry[1] == "120000") |
|
154 | s = (entry[1] == "120000") | |
|
155 | ||||
|
156 | if f == '.gitmodules': | |||
|
157 | subexists = True | |||
|
158 | changes.append(('.hgsub', '')) | |||
|
159 | elif entry[1] == '160000' or entry[0] == ':160000': | |||
|
160 | subexists = True | |||
|
161 | else: | |||
104 | self.modecache[(f, h)] = (p and "x") or (s and "l") or "" |
|
162 | self.modecache[(f, h)] = (p and "x") or (s and "l") or "" | |
105 | changes.append((f, h)) |
|
163 | changes.append((f, h)) | |
106 | entry = None |
|
164 | entry = None | |
107 | if fh.close(): |
|
165 | if fh.close(): | |
108 | raise util.Abort(_('cannot read changes in %s') % version) |
|
166 | raise util.Abort(_('cannot read changes in %s') % version) | |
|
167 | ||||
|
168 | if subexists: | |||
|
169 | self.retrievegitmodules(version) | |||
|
170 | changes.append(('.hgsubstate', '')) | |||
109 | return (changes, {}) |
|
171 | return (changes, {}) | |
110 |
|
172 | |||
111 | def getcommit(self, version): |
|
173 | def getcommit(self, version): |
@@ -298,3 +298,50 damage git repository and convert again | |||||
298 | $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | \ |
|
298 | $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | \ | |
299 | > grep 'abort:' | sed 's/abort:.*/abort:/g' |
|
299 | > grep 'abort:' | sed 's/abort:.*/abort:/g' | |
300 | abort: |
|
300 | abort: | |
|
301 | ||||
|
302 | test sub modules | |||
|
303 | ||||
|
304 | $ mkdir git-repo5 | |||
|
305 | $ cd git-repo5 | |||
|
306 | $ git init-db >/dev/null 2>/dev/null | |||
|
307 | $ echo 'sub' >> foo | |||
|
308 | $ git add foo | |||
|
309 | $ commit -a -m 'addfoo' | |||
|
310 | $ BASE=${PWD} | |||
|
311 | $ cd .. | |||
|
312 | $ mkdir git-repo6 | |||
|
313 | $ cd git-repo6 | |||
|
314 | $ git init-db >/dev/null 2>/dev/null | |||
|
315 | $ git submodule add ${BASE} >/dev/null 2>/dev/null | |||
|
316 | $ commit -a -m 'addsubmodule' >/dev/null 2>/dev/null | |||
|
317 | $ cd .. | |||
|
318 | ||||
|
319 | convert sub modules | |||
|
320 | $ hg convert git-repo6 git-repo6-hg | |||
|
321 | initializing destination git-repo6-hg repository | |||
|
322 | scanning source... | |||
|
323 | sorting... | |||
|
324 | converting... | |||
|
325 | 0 addsubmodule | |||
|
326 | updating bookmarks | |||
|
327 | $ hg -R git-repo6-hg log -v | |||
|
328 | changeset: 0:* (glob) | |||
|
329 | bookmark: master | |||
|
330 | tag: tip | |||
|
331 | user: nottest <test@example.org> | |||
|
332 | date: Mon Jan 01 00:00:23 2007 +0000 | |||
|
333 | files: .hgsub .hgsubstate | |||
|
334 | description: | |||
|
335 | addsubmodule | |||
|
336 | ||||
|
337 | committer: test <test@example.org> | |||
|
338 | ||||
|
339 | ||||
|
340 | ||||
|
341 | $ cd git-repo6-hg | |||
|
342 | $ hg up >/dev/null 2>/dev/null | |||
|
343 | $ cat .hgsubstate | |||
|
344 | * git-repo5 (glob) | |||
|
345 | $ cd git-repo5 | |||
|
346 | $ cat foo | |||
|
347 | sub |
General Comments 0
You need to be logged in to leave comments.
Login now