##// END OF EJS Templates
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
Mateusz Kwapich -
r28660:cdda7b96 stable
parent child Browse files
Show More
@@ -1,432 +1,438 b''
1 # git.py - git support for the convert extension
1 # git.py - git support for the convert extension
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
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 import subprocess
9 import subprocess
10 from mercurial import util, config, error
10 from mercurial import util, config, error
11 from mercurial.node import hex, nullid
11 from mercurial.node import hex, nullid
12 from mercurial.i18n import _
12 from mercurial.i18n import _
13
13
14 from common import NoRepo, commit, converter_source, checktool, commandline
14 from common import NoRepo, commit, converter_source, checktool, commandline
15
15
16 class submodule(object):
16 class submodule(object):
17 def __init__(self, path, node, url):
17 def __init__(self, path, node, url):
18 self.path = path
18 self.path = path
19 self.node = node
19 self.node = node
20 self.url = url
20 self.url = url
21
21
22 def hgsub(self):
22 def hgsub(self):
23 return "%s = [git]%s" % (self.path, self.url)
23 return "%s = [git]%s" % (self.path, self.url)
24
24
25 def hgsubstate(self):
25 def hgsubstate(self):
26 return "%s %s" % (self.node, self.path)
26 return "%s %s" % (self.node, self.path)
27
27
28 class convert_git(converter_source, commandline):
28 class convert_git(converter_source, commandline):
29 # Windows does not support GIT_DIR= construct while other systems
29 # Windows does not support GIT_DIR= construct while other systems
30 # cannot remove environment variable. Just assume none have
30 # cannot remove environment variable. Just assume none have
31 # both issues.
31 # both issues.
32 if util.safehasattr(os, 'unsetenv'):
32 if util.safehasattr(os, 'unsetenv'):
33 def gitopen(self, s, err=None):
33 def gitopen(self, s, err=None):
34 prevgitdir = os.environ.get('GIT_DIR')
34 prevgitdir = os.environ.get('GIT_DIR')
35 os.environ['GIT_DIR'] = self.path
35 os.environ['GIT_DIR'] = self.path
36 try:
36 try:
37 if err == subprocess.PIPE:
37 if err == subprocess.PIPE:
38 (stdin, stdout, stderr) = util.popen3(s)
38 (stdin, stdout, stderr) = util.popen3(s)
39 return stdout
39 return stdout
40 elif err == subprocess.STDOUT:
40 elif err == subprocess.STDOUT:
41 return self.popen_with_stderr(s)
41 return self.popen_with_stderr(s)
42 else:
42 else:
43 return util.popen(s, 'rb')
43 return util.popen(s, 'rb')
44 finally:
44 finally:
45 if prevgitdir is None:
45 if prevgitdir is None:
46 del os.environ['GIT_DIR']
46 del os.environ['GIT_DIR']
47 else:
47 else:
48 os.environ['GIT_DIR'] = prevgitdir
48 os.environ['GIT_DIR'] = prevgitdir
49
49
50 def gitpipe(self, s):
50 def gitpipe(self, s):
51 prevgitdir = os.environ.get('GIT_DIR')
51 prevgitdir = os.environ.get('GIT_DIR')
52 os.environ['GIT_DIR'] = self.path
52 os.environ['GIT_DIR'] = self.path
53 try:
53 try:
54 return util.popen3(s)
54 return util.popen3(s)
55 finally:
55 finally:
56 if prevgitdir is None:
56 if prevgitdir is None:
57 del os.environ['GIT_DIR']
57 del os.environ['GIT_DIR']
58 else:
58 else:
59 os.environ['GIT_DIR'] = prevgitdir
59 os.environ['GIT_DIR'] = prevgitdir
60
60
61 else:
61 else:
62 def gitopen(self, s, err=None):
62 def gitopen(self, s, err=None):
63 if err == subprocess.PIPE:
63 if err == subprocess.PIPE:
64 (sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s))
64 (sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s))
65 return so
65 return so
66 elif err == subprocess.STDOUT:
66 elif err == subprocess.STDOUT:
67 return self.popen_with_stderr(s)
67 return self.popen_with_stderr(s)
68 else:
68 else:
69 return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
69 return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
70
70
71 def gitpipe(self, s):
71 def gitpipe(self, s):
72 return util.popen3('GIT_DIR=%s %s' % (self.path, s))
72 return util.popen3('GIT_DIR=%s %s' % (self.path, s))
73
73
74 def _gitcmd(self, cmd, *args, **kwargs):
74 def _gitcmd(self, cmd, *args, **kwargs):
75 return cmd('--git-dir=%s' % self.path, *args, **kwargs)
75 return cmd('--git-dir=%s' % self.path, *args, **kwargs)
76
76
77 def gitrun0(self, *args, **kwargs):
77 def gitrun0(self, *args, **kwargs):
78 return self._gitcmd(self.run0, *args, **kwargs)
78 return self._gitcmd(self.run0, *args, **kwargs)
79
79
80 def gitrun(self, *args, **kwargs):
80 def gitrun(self, *args, **kwargs):
81 return self._gitcmd(self.run, *args, **kwargs)
81 return self._gitcmd(self.run, *args, **kwargs)
82
82
83 def gitrunlines0(self, *args, **kwargs):
83 def gitrunlines0(self, *args, **kwargs):
84 return self._gitcmd(self.runlines0, *args, **kwargs)
84 return self._gitcmd(self.runlines0, *args, **kwargs)
85
85
86 def gitrunlines(self, *args, **kwargs):
86 def gitrunlines(self, *args, **kwargs):
87 return self._gitcmd(self.runlines, *args, **kwargs)
87 return self._gitcmd(self.runlines, *args, **kwargs)
88
88
89 def popen_with_stderr(self, s):
89 def popen_with_stderr(self, s):
90 p = subprocess.Popen(s, shell=True, bufsize=-1,
90 p = subprocess.Popen(s, shell=True, bufsize=-1,
91 close_fds=util.closefds,
91 close_fds=util.closefds,
92 stdin=subprocess.PIPE,
92 stdin=subprocess.PIPE,
93 stdout=subprocess.PIPE,
93 stdout=subprocess.PIPE,
94 stderr=subprocess.STDOUT,
94 stderr=subprocess.STDOUT,
95 universal_newlines=False,
95 universal_newlines=False,
96 env=None)
96 env=None)
97 return p.stdout
97 return p.stdout
98
98
99 def gitread(self, s):
99 def gitread(self, s):
100 fh = self.gitopen(s)
100 fh = self.gitopen(s)
101 data = fh.read()
101 data = fh.read()
102 return data, fh.close()
102 return data, fh.close()
103
103
104 def __init__(self, ui, path, revs=None):
104 def __init__(self, ui, path, revs=None):
105 super(convert_git, self).__init__(ui, path, revs=revs)
105 super(convert_git, self).__init__(ui, path, revs=revs)
106 commandline.__init__(self, ui, 'git')
106 commandline.__init__(self, ui, 'git')
107
107
108 if os.path.isdir(path + "/.git"):
108 if os.path.isdir(path + "/.git"):
109 path += "/.git"
109 path += "/.git"
110 if not os.path.exists(path + "/objects"):
110 if not os.path.exists(path + "/objects"):
111 raise NoRepo(_("%s does not look like a Git repository") % path)
111 raise NoRepo(_("%s does not look like a Git repository") % path)
112
112
113 # The default value (50) is based on the default for 'git diff'.
113 # The default value (50) is based on the default for 'git diff'.
114 similarity = ui.configint('convert', 'git.similarity', default=50)
114 similarity = ui.configint('convert', 'git.similarity', default=50)
115 if similarity < 0 or similarity > 100:
115 if similarity < 0 or similarity > 100:
116 raise error.Abort(_('similarity must be between 0 and 100'))
116 raise error.Abort(_('similarity must be between 0 and 100'))
117 if similarity > 0:
117 if similarity > 0:
118 self.simopt = '-C%d%%' % similarity
118 self.simopt = ['-C%d%%' % similarity]
119 findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
119 findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
120 False)
120 False)
121 if findcopiesharder:
121 if findcopiesharder:
122 self.simopt += ' --find-copies-harder'
122 self.simopt.append('--find-copies-harder')
123 else:
123 else:
124 self.simopt = ''
124 self.simopt = []
125
125
126 checktool('git', 'git')
126 checktool('git', 'git')
127
127
128 self.path = path
128 self.path = path
129 self.submodules = []
129 self.submodules = []
130
130
131 self.catfilepipe = self.gitpipe('git cat-file --batch')
131 self.catfilepipe = self.gitpipe('git cat-file --batch')
132
132
133 def after(self):
133 def after(self):
134 for f in self.catfilepipe:
134 for f in self.catfilepipe:
135 f.close()
135 f.close()
136
136
137 def getheads(self):
137 def getheads(self):
138 if not self.revs:
138 if not self.revs:
139 heads, ret = self.gitread('git rev-parse --branches --remotes')
139 output, status = self.gitrun('rev-parse', '--branches', '--remotes')
140 heads = heads.splitlines()
140 heads = output.splitlines()
141 if ret:
141 if status:
142 raise error.Abort(_('cannot retrieve git heads'))
142 raise error.Abort(_('cannot retrieve git heads'))
143 else:
143 else:
144 heads = []
144 heads = []
145 for rev in self.revs:
145 for rev in self.revs:
146 rawhead, ret = self.gitread("git rev-parse --verify %s" % rev)
146 rawhead, ret = self.gitrun('rev-parse', '--verify', rev)
147 heads.append(rawhead[:-1])
147 heads.append(rawhead[:-1])
148 if ret:
148 if ret:
149 raise error.Abort(_('cannot retrieve git head "%s"') % rev)
149 raise error.Abort(_('cannot retrieve git head "%s"') % rev)
150 return heads
150 return heads
151
151
152 def catfile(self, rev, type):
152 def catfile(self, rev, type):
153 if rev == hex(nullid):
153 if rev == hex(nullid):
154 raise IOError
154 raise IOError
155 self.catfilepipe[0].write(rev+'\n')
155 self.catfilepipe[0].write(rev+'\n')
156 self.catfilepipe[0].flush()
156 self.catfilepipe[0].flush()
157 info = self.catfilepipe[1].readline().split()
157 info = self.catfilepipe[1].readline().split()
158 if info[1] != type:
158 if info[1] != type:
159 raise error.Abort(_('cannot read %r object at %s') % (type, rev))
159 raise error.Abort(_('cannot read %r object at %s') % (type, rev))
160 size = int(info[2])
160 size = int(info[2])
161 data = self.catfilepipe[1].read(size)
161 data = self.catfilepipe[1].read(size)
162 if len(data) < size:
162 if len(data) < size:
163 raise error.Abort(_('cannot read %r object at %s: unexpected size')
163 raise error.Abort(_('cannot read %r object at %s: unexpected size')
164 % (type, rev))
164 % (type, rev))
165 # read the trailing newline
165 # read the trailing newline
166 self.catfilepipe[1].read(1)
166 self.catfilepipe[1].read(1)
167 return data
167 return data
168
168
169 def getfile(self, name, rev):
169 def getfile(self, name, rev):
170 if rev == hex(nullid):
170 if rev == hex(nullid):
171 return None, None
171 return None, None
172 if name == '.hgsub':
172 if name == '.hgsub':
173 data = '\n'.join([m.hgsub() for m in self.submoditer()])
173 data = '\n'.join([m.hgsub() for m in self.submoditer()])
174 mode = ''
174 mode = ''
175 elif name == '.hgsubstate':
175 elif name == '.hgsubstate':
176 data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
176 data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
177 mode = ''
177 mode = ''
178 else:
178 else:
179 data = self.catfile(rev, "blob")
179 data = self.catfile(rev, "blob")
180 mode = self.modecache[(name, rev)]
180 mode = self.modecache[(name, rev)]
181 return data, mode
181 return data, mode
182
182
183 def submoditer(self):
183 def submoditer(self):
184 null = hex(nullid)
184 null = hex(nullid)
185 for m in sorted(self.submodules, key=lambda p: p.path):
185 for m in sorted(self.submodules, key=lambda p: p.path):
186 if m.node != null:
186 if m.node != null:
187 yield m
187 yield m
188
188
189 def parsegitmodules(self, content):
189 def parsegitmodules(self, content):
190 """Parse the formatted .gitmodules file, example file format:
190 """Parse the formatted .gitmodules file, example file format:
191 [submodule "sub"]\n
191 [submodule "sub"]\n
192 \tpath = sub\n
192 \tpath = sub\n
193 \turl = git://giturl\n
193 \turl = git://giturl\n
194 """
194 """
195 self.submodules = []
195 self.submodules = []
196 c = config.config()
196 c = config.config()
197 # Each item in .gitmodules starts with whitespace that cant be parsed
197 # Each item in .gitmodules starts with whitespace that cant be parsed
198 c.parse('.gitmodules', '\n'.join(line.strip() for line in
198 c.parse('.gitmodules', '\n'.join(line.strip() for line in
199 content.split('\n')))
199 content.split('\n')))
200 for sec in c.sections():
200 for sec in c.sections():
201 s = c[sec]
201 s = c[sec]
202 if 'url' in s and 'path' in s:
202 if 'url' in s and 'path' in s:
203 self.submodules.append(submodule(s['path'], '', s['url']))
203 self.submodules.append(submodule(s['path'], '', s['url']))
204
204
205 def retrievegitmodules(self, version):
205 def retrievegitmodules(self, version):
206 modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
206 modules, ret = self.gitrun('show', '%s:%s' % (version, '.gitmodules'))
207 if ret:
207 if ret:
208 # This can happen if a file is in the repo that has permissions
208 # This can happen if a file is in the repo that has permissions
209 # 160000, but there is no .gitmodules file.
209 # 160000, but there is no .gitmodules file.
210 self.ui.warn(_("warning: cannot read submodules config file in "
210 self.ui.warn(_("warning: cannot read submodules config file in "
211 "%s\n") % version)
211 "%s\n") % version)
212 return
212 return
213
213
214 try:
214 try:
215 self.parsegitmodules(modules)
215 self.parsegitmodules(modules)
216 except error.ParseError:
216 except error.ParseError:
217 self.ui.warn(_("warning: unable to parse .gitmodules in %s\n")
217 self.ui.warn(_("warning: unable to parse .gitmodules in %s\n")
218 % version)
218 % version)
219 return
219 return
220
220
221 for m in self.submodules:
221 for m in self.submodules:
222 node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path))
222 node, ret = self.gitrun('rev-parse', '%s:%s' % (version, m.path))
223 if ret:
223 if ret:
224 continue
224 continue
225 m.node = node.strip()
225 m.node = node.strip()
226
226
227 def getchanges(self, version, full):
227 def getchanges(self, version, full):
228 if full:
228 if full:
229 raise error.Abort(_("convert from git does not support --full"))
229 raise error.Abort(_("convert from git does not support --full"))
230 self.modecache = {}
230 self.modecache = {}
231 fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % (
231 cmd = ['diff-tree','-z', '--root', '-m', '-r'] + self.simopt + [version]
232 self.simopt, version))
232 output, status = self.gitrun(*cmd)
233 if status:
234 raise error.Abort(_('cannot read changes in %s') % version)
233 changes = []
235 changes = []
234 copies = {}
236 copies = {}
235 seen = set()
237 seen = set()
236 entry = None
238 entry = None
237 subexists = [False]
239 subexists = [False]
238 subdeleted = [False]
240 subdeleted = [False]
239 difftree = fh.read().split('\x00')
241 difftree = output.split('\x00')
240 lcount = len(difftree)
242 lcount = len(difftree)
241 i = 0
243 i = 0
242
244
243 skipsubmodules = self.ui.configbool('convert', 'git.skipsubmodules',
245 skipsubmodules = self.ui.configbool('convert', 'git.skipsubmodules',
244 False)
246 False)
245 def add(entry, f, isdest):
247 def add(entry, f, isdest):
246 seen.add(f)
248 seen.add(f)
247 h = entry[3]
249 h = entry[3]
248 p = (entry[1] == "100755")
250 p = (entry[1] == "100755")
249 s = (entry[1] == "120000")
251 s = (entry[1] == "120000")
250 renamesource = (not isdest and entry[4][0] == 'R')
252 renamesource = (not isdest and entry[4][0] == 'R')
251
253
252 if f == '.gitmodules':
254 if f == '.gitmodules':
253 if skipsubmodules:
255 if skipsubmodules:
254 return
256 return
255
257
256 subexists[0] = True
258 subexists[0] = True
257 if entry[4] == 'D' or renamesource:
259 if entry[4] == 'D' or renamesource:
258 subdeleted[0] = True
260 subdeleted[0] = True
259 changes.append(('.hgsub', hex(nullid)))
261 changes.append(('.hgsub', hex(nullid)))
260 else:
262 else:
261 changes.append(('.hgsub', ''))
263 changes.append(('.hgsub', ''))
262 elif entry[1] == '160000' or entry[0] == ':160000':
264 elif entry[1] == '160000' or entry[0] == ':160000':
263 if not skipsubmodules:
265 if not skipsubmodules:
264 subexists[0] = True
266 subexists[0] = True
265 else:
267 else:
266 if renamesource:
268 if renamesource:
267 h = hex(nullid)
269 h = hex(nullid)
268 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
270 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
269 changes.append((f, h))
271 changes.append((f, h))
270
272
271 while i < lcount:
273 while i < lcount:
272 l = difftree[i]
274 l = difftree[i]
273 i += 1
275 i += 1
274 if not entry:
276 if not entry:
275 if not l.startswith(':'):
277 if not l.startswith(':'):
276 continue
278 continue
277 entry = l.split()
279 entry = l.split()
278 continue
280 continue
279 f = l
281 f = l
280 if entry[4][0] == 'C':
282 if entry[4][0] == 'C':
281 copysrc = f
283 copysrc = f
282 copydest = difftree[i]
284 copydest = difftree[i]
283 i += 1
285 i += 1
284 f = copydest
286 f = copydest
285 copies[copydest] = copysrc
287 copies[copydest] = copysrc
286 if f not in seen:
288 if f not in seen:
287 add(entry, f, False)
289 add(entry, f, False)
288 # A file can be copied multiple times, or modified and copied
290 # A file can be copied multiple times, or modified and copied
289 # simultaneously. So f can be repeated even if fdest isn't.
291 # simultaneously. So f can be repeated even if fdest isn't.
290 if entry[4][0] == 'R':
292 if entry[4][0] == 'R':
291 # rename: next line is the destination
293 # rename: next line is the destination
292 fdest = difftree[i]
294 fdest = difftree[i]
293 i += 1
295 i += 1
294 if fdest not in seen:
296 if fdest not in seen:
295 add(entry, fdest, True)
297 add(entry, fdest, True)
296 # .gitmodules isn't imported at all, so it being copied to
298 # .gitmodules isn't imported at all, so it being copied to
297 # and fro doesn't really make sense
299 # and fro doesn't really make sense
298 if f != '.gitmodules' and fdest != '.gitmodules':
300 if f != '.gitmodules' and fdest != '.gitmodules':
299 copies[fdest] = f
301 copies[fdest] = f
300 entry = None
302 entry = None
301 if fh.close():
302 raise error.Abort(_('cannot read changes in %s') % version)
303
303
304 if subexists[0]:
304 if subexists[0]:
305 if subdeleted[0]:
305 if subdeleted[0]:
306 changes.append(('.hgsubstate', hex(nullid)))
306 changes.append(('.hgsubstate', hex(nullid)))
307 else:
307 else:
308 self.retrievegitmodules(version)
308 self.retrievegitmodules(version)
309 changes.append(('.hgsubstate', ''))
309 changes.append(('.hgsubstate', ''))
310 return (changes, copies, set())
310 return (changes, copies, set())
311
311
312 def getcommit(self, version):
312 def getcommit(self, version):
313 c = self.catfile(version, "commit") # read the commit hash
313 c = self.catfile(version, "commit") # read the commit hash
314 end = c.find("\n\n")
314 end = c.find("\n\n")
315 message = c[end + 2:]
315 message = c[end + 2:]
316 message = self.recode(message)
316 message = self.recode(message)
317 l = c[:end].splitlines()
317 l = c[:end].splitlines()
318 parents = []
318 parents = []
319 author = committer = None
319 author = committer = None
320 for e in l[1:]:
320 for e in l[1:]:
321 n, v = e.split(" ", 1)
321 n, v = e.split(" ", 1)
322 if n == "author":
322 if n == "author":
323 p = v.split()
323 p = v.split()
324 tm, tz = p[-2:]
324 tm, tz = p[-2:]
325 author = " ".join(p[:-2])
325 author = " ".join(p[:-2])
326 if author[0] == "<": author = author[1:-1]
326 if author[0] == "<": author = author[1:-1]
327 author = self.recode(author)
327 author = self.recode(author)
328 if n == "committer":
328 if n == "committer":
329 p = v.split()
329 p = v.split()
330 tm, tz = p[-2:]
330 tm, tz = p[-2:]
331 committer = " ".join(p[:-2])
331 committer = " ".join(p[:-2])
332 if committer[0] == "<": committer = committer[1:-1]
332 if committer[0] == "<": committer = committer[1:-1]
333 committer = self.recode(committer)
333 committer = self.recode(committer)
334 if n == "parent":
334 if n == "parent":
335 parents.append(v)
335 parents.append(v)
336
336
337 if committer and committer != author:
337 if committer and committer != author:
338 message += "\ncommitter: %s\n" % committer
338 message += "\ncommitter: %s\n" % committer
339 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
339 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
340 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
340 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
341 date = tm + " " + str(tz)
341 date = tm + " " + str(tz)
342
342
343 c = commit(parents=parents, date=date, author=author, desc=message,
343 c = commit(parents=parents, date=date, author=author, desc=message,
344 rev=version)
344 rev=version)
345 return c
345 return c
346
346
347 def numcommits(self):
347 def numcommits(self):
348 return len([None for _ in self.gitopen('git rev-list --all')])
348 output, ret = self.gitrunlines('rev-list', '--all')
349 if ret:
350 raise error.Abort(_('cannot retrieve number of commits in %s') \
351 % self.path)
352 return len(output)
349
353
350 def gettags(self):
354 def gettags(self):
351 tags = {}
355 tags = {}
352 alltags = {}
356 alltags = {}
353 fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
357 output, status = self.gitrunlines('ls-remote', '--tags', self.path)
354 err=subprocess.STDOUT)
358
359 if status:
360 raise error.Abort(_('cannot read tags from %s') % self.path)
355 prefix = 'refs/tags/'
361 prefix = 'refs/tags/'
356
362
357 # Build complete list of tags, both annotated and bare ones
363 # Build complete list of tags, both annotated and bare ones
358 for line in fh:
364 for line in output:
359 line = line.strip()
365 line = line.strip()
360 if line.startswith("error:") or line.startswith("fatal:"):
366 if line.startswith("error:") or line.startswith("fatal:"):
361 raise error.Abort(_('cannot read tags from %s') % self.path)
367 raise error.Abort(_('cannot read tags from %s') % self.path)
362 node, tag = line.split(None, 1)
368 node, tag = line.split(None, 1)
363 if not tag.startswith(prefix):
369 if not tag.startswith(prefix):
364 continue
370 continue
365 alltags[tag[len(prefix):]] = node
371 alltags[tag[len(prefix):]] = node
366 if fh.close():
367 raise error.Abort(_('cannot read tags from %s') % self.path)
368
372
369 # Filter out tag objects for annotated tag refs
373 # Filter out tag objects for annotated tag refs
370 for tag in alltags:
374 for tag in alltags:
371 if tag.endswith('^{}'):
375 if tag.endswith('^{}'):
372 tags[tag[:-3]] = alltags[tag]
376 tags[tag[:-3]] = alltags[tag]
373 else:
377 else:
374 if tag + '^{}' in alltags:
378 if tag + '^{}' in alltags:
375 continue
379 continue
376 else:
380 else:
377 tags[tag] = alltags[tag]
381 tags[tag] = alltags[tag]
378
382
379 return tags
383 return tags
380
384
381 def getchangedfiles(self, version, i):
385 def getchangedfiles(self, version, i):
382 changes = []
386 changes = []
383 if i is None:
387 if i is None:
384 fh = self.gitopen("git diff-tree --root -m -r %s" % version)
388 output, status = self.gitrunlines('diff-tree', '--root', '-m',
385 for l in fh:
389 '-r', version)
390 if status:
391 raise error.Abort(_('cannot read changes in %s') % version)
392 for l in output:
386 if "\t" not in l:
393 if "\t" not in l:
387 continue
394 continue
388 m, f = l[:-1].split("\t")
395 m, f = l[:-1].split("\t")
389 changes.append(f)
396 changes.append(f)
390 else:
397 else:
391 fh = self.gitopen('git diff-tree --name-only --root -r %s '
398 output, status = self.gitrunlines('diff-tree', '--name-only',
392 '"%s^%s" --' % (version, version, i + 1))
399 '--root', '-r', version,
393 changes = [f.rstrip('\n') for f in fh]
400 '%s^%s' % (version, i + 1), '--')
394 if fh.close():
401 changes = [f.rstrip('\n') for f in output]
395 raise error.Abort(_('cannot read changes in %s') % version)
396
402
397 return changes
403 return changes
398
404
399 def getbookmarks(self):
405 def getbookmarks(self):
400 bookmarks = {}
406 bookmarks = {}
401
407
402 # Handle local and remote branches
408 # Handle local and remote branches
403 remoteprefix = self.ui.config('convert', 'git.remoteprefix', 'remote')
409 remoteprefix = self.ui.config('convert', 'git.remoteprefix', 'remote')
404 reftypes = [
410 reftypes = [
405 # (git prefix, hg prefix)
411 # (git prefix, hg prefix)
406 ('refs/remotes/origin/', remoteprefix + '/'),
412 ('refs/remotes/origin/', remoteprefix + '/'),
407 ('refs/heads/', '')
413 ('refs/heads/', '')
408 ]
414 ]
409
415
410 exclude = set([
416 exclude = set([
411 'refs/remotes/origin/HEAD',
417 'refs/remotes/origin/HEAD',
412 ])
418 ])
413
419
414 try:
420 try:
415 fh = self.gitopen('git show-ref', err=subprocess.PIPE)
421 output, status = self.gitrunlines('show-ref')
416 for line in fh:
422 for line in output:
417 line = line.strip()
423 line = line.strip()
418 rev, name = line.split(None, 1)
424 rev, name = line.split(None, 1)
419 # Process each type of branch
425 # Process each type of branch
420 for gitprefix, hgprefix in reftypes:
426 for gitprefix, hgprefix in reftypes:
421 if not name.startswith(gitprefix) or name in exclude:
427 if not name.startswith(gitprefix) or name in exclude:
422 continue
428 continue
423 name = '%s%s' % (hgprefix, name[len(gitprefix):])
429 name = '%s%s' % (hgprefix, name[len(gitprefix):])
424 bookmarks[name] = rev
430 bookmarks[name] = rev
425 except Exception:
431 except Exception:
426 pass
432 pass
427
433
428 return bookmarks
434 return bookmarks
429
435
430 def checkrevformat(self, revstr, mapname='splicemap'):
436 def checkrevformat(self, revstr, mapname='splicemap'):
431 """ git revision string is a 40 byte hex """
437 """ git revision string is a 40 byte hex """
432 self.checkhexformat(revstr, mapname)
438 self.checkhexformat(revstr, mapname)
@@ -1,731 +1,731 b''
1 #require git
1 #require git
2
2
3 $ echo "[core]" >> $HOME/.gitconfig
3 $ echo "[core]" >> $HOME/.gitconfig
4 $ echo "autocrlf = false" >> $HOME/.gitconfig
4 $ echo "autocrlf = false" >> $HOME/.gitconfig
5 $ echo "[core]" >> $HOME/.gitconfig
5 $ echo "[core]" >> $HOME/.gitconfig
6 $ echo "autocrlf = false" >> $HOME/.gitconfig
6 $ echo "autocrlf = false" >> $HOME/.gitconfig
7 $ echo "[extensions]" >> $HGRCPATH
7 $ echo "[extensions]" >> $HGRCPATH
8 $ echo "convert=" >> $HGRCPATH
8 $ echo "convert=" >> $HGRCPATH
9 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
9 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
10 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
10 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
11 $ GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE
11 $ GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE
12 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
12 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
13 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
13 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
14 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
14 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
15 $ INVALIDID1=afd12345af
15 $ INVALIDID1=afd12345af
16 $ INVALIDID2=28173x36ddd1e67bf7098d541130558ef5534a86
16 $ INVALIDID2=28173x36ddd1e67bf7098d541130558ef5534a86
17 $ VALIDID1=39b3d83f9a69a9ba4ebb111461071a0af0027357
17 $ VALIDID1=39b3d83f9a69a9ba4ebb111461071a0af0027357
18 $ VALIDID2=8dd6476bd09d9c7776355dc454dafe38efaec5da
18 $ VALIDID2=8dd6476bd09d9c7776355dc454dafe38efaec5da
19 $ count=10
19 $ count=10
20 $ commit()
20 $ commit()
21 > {
21 > {
22 > GIT_AUTHOR_DATE="2007-01-01 00:00:$count +0000"
22 > GIT_AUTHOR_DATE="2007-01-01 00:00:$count +0000"
23 > GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
23 > GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
24 > git commit "$@" >/dev/null 2>/dev/null || echo "git commit error"
24 > git commit "$@" >/dev/null 2>/dev/null || echo "git commit error"
25 > count=`expr $count + 1`
25 > count=`expr $count + 1`
26 > }
26 > }
27 $ mkdir git-repo
27 $ mkdir git-repo
28 $ cd git-repo
28 $ cd git-repo
29 $ git init-db >/dev/null 2>/dev/null
29 $ git init-db >/dev/null 2>/dev/null
30 $ echo a > a
30 $ echo a > a
31 $ mkdir d
31 $ mkdir d
32 $ echo b > d/b
32 $ echo b > d/b
33 $ git add a d
33 $ git add a d
34 $ commit -a -m t1
34 $ commit -a -m t1
35
35
36 Remove the directory, then try to replace it with a file (issue754)
36 Remove the directory, then try to replace it with a file (issue754)
37
37
38 $ git rm -f d/b
38 $ git rm -f d/b
39 rm 'd/b'
39 rm 'd/b'
40 $ commit -m t2
40 $ commit -m t2
41 $ echo d > d
41 $ echo d > d
42 $ git add d
42 $ git add d
43 $ commit -m t3
43 $ commit -m t3
44 $ echo b >> a
44 $ echo b >> a
45 $ commit -a -m t4.1
45 $ commit -a -m t4.1
46 $ git checkout -b other HEAD~ >/dev/null 2>/dev/null
46 $ git checkout -b other HEAD~ >/dev/null 2>/dev/null
47 $ echo c > a
47 $ echo c > a
48 $ echo a >> a
48 $ echo a >> a
49 $ commit -a -m t4.2
49 $ commit -a -m t4.2
50 $ git checkout master >/dev/null 2>/dev/null
50 $ git checkout master >/dev/null 2>/dev/null
51 $ git pull --no-commit . other > /dev/null 2>/dev/null
51 $ git pull --no-commit . other > /dev/null 2>/dev/null
52 $ commit -m 'Merge branch other'
52 $ commit -m 'Merge branch other'
53 $ cd ..
53 $ cd ..
54 $ hg convert --config extensions.progress= --config progress.assume-tty=1 \
54 $ hg convert --config extensions.progress= --config progress.assume-tty=1 \
55 > --config progress.delay=0 --config progress.changedelay=0 \
55 > --config progress.delay=0 --config progress.changedelay=0 \
56 > --config progress.refresh=0 --config progress.width=60 \
56 > --config progress.refresh=0 --config progress.width=60 \
57 > --config progress.format='topic, bar, number' --datesort git-repo
57 > --config progress.format='topic, bar, number' --datesort git-repo
58 \r (no-eol) (esc)
58 \r (no-eol) (esc)
59 scanning [======> ] 1/6\r (no-eol) (esc)
59 scanning [======> ] 1/6\r (no-eol) (esc)
60 scanning [=============> ] 2/6\r (no-eol) (esc)
60 scanning [=============> ] 2/6\r (no-eol) (esc)
61 scanning [=====================> ] 3/6\r (no-eol) (esc)
61 scanning [=====================> ] 3/6\r (no-eol) (esc)
62 scanning [============================> ] 4/6\r (no-eol) (esc)
62 scanning [============================> ] 4/6\r (no-eol) (esc)
63 scanning [===================================> ] 5/6\r (no-eol) (esc)
63 scanning [===================================> ] 5/6\r (no-eol) (esc)
64 scanning [===========================================>] 6/6\r (no-eol) (esc)
64 scanning [===========================================>] 6/6\r (no-eol) (esc)
65 \r (no-eol) (esc)
65 \r (no-eol) (esc)
66 \r (no-eol) (esc)
66 \r (no-eol) (esc)
67 converting [ ] 0/6\r (no-eol) (esc)
67 converting [ ] 0/6\r (no-eol) (esc)
68 getting files [==================> ] 1/2\r (no-eol) (esc)
68 getting files [==================> ] 1/2\r (no-eol) (esc)
69 getting files [======================================>] 2/2\r (no-eol) (esc)
69 getting files [======================================>] 2/2\r (no-eol) (esc)
70 \r (no-eol) (esc)
70 \r (no-eol) (esc)
71 \r (no-eol) (esc)
71 \r (no-eol) (esc)
72 converting [======> ] 1/6\r (no-eol) (esc)
72 converting [======> ] 1/6\r (no-eol) (esc)
73 getting files [======================================>] 1/1\r (no-eol) (esc)
73 getting files [======================================>] 1/1\r (no-eol) (esc)
74 \r (no-eol) (esc)
74 \r (no-eol) (esc)
75 \r (no-eol) (esc)
75 \r (no-eol) (esc)
76 converting [=============> ] 2/6\r (no-eol) (esc)
76 converting [=============> ] 2/6\r (no-eol) (esc)
77 getting files [======================================>] 1/1\r (no-eol) (esc)
77 getting files [======================================>] 1/1\r (no-eol) (esc)
78 \r (no-eol) (esc)
78 \r (no-eol) (esc)
79 \r (no-eol) (esc)
79 \r (no-eol) (esc)
80 converting [====================> ] 3/6\r (no-eol) (esc)
80 converting [====================> ] 3/6\r (no-eol) (esc)
81 getting files [======================================>] 1/1\r (no-eol) (esc)
81 getting files [======================================>] 1/1\r (no-eol) (esc)
82 \r (no-eol) (esc)
82 \r (no-eol) (esc)
83 \r (no-eol) (esc)
83 \r (no-eol) (esc)
84 converting [===========================> ] 4/6\r (no-eol) (esc)
84 converting [===========================> ] 4/6\r (no-eol) (esc)
85 getting files [======================================>] 1/1\r (no-eol) (esc)
85 getting files [======================================>] 1/1\r (no-eol) (esc)
86 \r (no-eol) (esc)
86 \r (no-eol) (esc)
87 \r (no-eol) (esc)
87 \r (no-eol) (esc)
88 converting [==================================> ] 5/6\r (no-eol) (esc)
88 converting [==================================> ] 5/6\r (no-eol) (esc)
89 getting files [======================================>] 1/1\r (no-eol) (esc)
89 getting files [======================================>] 1/1\r (no-eol) (esc)
90 \r (no-eol) (esc)
90 \r (no-eol) (esc)
91 assuming destination git-repo-hg
91 assuming destination git-repo-hg
92 initializing destination git-repo-hg repository
92 initializing destination git-repo-hg repository
93 scanning source...
93 scanning source...
94 sorting...
94 sorting...
95 converting...
95 converting...
96 5 t1
96 5 t1
97 4 t2
97 4 t2
98 3 t3
98 3 t3
99 2 t4.1
99 2 t4.1
100 1 t4.2
100 1 t4.2
101 0 Merge branch other
101 0 Merge branch other
102 updating bookmarks
102 updating bookmarks
103 $ hg up -q -R git-repo-hg
103 $ hg up -q -R git-repo-hg
104 $ hg -R git-repo-hg tip -v
104 $ hg -R git-repo-hg tip -v
105 changeset: 5:c78094926be2
105 changeset: 5:c78094926be2
106 bookmark: master
106 bookmark: master
107 tag: tip
107 tag: tip
108 parent: 3:f5f5cb45432b
108 parent: 3:f5f5cb45432b
109 parent: 4:4e174f80c67c
109 parent: 4:4e174f80c67c
110 user: test <test@example.org>
110 user: test <test@example.org>
111 date: Mon Jan 01 00:00:15 2007 +0000
111 date: Mon Jan 01 00:00:15 2007 +0000
112 files: a
112 files: a
113 description:
113 description:
114 Merge branch other
114 Merge branch other
115
115
116
116
117 $ count=10
117 $ count=10
118 $ mkdir git-repo2
118 $ mkdir git-repo2
119 $ cd git-repo2
119 $ cd git-repo2
120 $ git init-db >/dev/null 2>/dev/null
120 $ git init-db >/dev/null 2>/dev/null
121 $ echo foo > foo
121 $ echo foo > foo
122 $ git add foo
122 $ git add foo
123 $ commit -a -m 'add foo'
123 $ commit -a -m 'add foo'
124 $ echo >> foo
124 $ echo >> foo
125 $ commit -a -m 'change foo'
125 $ commit -a -m 'change foo'
126 $ git checkout -b Bar HEAD~ >/dev/null 2>/dev/null
126 $ git checkout -b Bar HEAD~ >/dev/null 2>/dev/null
127 $ echo quux >> quux
127 $ echo quux >> quux
128 $ git add quux
128 $ git add quux
129 $ commit -a -m 'add quux'
129 $ commit -a -m 'add quux'
130 $ echo bar > bar
130 $ echo bar > bar
131 $ git add bar
131 $ git add bar
132 $ commit -a -m 'add bar'
132 $ commit -a -m 'add bar'
133 $ git checkout -b Baz HEAD~ >/dev/null 2>/dev/null
133 $ git checkout -b Baz HEAD~ >/dev/null 2>/dev/null
134 $ echo baz > baz
134 $ echo baz > baz
135 $ git add baz
135 $ git add baz
136 $ commit -a -m 'add baz'
136 $ commit -a -m 'add baz'
137 $ git checkout master >/dev/null 2>/dev/null
137 $ git checkout master >/dev/null 2>/dev/null
138 $ git pull --no-commit . Bar Baz > /dev/null 2>/dev/null
138 $ git pull --no-commit . Bar Baz > /dev/null 2>/dev/null
139 $ commit -m 'Octopus merge'
139 $ commit -m 'Octopus merge'
140 $ echo bar >> bar
140 $ echo bar >> bar
141 $ commit -a -m 'change bar'
141 $ commit -a -m 'change bar'
142 $ git checkout -b Foo HEAD~ >/dev/null 2>/dev/null
142 $ git checkout -b Foo HEAD~ >/dev/null 2>/dev/null
143 $ echo >> foo
143 $ echo >> foo
144 $ commit -a -m 'change foo'
144 $ commit -a -m 'change foo'
145 $ git checkout master >/dev/null 2>/dev/null
145 $ git checkout master >/dev/null 2>/dev/null
146 $ git pull --no-commit -s ours . Foo > /dev/null 2>/dev/null
146 $ git pull --no-commit -s ours . Foo > /dev/null 2>/dev/null
147 $ commit -m 'Discard change to foo'
147 $ commit -m 'Discard change to foo'
148 $ cd ..
148 $ cd ..
149 $ glog()
149 $ glog()
150 > {
150 > {
151 > hg log -G --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
151 > hg log -G --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
152 > }
152 > }
153 $ splitrepo()
153 $ splitrepo()
154 > {
154 > {
155 > msg="$1"
155 > msg="$1"
156 > files="$2"
156 > files="$2"
157 > opts=$3
157 > opts=$3
158 > echo "% $files: $msg"
158 > echo "% $files: $msg"
159 > prefix=`echo "$files" | sed -e 's/ /-/g'`
159 > prefix=`echo "$files" | sed -e 's/ /-/g'`
160 > fmap="$prefix.fmap"
160 > fmap="$prefix.fmap"
161 > repo="$prefix.repo"
161 > repo="$prefix.repo"
162 > for i in $files; do
162 > for i in $files; do
163 > echo "include $i" >> "$fmap"
163 > echo "include $i" >> "$fmap"
164 > done
164 > done
165 > hg -q convert $opts --filemap "$fmap" --datesort git-repo2 "$repo"
165 > hg -q convert $opts --filemap "$fmap" --datesort git-repo2 "$repo"
166 > hg up -q -R "$repo"
166 > hg up -q -R "$repo"
167 > glog -R "$repo"
167 > glog -R "$repo"
168 > hg -R "$repo" manifest --debug
168 > hg -R "$repo" manifest --debug
169 > }
169 > }
170
170
171 full conversion
171 full conversion
172
172
173 $ hg convert --datesort git-repo2 fullrepo \
173 $ hg convert --datesort git-repo2 fullrepo \
174 > --config extensions.progress= --config progress.assume-tty=1 \
174 > --config extensions.progress= --config progress.assume-tty=1 \
175 > --config progress.delay=0 --config progress.changedelay=0 \
175 > --config progress.delay=0 --config progress.changedelay=0 \
176 > --config progress.refresh=0 --config progress.width=60 \
176 > --config progress.refresh=0 --config progress.width=60 \
177 > --config progress.format='topic, bar, number'
177 > --config progress.format='topic, bar, number'
178 \r (no-eol) (esc)
178 \r (no-eol) (esc)
179 scanning [===> ] 1/9\r (no-eol) (esc)
179 scanning [===> ] 1/9\r (no-eol) (esc)
180 scanning [========> ] 2/9\r (no-eol) (esc)
180 scanning [========> ] 2/9\r (no-eol) (esc)
181 scanning [=============> ] 3/9\r (no-eol) (esc)
181 scanning [=============> ] 3/9\r (no-eol) (esc)
182 scanning [==================> ] 4/9\r (no-eol) (esc)
182 scanning [==================> ] 4/9\r (no-eol) (esc)
183 scanning [=======================> ] 5/9\r (no-eol) (esc)
183 scanning [=======================> ] 5/9\r (no-eol) (esc)
184 scanning [============================> ] 6/9\r (no-eol) (esc)
184 scanning [============================> ] 6/9\r (no-eol) (esc)
185 scanning [=================================> ] 7/9\r (no-eol) (esc)
185 scanning [=================================> ] 7/9\r (no-eol) (esc)
186 scanning [======================================> ] 8/9\r (no-eol) (esc)
186 scanning [======================================> ] 8/9\r (no-eol) (esc)
187 scanning [===========================================>] 9/9\r (no-eol) (esc)
187 scanning [===========================================>] 9/9\r (no-eol) (esc)
188 \r (no-eol) (esc)
188 \r (no-eol) (esc)
189 \r (no-eol) (esc)
189 \r (no-eol) (esc)
190 converting [ ] 0/9\r (no-eol) (esc)
190 converting [ ] 0/9\r (no-eol) (esc)
191 getting files [======================================>] 1/1\r (no-eol) (esc)
191 getting files [======================================>] 1/1\r (no-eol) (esc)
192 \r (no-eol) (esc)
192 \r (no-eol) (esc)
193 \r (no-eol) (esc)
193 \r (no-eol) (esc)
194 converting [===> ] 1/9\r (no-eol) (esc)
194 converting [===> ] 1/9\r (no-eol) (esc)
195 getting files [======================================>] 1/1\r (no-eol) (esc)
195 getting files [======================================>] 1/1\r (no-eol) (esc)
196 \r (no-eol) (esc)
196 \r (no-eol) (esc)
197 \r (no-eol) (esc)
197 \r (no-eol) (esc)
198 converting [========> ] 2/9\r (no-eol) (esc)
198 converting [========> ] 2/9\r (no-eol) (esc)
199 getting files [======================================>] 1/1\r (no-eol) (esc)
199 getting files [======================================>] 1/1\r (no-eol) (esc)
200 \r (no-eol) (esc)
200 \r (no-eol) (esc)
201 \r (no-eol) (esc)
201 \r (no-eol) (esc)
202 converting [=============> ] 3/9\r (no-eol) (esc)
202 converting [=============> ] 3/9\r (no-eol) (esc)
203 getting files [======================================>] 1/1\r (no-eol) (esc)
203 getting files [======================================>] 1/1\r (no-eol) (esc)
204 \r (no-eol) (esc)
204 \r (no-eol) (esc)
205 \r (no-eol) (esc)
205 \r (no-eol) (esc)
206 converting [=================> ] 4/9\r (no-eol) (esc)
206 converting [=================> ] 4/9\r (no-eol) (esc)
207 getting files [======================================>] 1/1\r (no-eol) (esc)
207 getting files [======================================>] 1/1\r (no-eol) (esc)
208 \r (no-eol) (esc)
208 \r (no-eol) (esc)
209 \r (no-eol) (esc)
209 \r (no-eol) (esc)
210 converting [======================> ] 5/9\r (no-eol) (esc)
210 converting [======================> ] 5/9\r (no-eol) (esc)
211 getting files [===> ] 1/8\r (no-eol) (esc)
211 getting files [===> ] 1/8\r (no-eol) (esc)
212 getting files [========> ] 2/8\r (no-eol) (esc)
212 getting files [========> ] 2/8\r (no-eol) (esc)
213 getting files [=============> ] 3/8\r (no-eol) (esc)
213 getting files [=============> ] 3/8\r (no-eol) (esc)
214 getting files [==================> ] 4/8\r (no-eol) (esc)
214 getting files [==================> ] 4/8\r (no-eol) (esc)
215 getting files [=======================> ] 5/8\r (no-eol) (esc)
215 getting files [=======================> ] 5/8\r (no-eol) (esc)
216 getting files [============================> ] 6/8\r (no-eol) (esc)
216 getting files [============================> ] 6/8\r (no-eol) (esc)
217 getting files [=================================> ] 7/8\r (no-eol) (esc)
217 getting files [=================================> ] 7/8\r (no-eol) (esc)
218 getting files [======================================>] 8/8\r (no-eol) (esc)
218 getting files [======================================>] 8/8\r (no-eol) (esc)
219 \r (no-eol) (esc)
219 \r (no-eol) (esc)
220 \r (no-eol) (esc)
220 \r (no-eol) (esc)
221 converting [===========================> ] 6/9\r (no-eol) (esc)
221 converting [===========================> ] 6/9\r (no-eol) (esc)
222 getting files [======================================>] 1/1\r (no-eol) (esc)
222 getting files [======================================>] 1/1\r (no-eol) (esc)
223 \r (no-eol) (esc)
223 \r (no-eol) (esc)
224 \r (no-eol) (esc)
224 \r (no-eol) (esc)
225 converting [===============================> ] 7/9\r (no-eol) (esc)
225 converting [===============================> ] 7/9\r (no-eol) (esc)
226 getting files [======================================>] 1/1\r (no-eol) (esc)
226 getting files [======================================>] 1/1\r (no-eol) (esc)
227 \r (no-eol) (esc)
227 \r (no-eol) (esc)
228 \r (no-eol) (esc)
228 \r (no-eol) (esc)
229 converting [====================================> ] 8/9\r (no-eol) (esc)
229 converting [====================================> ] 8/9\r (no-eol) (esc)
230 getting files [==================> ] 1/2\r (no-eol) (esc)
230 getting files [==================> ] 1/2\r (no-eol) (esc)
231 getting files [======================================>] 2/2\r (no-eol) (esc)
231 getting files [======================================>] 2/2\r (no-eol) (esc)
232 \r (no-eol) (esc)
232 \r (no-eol) (esc)
233 initializing destination fullrepo repository
233 initializing destination fullrepo repository
234 scanning source...
234 scanning source...
235 sorting...
235 sorting...
236 converting...
236 converting...
237 8 add foo
237 8 add foo
238 7 change foo
238 7 change foo
239 6 add quux
239 6 add quux
240 5 add bar
240 5 add bar
241 4 add baz
241 4 add baz
242 3 Octopus merge
242 3 Octopus merge
243 2 change bar
243 2 change bar
244 1 change foo
244 1 change foo
245 0 Discard change to foo
245 0 Discard change to foo
246 updating bookmarks
246 updating bookmarks
247 $ hg up -q -R fullrepo
247 $ hg up -q -R fullrepo
248 $ glog -R fullrepo
248 $ glog -R fullrepo
249 @ 9 "Discard change to foo" files: foo
249 @ 9 "Discard change to foo" files: foo
250 |\
250 |\
251 | o 8 "change foo" files: foo
251 | o 8 "change foo" files: foo
252 | |
252 | |
253 o | 7 "change bar" files: bar
253 o | 7 "change bar" files: bar
254 |/
254 |/
255 o 6 "(octopus merge fixup)" files:
255 o 6 "(octopus merge fixup)" files:
256 |\
256 |\
257 | o 5 "Octopus merge" files: baz
257 | o 5 "Octopus merge" files: baz
258 | |\
258 | |\
259 o | | 4 "add baz" files: baz
259 o | | 4 "add baz" files: baz
260 | | |
260 | | |
261 +---o 3 "add bar" files: bar
261 +---o 3 "add bar" files: bar
262 | |
262 | |
263 o | 2 "add quux" files: quux
263 o | 2 "add quux" files: quux
264 | |
264 | |
265 | o 1 "change foo" files: foo
265 | o 1 "change foo" files: foo
266 |/
266 |/
267 o 0 "add foo" files: foo
267 o 0 "add foo" files: foo
268
268
269 $ hg -R fullrepo manifest --debug
269 $ hg -R fullrepo manifest --debug
270 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
270 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
271 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
271 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
272 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
272 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
273 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
273 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
274 $ splitrepo 'octopus merge' 'foo bar baz'
274 $ splitrepo 'octopus merge' 'foo bar baz'
275 % foo bar baz: octopus merge
275 % foo bar baz: octopus merge
276 @ 8 "Discard change to foo" files: foo
276 @ 8 "Discard change to foo" files: foo
277 |\
277 |\
278 | o 7 "change foo" files: foo
278 | o 7 "change foo" files: foo
279 | |
279 | |
280 o | 6 "change bar" files: bar
280 o | 6 "change bar" files: bar
281 |/
281 |/
282 o 5 "(octopus merge fixup)" files:
282 o 5 "(octopus merge fixup)" files:
283 |\
283 |\
284 | o 4 "Octopus merge" files: baz
284 | o 4 "Octopus merge" files: baz
285 | |\
285 | |\
286 o | | 3 "add baz" files: baz
286 o | | 3 "add baz" files: baz
287 | | |
287 | | |
288 +---o 2 "add bar" files: bar
288 +---o 2 "add bar" files: bar
289 | |
289 | |
290 | o 1 "change foo" files: foo
290 | o 1 "change foo" files: foo
291 |/
291 |/
292 o 0 "add foo" files: foo
292 o 0 "add foo" files: foo
293
293
294 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
294 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
295 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
295 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
296 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
296 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
297 $ splitrepo 'only some parents of an octopus merge; "discard" a head' 'foo baz quux'
297 $ splitrepo 'only some parents of an octopus merge; "discard" a head' 'foo baz quux'
298 % foo baz quux: only some parents of an octopus merge; "discard" a head
298 % foo baz quux: only some parents of an octopus merge; "discard" a head
299 @ 6 "Discard change to foo" files: foo
299 @ 6 "Discard change to foo" files: foo
300 |
300 |
301 o 5 "change foo" files: foo
301 o 5 "change foo" files: foo
302 |
302 |
303 o 4 "Octopus merge" files:
303 o 4 "Octopus merge" files:
304 |\
304 |\
305 | o 3 "add baz" files: baz
305 | o 3 "add baz" files: baz
306 | |
306 | |
307 | o 2 "add quux" files: quux
307 | o 2 "add quux" files: quux
308 | |
308 | |
309 o | 1 "change foo" files: foo
309 o | 1 "change foo" files: foo
310 |/
310 |/
311 o 0 "add foo" files: foo
311 o 0 "add foo" files: foo
312
312
313 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
313 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
314 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
314 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
315 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
315 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
316
316
317 test importing git renames and copies
317 test importing git renames and copies
318
318
319 $ cd git-repo2
319 $ cd git-repo2
320 $ git mv foo foo-renamed
320 $ git mv foo foo-renamed
321 since bar is not touched in this commit, this copy will not be detected
321 since bar is not touched in this commit, this copy will not be detected
322 $ cp bar bar-copied
322 $ cp bar bar-copied
323 $ cp baz baz-copied
323 $ cp baz baz-copied
324 $ cp baz baz-copied2
324 $ cp baz baz-copied2
325 $ cp baz ba-copy
325 $ cp baz ba-copy
326 $ echo baz2 >> baz
326 $ echo baz2 >> baz
327 $ git add bar-copied baz-copied baz-copied2 ba-copy
327 $ git add bar-copied baz-copied baz-copied2 ba-copy
328 $ commit -a -m 'rename and copy'
328 $ commit -a -m 'rename and copy'
329 $ cd ..
329 $ cd ..
330
330
331 input validation
331 input validation
332 $ hg convert --config convert.git.similarity=foo --datesort git-repo2 fullrepo
332 $ hg convert --config convert.git.similarity=foo --datesort git-repo2 fullrepo
333 abort: convert.git.similarity is not an integer ('foo')
333 abort: convert.git.similarity is not an integer ('foo')
334 [255]
334 [255]
335 $ hg convert --config convert.git.similarity=-1 --datesort git-repo2 fullrepo
335 $ hg convert --config convert.git.similarity=-1 --datesort git-repo2 fullrepo
336 abort: similarity must be between 0 and 100
336 abort: similarity must be between 0 and 100
337 [255]
337 [255]
338 $ hg convert --config convert.git.similarity=101 --datesort git-repo2 fullrepo
338 $ hg convert --config convert.git.similarity=101 --datesort git-repo2 fullrepo
339 abort: similarity must be between 0 and 100
339 abort: similarity must be between 0 and 100
340 [255]
340 [255]
341
341
342 $ hg -q convert --config convert.git.similarity=100 --datesort git-repo2 fullrepo
342 $ hg -q convert --config convert.git.similarity=100 --datesort git-repo2 fullrepo
343 $ hg -R fullrepo status -C --change master
343 $ hg -R fullrepo status -C --change master
344 M baz
344 M baz
345 A ba-copy
345 A ba-copy
346 baz
346 baz
347 A bar-copied
347 A bar-copied
348 A baz-copied
348 A baz-copied
349 baz
349 baz
350 A baz-copied2
350 A baz-copied2
351 baz
351 baz
352 A foo-renamed
352 A foo-renamed
353 foo
353 foo
354 R foo
354 R foo
355
355
356 Ensure that the modification to the copy source was preserved
356 Ensure that the modification to the copy source was preserved
357 (there was a bug where if the copy dest was alphabetically prior to the copy
357 (there was a bug where if the copy dest was alphabetically prior to the copy
358 source, the copy source took the contents of the copy dest)
358 source, the copy source took the contents of the copy dest)
359 $ hg cat -r tip fullrepo/baz
359 $ hg cat -r tip fullrepo/baz
360 baz
360 baz
361 baz2
361 baz2
362
362
363 $ cd git-repo2
363 $ cd git-repo2
364 $ echo bar2 >> bar
364 $ echo bar2 >> bar
365 $ commit -a -m 'change bar'
365 $ commit -a -m 'change bar'
366 $ cp bar bar-copied2
366 $ cp bar bar-copied2
367 $ git add bar-copied2
367 $ git add bar-copied2
368 $ commit -a -m 'copy with no changes'
368 $ commit -a -m 'copy with no changes'
369 $ cd ..
369 $ cd ..
370
370
371 $ hg -q convert --config convert.git.similarity=100 \
371 $ hg -q convert --config convert.git.similarity=100 \
372 > --config convert.git.findcopiesharder=1 --datesort git-repo2 fullrepo
372 > --config convert.git.findcopiesharder=1 --datesort git-repo2 fullrepo
373 $ hg -R fullrepo status -C --change master
373 $ hg -R fullrepo status -C --change master
374 A bar-copied2
374 A bar-copied2
375 bar
375 bar
376
376
377 test binary conversion (issue1359)
377 test binary conversion (issue1359)
378
378
379 $ count=19
379 $ count=19
380 $ mkdir git-repo3
380 $ mkdir git-repo3
381 $ cd git-repo3
381 $ cd git-repo3
382 $ git init-db >/dev/null 2>/dev/null
382 $ git init-db >/dev/null 2>/dev/null
383 $ $PYTHON -c 'file("b", "wb").write("".join([chr(i) for i in range(256)])*16)'
383 $ $PYTHON -c 'file("b", "wb").write("".join([chr(i) for i in range(256)])*16)'
384 $ git add b
384 $ git add b
385 $ commit -a -m addbinary
385 $ commit -a -m addbinary
386 $ cd ..
386 $ cd ..
387
387
388 convert binary file
388 convert binary file
389
389
390 $ hg convert git-repo3 git-repo3-hg
390 $ hg convert git-repo3 git-repo3-hg
391 initializing destination git-repo3-hg repository
391 initializing destination git-repo3-hg repository
392 scanning source...
392 scanning source...
393 sorting...
393 sorting...
394 converting...
394 converting...
395 0 addbinary
395 0 addbinary
396 updating bookmarks
396 updating bookmarks
397 $ cd git-repo3-hg
397 $ cd git-repo3-hg
398 $ hg up -C
398 $ hg up -C
399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 $ $PYTHON -c 'print len(file("b", "rb").read())'
400 $ $PYTHON -c 'print len(file("b", "rb").read())'
401 4096
401 4096
402 $ cd ..
402 $ cd ..
403
403
404 test author vs committer
404 test author vs committer
405
405
406 $ mkdir git-repo4
406 $ mkdir git-repo4
407 $ cd git-repo4
407 $ cd git-repo4
408 $ git init-db >/dev/null 2>/dev/null
408 $ git init-db >/dev/null 2>/dev/null
409 $ echo >> foo
409 $ echo >> foo
410 $ git add foo
410 $ git add foo
411 $ commit -a -m addfoo
411 $ commit -a -m addfoo
412 $ echo >> foo
412 $ echo >> foo
413 $ GIT_AUTHOR_NAME="nottest"
413 $ GIT_AUTHOR_NAME="nottest"
414 $ commit -a -m addfoo2
414 $ commit -a -m addfoo2
415 $ cd ..
415 $ cd ..
416
416
417 convert author committer
417 convert author committer
418
418
419 $ hg convert git-repo4 git-repo4-hg
419 $ hg convert git-repo4 git-repo4-hg
420 initializing destination git-repo4-hg repository
420 initializing destination git-repo4-hg repository
421 scanning source...
421 scanning source...
422 sorting...
422 sorting...
423 converting...
423 converting...
424 1 addfoo
424 1 addfoo
425 0 addfoo2
425 0 addfoo2
426 updating bookmarks
426 updating bookmarks
427 $ hg -R git-repo4-hg log -v
427 $ hg -R git-repo4-hg log -v
428 changeset: 1:d63e967f93da
428 changeset: 1:d63e967f93da
429 bookmark: master
429 bookmark: master
430 tag: tip
430 tag: tip
431 user: nottest <test@example.org>
431 user: nottest <test@example.org>
432 date: Mon Jan 01 00:00:21 2007 +0000
432 date: Mon Jan 01 00:00:21 2007 +0000
433 files: foo
433 files: foo
434 description:
434 description:
435 addfoo2
435 addfoo2
436
436
437 committer: test <test@example.org>
437 committer: test <test@example.org>
438
438
439
439
440 changeset: 0:0735477b0224
440 changeset: 0:0735477b0224
441 user: test <test@example.org>
441 user: test <test@example.org>
442 date: Mon Jan 01 00:00:20 2007 +0000
442 date: Mon Jan 01 00:00:20 2007 +0000
443 files: foo
443 files: foo
444 description:
444 description:
445 addfoo
445 addfoo
446
446
447
447
448
448
449 --sourceorder should fail
449 --sourceorder should fail
450
450
451 $ hg convert --sourcesort git-repo4 git-repo4-sourcesort-hg
451 $ hg convert --sourcesort git-repo4 git-repo4-sourcesort-hg
452 initializing destination git-repo4-sourcesort-hg repository
452 initializing destination git-repo4-sourcesort-hg repository
453 abort: --sourcesort is not supported by this data source
453 abort: --sourcesort is not supported by this data source
454 [255]
454 [255]
455
455
456 test converting certain branches
456 test converting certain branches
457
457
458 $ mkdir git-testrevs
458 $ mkdir git-testrevs
459 $ cd git-testrevs
459 $ cd git-testrevs
460 $ git init
460 $ git init
461 Initialized empty Git repository in $TESTTMP/git-testrevs/.git/
461 Initialized empty Git repository in $TESTTMP/git-testrevs/.git/
462 $ echo a >> a ; git add a > /dev/null; git commit -m 'first' > /dev/null
462 $ echo a >> a ; git add a > /dev/null; git commit -m 'first' > /dev/null
463 $ echo a >> a ; git add a > /dev/null; git commit -m 'master commit' > /dev/null
463 $ echo a >> a ; git add a > /dev/null; git commit -m 'master commit' > /dev/null
464 $ git checkout -b goodbranch 'HEAD^'
464 $ git checkout -b goodbranch 'HEAD^'
465 Switched to a new branch 'goodbranch'
465 Switched to a new branch 'goodbranch'
466 $ echo a >> b ; git add b > /dev/null; git commit -m 'good branch commit' > /dev/null
466 $ echo a >> b ; git add b > /dev/null; git commit -m 'good branch commit' > /dev/null
467 $ git checkout -b badbranch 'HEAD^'
467 $ git checkout -b badbranch 'HEAD^'
468 Switched to a new branch 'badbranch'
468 Switched to a new branch 'badbranch'
469 $ echo a >> c ; git add c > /dev/null; git commit -m 'bad branch commit' > /dev/null
469 $ echo a >> c ; git add c > /dev/null; git commit -m 'bad branch commit' > /dev/null
470 $ cd ..
470 $ cd ..
471 $ hg convert git-testrevs hg-testrevs --rev master --rev goodbranch
471 $ hg convert git-testrevs hg-testrevs --rev master --rev goodbranch
472 initializing destination hg-testrevs repository
472 initializing destination hg-testrevs repository
473 scanning source...
473 scanning source...
474 sorting...
474 sorting...
475 converting...
475 converting...
476 2 first
476 2 first
477 1 good branch commit
477 1 good branch commit
478 0 master commit
478 0 master commit
479 updating bookmarks
479 updating bookmarks
480 $ cd hg-testrevs
480 $ cd hg-testrevs
481 $ hg log -G -T '{rev} {bookmarks}'
481 $ hg log -G -T '{rev} {bookmarks}'
482 o 2 master
482 o 2 master
483 |
483 |
484 | o 1 goodbranch
484 | o 1 goodbranch
485 |/
485 |/
486 o 0
486 o 0
487
487
488 $ cd ..
488 $ cd ..
489
489
490 test sub modules
490 test sub modules
491
491
492 $ mkdir git-repo5
492 $ mkdir git-repo5
493 $ cd git-repo5
493 $ cd git-repo5
494 $ git init-db >/dev/null 2>/dev/null
494 $ git init-db >/dev/null 2>/dev/null
495 $ echo 'sub' >> foo
495 $ echo 'sub' >> foo
496 $ git add foo
496 $ git add foo
497 $ commit -a -m 'addfoo'
497 $ commit -a -m 'addfoo'
498 $ BASE=`pwd`
498 $ BASE=`pwd`
499 $ cd ..
499 $ cd ..
500 $ mkdir git-repo6
500 $ mkdir git-repo6
501 $ cd git-repo6
501 $ cd git-repo6
502 $ git init-db >/dev/null 2>/dev/null
502 $ git init-db >/dev/null 2>/dev/null
503 $ git submodule add ${BASE} >/dev/null 2>/dev/null
503 $ git submodule add ${BASE} >/dev/null 2>/dev/null
504 $ commit -a -m 'addsubmodule' >/dev/null 2>/dev/null
504 $ commit -a -m 'addsubmodule' >/dev/null 2>/dev/null
505
505
506 test non-tab whitespace .gitmodules
506 test non-tab whitespace .gitmodules
507
507
508 $ cat >> .gitmodules <<EOF
508 $ cat >> .gitmodules <<EOF
509 > [submodule "git-repo5"]
509 > [submodule "git-repo5"]
510 > path = git-repo5
510 > path = git-repo5
511 > url = git-repo5
511 > url = git-repo5
512 > EOF
512 > EOF
513 $ git commit -q -a -m "weird white space submodule"
513 $ git commit -q -a -m "weird white space submodule"
514 $ cd ..
514 $ cd ..
515 $ hg convert git-repo6 hg-repo6
515 $ hg convert git-repo6 hg-repo6
516 initializing destination hg-repo6 repository
516 initializing destination hg-repo6 repository
517 scanning source...
517 scanning source...
518 sorting...
518 sorting...
519 converting...
519 converting...
520 1 addsubmodule
520 1 addsubmodule
521 0 weird white space submodule
521 0 weird white space submodule
522 updating bookmarks
522 updating bookmarks
523
523
524 $ rm -rf hg-repo6
524 $ rm -rf hg-repo6
525 $ cd git-repo6
525 $ cd git-repo6
526 $ git reset --hard 'HEAD^' > /dev/null
526 $ git reset --hard 'HEAD^' > /dev/null
527
527
528 test missing .gitmodules
528 test missing .gitmodules
529
529
530 $ git submodule add ../git-repo4 >/dev/null 2>/dev/null
530 $ git submodule add ../git-repo4 >/dev/null 2>/dev/null
531 $ git checkout HEAD .gitmodules
531 $ git checkout HEAD .gitmodules
532 $ git rm .gitmodules
532 $ git rm .gitmodules
533 rm '.gitmodules'
533 rm '.gitmodules'
534 $ git commit -q -m "remove .gitmodules" .gitmodules
534 $ git commit -q -m "remove .gitmodules" .gitmodules
535 $ git commit -q -m "missing .gitmodules"
535 $ git commit -q -m "missing .gitmodules"
536 $ cd ..
536 $ cd ..
537 $ hg convert git-repo6 hg-repo6 --traceback 2>&1 | grep -v "fatal: Path '.gitmodules' does not exist"
537 $ hg convert git-repo6 hg-repo6 --traceback 2>&1 | grep -v "fatal: Path '.gitmodules' does not exist"
538 initializing destination hg-repo6 repository
538 initializing destination hg-repo6 repository
539 scanning source...
539 scanning source...
540 sorting...
540 sorting...
541 converting...
541 converting...
542 2 addsubmodule
542 2 addsubmodule
543 1 remove .gitmodules
543 1 remove .gitmodules
544 0 missing .gitmodules
544 0 missing .gitmodules
545 warning: cannot read submodules config file in * (glob)
545 warning: cannot read submodules config file in * (glob)
546 updating bookmarks
546 updating bookmarks
547 $ rm -rf hg-repo6
547 $ rm -rf hg-repo6
548 $ cd git-repo6
548 $ cd git-repo6
549 $ rm -rf git-repo4
549 $ rm -rf git-repo4
550 $ git reset --hard 'HEAD^^' > /dev/null
550 $ git reset --hard 'HEAD^^' > /dev/null
551 $ cd ..
551 $ cd ..
552
552
553 test invalid splicemap1
553 test invalid splicemap1
554
554
555 $ cat > splicemap <<EOF
555 $ cat > splicemap <<EOF
556 > $VALIDID1
556 > $VALIDID1
557 > EOF
557 > EOF
558 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap1-hg
558 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap1-hg
559 initializing destination git-repo2-splicemap1-hg repository
559 initializing destination git-repo2-splicemap1-hg repository
560 abort: syntax error in splicemap(1): child parent1[,parent2] expected
560 abort: syntax error in splicemap(1): child parent1[,parent2] expected
561 [255]
561 [255]
562
562
563 test invalid splicemap2
563 test invalid splicemap2
564
564
565 $ cat > splicemap <<EOF
565 $ cat > splicemap <<EOF
566 > $VALIDID1 $VALIDID2, $VALIDID2, $VALIDID2
566 > $VALIDID1 $VALIDID2, $VALIDID2, $VALIDID2
567 > EOF
567 > EOF
568 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap2-hg
568 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap2-hg
569 initializing destination git-repo2-splicemap2-hg repository
569 initializing destination git-repo2-splicemap2-hg repository
570 abort: syntax error in splicemap(1): child parent1[,parent2] expected
570 abort: syntax error in splicemap(1): child parent1[,parent2] expected
571 [255]
571 [255]
572
572
573 test invalid splicemap3
573 test invalid splicemap3
574
574
575 $ cat > splicemap <<EOF
575 $ cat > splicemap <<EOF
576 > $INVALIDID1 $INVALIDID2
576 > $INVALIDID1 $INVALIDID2
577 > EOF
577 > EOF
578 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap3-hg
578 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap3-hg
579 initializing destination git-repo2-splicemap3-hg repository
579 initializing destination git-repo2-splicemap3-hg repository
580 abort: splicemap entry afd12345af is not a valid revision identifier
580 abort: splicemap entry afd12345af is not a valid revision identifier
581 [255]
581 [255]
582
582
583 convert sub modules
583 convert sub modules
584 $ hg convert git-repo6 git-repo6-hg
584 $ hg convert git-repo6 git-repo6-hg
585 initializing destination git-repo6-hg repository
585 initializing destination git-repo6-hg repository
586 scanning source...
586 scanning source...
587 sorting...
587 sorting...
588 converting...
588 converting...
589 0 addsubmodule
589 0 addsubmodule
590 updating bookmarks
590 updating bookmarks
591 $ hg -R git-repo6-hg log -v
591 $ hg -R git-repo6-hg log -v
592 changeset: 0:* (glob)
592 changeset: 0:* (glob)
593 bookmark: master
593 bookmark: master
594 tag: tip
594 tag: tip
595 user: nottest <test@example.org>
595 user: nottest <test@example.org>
596 date: Mon Jan 01 00:00:23 2007 +0000
596 date: Mon Jan 01 00:00:23 2007 +0000
597 files: .hgsub .hgsubstate
597 files: .hgsub .hgsubstate
598 description:
598 description:
599 addsubmodule
599 addsubmodule
600
600
601 committer: test <test@example.org>
601 committer: test <test@example.org>
602
602
603
603
604
604
605 $ cd git-repo6-hg
605 $ cd git-repo6-hg
606 $ hg up >/dev/null 2>/dev/null
606 $ hg up >/dev/null 2>/dev/null
607 $ cat .hgsubstate
607 $ cat .hgsubstate
608 * git-repo5 (glob)
608 * git-repo5 (glob)
609 $ cd git-repo5
609 $ cd git-repo5
610 $ cat foo
610 $ cat foo
611 sub
611 sub
612
612
613 $ cd ../..
613 $ cd ../..
614
614
615 make sure rename detection doesn't break removing and adding gitmodules
615 make sure rename detection doesn't break removing and adding gitmodules
616
616
617 $ cd git-repo6
617 $ cd git-repo6
618 $ git mv .gitmodules .gitmodules-renamed
618 $ git mv .gitmodules .gitmodules-renamed
619 $ commit -a -m 'rename .gitmodules'
619 $ commit -a -m 'rename .gitmodules'
620 $ git mv .gitmodules-renamed .gitmodules
620 $ git mv .gitmodules-renamed .gitmodules
621 $ commit -a -m 'rename .gitmodules back'
621 $ commit -a -m 'rename .gitmodules back'
622 $ cd ..
622 $ cd ..
623
623
624 $ hg --config convert.git.similarity=100 convert -q git-repo6 git-repo6-hg
624 $ hg --config convert.git.similarity=100 convert -q git-repo6 git-repo6-hg
625 $ hg -R git-repo6-hg log -r 'tip^' -T "{desc|firstline}\n"
625 $ hg -R git-repo6-hg log -r 'tip^' -T "{desc|firstline}\n"
626 rename .gitmodules
626 rename .gitmodules
627 $ hg -R git-repo6-hg status -C --change 'tip^'
627 $ hg -R git-repo6-hg status -C --change 'tip^'
628 A .gitmodules-renamed
628 A .gitmodules-renamed
629 R .hgsub
629 R .hgsub
630 R .hgsubstate
630 R .hgsubstate
631 $ hg -R git-repo6-hg log -r tip -T "{desc|firstline}\n"
631 $ hg -R git-repo6-hg log -r tip -T "{desc|firstline}\n"
632 rename .gitmodules back
632 rename .gitmodules back
633 $ hg -R git-repo6-hg status -C --change tip
633 $ hg -R git-repo6-hg status -C --change tip
634 A .hgsub
634 A .hgsub
635 A .hgsubstate
635 A .hgsubstate
636 R .gitmodules-renamed
636 R .gitmodules-renamed
637
637
638 convert the revision removing '.gitmodules' itself (and related
638 convert the revision removing '.gitmodules' itself (and related
639 submodules)
639 submodules)
640
640
641 $ cd git-repo6
641 $ cd git-repo6
642 $ git rm .gitmodules
642 $ git rm .gitmodules
643 rm '.gitmodules'
643 rm '.gitmodules'
644 $ git rm --cached git-repo5
644 $ git rm --cached git-repo5
645 rm 'git-repo5'
645 rm 'git-repo5'
646 $ commit -a -m 'remove .gitmodules and submodule git-repo5'
646 $ commit -a -m 'remove .gitmodules and submodule git-repo5'
647 $ cd ..
647 $ cd ..
648
648
649 $ hg convert -q git-repo6 git-repo6-hg
649 $ hg convert -q git-repo6 git-repo6-hg
650 $ hg -R git-repo6-hg tip -T "{desc|firstline}\n"
650 $ hg -R git-repo6-hg tip -T "{desc|firstline}\n"
651 remove .gitmodules and submodule git-repo5
651 remove .gitmodules and submodule git-repo5
652 $ hg -R git-repo6-hg tip -T "{file_dels}\n"
652 $ hg -R git-repo6-hg tip -T "{file_dels}\n"
653 .hgsub .hgsubstate
653 .hgsub .hgsubstate
654
654
655 skip submodules in the conversion
655 skip submodules in the conversion
656
656
657 $ hg convert -q git-repo6 no-submodules --config convert.git.skipsubmodules=True
657 $ hg convert -q git-repo6 no-submodules --config convert.git.skipsubmodules=True
658 $ hg -R no-submodules manifest --all
658 $ hg -R no-submodules manifest --all
659 .gitmodules-renamed
659 .gitmodules-renamed
660
660
661 convert using a different remote prefix
661 convert using a different remote prefix
662 $ git init git-repo7
662 $ git init git-repo7
663 Initialized empty Git repository in $TESTTMP/git-repo7/.git/
663 Initialized empty Git repository in $TESTTMP/git-repo7/.git/
664 $ cd git-repo7
664 $ cd git-repo7
665 TODO: it'd be nice to use (?) lines instead of grep -v to handle the
665 TODO: it'd be nice to use (?) lines instead of grep -v to handle the
666 git output variance, but that doesn't currently work in the middle of
666 git output variance, but that doesn't currently work in the middle of
667 a block, so do this for now.
667 a block, so do this for now.
668 $ touch a && git add a && git commit -am "commit a" | grep -v changed
668 $ touch a && git add a && git commit -am "commit a" | grep -v changed
669 [master (root-commit) 8ae5f69] commit a
669 [master (root-commit) 8ae5f69] commit a
670 Author: nottest <test@example.org>
670 Author: nottest <test@example.org>
671 create mode 100644 a
671 create mode 100644 a
672 $ cd ..
672 $ cd ..
673 $ git clone git-repo7 git-repo7-client
673 $ git clone git-repo7 git-repo7-client
674 Cloning into 'git-repo7-client'...
674 Cloning into 'git-repo7-client'...
675 done.
675 done.
676 $ hg convert --config convert.git.remoteprefix=origin git-repo7-client hg-repo7
676 $ hg convert --config convert.git.remoteprefix=origin git-repo7-client hg-repo7
677 initializing destination hg-repo7 repository
677 initializing destination hg-repo7 repository
678 scanning source...
678 scanning source...
679 sorting...
679 sorting...
680 converting...
680 converting...
681 0 commit a
681 0 commit a
682 updating bookmarks
682 updating bookmarks
683 $ hg -R hg-repo7 bookmarks
683 $ hg -R hg-repo7 bookmarks
684 master 0:03bf38caa4c6
684 master 0:03bf38caa4c6
685 origin/master 0:03bf38caa4c6
685 origin/master 0:03bf38caa4c6
686
686
687 Run convert when the remote branches have changed
687 Run convert when the remote branches have changed
688 (there was an old bug where the local convert read branches from the server)
688 (there was an old bug where the local convert read branches from the server)
689
689
690 $ cd git-repo7
690 $ cd git-repo7
691 $ echo a >> a
691 $ echo a >> a
692 $ git commit -q -am "move master forward"
692 $ git commit -q -am "move master forward"
693 $ cd ..
693 $ cd ..
694 $ rm -rf hg-repo7
694 $ rm -rf hg-repo7
695 $ hg convert --config convert.git.remoteprefix=origin git-repo7-client hg-repo7
695 $ hg convert --config convert.git.remoteprefix=origin git-repo7-client hg-repo7
696 initializing destination hg-repo7 repository
696 initializing destination hg-repo7 repository
697 scanning source...
697 scanning source...
698 sorting...
698 sorting...
699 converting...
699 converting...
700 0 commit a
700 0 commit a
701 updating bookmarks
701 updating bookmarks
702 $ hg -R hg-repo7 bookmarks
702 $ hg -R hg-repo7 bookmarks
703 master 0:03bf38caa4c6
703 master 0:03bf38caa4c6
704 origin/master 0:03bf38caa4c6
704 origin/master 0:03bf38caa4c6
705
705
706 damaged git repository tests:
706 damaged git repository tests:
707 In case the hard-coded hashes change, the following commands can be used to
707 In case the hard-coded hashes change, the following commands can be used to
708 list the hashes and their corresponding types in the repository:
708 list the hashes and their corresponding types in the repository:
709 cd git-repo4/.git/objects
709 cd git-repo4/.git/objects
710 find . -type f | cut -c 3- | sed 's_/__' | xargs -n 1 -t git cat-file -t
710 find . -type f | cut -c 3- | sed 's_/__' | xargs -n 1 -t git cat-file -t
711 cd ../../..
711 cd ../../..
712
712
713 damage git repository by renaming a commit object
713 damage git repository by renaming a commit object
714 $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
714 $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
715 $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
715 $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
716 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
716 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
717 abort: cannot read tags from git-repo4/.git
717 abort: cannot retrieve number of commits in git-repo4/.git
718 $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
718 $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
719 damage git repository by renaming a blob object
719 damage git repository by renaming a blob object
720
720
721 $ BLOB_OBJ=8b/137891791fe96927ad78e64b0aad7bded08bdc
721 $ BLOB_OBJ=8b/137891791fe96927ad78e64b0aad7bded08bdc
722 $ mv git-repo4/.git/objects/$BLOB_OBJ git-repo4/.git/objects/$BLOB_OBJ.tmp
722 $ mv git-repo4/.git/objects/$BLOB_OBJ git-repo4/.git/objects/$BLOB_OBJ.tmp
723 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
723 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
724 abort: cannot read 'blob' object at 8b137891791fe96927ad78e64b0aad7bded08bdc
724 abort: cannot read 'blob' object at 8b137891791fe96927ad78e64b0aad7bded08bdc
725 $ mv git-repo4/.git/objects/$BLOB_OBJ.tmp git-repo4/.git/objects/$BLOB_OBJ
725 $ mv git-repo4/.git/objects/$BLOB_OBJ.tmp git-repo4/.git/objects/$BLOB_OBJ
726 damage git repository by renaming a tree object
726 damage git repository by renaming a tree object
727
727
728 $ TREE_OBJ=72/49f083d2a63a41cc737764a86981eb5f3e4635
728 $ TREE_OBJ=72/49f083d2a63a41cc737764a86981eb5f3e4635
729 $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp
729 $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp
730 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
730 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
731 abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
731 abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
General Comments 0
You need to be logged in to leave comments. Login now