##// END OF EJS Templates
convert: add support for converting git submodule (issue3528)...
YaNan Xu -
r17929:0eed6632 default
parent child Browse files
Show More
@@ -6,12 +6,24 b''
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 import os
9 from mercurial import util
9 from mercurial import util, config
10 10 from mercurial.node import hex, nullid
11 11 from mercurial.i18n import _
12 12
13 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 27 class convert_git(converter_source):
16 28 # Windows does not support GIT_DIR= construct while other systems
17 29 # cannot remove environment variable. Just assume none have
@@ -55,6 +67,7 b' class convert_git(converter_source):'
55 67 checktool('git', 'git')
56 68
57 69 self.path = path
70 self.submodules = []
58 71
59 72 def getheads(self):
60 73 if not self.rev:
@@ -76,16 +89,56 b' class convert_git(converter_source):'
76 89 return data
77 90
78 91 def getfile(self, name, rev):
79 data = self.catfile(rev, "blob")
80 mode = self.modecache[(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:
99 data = self.catfile(rev, "blob")
100 mode = self.modecache[(name, rev)]
81 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 135 def getchanges(self, version):
84 136 self.modecache = {}
85 137 fh = self.gitopen("git diff-tree -z --root -m -r %s" % version)
86 138 changes = []
87 139 seen = set()
88 140 entry = None
141 subexists = False
89 142 for l in fh.read().split('\x00'):
90 143 if not entry:
91 144 if not l.startswith(':'):
@@ -97,15 +150,24 b' class convert_git(converter_source):'
97 150 seen.add(f)
98 151 entry = entry.split()
99 152 h = entry[3]
100 if entry[1] == '160000':
101 raise util.Abort('git submodules are not supported!')
102 153 p = (entry[1] == "100755")
103 154 s = (entry[1] == "120000")
104 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
105 changes.append((f, h))
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:
162 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
163 changes.append((f, h))
106 164 entry = None
107 165 if fh.close():
108 166 raise util.Abort(_('cannot read changes in %s') % version)
167
168 if subexists:
169 self.retrievegitmodules(version)
170 changes.append(('.hgsubstate', ''))
109 171 return (changes, {})
110 172
111 173 def getcommit(self, version):
@@ -298,3 +298,50 b' damage git repository and convert again'
298 298 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | \
299 299 > grep 'abort:' | sed 's/abort:.*/abort:/g'
300 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