##// END OF EJS Templates
convert: fix git convert using servers branches...
Durham Goode -
r25905:80149d0b default
parent child Browse files
Show More
@@ -1,401 +1,404 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 os.path.isdir(path + "/.git"):
92 if os.path.isdir(path + "/.git"):
93 path += "/.git"
93 path += "/.git"
94 if not os.path.exists(path + "/objects"):
94 if not os.path.exists(path + "/objects"):
95 raise NoRepo(_("%s does not look like a Git repository") % path)
95 raise NoRepo(_("%s does not look like a Git repository") % path)
96
96
97 # 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'.
98 similarity = ui.configint('convert', 'git.similarity', default=50)
98 similarity = ui.configint('convert', 'git.similarity', default=50)
99 if similarity < 0 or similarity > 100:
99 if similarity < 0 or similarity > 100:
100 raise util.Abort(_('similarity must be between 0 and 100'))
100 raise util.Abort(_('similarity must be between 0 and 100'))
101 if similarity > 0:
101 if similarity > 0:
102 self.simopt = '-C%d%%' % similarity
102 self.simopt = '-C%d%%' % similarity
103 findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
103 findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
104 False)
104 False)
105 if findcopiesharder:
105 if findcopiesharder:
106 self.simopt += ' --find-copies-harder'
106 self.simopt += ' --find-copies-harder'
107 else:
107 else:
108 self.simopt = ''
108 self.simopt = ''
109
109
110 checktool('git', 'git')
110 checktool('git', 'git')
111
111
112 self.path = path
112 self.path = path
113 self.submodules = []
113 self.submodules = []
114
114
115 self.catfilepipe = self.gitpipe('git cat-file --batch')
115 self.catfilepipe = self.gitpipe('git cat-file --batch')
116
116
117 def after(self):
117 def after(self):
118 for f in self.catfilepipe:
118 for f in self.catfilepipe:
119 f.close()
119 f.close()
120
120
121 def getheads(self):
121 def getheads(self):
122 if not self.revs:
122 if not self.revs:
123 heads, ret = self.gitread('git rev-parse --branches --remotes')
123 heads, ret = self.gitread('git rev-parse --branches --remotes')
124 heads = heads.splitlines()
124 heads = heads.splitlines()
125 if ret:
125 if ret:
126 raise util.Abort(_('cannot retrieve git heads'))
126 raise util.Abort(_('cannot retrieve git heads'))
127 else:
127 else:
128 heads = []
128 heads = []
129 for rev in self.revs:
129 for rev in self.revs:
130 rawhead, ret = self.gitread("git rev-parse --verify %s" % rev)
130 rawhead, ret = self.gitread("git rev-parse --verify %s" % rev)
131 heads.append(rawhead[:-1])
131 heads.append(rawhead[:-1])
132 if ret:
132 if ret:
133 raise util.Abort(_('cannot retrieve git head "%s"') % rev)
133 raise util.Abort(_('cannot retrieve git head "%s"') % rev)
134 return heads
134 return heads
135
135
136 def catfile(self, rev, type):
136 def catfile(self, rev, type):
137 if rev == hex(nullid):
137 if rev == hex(nullid):
138 raise IOError
138 raise IOError
139 self.catfilepipe[0].write(rev+'\n')
139 self.catfilepipe[0].write(rev+'\n')
140 self.catfilepipe[0].flush()
140 self.catfilepipe[0].flush()
141 info = self.catfilepipe[1].readline().split()
141 info = self.catfilepipe[1].readline().split()
142 if info[1] != type:
142 if info[1] != type:
143 raise util.Abort(_('cannot read %r object at %s') % (type, rev))
143 raise util.Abort(_('cannot read %r object at %s') % (type, rev))
144 size = int(info[2])
144 size = int(info[2])
145 data = self.catfilepipe[1].read(size)
145 data = self.catfilepipe[1].read(size)
146 if len(data) < size:
146 if len(data) < size:
147 raise util.Abort(_('cannot read %r object at %s: unexpected size')
147 raise util.Abort(_('cannot read %r object at %s: unexpected size')
148 % (type, rev))
148 % (type, rev))
149 # read the trailing newline
149 # read the trailing newline
150 self.catfilepipe[1].read(1)
150 self.catfilepipe[1].read(1)
151 return data
151 return data
152
152
153 def getfile(self, name, rev):
153 def getfile(self, name, rev):
154 if rev == hex(nullid):
154 if rev == hex(nullid):
155 return None, None
155 return None, None
156 if name == '.hgsub':
156 if name == '.hgsub':
157 data = '\n'.join([m.hgsub() for m in self.submoditer()])
157 data = '\n'.join([m.hgsub() for m in self.submoditer()])
158 mode = ''
158 mode = ''
159 elif name == '.hgsubstate':
159 elif name == '.hgsubstate':
160 data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
160 data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
161 mode = ''
161 mode = ''
162 else:
162 else:
163 data = self.catfile(rev, "blob")
163 data = self.catfile(rev, "blob")
164 mode = self.modecache[(name, rev)]
164 mode = self.modecache[(name, rev)]
165 return data, mode
165 return data, mode
166
166
167 def submoditer(self):
167 def submoditer(self):
168 null = hex(nullid)
168 null = hex(nullid)
169 for m in sorted(self.submodules, key=lambda p: p.path):
169 for m in sorted(self.submodules, key=lambda p: p.path):
170 if m.node != null:
170 if m.node != null:
171 yield m
171 yield m
172
172
173 def parsegitmodules(self, content):
173 def parsegitmodules(self, content):
174 """Parse the formatted .gitmodules file, example file format:
174 """Parse the formatted .gitmodules file, example file format:
175 [submodule "sub"]\n
175 [submodule "sub"]\n
176 \tpath = sub\n
176 \tpath = sub\n
177 \turl = git://giturl\n
177 \turl = git://giturl\n
178 """
178 """
179 self.submodules = []
179 self.submodules = []
180 c = config.config()
180 c = config.config()
181 # Each item in .gitmodules starts with whitespace that cant be parsed
181 # Each item in .gitmodules starts with whitespace that cant be parsed
182 c.parse('.gitmodules', '\n'.join(line.strip() for line in
182 c.parse('.gitmodules', '\n'.join(line.strip() for line in
183 content.split('\n')))
183 content.split('\n')))
184 for sec in c.sections():
184 for sec in c.sections():
185 s = c[sec]
185 s = c[sec]
186 if 'url' in s and 'path' in s:
186 if 'url' in s and 'path' in s:
187 self.submodules.append(submodule(s['path'], '', s['url']))
187 self.submodules.append(submodule(s['path'], '', s['url']))
188
188
189 def retrievegitmodules(self, version):
189 def retrievegitmodules(self, version):
190 modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
190 modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
191 if ret:
191 if ret:
192 # 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
193 # 160000, but there is no .gitmodules file.
193 # 160000, but there is no .gitmodules file.
194 self.ui.warn(_("warning: cannot read submodules config file in "
194 self.ui.warn(_("warning: cannot read submodules config file in "
195 "%s\n") % version)
195 "%s\n") % version)
196 return
196 return
197
197
198 try:
198 try:
199 self.parsegitmodules(modules)
199 self.parsegitmodules(modules)
200 except error.ParseError:
200 except error.ParseError:
201 self.ui.warn(_("warning: unable to parse .gitmodules in %s\n")
201 self.ui.warn(_("warning: unable to parse .gitmodules in %s\n")
202 % version)
202 % version)
203 return
203 return
204
204
205 for m in self.submodules:
205 for m in self.submodules:
206 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))
207 if ret:
207 if ret:
208 continue
208 continue
209 m.node = node.strip()
209 m.node = node.strip()
210
210
211 def getchanges(self, version, full):
211 def getchanges(self, version, full):
212 if full:
212 if full:
213 raise util.Abort(_("convert from git do not support --full"))
213 raise util.Abort(_("convert from git do not support --full"))
214 self.modecache = {}
214 self.modecache = {}
215 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" % (
216 self.simopt, version))
216 self.simopt, version))
217 changes = []
217 changes = []
218 copies = {}
218 copies = {}
219 seen = set()
219 seen = set()
220 entry = None
220 entry = None
221 subexists = [False]
221 subexists = [False]
222 subdeleted = [False]
222 subdeleted = [False]
223 difftree = fh.read().split('\x00')
223 difftree = fh.read().split('\x00')
224 lcount = len(difftree)
224 lcount = len(difftree)
225 i = 0
225 i = 0
226
226
227 def add(entry, f, isdest):
227 def add(entry, f, isdest):
228 seen.add(f)
228 seen.add(f)
229 h = entry[3]
229 h = entry[3]
230 p = (entry[1] == "100755")
230 p = (entry[1] == "100755")
231 s = (entry[1] == "120000")
231 s = (entry[1] == "120000")
232 renamesource = (not isdest and entry[4][0] == 'R')
232 renamesource = (not isdest and entry[4][0] == 'R')
233
233
234 if f == '.gitmodules':
234 if f == '.gitmodules':
235 subexists[0] = True
235 subexists[0] = True
236 if entry[4] == 'D' or renamesource:
236 if entry[4] == 'D' or renamesource:
237 subdeleted[0] = True
237 subdeleted[0] = True
238 changes.append(('.hgsub', hex(nullid)))
238 changes.append(('.hgsub', hex(nullid)))
239 else:
239 else:
240 changes.append(('.hgsub', ''))
240 changes.append(('.hgsub', ''))
241 elif entry[1] == '160000' or entry[0] == ':160000':
241 elif entry[1] == '160000' or entry[0] == ':160000':
242 subexists[0] = True
242 subexists[0] = True
243 else:
243 else:
244 if renamesource:
244 if renamesource:
245 h = hex(nullid)
245 h = hex(nullid)
246 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 ""
247 changes.append((f, h))
247 changes.append((f, h))
248
248
249 while i < lcount:
249 while i < lcount:
250 l = difftree[i]
250 l = difftree[i]
251 i += 1
251 i += 1
252 if not entry:
252 if not entry:
253 if not l.startswith(':'):
253 if not l.startswith(':'):
254 continue
254 continue
255 entry = l.split()
255 entry = l.split()
256 continue
256 continue
257 f = l
257 f = l
258 if f not in seen:
258 if f not in seen:
259 add(entry, f, False)
259 add(entry, f, False)
260 # A file can be copied multiple times, or modified and copied
260 # A file can be copied multiple times, or modified and copied
261 # simultaneously. So f can be repeated even if fdest isn't.
261 # simultaneously. So f can be repeated even if fdest isn't.
262 if entry[4][0] in 'RC':
262 if entry[4][0] in 'RC':
263 # rename or copy: next line is the destination
263 # rename or copy: next line is the destination
264 fdest = difftree[i]
264 fdest = difftree[i]
265 i += 1
265 i += 1
266 if fdest not in seen:
266 if fdest not in seen:
267 add(entry, fdest, True)
267 add(entry, fdest, True)
268 # .gitmodules isn't imported at all, so it being copied to
268 # .gitmodules isn't imported at all, so it being copied to
269 # and fro doesn't really make sense
269 # and fro doesn't really make sense
270 if f != '.gitmodules' and fdest != '.gitmodules':
270 if f != '.gitmodules' and fdest != '.gitmodules':
271 copies[fdest] = f
271 copies[fdest] = f
272 entry = None
272 entry = None
273 if fh.close():
273 if fh.close():
274 raise util.Abort(_('cannot read changes in %s') % version)
274 raise util.Abort(_('cannot read changes in %s') % version)
275
275
276 if subexists[0]:
276 if subexists[0]:
277 if subdeleted[0]:
277 if subdeleted[0]:
278 changes.append(('.hgsubstate', hex(nullid)))
278 changes.append(('.hgsubstate', hex(nullid)))
279 else:
279 else:
280 self.retrievegitmodules(version)
280 self.retrievegitmodules(version)
281 changes.append(('.hgsubstate', ''))
281 changes.append(('.hgsubstate', ''))
282 return (changes, copies, set())
282 return (changes, copies, set())
283
283
284 def getcommit(self, version):
284 def getcommit(self, version):
285 c = self.catfile(version, "commit") # read the commit hash
285 c = self.catfile(version, "commit") # read the commit hash
286 end = c.find("\n\n")
286 end = c.find("\n\n")
287 message = c[end + 2:]
287 message = c[end + 2:]
288 message = self.recode(message)
288 message = self.recode(message)
289 l = c[:end].splitlines()
289 l = c[:end].splitlines()
290 parents = []
290 parents = []
291 author = committer = None
291 author = committer = None
292 for e in l[1:]:
292 for e in l[1:]:
293 n, v = e.split(" ", 1)
293 n, v = e.split(" ", 1)
294 if n == "author":
294 if n == "author":
295 p = v.split()
295 p = v.split()
296 tm, tz = p[-2:]
296 tm, tz = p[-2:]
297 author = " ".join(p[:-2])
297 author = " ".join(p[:-2])
298 if author[0] == "<": author = author[1:-1]
298 if author[0] == "<": author = author[1:-1]
299 author = self.recode(author)
299 author = self.recode(author)
300 if n == "committer":
300 if n == "committer":
301 p = v.split()
301 p = v.split()
302 tm, tz = p[-2:]
302 tm, tz = p[-2:]
303 committer = " ".join(p[:-2])
303 committer = " ".join(p[:-2])
304 if committer[0] == "<": committer = committer[1:-1]
304 if committer[0] == "<": committer = committer[1:-1]
305 committer = self.recode(committer)
305 committer = self.recode(committer)
306 if n == "parent":
306 if n == "parent":
307 parents.append(v)
307 parents.append(v)
308
308
309 if committer and committer != author:
309 if committer and committer != author:
310 message += "\ncommitter: %s\n" % committer
310 message += "\ncommitter: %s\n" % committer
311 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:]
312 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
312 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
313 date = tm + " " + str(tz)
313 date = tm + " " + str(tz)
314
314
315 c = commit(parents=parents, date=date, author=author, desc=message,
315 c = commit(parents=parents, date=date, author=author, desc=message,
316 rev=version)
316 rev=version)
317 return c
317 return c
318
318
319 def numcommits(self):
319 def numcommits(self):
320 return len([None for _ in self.gitopen('git rev-list --all')])
320 return len([None for _ in self.gitopen('git rev-list --all')])
321
321
322 def gettags(self):
322 def gettags(self):
323 tags = {}
323 tags = {}
324 alltags = {}
324 alltags = {}
325 fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
325 fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
326 err=subprocess.STDOUT)
326 err=subprocess.STDOUT)
327 prefix = 'refs/tags/'
327 prefix = 'refs/tags/'
328
328
329 # Build complete list of tags, both annotated and bare ones
329 # Build complete list of tags, both annotated and bare ones
330 for line in fh:
330 for line in fh:
331 line = line.strip()
331 line = line.strip()
332 if line.startswith("error:") or line.startswith("fatal:"):
332 if line.startswith("error:") or line.startswith("fatal:"):
333 raise util.Abort(_('cannot read tags from %s') % self.path)
333 raise util.Abort(_('cannot read tags from %s') % self.path)
334 node, tag = line.split(None, 1)
334 node, tag = line.split(None, 1)
335 if not tag.startswith(prefix):
335 if not tag.startswith(prefix):
336 continue
336 continue
337 alltags[tag[len(prefix):]] = node
337 alltags[tag[len(prefix):]] = node
338 if fh.close():
338 if fh.close():
339 raise util.Abort(_('cannot read tags from %s') % self.path)
339 raise util.Abort(_('cannot read tags from %s') % self.path)
340
340
341 # Filter out tag objects for annotated tag refs
341 # Filter out tag objects for annotated tag refs
342 for tag in alltags:
342 for tag in alltags:
343 if tag.endswith('^{}'):
343 if tag.endswith('^{}'):
344 tags[tag[:-3]] = alltags[tag]
344 tags[tag[:-3]] = alltags[tag]
345 else:
345 else:
346 if tag + '^{}' in alltags:
346 if tag + '^{}' in alltags:
347 continue
347 continue
348 else:
348 else:
349 tags[tag] = alltags[tag]
349 tags[tag] = alltags[tag]
350
350
351 return tags
351 return tags
352
352
353 def getchangedfiles(self, version, i):
353 def getchangedfiles(self, version, i):
354 changes = []
354 changes = []
355 if i is None:
355 if i is None:
356 fh = self.gitopen("git diff-tree --root -m -r %s" % version)
356 fh = self.gitopen("git diff-tree --root -m -r %s" % version)
357 for l in fh:
357 for l in fh:
358 if "\t" not in l:
358 if "\t" not in l:
359 continue
359 continue
360 m, f = l[:-1].split("\t")
360 m, f = l[:-1].split("\t")
361 changes.append(f)
361 changes.append(f)
362 else:
362 else:
363 fh = self.gitopen('git diff-tree --name-only --root -r %s '
363 fh = self.gitopen('git diff-tree --name-only --root -r %s '
364 '"%s^%s" --' % (version, version, i + 1))
364 '"%s^%s" --' % (version, version, i + 1))
365 changes = [f.rstrip('\n') for f in fh]
365 changes = [f.rstrip('\n') for f in fh]
366 if fh.close():
366 if fh.close():
367 raise util.Abort(_('cannot read changes in %s') % version)
367 raise util.Abort(_('cannot read changes in %s') % version)
368
368
369 return changes
369 return changes
370
370
371 def getbookmarks(self):
371 def getbookmarks(self):
372 bookmarks = {}
372 bookmarks = {}
373
373
374 # Interesting references in git are prefixed
374 # Handle local and remote branches
375 prefix = 'refs/heads/'
375 remoteprefix = self.ui.config('convert', 'git.remoteprefix', 'remote')
376 prefixlen = len(prefix)
376 reftypes = [
377 # (git prefix, hg prefix)
378 ('refs/remotes/origin/', remoteprefix + '/'),
379 ('refs/heads/', '')
380 ]
377
381
378 # factor two commands
382 exclude = set([
379 remoteprefix = self.ui.config('convert', 'git.remoteprefix', 'remote')
383 'refs/remotes/origin/HEAD',
380 gitcmd = { remoteprefix + '/': 'git ls-remote --heads origin',
384 ])
381 '': 'git show-ref'}
382
385
383 # Origin heads
386 try:
384 for reftype in gitcmd:
387 fh = self.gitopen('git show-ref', err=subprocess.PIPE)
385 try:
388 for line in fh:
386 fh = self.gitopen(gitcmd[reftype], err=subprocess.PIPE)
389 line = line.strip()
387 for line in fh:
390 rev, name = line.split(None, 1)
388 line = line.strip()
391 # Process each type of branch
389 rev, name = line.split(None, 1)
392 for gitprefix, hgprefix in reftypes:
390 if not name.startswith(prefix):
393 if not name.startswith(gitprefix) or name in exclude:
391 continue
394 continue
392 name = '%s%s' % (reftype, name[prefixlen:])
395 name = '%s%s' % (hgprefix, name[len(gitprefix):])
393 bookmarks[name] = rev
396 bookmarks[name] = rev
394 except Exception:
397 except Exception:
395 pass
398 pass
396
399
397 return bookmarks
400 return bookmarks
398
401
399 def checkrevformat(self, revstr, mapname='splicemap'):
402 def checkrevformat(self, revstr, mapname='splicemap'):
400 """ git revision string is a 40 byte hex """
403 """ git revision string is a 40 byte hex """
401 self.checkhexformat(revstr, mapname)
404 self.checkhexformat(revstr, mapname)
@@ -1,694 +1,716 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
445 test converting certain branches
446
446
447 $ mkdir git-testrevs
447 $ mkdir git-testrevs
448 $ cd git-testrevs
448 $ cd git-testrevs
449 $ git init
449 $ git init
450 Initialized empty Git repository in $TESTTMP/git-testrevs/.git/
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
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
452 $ echo a >> a ; git add a > /dev/null; git commit -m 'master commit' > /dev/null
453 $ git checkout -b goodbranch 'HEAD^'
453 $ git checkout -b goodbranch 'HEAD^'
454 Switched to a new branch 'goodbranch'
454 Switched to a new branch 'goodbranch'
455 $ echo a >> b ; git add b > /dev/null; git commit -m 'good branch commit' > /dev/null
455 $ echo a >> b ; git add b > /dev/null; git commit -m 'good branch commit' > /dev/null
456 $ git checkout -b badbranch 'HEAD^'
456 $ git checkout -b badbranch 'HEAD^'
457 Switched to a new branch 'badbranch'
457 Switched to a new branch 'badbranch'
458 $ echo a >> c ; git add c > /dev/null; git commit -m 'bad branch commit' > /dev/null
458 $ echo a >> c ; git add c > /dev/null; git commit -m 'bad branch commit' > /dev/null
459 $ cd ..
459 $ cd ..
460 $ hg convert git-testrevs hg-testrevs --rev master --rev goodbranch
460 $ hg convert git-testrevs hg-testrevs --rev master --rev goodbranch
461 initializing destination hg-testrevs repository
461 initializing destination hg-testrevs repository
462 scanning source...
462 scanning source...
463 sorting...
463 sorting...
464 converting...
464 converting...
465 2 first
465 2 first
466 1 good branch commit
466 1 good branch commit
467 0 master commit
467 0 master commit
468 updating bookmarks
468 updating bookmarks
469 $ cd hg-testrevs
469 $ cd hg-testrevs
470 $ hg log -G -T '{rev} {bookmarks}'
470 $ hg log -G -T '{rev} {bookmarks}'
471 o 2 master
471 o 2 master
472 |
472 |
473 | o 1 goodbranch
473 | o 1 goodbranch
474 |/
474 |/
475 o 0
475 o 0
476
476
477 $ cd ..
477 $ cd ..
478
478
479 test sub modules
479 test sub modules
480
480
481 $ mkdir git-repo5
481 $ mkdir git-repo5
482 $ cd git-repo5
482 $ cd git-repo5
483 $ git init-db >/dev/null 2>/dev/null
483 $ git init-db >/dev/null 2>/dev/null
484 $ echo 'sub' >> foo
484 $ echo 'sub' >> foo
485 $ git add foo
485 $ git add foo
486 $ commit -a -m 'addfoo'
486 $ commit -a -m 'addfoo'
487 $ BASE=`pwd`
487 $ BASE=`pwd`
488 $ cd ..
488 $ cd ..
489 $ mkdir git-repo6
489 $ mkdir git-repo6
490 $ cd git-repo6
490 $ cd git-repo6
491 $ git init-db >/dev/null 2>/dev/null
491 $ git init-db >/dev/null 2>/dev/null
492 $ git submodule add ${BASE} >/dev/null 2>/dev/null
492 $ git submodule add ${BASE} >/dev/null 2>/dev/null
493 $ commit -a -m 'addsubmodule' >/dev/null 2>/dev/null
493 $ commit -a -m 'addsubmodule' >/dev/null 2>/dev/null
494
494
495 test non-tab whitespace .gitmodules
495 test non-tab whitespace .gitmodules
496
496
497 $ cat >> .gitmodules <<EOF
497 $ cat >> .gitmodules <<EOF
498 > [submodule "git-repo5"]
498 > [submodule "git-repo5"]
499 > path = git-repo5
499 > path = git-repo5
500 > url = git-repo5
500 > url = git-repo5
501 > EOF
501 > EOF
502 $ git commit -q -a -m "weird white space submodule"
502 $ git commit -q -a -m "weird white space submodule"
503 $ cd ..
503 $ cd ..
504 $ hg convert git-repo6 hg-repo6
504 $ hg convert git-repo6 hg-repo6
505 initializing destination hg-repo6 repository
505 initializing destination hg-repo6 repository
506 scanning source...
506 scanning source...
507 sorting...
507 sorting...
508 converting...
508 converting...
509 1 addsubmodule
509 1 addsubmodule
510 0 weird white space submodule
510 0 weird white space submodule
511 updating bookmarks
511 updating bookmarks
512
512
513 $ rm -rf hg-repo6
513 $ rm -rf hg-repo6
514 $ cd git-repo6
514 $ cd git-repo6
515 $ git reset --hard 'HEAD^' > /dev/null
515 $ git reset --hard 'HEAD^' > /dev/null
516
516
517 test missing .gitmodules
517 test missing .gitmodules
518
518
519 $ git submodule add ../git-repo4 >/dev/null 2>/dev/null
519 $ git submodule add ../git-repo4 >/dev/null 2>/dev/null
520 $ git checkout HEAD .gitmodules
520 $ git checkout HEAD .gitmodules
521 $ git rm .gitmodules
521 $ git rm .gitmodules
522 rm '.gitmodules'
522 rm '.gitmodules'
523 $ git commit -q -m "remove .gitmodules" .gitmodules
523 $ git commit -q -m "remove .gitmodules" .gitmodules
524 $ git commit -q -m "missing .gitmodules"
524 $ git commit -q -m "missing .gitmodules"
525 $ cd ..
525 $ cd ..
526 $ hg convert git-repo6 hg-repo6 --traceback
526 $ hg convert git-repo6 hg-repo6 --traceback
527 fatal: Path '.gitmodules' does not exist in '*' (glob)
527 fatal: Path '.gitmodules' does not exist in '*' (glob)
528 initializing destination hg-repo6 repository
528 initializing destination hg-repo6 repository
529 scanning source...
529 scanning source...
530 sorting...
530 sorting...
531 converting...
531 converting...
532 2 addsubmodule
532 2 addsubmodule
533 1 remove .gitmodules
533 1 remove .gitmodules
534 0 missing .gitmodules
534 0 missing .gitmodules
535 warning: cannot read submodules config file in * (glob)
535 warning: cannot read submodules config file in * (glob)
536 updating bookmarks
536 updating bookmarks
537 $ rm -rf hg-repo6
537 $ rm -rf hg-repo6
538 $ cd git-repo6
538 $ cd git-repo6
539 $ rm -rf git-repo4
539 $ rm -rf git-repo4
540 $ git reset --hard 'HEAD^^' > /dev/null
540 $ git reset --hard 'HEAD^^' > /dev/null
541 $ cd ..
541 $ cd ..
542
542
543 test invalid splicemap1
543 test invalid splicemap1
544
544
545 $ cat > splicemap <<EOF
545 $ cat > splicemap <<EOF
546 > $VALIDID1
546 > $VALIDID1
547 > EOF
547 > EOF
548 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap1-hg
548 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap1-hg
549 initializing destination git-repo2-splicemap1-hg repository
549 initializing destination git-repo2-splicemap1-hg repository
550 abort: syntax error in splicemap(1): child parent1[,parent2] expected
550 abort: syntax error in splicemap(1): child parent1[,parent2] expected
551 [255]
551 [255]
552
552
553 test invalid splicemap2
553 test invalid splicemap2
554
554
555 $ cat > splicemap <<EOF
555 $ cat > splicemap <<EOF
556 > $VALIDID1 $VALIDID2, $VALIDID2, $VALIDID2
556 > $VALIDID1 $VALIDID2, $VALIDID2, $VALIDID2
557 > EOF
557 > EOF
558 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap2-hg
558 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap2-hg
559 initializing destination git-repo2-splicemap2-hg repository
559 initializing destination git-repo2-splicemap2-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 splicemap3
563 test invalid splicemap3
564
564
565 $ cat > splicemap <<EOF
565 $ cat > splicemap <<EOF
566 > $INVALIDID1 $INVALIDID2
566 > $INVALIDID1 $INVALIDID2
567 > EOF
567 > EOF
568 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap3-hg
568 $ hg convert --splicemap splicemap git-repo2 git-repo2-splicemap3-hg
569 initializing destination git-repo2-splicemap3-hg repository
569 initializing destination git-repo2-splicemap3-hg repository
570 abort: splicemap entry afd12345af is not a valid revision identifier
570 abort: splicemap entry afd12345af is not a valid revision identifier
571 [255]
571 [255]
572
572
573 convert sub modules
573 convert sub modules
574 $ hg convert git-repo6 git-repo6-hg
574 $ hg convert git-repo6 git-repo6-hg
575 initializing destination git-repo6-hg repository
575 initializing destination git-repo6-hg repository
576 scanning source...
576 scanning source...
577 sorting...
577 sorting...
578 converting...
578 converting...
579 0 addsubmodule
579 0 addsubmodule
580 updating bookmarks
580 updating bookmarks
581 $ hg -R git-repo6-hg log -v
581 $ hg -R git-repo6-hg log -v
582 changeset: 0:* (glob)
582 changeset: 0:* (glob)
583 bookmark: master
583 bookmark: master
584 tag: tip
584 tag: tip
585 user: nottest <test@example.org>
585 user: nottest <test@example.org>
586 date: Mon Jan 01 00:00:23 2007 +0000
586 date: Mon Jan 01 00:00:23 2007 +0000
587 files: .hgsub .hgsubstate
587 files: .hgsub .hgsubstate
588 description:
588 description:
589 addsubmodule
589 addsubmodule
590
590
591 committer: test <test@example.org>
591 committer: test <test@example.org>
592
592
593
593
594
594
595 $ cd git-repo6-hg
595 $ cd git-repo6-hg
596 $ hg up >/dev/null 2>/dev/null
596 $ hg up >/dev/null 2>/dev/null
597 $ cat .hgsubstate
597 $ cat .hgsubstate
598 * git-repo5 (glob)
598 * git-repo5 (glob)
599 $ cd git-repo5
599 $ cd git-repo5
600 $ cat foo
600 $ cat foo
601 sub
601 sub
602
602
603 $ cd ../..
603 $ cd ../..
604
604
605 make sure rename detection doesn't break removing and adding gitmodules
605 make sure rename detection doesn't break removing and adding gitmodules
606
606
607 $ cd git-repo6
607 $ cd git-repo6
608 $ git mv .gitmodules .gitmodules-renamed
608 $ git mv .gitmodules .gitmodules-renamed
609 $ commit -a -m 'rename .gitmodules'
609 $ commit -a -m 'rename .gitmodules'
610 $ git mv .gitmodules-renamed .gitmodules
610 $ git mv .gitmodules-renamed .gitmodules
611 $ commit -a -m 'rename .gitmodules back'
611 $ commit -a -m 'rename .gitmodules back'
612 $ cd ..
612 $ cd ..
613
613
614 $ 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
615 $ 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"
616 rename .gitmodules
616 rename .gitmodules
617 $ hg -R git-repo6-hg status -C --change 'tip^'
617 $ hg -R git-repo6-hg status -C --change 'tip^'
618 A .gitmodules-renamed
618 A .gitmodules-renamed
619 R .hgsub
619 R .hgsub
620 R .hgsubstate
620 R .hgsubstate
621 $ 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"
622 rename .gitmodules back
622 rename .gitmodules back
623 $ hg -R git-repo6-hg status -C --change tip
623 $ hg -R git-repo6-hg status -C --change tip
624 A .hgsub
624 A .hgsub
625 A .hgsubstate
625 A .hgsubstate
626 R .gitmodules-renamed
626 R .gitmodules-renamed
627
627
628 convert the revision removing '.gitmodules' itself (and related
628 convert the revision removing '.gitmodules' itself (and related
629 submodules)
629 submodules)
630
630
631 $ cd git-repo6
631 $ cd git-repo6
632 $ git rm .gitmodules
632 $ git rm .gitmodules
633 rm '.gitmodules'
633 rm '.gitmodules'
634 $ git rm --cached git-repo5
634 $ git rm --cached git-repo5
635 rm 'git-repo5'
635 rm 'git-repo5'
636 $ commit -a -m 'remove .gitmodules and submodule git-repo5'
636 $ commit -a -m 'remove .gitmodules and submodule git-repo5'
637 $ cd ..
637 $ cd ..
638
638
639 $ hg convert -q git-repo6 git-repo6-hg
639 $ hg convert -q git-repo6 git-repo6-hg
640 $ hg -R git-repo6-hg tip -T "{desc|firstline}\n"
640 $ hg -R git-repo6-hg tip -T "{desc|firstline}\n"
641 remove .gitmodules and submodule git-repo5
641 remove .gitmodules and submodule git-repo5
642 $ hg -R git-repo6-hg tip -T "{file_dels}\n"
642 $ hg -R git-repo6-hg tip -T "{file_dels}\n"
643 .hgsub .hgsubstate
643 .hgsub .hgsubstate
644
644
645 convert using a different remote prefix
645 convert using a different remote prefix
646 $ git init git-repo7
646 $ git init git-repo7
647 Initialized empty Git repository in $TESTTMP/git-repo7/.git/
647 Initialized empty Git repository in $TESTTMP/git-repo7/.git/
648 $ cd git-repo7
648 $ cd git-repo7
649 $ touch a && git add a && git commit -am "commit a"
649 $ touch a && git add a && git commit -am "commit a"
650 [master (root-commit) 8ae5f69] commit a
650 [master (root-commit) 8ae5f69] commit a
651 Author: nottest <test@example.org>
651 Author: nottest <test@example.org>
652 1 file changed, 0 insertions(+), 0 deletions(-)
652 1 file changed, 0 insertions(+), 0 deletions(-)
653 create mode 100644 a
653 create mode 100644 a
654 $ cd ..
654 $ cd ..
655 $ git clone git-repo7 git-repo7-client
655 $ git clone git-repo7 git-repo7-client
656 Cloning into 'git-repo7-client'...
656 Cloning into 'git-repo7-client'...
657 done.
657 done.
658 $ hg convert --config convert.git.remoteprefix=origin git-repo7-client hg-repo7
658 $ hg convert --config convert.git.remoteprefix=origin git-repo7-client hg-repo7
659 initializing destination hg-repo7 repository
659 initializing destination hg-repo7 repository
660 scanning source...
660 scanning source...
661 sorting...
661 sorting...
662 converting...
662 converting...
663 0 commit a
663 0 commit a
664 updating bookmarks
664 updating bookmarks
665 $ hg -R hg-repo7 bookmarks
665 $ hg -R hg-repo7 bookmarks
666 master 0:03bf38caa4c6
666 master 0:03bf38caa4c6
667 origin/master 0:03bf38caa4c6
667 origin/master 0:03bf38caa4c6
668
668
669 Run convert when the remote branches have changed
670 (there was an old bug where the local convert read branches from the server)
671
672 $ cd git-repo7
673 $ echo a >> a
674 $ git commit -am "move master forward"
675 [master 0c81947] move master forward
676 Author: nottest <test@example.org>
677 1 file changed, 1 insertion(+)
678 $ cd ..
679 $ rm -rf hg-repo7
680 $ hg convert --config convert.git.remoteprefix=origin git-repo7-client hg-repo7
681 initializing destination hg-repo7 repository
682 scanning source...
683 sorting...
684 converting...
685 0 commit a
686 updating bookmarks
687 $ hg -R hg-repo7 bookmarks
688 master 0:03bf38caa4c6
689 origin/master 0:03bf38caa4c6
690
669 damaged git repository tests:
691 damaged git repository tests:
670 In case the hard-coded hashes change, the following commands can be used to
692 In case the hard-coded hashes change, the following commands can be used to
671 list the hashes and their corresponding types in the repository:
693 list the hashes and their corresponding types in the repository:
672 cd git-repo4/.git/objects
694 cd git-repo4/.git/objects
673 find . -type f | cut -c 3- | sed 's_/__' | xargs -n 1 -t git cat-file -t
695 find . -type f | cut -c 3- | sed 's_/__' | xargs -n 1 -t git cat-file -t
674 cd ../../..
696 cd ../../..
675
697
676 damage git repository by renaming a commit object
698 damage git repository by renaming a commit object
677 $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
699 $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
678 $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
700 $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
679 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
701 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
680 abort: cannot read tags from git-repo4/.git
702 abort: cannot read tags from git-repo4/.git
681 $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
703 $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
682 damage git repository by renaming a blob object
704 damage git repository by renaming a blob object
683
705
684 $ BLOB_OBJ=8b/137891791fe96927ad78e64b0aad7bded08bdc
706 $ BLOB_OBJ=8b/137891791fe96927ad78e64b0aad7bded08bdc
685 $ mv git-repo4/.git/objects/$BLOB_OBJ git-repo4/.git/objects/$BLOB_OBJ.tmp
707 $ mv git-repo4/.git/objects/$BLOB_OBJ git-repo4/.git/objects/$BLOB_OBJ.tmp
686 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
708 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
687 abort: cannot read 'blob' object at 8b137891791fe96927ad78e64b0aad7bded08bdc
709 abort: cannot read 'blob' object at 8b137891791fe96927ad78e64b0aad7bded08bdc
688 $ mv git-repo4/.git/objects/$BLOB_OBJ.tmp git-repo4/.git/objects/$BLOB_OBJ
710 $ mv git-repo4/.git/objects/$BLOB_OBJ.tmp git-repo4/.git/objects/$BLOB_OBJ
689 damage git repository by renaming a tree object
711 damage git repository by renaming a tree object
690
712
691 $ TREE_OBJ=72/49f083d2a63a41cc737764a86981eb5f3e4635
713 $ TREE_OBJ=72/49f083d2a63a41cc737764a86981eb5f3e4635
692 $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp
714 $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp
693 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
715 $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
694 abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
716 abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
General Comments 0
You need to be logged in to leave comments. Login now