##// END OF EJS Templates
convert: support multiple specifed revs in git source...
Durham Goode -
r25749:f2748cc4 default
parent child Browse files
Show More
@@ -1,401 +1,400 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
14 from common import NoRepo, commit, converter_source, checktool
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):
28 class convert_git(converter_source):
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 popen_with_stderr(self, s):
74 def popen_with_stderr(self, s):
75 p = subprocess.Popen(s, shell=True, bufsize=-1,
75 p = subprocess.Popen(s, shell=True, bufsize=-1,
76 close_fds=util.closefds,
76 close_fds=util.closefds,
77 stdin=subprocess.PIPE,
77 stdin=subprocess.PIPE,
78 stdout=subprocess.PIPE,
78 stdout=subprocess.PIPE,
79 stderr=subprocess.STDOUT,
79 stderr=subprocess.STDOUT,
80 universal_newlines=False,
80 universal_newlines=False,
81 env=None)
81 env=None)
82 return p.stdout
82 return p.stdout
83
83
84 def gitread(self, s):
84 def gitread(self, s):
85 fh = self.gitopen(s)
85 fh = self.gitopen(s)
86 data = fh.read()
86 data = fh.read()
87 return data, fh.close()
87 return data, fh.close()
88
88
89 def __init__(self, ui, path, revs=None):
89 def __init__(self, ui, path, revs=None):
90 super(convert_git, self).__init__(ui, path, revs=revs)
90 super(convert_git, self).__init__(ui, path, revs=revs)
91
91
92 if revs and len(revs) > 1:
93 raise util.Abort(_("git source does not support specifying "
94 "multiple revs"))
95
96 if os.path.isdir(path + "/.git"):
92 if os.path.isdir(path + "/.git"):
97 path += "/.git"
93 path += "/.git"
98 if not os.path.exists(path + "/objects"):
94 if not os.path.exists(path + "/objects"):
99 raise NoRepo(_("%s does not look like a Git repository") % path)
95 raise NoRepo(_("%s does not look like a Git repository") % path)
100
96
101 # The default value (50) is based on the default for 'git diff'.
97 # The default value (50) is based on the default for 'git diff'.
102 similarity = ui.configint('convert', 'git.similarity', default=50)
98 similarity = ui.configint('convert', 'git.similarity', default=50)
103 if similarity < 0 or similarity > 100:
99 if similarity < 0 or similarity > 100:
104 raise util.Abort(_('similarity must be between 0 and 100'))
100 raise util.Abort(_('similarity must be between 0 and 100'))
105 if similarity > 0:
101 if similarity > 0:
106 self.simopt = '-C%d%%' % similarity
102 self.simopt = '-C%d%%' % similarity
107 findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
103 findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
108 False)
104 False)
109 if findcopiesharder:
105 if findcopiesharder:
110 self.simopt += ' --find-copies-harder'
106 self.simopt += ' --find-copies-harder'
111 else:
107 else:
112 self.simopt = ''
108 self.simopt = ''
113
109
114 checktool('git', 'git')
110 checktool('git', 'git')
115
111
116 self.path = path
112 self.path = path
117 self.submodules = []
113 self.submodules = []
118
114
119 self.catfilepipe = self.gitpipe('git cat-file --batch')
115 self.catfilepipe = self.gitpipe('git cat-file --batch')
120
116
121 def after(self):
117 def after(self):
122 for f in self.catfilepipe:
118 for f in self.catfilepipe:
123 f.close()
119 f.close()
124
120
125 def getheads(self):
121 def getheads(self):
126 if not self.revs:
122 if not self.revs:
127 heads, ret = self.gitread('git rev-parse --branches --remotes')
123 heads, ret = self.gitread('git rev-parse --branches --remotes')
128 heads = heads.splitlines()
124 heads = heads.splitlines()
125 if ret:
126 raise util.Abort(_('cannot retrieve git heads'))
129 else:
127 else:
130 heads, ret = self.gitread("git rev-parse --verify %s" %
128 heads = []
131 self.revs[0])
129 for rev in self.revs:
132 heads = [heads[:-1]]
130 rawhead, ret = self.gitread("git rev-parse --verify %s" % rev)
133 if ret:
131 heads.append(rawhead[:-1])
134 raise util.Abort(_('cannot retrieve git heads'))
132 if ret:
133 raise util.Abort(_('cannot retrieve git head "%s"') % rev)
135 return heads
134 return heads
136
135
137 def catfile(self, rev, type):
136 def catfile(self, rev, type):
138 if rev == hex(nullid):
137 if rev == hex(nullid):
139 raise IOError
138 raise IOError
140 self.catfilepipe[0].write(rev+'\n')
139 self.catfilepipe[0].write(rev+'\n')
141 self.catfilepipe[0].flush()
140 self.catfilepipe[0].flush()
142 info = self.catfilepipe[1].readline().split()
141 info = self.catfilepipe[1].readline().split()
143 if info[1] != type:
142 if info[1] != type:
144 raise util.Abort(_('cannot read %r object at %s') % (type, rev))
143 raise util.Abort(_('cannot read %r object at %s') % (type, rev))
145 size = int(info[2])
144 size = int(info[2])
146 data = self.catfilepipe[1].read(size)
145 data = self.catfilepipe[1].read(size)
147 if len(data) < size:
146 if len(data) < size:
148 raise util.Abort(_('cannot read %r object at %s: unexpected size')
147 raise util.Abort(_('cannot read %r object at %s: unexpected size')
149 % (type, rev))
148 % (type, rev))
150 # read the trailing newline
149 # read the trailing newline
151 self.catfilepipe[1].read(1)
150 self.catfilepipe[1].read(1)
152 return data
151 return data
153
152
154 def getfile(self, name, rev):
153 def getfile(self, name, rev):
155 if rev == hex(nullid):
154 if rev == hex(nullid):
156 return None, None
155 return None, None
157 if name == '.hgsub':
156 if name == '.hgsub':
158 data = '\n'.join([m.hgsub() for m in self.submoditer()])
157 data = '\n'.join([m.hgsub() for m in self.submoditer()])
159 mode = ''
158 mode = ''
160 elif name == '.hgsubstate':
159 elif name == '.hgsubstate':
161 data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
160 data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
162 mode = ''
161 mode = ''
163 else:
162 else:
164 data = self.catfile(rev, "blob")
163 data = self.catfile(rev, "blob")
165 mode = self.modecache[(name, rev)]
164 mode = self.modecache[(name, rev)]
166 return data, mode
165 return data, mode
167
166
168 def submoditer(self):
167 def submoditer(self):
169 null = hex(nullid)
168 null = hex(nullid)
170 for m in sorted(self.submodules, key=lambda p: p.path):
169 for m in sorted(self.submodules, key=lambda p: p.path):
171 if m.node != null:
170 if m.node != null:
172 yield m
171 yield m
173
172
174 def parsegitmodules(self, content):
173 def parsegitmodules(self, content):
175 """Parse the formatted .gitmodules file, example file format:
174 """Parse the formatted .gitmodules file, example file format:
176 [submodule "sub"]\n
175 [submodule "sub"]\n
177 \tpath = sub\n
176 \tpath = sub\n
178 \turl = git://giturl\n
177 \turl = git://giturl\n
179 """
178 """
180 self.submodules = []
179 self.submodules = []
181 c = config.config()
180 c = config.config()
182 # Each item in .gitmodules starts with whitespace that cant be parsed
181 # Each item in .gitmodules starts with whitespace that cant be parsed
183 c.parse('.gitmodules', '\n'.join(line.strip() for line in
182 c.parse('.gitmodules', '\n'.join(line.strip() for line in
184 content.split('\n')))
183 content.split('\n')))
185 for sec in c.sections():
184 for sec in c.sections():
186 s = c[sec]
185 s = c[sec]
187 if 'url' in s and 'path' in s:
186 if 'url' in s and 'path' in s:
188 self.submodules.append(submodule(s['path'], '', s['url']))
187 self.submodules.append(submodule(s['path'], '', s['url']))
189
188
190 def retrievegitmodules(self, version):
189 def retrievegitmodules(self, version):
191 modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
190 modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
192 if ret:
191 if ret:
193 # This can happen if a file is in the repo that has permissions
192 # This can happen if a file is in the repo that has permissions
194 # 160000, but there is no .gitmodules file.
193 # 160000, but there is no .gitmodules file.
195 self.ui.warn(_("warning: cannot read submodules config file in "
194 self.ui.warn(_("warning: cannot read submodules config file in "
196 "%s\n") % version)
195 "%s\n") % version)
197 return
196 return
198
197
199 try:
198 try:
200 self.parsegitmodules(modules)
199 self.parsegitmodules(modules)
201 except error.ParseError:
200 except error.ParseError:
202 self.ui.warn(_("warning: unable to parse .gitmodules in %s\n")
201 self.ui.warn(_("warning: unable to parse .gitmodules in %s\n")
203 % version)
202 % version)
204 return
203 return
205
204
206 for m in self.submodules:
205 for m in self.submodules:
207 node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path))
206 node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path))
208 if ret:
207 if ret:
209 continue
208 continue
210 m.node = node.strip()
209 m.node = node.strip()
211
210
212 def getchanges(self, version, full):
211 def getchanges(self, version, full):
213 if full:
212 if full:
214 raise util.Abort(_("convert from git do not support --full"))
213 raise util.Abort(_("convert from git do not support --full"))
215 self.modecache = {}
214 self.modecache = {}
216 fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % (
215 fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % (
217 self.simopt, version))
216 self.simopt, version))
218 changes = []
217 changes = []
219 copies = {}
218 copies = {}
220 seen = set()
219 seen = set()
221 entry = None
220 entry = None
222 subexists = [False]
221 subexists = [False]
223 subdeleted = [False]
222 subdeleted = [False]
224 difftree = fh.read().split('\x00')
223 difftree = fh.read().split('\x00')
225 lcount = len(difftree)
224 lcount = len(difftree)
226 i = 0
225 i = 0
227
226
228 def add(entry, f, isdest):
227 def add(entry, f, isdest):
229 seen.add(f)
228 seen.add(f)
230 h = entry[3]
229 h = entry[3]
231 p = (entry[1] == "100755")
230 p = (entry[1] == "100755")
232 s = (entry[1] == "120000")
231 s = (entry[1] == "120000")
233 renamesource = (not isdest and entry[4][0] == 'R')
232 renamesource = (not isdest and entry[4][0] == 'R')
234
233
235 if f == '.gitmodules':
234 if f == '.gitmodules':
236 subexists[0] = True
235 subexists[0] = True
237 if entry[4] == 'D' or renamesource:
236 if entry[4] == 'D' or renamesource:
238 subdeleted[0] = True
237 subdeleted[0] = True
239 changes.append(('.hgsub', hex(nullid)))
238 changes.append(('.hgsub', hex(nullid)))
240 else:
239 else:
241 changes.append(('.hgsub', ''))
240 changes.append(('.hgsub', ''))
242 elif entry[1] == '160000' or entry[0] == ':160000':
241 elif entry[1] == '160000' or entry[0] == ':160000':
243 subexists[0] = True
242 subexists[0] = True
244 else:
243 else:
245 if renamesource:
244 if renamesource:
246 h = hex(nullid)
245 h = hex(nullid)
247 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
246 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
248 changes.append((f, h))
247 changes.append((f, h))
249
248
250 while i < lcount:
249 while i < lcount:
251 l = difftree[i]
250 l = difftree[i]
252 i += 1
251 i += 1
253 if not entry:
252 if not entry:
254 if not l.startswith(':'):
253 if not l.startswith(':'):
255 continue
254 continue
256 entry = l.split()
255 entry = l.split()
257 continue
256 continue
258 f = l
257 f = l
259 if f not in seen:
258 if f not in seen:
260 add(entry, f, False)
259 add(entry, f, False)
261 # A file can be copied multiple times, or modified and copied
260 # A file can be copied multiple times, or modified and copied
262 # simultaneously. So f can be repeated even if fdest isn't.
261 # simultaneously. So f can be repeated even if fdest isn't.
263 if entry[4][0] in 'RC':
262 if entry[4][0] in 'RC':
264 # rename or copy: next line is the destination
263 # rename or copy: next line is the destination
265 fdest = difftree[i]
264 fdest = difftree[i]
266 i += 1
265 i += 1
267 if fdest not in seen:
266 if fdest not in seen:
268 add(entry, fdest, True)
267 add(entry, fdest, True)
269 # .gitmodules isn't imported at all, so it being copied to
268 # .gitmodules isn't imported at all, so it being copied to
270 # and fro doesn't really make sense
269 # and fro doesn't really make sense
271 if f != '.gitmodules' and fdest != '.gitmodules':
270 if f != '.gitmodules' and fdest != '.gitmodules':
272 copies[fdest] = f
271 copies[fdest] = f
273 entry = None
272 entry = None
274 if fh.close():
273 if fh.close():
275 raise util.Abort(_('cannot read changes in %s') % version)
274 raise util.Abort(_('cannot read changes in %s') % version)
276
275
277 if subexists[0]:
276 if subexists[0]:
278 if subdeleted[0]:
277 if subdeleted[0]:
279 changes.append(('.hgsubstate', hex(nullid)))
278 changes.append(('.hgsubstate', hex(nullid)))
280 else:
279 else:
281 self.retrievegitmodules(version)
280 self.retrievegitmodules(version)
282 changes.append(('.hgsubstate', ''))
281 changes.append(('.hgsubstate', ''))
283 return (changes, copies, set())
282 return (changes, copies, set())
284
283
285 def getcommit(self, version):
284 def getcommit(self, version):
286 c = self.catfile(version, "commit") # read the commit hash
285 c = self.catfile(version, "commit") # read the commit hash
287 end = c.find("\n\n")
286 end = c.find("\n\n")
288 message = c[end + 2:]
287 message = c[end + 2:]
289 message = self.recode(message)
288 message = self.recode(message)
290 l = c[:end].splitlines()
289 l = c[:end].splitlines()
291 parents = []
290 parents = []
292 author = committer = None
291 author = committer = None
293 for e in l[1:]:
292 for e in l[1:]:
294 n, v = e.split(" ", 1)
293 n, v = e.split(" ", 1)
295 if n == "author":
294 if n == "author":
296 p = v.split()
295 p = v.split()
297 tm, tz = p[-2:]
296 tm, tz = p[-2:]
298 author = " ".join(p[:-2])
297 author = " ".join(p[:-2])
299 if author[0] == "<": author = author[1:-1]
298 if author[0] == "<": author = author[1:-1]
300 author = self.recode(author)
299 author = self.recode(author)
301 if n == "committer":
300 if n == "committer":
302 p = v.split()
301 p = v.split()
303 tm, tz = p[-2:]
302 tm, tz = p[-2:]
304 committer = " ".join(p[:-2])
303 committer = " ".join(p[:-2])
305 if committer[0] == "<": committer = committer[1:-1]
304 if committer[0] == "<": committer = committer[1:-1]
306 committer = self.recode(committer)
305 committer = self.recode(committer)
307 if n == "parent":
306 if n == "parent":
308 parents.append(v)
307 parents.append(v)
309
308
310 if committer and committer != author:
309 if committer and committer != author:
311 message += "\ncommitter: %s\n" % committer
310 message += "\ncommitter: %s\n" % committer
312 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
311 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
313 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
312 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
314 date = tm + " " + str(tz)
313 date = tm + " " + str(tz)
315
314
316 c = commit(parents=parents, date=date, author=author, desc=message,
315 c = commit(parents=parents, date=date, author=author, desc=message,
317 rev=version)
316 rev=version)
318 return c
317 return c
319
318
320 def numcommits(self):
319 def numcommits(self):
321 return len([None for _ in self.gitopen('git rev-list --all')])
320 return len([None for _ in self.gitopen('git rev-list --all')])
322
321
323 def gettags(self):
322 def gettags(self):
324 tags = {}
323 tags = {}
325 alltags = {}
324 alltags = {}
326 fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
325 fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
327 err=subprocess.STDOUT)
326 err=subprocess.STDOUT)
328 prefix = 'refs/tags/'
327 prefix = 'refs/tags/'
329
328
330 # Build complete list of tags, both annotated and bare ones
329 # Build complete list of tags, both annotated and bare ones
331 for line in fh:
330 for line in fh:
332 line = line.strip()
331 line = line.strip()
333 if line.startswith("error:") or line.startswith("fatal:"):
332 if line.startswith("error:") or line.startswith("fatal:"):
334 raise util.Abort(_('cannot read tags from %s') % self.path)
333 raise util.Abort(_('cannot read tags from %s') % self.path)
335 node, tag = line.split(None, 1)
334 node, tag = line.split(None, 1)
336 if not tag.startswith(prefix):
335 if not tag.startswith(prefix):
337 continue
336 continue
338 alltags[tag[len(prefix):]] = node
337 alltags[tag[len(prefix):]] = node
339 if fh.close():
338 if fh.close():
340 raise util.Abort(_('cannot read tags from %s') % self.path)
339 raise util.Abort(_('cannot read tags from %s') % self.path)
341
340
342 # Filter out tag objects for annotated tag refs
341 # Filter out tag objects for annotated tag refs
343 for tag in alltags:
342 for tag in alltags:
344 if tag.endswith('^{}'):
343 if tag.endswith('^{}'):
345 tags[tag[:-3]] = alltags[tag]
344 tags[tag[:-3]] = alltags[tag]
346 else:
345 else:
347 if tag + '^{}' in alltags:
346 if tag + '^{}' in alltags:
348 continue
347 continue
349 else:
348 else:
350 tags[tag] = alltags[tag]
349 tags[tag] = alltags[tag]
351
350
352 return tags
351 return tags
353
352
354 def getchangedfiles(self, version, i):
353 def getchangedfiles(self, version, i):
355 changes = []
354 changes = []
356 if i is None:
355 if i is None:
357 fh = self.gitopen("git diff-tree --root -m -r %s" % version)
356 fh = self.gitopen("git diff-tree --root -m -r %s" % version)
358 for l in fh:
357 for l in fh:
359 if "\t" not in l:
358 if "\t" not in l:
360 continue
359 continue
361 m, f = l[:-1].split("\t")
360 m, f = l[:-1].split("\t")
362 changes.append(f)
361 changes.append(f)
363 else:
362 else:
364 fh = self.gitopen('git diff-tree --name-only --root -r %s '
363 fh = self.gitopen('git diff-tree --name-only --root -r %s '
365 '"%s^%s" --' % (version, version, i + 1))
364 '"%s^%s" --' % (version, version, i + 1))
366 changes = [f.rstrip('\n') for f in fh]
365 changes = [f.rstrip('\n') for f in fh]
367 if fh.close():
366 if fh.close():
368 raise util.Abort(_('cannot read changes in %s') % version)
367 raise util.Abort(_('cannot read changes in %s') % version)
369
368
370 return changes
369 return changes
371
370
372 def getbookmarks(self):
371 def getbookmarks(self):
373 bookmarks = {}
372 bookmarks = {}
374
373
375 # Interesting references in git are prefixed
374 # Interesting references in git are prefixed
376 prefix = 'refs/heads/'
375 prefix = 'refs/heads/'
377 prefixlen = len(prefix)
376 prefixlen = len(prefix)
378
377
379 # factor two commands
378 # factor two commands
380 gitcmd = { 'remote/': 'git ls-remote --heads origin',
379 gitcmd = { 'remote/': 'git ls-remote --heads origin',
381 '': 'git show-ref'}
380 '': 'git show-ref'}
382
381
383 # Origin heads
382 # Origin heads
384 for reftype in gitcmd:
383 for reftype in gitcmd:
385 try:
384 try:
386 fh = self.gitopen(gitcmd[reftype], err=subprocess.PIPE)
385 fh = self.gitopen(gitcmd[reftype], err=subprocess.PIPE)
387 for line in fh:
386 for line in fh:
388 line = line.strip()
387 line = line.strip()
389 rev, name = line.split(None, 1)
388 rev, name = line.split(None, 1)
390 if not name.startswith(prefix):
389 if not name.startswith(prefix):
391 continue
390 continue
392 name = '%s%s' % (reftype, name[prefixlen:])
391 name = '%s%s' % (reftype, name[prefixlen:])
393 bookmarks[name] = rev
392 bookmarks[name] = rev
394 except Exception:
393 except Exception:
395 pass
394 pass
396
395
397 return bookmarks
396 return bookmarks
398
397
399 def checkrevformat(self, revstr, mapname='splicemap'):
398 def checkrevformat(self, revstr, mapname='splicemap'):
400 """ git revision string is a 40 byte hex """
399 """ git revision string is a 40 byte hex """
401 self.checkhexformat(revstr, mapname)
400 self.checkhexformat(revstr, mapname)
@@ -1,636 +1,670 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 > --datesort git-repo
57 > --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 \r (no-eol) (esc)
177 \r (no-eol) (esc)
178 scanning [===> ] 1/9\r (no-eol) (esc)
178 scanning [===> ] 1/9\r (no-eol) (esc)
179 scanning [========> ] 2/9\r (no-eol) (esc)
179 scanning [========> ] 2/9\r (no-eol) (esc)
180 scanning [=============> ] 3/9\r (no-eol) (esc)
180 scanning [=============> ] 3/9\r (no-eol) (esc)
181 scanning [==================> ] 4/9\r (no-eol) (esc)
181 scanning [==================> ] 4/9\r (no-eol) (esc)
182 scanning [=======================> ] 5/9\r (no-eol) (esc)
182 scanning [=======================> ] 5/9\r (no-eol) (esc)
183 scanning [============================> ] 6/9\r (no-eol) (esc)
183 scanning [============================> ] 6/9\r (no-eol) (esc)
184 scanning [=================================> ] 7/9\r (no-eol) (esc)
184 scanning [=================================> ] 7/9\r (no-eol) (esc)
185 scanning [======================================> ] 8/9\r (no-eol) (esc)
185 scanning [======================================> ] 8/9\r (no-eol) (esc)
186 scanning [===========================================>] 9/9\r (no-eol) (esc)
186 scanning [===========================================>] 9/9\r (no-eol) (esc)
187 \r (no-eol) (esc)
187 \r (no-eol) (esc)
188 \r (no-eol) (esc)
188 \r (no-eol) (esc)
189 converting [ ] 0/9\r (no-eol) (esc)
189 converting [ ] 0/9\r (no-eol) (esc)
190 getting files [======================================>] 1/1\r (no-eol) (esc)
190 getting files [======================================>] 1/1\r (no-eol) (esc)
191 \r (no-eol) (esc)
191 \r (no-eol) (esc)
192 \r (no-eol) (esc)
192 \r (no-eol) (esc)
193 converting [===> ] 1/9\r (no-eol) (esc)
193 converting [===> ] 1/9\r (no-eol) (esc)
194 getting files [======================================>] 1/1\r (no-eol) (esc)
194 getting files [======================================>] 1/1\r (no-eol) (esc)
195 \r (no-eol) (esc)
195 \r (no-eol) (esc)
196 \r (no-eol) (esc)
196 \r (no-eol) (esc)
197 converting [========> ] 2/9\r (no-eol) (esc)
197 converting [========> ] 2/9\r (no-eol) (esc)
198 getting files [======================================>] 1/1\r (no-eol) (esc)
198 getting files [======================================>] 1/1\r (no-eol) (esc)
199 \r (no-eol) (esc)
199 \r (no-eol) (esc)
200 \r (no-eol) (esc)
200 \r (no-eol) (esc)
201 converting [=============> ] 3/9\r (no-eol) (esc)
201 converting [=============> ] 3/9\r (no-eol) (esc)
202 getting files [======================================>] 1/1\r (no-eol) (esc)
202 getting files [======================================>] 1/1\r (no-eol) (esc)
203 \r (no-eol) (esc)
203 \r (no-eol) (esc)
204 \r (no-eol) (esc)
204 \r (no-eol) (esc)
205 converting [=================> ] 4/9\r (no-eol) (esc)
205 converting [=================> ] 4/9\r (no-eol) (esc)
206 getting files [======================================>] 1/1\r (no-eol) (esc)
206 getting files [======================================>] 1/1\r (no-eol) (esc)
207 \r (no-eol) (esc)
207 \r (no-eol) (esc)
208 \r (no-eol) (esc)
208 \r (no-eol) (esc)
209 converting [======================> ] 5/9\r (no-eol) (esc)
209 converting [======================> ] 5/9\r (no-eol) (esc)
210 getting files [===> ] 1/8\r (no-eol) (esc)
210 getting files [===> ] 1/8\r (no-eol) (esc)
211 getting files [========> ] 2/8\r (no-eol) (esc)
211 getting files [========> ] 2/8\r (no-eol) (esc)
212 getting files [=============> ] 3/8\r (no-eol) (esc)
212 getting files [=============> ] 3/8\r (no-eol) (esc)
213 getting files [==================> ] 4/8\r (no-eol) (esc)
213 getting files [==================> ] 4/8\r (no-eol) (esc)
214 getting files [=======================> ] 5/8\r (no-eol) (esc)
214 getting files [=======================> ] 5/8\r (no-eol) (esc)
215 getting files [============================> ] 6/8\r (no-eol) (esc)
215 getting files [============================> ] 6/8\r (no-eol) (esc)
216 getting files [=================================> ] 7/8\r (no-eol) (esc)
216 getting files [=================================> ] 7/8\r (no-eol) (esc)
217 getting files [======================================>] 8/8\r (no-eol) (esc)
217 getting files [======================================>] 8/8\r (no-eol) (esc)
218 \r (no-eol) (esc)
218 \r (no-eol) (esc)
219 \r (no-eol) (esc)
219 \r (no-eol) (esc)
220 converting [===========================> ] 6/9\r (no-eol) (esc)
220 converting [===========================> ] 6/9\r (no-eol) (esc)
221 getting files [======================================>] 1/1\r (no-eol) (esc)
221 getting files [======================================>] 1/1\r (no-eol) (esc)
222 \r (no-eol) (esc)
222 \r (no-eol) (esc)
223 \r (no-eol) (esc)
223 \r (no-eol) (esc)
224 converting [===============================> ] 7/9\r (no-eol) (esc)
224 converting [===============================> ] 7/9\r (no-eol) (esc)
225 getting files [======================================>] 1/1\r (no-eol) (esc)
225 getting files [======================================>] 1/1\r (no-eol) (esc)
226 \r (no-eol) (esc)
226 \r (no-eol) (esc)
227 \r (no-eol) (esc)
227 \r (no-eol) (esc)
228 converting [====================================> ] 8/9\r (no-eol) (esc)
228 converting [====================================> ] 8/9\r (no-eol) (esc)
229 getting files [==================> ] 1/2\r (no-eol) (esc)
229 getting files [==================> ] 1/2\r (no-eol) (esc)
230 getting files [======================================>] 2/2\r (no-eol) (esc)
230 getting files [======================================>] 2/2\r (no-eol) (esc)
231 \r (no-eol) (esc)
231 \r (no-eol) (esc)
232 initializing destination fullrepo repository
232 initializing destination fullrepo repository
233 scanning source...
233 scanning source...
234 sorting...
234 sorting...
235 converting...
235 converting...
236 8 add foo
236 8 add foo
237 7 change foo
237 7 change foo
238 6 add quux
238 6 add quux
239 5 add bar
239 5 add bar
240 4 add baz
240 4 add baz
241 3 Octopus merge
241 3 Octopus merge
242 2 change bar
242 2 change bar
243 1 change foo
243 1 change foo
244 0 Discard change to foo
244 0 Discard change to foo
245 updating bookmarks
245 updating bookmarks
246 $ hg up -q -R fullrepo
246 $ hg up -q -R fullrepo
247 $ glog -R fullrepo
247 $ glog -R fullrepo
248 @ 9 "Discard change to foo" files: foo
248 @ 9 "Discard change to foo" files: foo
249 |\
249 |\
250 | o 8 "change foo" files: foo
250 | o 8 "change foo" files: foo
251 | |
251 | |
252 o | 7 "change bar" files: bar
252 o | 7 "change bar" files: bar
253 |/
253 |/
254 o 6 "(octopus merge fixup)" files:
254 o 6 "(octopus merge fixup)" files:
255 |\
255 |\
256 | o 5 "Octopus merge" files: baz
256 | o 5 "Octopus merge" files: baz
257 | |\
257 | |\
258 o | | 4 "add baz" files: baz
258 o | | 4 "add baz" files: baz
259 | | |
259 | | |
260 +---o 3 "add bar" files: bar
260 +---o 3 "add bar" files: bar
261 | |
261 | |
262 o | 2 "add quux" files: quux
262 o | 2 "add quux" files: quux
263 | |
263 | |
264 | o 1 "change foo" files: foo
264 | o 1 "change foo" files: foo
265 |/
265 |/
266 o 0 "add foo" files: foo
266 o 0 "add foo" files: foo
267
267
268 $ hg -R fullrepo manifest --debug
268 $ hg -R fullrepo manifest --debug
269 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
269 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
270 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
270 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
271 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
271 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
272 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
272 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
273 $ splitrepo 'octopus merge' 'foo bar baz'
273 $ splitrepo 'octopus merge' 'foo bar baz'
274 % foo bar baz: octopus merge
274 % foo bar baz: octopus merge
275 @ 8 "Discard change to foo" files: foo
275 @ 8 "Discard change to foo" files: foo
276 |\
276 |\
277 | o 7 "change foo" files: foo
277 | o 7 "change foo" files: foo
278 | |
278 | |
279 o | 6 "change bar" files: bar
279 o | 6 "change bar" files: bar
280 |/
280 |/
281 o 5 "(octopus merge fixup)" files:
281 o 5 "(octopus merge fixup)" files:
282 |\
282 |\
283 | o 4 "Octopus merge" files: baz
283 | o 4 "Octopus merge" files: baz
284 | |\
284 | |\
285 o | | 3 "add baz" files: baz
285 o | | 3 "add baz" files: baz
286 | | |
286 | | |
287 +---o 2 "add bar" files: bar
287 +---o 2 "add bar" files: bar
288 | |
288 | |
289 | o 1 "change foo" files: foo
289 | o 1 "change foo" files: foo
290 |/
290 |/
291 o 0 "add foo" files: foo
291 o 0 "add foo" files: foo
292
292
293 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
293 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
294 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
294 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
295 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
295 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
296 $ splitrepo 'only some parents of an octopus merge; "discard" a head' 'foo baz quux'
296 $ splitrepo 'only some parents of an octopus merge; "discard" a head' 'foo baz quux'
297 % foo baz quux: only some parents of an octopus merge; "discard" a head
297 % foo baz quux: only some parents of an octopus merge; "discard" a head
298 @ 6 "Discard change to foo" files: foo
298 @ 6 "Discard change to foo" files: foo
299 |
299 |
300 o 5 "change foo" files: foo
300 o 5 "change foo" files: foo
301 |
301 |
302 o 4 "Octopus merge" files:
302 o 4 "Octopus merge" files:
303 |\
303 |\
304 | o 3 "add baz" files: baz
304 | o 3 "add baz" files: baz
305 | |
305 | |
306 | o 2 "add quux" files: quux
306 | o 2 "add quux" files: quux
307 | |
307 | |
308 o | 1 "change foo" files: foo
308 o | 1 "change foo" files: foo
309 |/
309 |/
310 o 0 "add foo" files: foo
310 o 0 "add foo" files: foo
311
311
312 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
312 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
313 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
313 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
314 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
314 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
315
315
316 test importing git renames and copies
316 test importing git renames and copies
317
317
318 $ cd git-repo2
318 $ cd git-repo2
319 $ git mv foo foo-renamed
319 $ git mv foo foo-renamed
320 since bar is not touched in this commit, this copy will not be detected
320 since bar is not touched in this commit, this copy will not be detected
321 $ cp bar bar-copied
321 $ cp bar bar-copied
322 $ cp baz baz-copied
322 $ cp baz baz-copied
323 $ cp baz baz-copied2
323 $ cp baz baz-copied2
324 $ echo baz2 >> baz
324 $ echo baz2 >> baz
325 $ git add bar-copied baz-copied baz-copied2
325 $ git add bar-copied baz-copied baz-copied2
326 $ commit -a -m 'rename and copy'
326 $ commit -a -m 'rename and copy'
327 $ cd ..
327 $ cd ..
328
328
329 input validation
329 input validation
330 $ hg convert --config convert.git.similarity=foo --datesort git-repo2 fullrepo
330 $ hg convert --config convert.git.similarity=foo --datesort git-repo2 fullrepo
331 abort: convert.git.similarity is not an integer ('foo')
331 abort: convert.git.similarity is not an integer ('foo')
332 [255]
332 [255]
333 $ hg convert --config convert.git.similarity=-1 --datesort git-repo2 fullrepo
333 $ hg convert --config convert.git.similarity=-1 --datesort git-repo2 fullrepo
334 abort: similarity must be between 0 and 100
334 abort: similarity must be between 0 and 100
335 [255]
335 [255]
336 $ hg convert --config convert.git.similarity=101 --datesort git-repo2 fullrepo
336 $ hg convert --config convert.git.similarity=101 --datesort git-repo2 fullrepo
337 abort: similarity must be between 0 and 100
337 abort: similarity must be between 0 and 100
338 [255]
338 [255]
339
339
340 $ hg -q convert --config convert.git.similarity=100 --datesort git-repo2 fullrepo
340 $ hg -q convert --config convert.git.similarity=100 --datesort git-repo2 fullrepo
341 $ hg -R fullrepo status -C --change master
341 $ hg -R fullrepo status -C --change master
342 M baz
342 M baz
343 A bar-copied
343 A bar-copied
344 A baz-copied
344 A baz-copied
345 baz
345 baz
346 A baz-copied2
346 A baz-copied2
347 baz
347 baz
348 A foo-renamed
348 A foo-renamed
349 foo
349 foo
350 R foo
350 R foo
351
351
352 $ cd git-repo2
352 $ cd git-repo2
353 $ echo bar2 >> bar
353 $ echo bar2 >> bar
354 $ commit -a -m 'change bar'
354 $ commit -a -m 'change bar'
355 $ cp bar bar-copied2
355 $ cp bar bar-copied2
356 $ git add bar-copied2
356 $ git add bar-copied2
357 $ commit -a -m 'copy with no changes'
357 $ commit -a -m 'copy with no changes'
358 $ cd ..
358 $ cd ..
359
359
360 $ hg -q convert --config convert.git.similarity=100 \
360 $ hg -q convert --config convert.git.similarity=100 \
361 > --config convert.git.findcopiesharder=1 --datesort git-repo2 fullrepo
361 > --config convert.git.findcopiesharder=1 --datesort git-repo2 fullrepo
362 $ hg -R fullrepo status -C --change master
362 $ hg -R fullrepo status -C --change master
363 A bar-copied2
363 A bar-copied2
364 bar
364 bar
365
365
366 test binary conversion (issue1359)
366 test binary conversion (issue1359)
367
367
368 $ count=19
368 $ count=19
369 $ mkdir git-repo3
369 $ mkdir git-repo3
370 $ cd git-repo3
370 $ cd git-repo3
371 $ git init-db >/dev/null 2>/dev/null
371 $ git init-db >/dev/null 2>/dev/null
372 $ $PYTHON -c 'file("b", "wb").write("".join([chr(i) for i in range(256)])*16)'
372 $ $PYTHON -c 'file("b", "wb").write("".join([chr(i) for i in range(256)])*16)'
373 $ git add b
373 $ git add b
374 $ commit -a -m addbinary
374 $ commit -a -m addbinary
375 $ cd ..
375 $ cd ..
376
376
377 convert binary file
377 convert binary file
378
378
379 $ hg convert git-repo3 git-repo3-hg
379 $ hg convert git-repo3 git-repo3-hg
380 initializing destination git-repo3-hg repository
380 initializing destination git-repo3-hg repository
381 scanning source...
381 scanning source...
382 sorting...
382 sorting...
383 converting...
383 converting...
384 0 addbinary
384 0 addbinary
385 updating bookmarks
385 updating bookmarks
386 $ cd git-repo3-hg
386 $ cd git-repo3-hg
387 $ hg up -C
387 $ hg up -C
388 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
388 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
389 $ $PYTHON -c 'print len(file("b", "rb").read())'
389 $ $PYTHON -c 'print len(file("b", "rb").read())'
390 4096
390 4096
391 $ cd ..
391 $ cd ..
392
392
393 test author vs committer
393 test author vs committer
394
394
395 $ mkdir git-repo4
395 $ mkdir git-repo4
396 $ cd git-repo4
396 $ cd git-repo4
397 $ git init-db >/dev/null 2>/dev/null
397 $ git init-db >/dev/null 2>/dev/null
398 $ echo >> foo
398 $ echo >> foo
399 $ git add foo
399 $ git add foo
400 $ commit -a -m addfoo
400 $ commit -a -m addfoo
401 $ echo >> foo
401 $ echo >> foo
402 $ GIT_AUTHOR_NAME="nottest"
402 $ GIT_AUTHOR_NAME="nottest"
403 $ commit -a -m addfoo2
403 $ commit -a -m addfoo2
404 $ cd ..
404 $ cd ..
405
405
406 convert author committer
406 convert author committer
407
407
408 $ hg convert git-repo4 git-repo4-hg
408 $ hg convert git-repo4 git-repo4-hg
409 initializing destination git-repo4-hg repository
409 initializing destination git-repo4-hg repository
410 scanning source...
410 scanning source...
411 sorting...
411 sorting...
412 converting...
412 converting...
413 1 addfoo
413 1 addfoo
414 0 addfoo2
414 0 addfoo2
415 updating bookmarks
415 updating bookmarks
416 $ hg -R git-repo4-hg log -v
416 $ hg -R git-repo4-hg log -v
417 changeset: 1:d63e967f93da
417 changeset: 1:d63e967f93da
418 bookmark: master
418 bookmark: master
419 tag: tip
419 tag: tip
420 user: nottest <test@example.org>
420 user: nottest <test@example.org>
421 date: Mon Jan 01 00:00:21 2007 +0000
421 date: Mon Jan 01 00:00:21 2007 +0000
422 files: foo
422 files: foo
423 description:
423 description:
424 addfoo2
424 addfoo2
425
425
426 committer: test <test@example.org>
426 committer: test <test@example.org>
427
427
428
428
429 changeset: 0:0735477b0224
429 changeset: 0:0735477b0224
430 user: test <test@example.org>
430 user: test <test@example.org>
431 date: Mon Jan 01 00:00:20 2007 +0000
431 date: Mon Jan 01 00:00:20 2007 +0000
432 files: foo
432 files: foo
433 description:
433 description:
434 addfoo
434 addfoo
435
435
436
436
437
437
438 --sourceorder should fail
438 --sourceorder should fail
439
439
440 $ hg convert --sourcesort git-repo4 git-repo4-sourcesort-hg
440 $ hg convert --sourcesort git-repo4 git-repo4-sourcesort-hg
441 initializing destination git-repo4-sourcesort-hg repository
441 initializing destination git-repo4-sourcesort-hg repository
442 abort: --sourcesort is not supported by this data source
442 abort: --sourcesort is not supported by this data source
443 [255]
443 [255]
444
444
445 test converting certain branches
446
447 $ mkdir git-testrevs
448 $ cd git-testrevs
449 $ git init
450 Initialized empty Git repository in $TESTTMP/git-testrevs/.git/
451 $ echo a >> a ; git add a > /dev/null; git commit -m 'first' > /dev/null
452 $ echo a >> a ; git add a > /dev/null; git commit -m 'master commit' > /dev/null
453 $ git checkout -b goodbranch 'HEAD^'
454 Switched to a new branch 'goodbranch'
455 $ echo a >> b ; git add b > /dev/null; git commit -m 'good branch commit' > /dev/null
456 $ git checkout -b badbranch 'HEAD^'
457 Switched to a new branch 'badbranch'
458 $ echo a >> c ; git add c > /dev/null; git commit -m 'bad branch commit' > /dev/null
459 $ cd ..
460 $ hg convert git-testrevs hg-testrevs --rev master --rev goodbranch
461 initializing destination hg-testrevs repository
462 scanning source...
463 sorting...
464 converting...
465 2 first
466 1 good branch commit
467 0 master commit
468 updating bookmarks
469 $ cd hg-testrevs
470 $ hg log -G -T '{rev} {bookmarks}'
471 o 2 master
472 |
473 | o 1 goodbranch
474 |/
475 o 0
476
477 $ cd ..
478
445 test sub modules
479 test sub modules
446
480
447 $ mkdir git-repo5
481 $ mkdir git-repo5
448 $ cd git-repo5
482 $ cd git-repo5
449 $ git init-db >/dev/null 2>/dev/null
483 $ git init-db >/dev/null 2>/dev/null
450 $ echo 'sub' >> foo
484 $ echo 'sub' >> foo
451 $ git add foo
485 $ git add foo
452 $ commit -a -m 'addfoo'
486 $ commit -a -m 'addfoo'
453 $ BASE=`pwd`
487 $ BASE=`pwd`
454 $ cd ..
488 $ cd ..
455 $ mkdir git-repo6
489 $ mkdir git-repo6
456 $ cd git-repo6
490 $ cd git-repo6
457 $ git init-db >/dev/null 2>/dev/null
491 $ git init-db >/dev/null 2>/dev/null
458 $ git submodule add ${BASE} >/dev/null 2>/dev/null
492 $ git submodule add ${BASE} >/dev/null 2>/dev/null
459 $ commit -a -m 'addsubmodule' >/dev/null 2>/dev/null
493 $ commit -a -m 'addsubmodule' >/dev/null 2>/dev/null
460
494
461 test non-tab whitespace .gitmodules
495 test non-tab whitespace .gitmodules
462
496
463 $ cat >> .gitmodules <<EOF
497 $ cat >> .gitmodules <<EOF
464 > [submodule "git-repo5"]
498 > [submodule "git-repo5"]
465 > path = git-repo5
499 > path = git-repo5
466 > url = git-repo5
500 > url = git-repo5
467 > EOF
501 > EOF
468 $ git commit -q -a -m "weird white space submodule"
502 $ git commit -q -a -m "weird white space submodule"
469 $ cd ..
503 $ cd ..
470 $ hg convert git-repo6 hg-repo6
504 $ hg convert git-repo6 hg-repo6
471 initializing destination hg-repo6 repository
505 initializing destination hg-repo6 repository
472 scanning source...
506 scanning source...
473 sorting...
507 sorting...
474 converting...
508 converting...
475 1 addsubmodule
509 1 addsubmodule
476 0 weird white space submodule
510 0 weird white space submodule
477 updating bookmarks
511 updating bookmarks
478
512
479 $ rm -rf hg-repo6
513 $ rm -rf hg-repo6
480 $ cd git-repo6
514 $ cd git-repo6
481 $ git reset --hard 'HEAD^' > /dev/null
515 $ git reset --hard 'HEAD^' > /dev/null
482
516
483 test missing .gitmodules
517 test missing .gitmodules
484
518
485 $ git submodule add ../git-repo4 >/dev/null 2>/dev/null
519 $ git submodule add ../git-repo4 >/dev/null 2>/dev/null
486 $ git checkout HEAD .gitmodules
520 $ git checkout HEAD .gitmodules
487 $ git rm .gitmodules
521 $ git rm .gitmodules
488 rm '.gitmodules'
522 rm '.gitmodules'
489 $ git commit -q -m "remove .gitmodules" .gitmodules
523 $ git commit -q -m "remove .gitmodules" .gitmodules
490 $ git commit -q -m "missing .gitmodules"
524 $ git commit -q -m "missing .gitmodules"
491 $ cd ..
525 $ cd ..
492 $ hg convert git-repo6 hg-repo6 --traceback
526 $ hg convert git-repo6 hg-repo6 --traceback
493 fatal: Path '.gitmodules' does not exist in '*' (glob)
527 fatal: Path '.gitmodules' does not exist in '*' (glob)
494 initializing destination hg-repo6 repository
528 initializing destination hg-repo6 repository
495 scanning source...
529 scanning source...
496 sorting...
530 sorting...
497 converting...
531 converting...
498 2 addsubmodule
532 2 addsubmodule
499 1 remove .gitmodules
533 1 remove .gitmodules
500 0 missing .gitmodules
534 0 missing .gitmodules
501 warning: cannot read submodules config file in * (glob)
535 warning: cannot read submodules config file in * (glob)
502 updating bookmarks
536 updating bookmarks
503 $ rm -rf hg-repo6
537 $ rm -rf hg-repo6
504 $ cd git-repo6
538 $ cd git-repo6
505 $ rm -rf git-repo4
539 $ rm -rf git-repo4
506 $ git reset --hard 'HEAD^^' > /dev/null
540 $ git reset --hard 'HEAD^^' > /dev/null
507 $ cd ..
541 $ cd ..
508
542
509 test invalid splicemap1
543 test invalid splicemap1
510
544
511 $ cat > splicemap <<EOF
545 $ cat > splicemap <<EOF
512 > $VALIDID1
546 > $VALIDID1
513 > EOF
547 > EOF
514 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap1-hg
548 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap1-hg
515 initializing destination git-repo2-splicemap1-hg repository
549 initializing destination git-repo2-splicemap1-hg repository
516 abort: syntax error in splicemap(1): child parent1[,parent2] expected
550 abort: syntax error in splicemap(1): child parent1[,parent2] expected
517 [255]
551 [255]
518
552
519 test invalid splicemap2
553 test invalid splicemap2
520
554
521 $ cat > splicemap <<EOF
555 $ cat > splicemap <<EOF
522 > $VALIDID1 $VALIDID2, $VALIDID2, $VALIDID2
556 > $VALIDID1 $VALIDID2, $VALIDID2, $VALIDID2
523 > EOF
557 > EOF
524 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap2-hg
558 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap2-hg
525 initializing destination git-repo2-splicemap2-hg repository
559 initializing destination git-repo2-splicemap2-hg repository
526 abort: syntax error in splicemap(1): child parent1[,parent2] expected
560 abort: syntax error in splicemap(1): child parent1[,parent2] expected
527 [255]
561 [255]
528
562
529 test invalid splicemap3
563 test invalid splicemap3
530
564
531 $ cat > splicemap <<EOF
565 $ cat > splicemap <<EOF
532 > $INVALIDID1 $INVALIDID2
566 > $INVALIDID1 $INVALIDID2
533 > EOF
567 > EOF
534 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap3-hg
568 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap3-hg
535 initializing destination git-repo2-splicemap3-hg repository
569 initializing destination git-repo2-splicemap3-hg repository
536 abort: splicemap entry afd12345af is not a valid revision identifier
570 abort: splicemap entry afd12345af is not a valid revision identifier
537 [255]
571 [255]
538
572
539 convert sub modules
573 convert sub modules
540 $ hg convert git-repo6 git-repo6-hg
574 $ hg convert git-repo6 git-repo6-hg
541 initializing destination git-repo6-hg repository
575 initializing destination git-repo6-hg repository
542 scanning source...
576 scanning source...
543 sorting...
577 sorting...
544 converting...
578 converting...
545 0 addsubmodule
579 0 addsubmodule
546 updating bookmarks
580 updating bookmarks
547 $ hg -R git-repo6-hg log -v
581 $ hg -R git-repo6-hg log -v
548 changeset: 0:* (glob)
582 changeset: 0:* (glob)
549 bookmark: master
583 bookmark: master
550 tag: tip
584 tag: tip
551 user: nottest <test@example.org>
585 user: nottest <test@example.org>
552 date: Mon Jan 01 00:00:23 2007 +0000
586 date: Mon Jan 01 00:00:23 2007 +0000
553 files: .hgsub .hgsubstate
587 files: .hgsub .hgsubstate
554 description:
588 description:
555 addsubmodule
589 addsubmodule
556
590
557 committer: test <test@example.org>
591 committer: test <test@example.org>
558
592
559
593
560
594
561 $ cd git-repo6-hg
595 $ cd git-repo6-hg
562 $ hg up >/dev/null 2>/dev/null
596 $ hg up >/dev/null 2>/dev/null
563 $ cat .hgsubstate
597 $ cat .hgsubstate
564 * git-repo5 (glob)
598 * git-repo5 (glob)
565 $ cd git-repo5
599 $ cd git-repo5
566 $ cat foo
600 $ cat foo
567 sub
601 sub
568
602
569 $ cd ../..
603 $ cd ../..
570
604
571 make sure rename detection doesn't break removing and adding gitmodules
605 make sure rename detection doesn't break removing and adding gitmodules
572
606
573 $ cd git-repo6
607 $ cd git-repo6
574 $ git mv .gitmodules .gitmodules-renamed
608 $ git mv .gitmodules .gitmodules-renamed
575 $ commit -a -m 'rename .gitmodules'
609 $ commit -a -m 'rename .gitmodules'
576 $ git mv .gitmodules-renamed .gitmodules
610 $ git mv .gitmodules-renamed .gitmodules
577 $ commit -a -m 'rename .gitmodules back'
611 $ commit -a -m 'rename .gitmodules back'
578 $ cd ..
612 $ cd ..
579
613
580 $ hg --config convert.git.similarity=100 convert -q git-repo6 git-repo6-hg
614 $ hg --config convert.git.similarity=100 convert -q git-repo6 git-repo6-hg
581 $ hg -R git-repo6-hg log -r 'tip^' -T "{desc|firstline}\n"
615 $ hg -R git-repo6-hg log -r 'tip^' -T "{desc|firstline}\n"
582 rename .gitmodules
616 rename .gitmodules
583 $ hg -R git-repo6-hg status -C --change 'tip^'
617 $ hg -R git-repo6-hg status -C --change 'tip^'
584 A .gitmodules-renamed
618 A .gitmodules-renamed
585 R .hgsub
619 R .hgsub
586 R .hgsubstate
620 R .hgsubstate
587 $ hg -R git-repo6-hg log -r tip -T "{desc|firstline}\n"
621 $ hg -R git-repo6-hg log -r tip -T "{desc|firstline}\n"
588 rename .gitmodules back
622 rename .gitmodules back
589 $ hg -R git-repo6-hg status -C --change tip
623 $ hg -R git-repo6-hg status -C --change tip
590 A .hgsub
624 A .hgsub
591 A .hgsubstate
625 A .hgsubstate
592 R .gitmodules-renamed
626 R .gitmodules-renamed
593
627
594 convert the revision removing '.gitmodules' itself (and related
628 convert the revision removing '.gitmodules' itself (and related
595 submodules)
629 submodules)
596
630
597 $ cd git-repo6
631 $ cd git-repo6
598 $ git rm .gitmodules
632 $ git rm .gitmodules
599 rm '.gitmodules'
633 rm '.gitmodules'
600 $ git rm --cached git-repo5
634 $ git rm --cached git-repo5
601 rm 'git-repo5'
635 rm 'git-repo5'
602 $ commit -a -m 'remove .gitmodules and submodule git-repo5'
636 $ commit -a -m 'remove .gitmodules and submodule git-repo5'
603 $ cd ..
637 $ cd ..
604
638
605 $ hg convert -q git-repo6 git-repo6-hg
639 $ hg convert -q git-repo6 git-repo6-hg
606 $ hg -R git-repo6-hg tip -T "{desc|firstline}\n"
640 $ hg -R git-repo6-hg tip -T "{desc|firstline}\n"
607 remove .gitmodules and submodule git-repo5
641 remove .gitmodules and submodule git-repo5
608 $ hg -R git-repo6-hg tip -T "{file_dels}\n"
642 $ hg -R git-repo6-hg tip -T "{file_dels}\n"
609 .hgsub .hgsubstate
643 .hgsub .hgsubstate
610
644
611 damaged git repository tests:
645 damaged git repository tests:
612 In case the hard-coded hashes change, the following commands can be used to
646 In case the hard-coded hashes change, the following commands can be used to
613 list the hashes and their corresponding types in the repository:
647 list the hashes and their corresponding types in the repository:
614 cd git-repo4/.git/objects
648 cd git-repo4/.git/objects
615 find . -type f | cut -c 3- | sed 's_/__' | xargs -n 1 -t git cat-file -t
649 find . -type f | cut -c 3- | sed 's_/__' | xargs -n 1 -t git cat-file -t
616 cd ../../..
650 cd ../../..
617
651
618 damage git repository by renaming a commit object
652 damage git repository by renaming a commit object
619 $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
653 $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
620 $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
654 $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
621 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
655 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
622 abort: cannot read tags from git-repo4/.git
656 abort: cannot read tags from git-repo4/.git
623 $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
657 $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
624 damage git repository by renaming a blob object
658 damage git repository by renaming a blob object
625
659
626 $ BLOB_OBJ=8b/137891791fe96927ad78e64b0aad7bded08bdc
660 $ BLOB_OBJ=8b/137891791fe96927ad78e64b0aad7bded08bdc
627 $ mv git-repo4/.git/objects/$BLOB_OBJ git-repo4/.git/objects/$BLOB_OBJ.tmp
661 $ mv git-repo4/.git/objects/$BLOB_OBJ git-repo4/.git/objects/$BLOB_OBJ.tmp
628 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
662 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
629 abort: cannot read 'blob' object at 8b137891791fe96927ad78e64b0aad7bded08bdc
663 abort: cannot read 'blob' object at 8b137891791fe96927ad78e64b0aad7bded08bdc
630 $ mv git-repo4/.git/objects/$BLOB_OBJ.tmp git-repo4/.git/objects/$BLOB_OBJ
664 $ mv git-repo4/.git/objects/$BLOB_OBJ.tmp git-repo4/.git/objects/$BLOB_OBJ
631 damage git repository by renaming a tree object
665 damage git repository by renaming a tree object
632
666
633 $ TREE_OBJ=72/49f083d2a63a41cc737764a86981eb5f3e4635
667 $ TREE_OBJ=72/49f083d2a63a41cc737764a86981eb5f3e4635
634 $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp
668 $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp
635 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
669 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
636 abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
670 abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
General Comments 0
You need to be logged in to leave comments. Login now