##// END OF EJS Templates
convert: update 'intermediate-source' in the destination's extras dictionary
Matt Harbison -
r25589:273d9425 default
parent child Browse files
Show More
@@ -1,560 +1,561
1 # hg.py - hg backend for convert extension
1 # hg.py - hg backend for 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 # Notes for hg->hg conversion:
8 # Notes for hg->hg conversion:
9 #
9 #
10 # * Old versions of Mercurial didn't trim the whitespace from the ends
10 # * Old versions of Mercurial didn't trim the whitespace from the ends
11 # of commit messages, but new versions do. Changesets created by
11 # of commit messages, but new versions do. Changesets created by
12 # those older versions, then converted, may thus have different
12 # those older versions, then converted, may thus have different
13 # hashes for changesets that are otherwise identical.
13 # hashes for changesets that are otherwise identical.
14 #
14 #
15 # * Using "--config convert.hg.saverev=true" will make the source
15 # * Using "--config convert.hg.saverev=true" will make the source
16 # identifier to be stored in the converted revision. This will cause
16 # identifier to be stored in the converted revision. This will cause
17 # the converted revision to have a different identity than the
17 # the converted revision to have a different identity than the
18 # source.
18 # source.
19
19
20
20
21 import os, time, cStringIO
21 import os, time, cStringIO
22 from mercurial.i18n import _
22 from mercurial.i18n import _
23 from mercurial.node import bin, hex, nullid
23 from mercurial.node import bin, hex, nullid
24 from mercurial import hg, util, context, bookmarks, error, scmutil, exchange
24 from mercurial import hg, util, context, bookmarks, error, scmutil, exchange
25 from mercurial import phases
25 from mercurial import phases
26
26
27 from common import NoRepo, commit, converter_source, converter_sink, mapfile
27 from common import NoRepo, commit, converter_source, converter_sink, mapfile
28
28
29 import re
29 import re
30 sha1re = re.compile(r'\b[0-9a-f]{12,40}\b')
30 sha1re = re.compile(r'\b[0-9a-f]{12,40}\b')
31
31
32 class mercurial_sink(converter_sink):
32 class mercurial_sink(converter_sink):
33 def __init__(self, ui, path):
33 def __init__(self, ui, path):
34 converter_sink.__init__(self, ui, path)
34 converter_sink.__init__(self, ui, path)
35 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
35 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
36 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
36 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
37 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
37 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
38 self.lastbranch = None
38 self.lastbranch = None
39 if os.path.isdir(path) and len(os.listdir(path)) > 0:
39 if os.path.isdir(path) and len(os.listdir(path)) > 0:
40 try:
40 try:
41 self.repo = hg.repository(self.ui, path)
41 self.repo = hg.repository(self.ui, path)
42 if not self.repo.local():
42 if not self.repo.local():
43 raise NoRepo(_('%s is not a local Mercurial repository')
43 raise NoRepo(_('%s is not a local Mercurial repository')
44 % path)
44 % path)
45 except error.RepoError, err:
45 except error.RepoError, err:
46 ui.traceback()
46 ui.traceback()
47 raise NoRepo(err.args[0])
47 raise NoRepo(err.args[0])
48 else:
48 else:
49 try:
49 try:
50 ui.status(_('initializing destination %s repository\n') % path)
50 ui.status(_('initializing destination %s repository\n') % path)
51 self.repo = hg.repository(self.ui, path, create=True)
51 self.repo = hg.repository(self.ui, path, create=True)
52 if not self.repo.local():
52 if not self.repo.local():
53 raise NoRepo(_('%s is not a local Mercurial repository')
53 raise NoRepo(_('%s is not a local Mercurial repository')
54 % path)
54 % path)
55 self.created.append(path)
55 self.created.append(path)
56 except error.RepoError:
56 except error.RepoError:
57 ui.traceback()
57 ui.traceback()
58 raise NoRepo(_("could not create hg repository %s as sink")
58 raise NoRepo(_("could not create hg repository %s as sink")
59 % path)
59 % path)
60 self.lock = None
60 self.lock = None
61 self.wlock = None
61 self.wlock = None
62 self.filemapmode = False
62 self.filemapmode = False
63 self.subrevmaps = {}
63 self.subrevmaps = {}
64
64
65 def before(self):
65 def before(self):
66 self.ui.debug('run hg sink pre-conversion action\n')
66 self.ui.debug('run hg sink pre-conversion action\n')
67 self.wlock = self.repo.wlock()
67 self.wlock = self.repo.wlock()
68 self.lock = self.repo.lock()
68 self.lock = self.repo.lock()
69
69
70 def after(self):
70 def after(self):
71 self.ui.debug('run hg sink post-conversion action\n')
71 self.ui.debug('run hg sink post-conversion action\n')
72 if self.lock:
72 if self.lock:
73 self.lock.release()
73 self.lock.release()
74 if self.wlock:
74 if self.wlock:
75 self.wlock.release()
75 self.wlock.release()
76
76
77 def revmapfile(self):
77 def revmapfile(self):
78 return self.repo.join("shamap")
78 return self.repo.join("shamap")
79
79
80 def authorfile(self):
80 def authorfile(self):
81 return self.repo.join("authormap")
81 return self.repo.join("authormap")
82
82
83 def setbranch(self, branch, pbranches):
83 def setbranch(self, branch, pbranches):
84 if not self.clonebranches:
84 if not self.clonebranches:
85 return
85 return
86
86
87 setbranch = (branch != self.lastbranch)
87 setbranch = (branch != self.lastbranch)
88 self.lastbranch = branch
88 self.lastbranch = branch
89 if not branch:
89 if not branch:
90 branch = 'default'
90 branch = 'default'
91 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
91 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
92 if pbranches:
92 if pbranches:
93 pbranch = pbranches[0][1]
93 pbranch = pbranches[0][1]
94 else:
94 else:
95 pbranch = 'default'
95 pbranch = 'default'
96
96
97 branchpath = os.path.join(self.path, branch)
97 branchpath = os.path.join(self.path, branch)
98 if setbranch:
98 if setbranch:
99 self.after()
99 self.after()
100 try:
100 try:
101 self.repo = hg.repository(self.ui, branchpath)
101 self.repo = hg.repository(self.ui, branchpath)
102 except Exception:
102 except Exception:
103 self.repo = hg.repository(self.ui, branchpath, create=True)
103 self.repo = hg.repository(self.ui, branchpath, create=True)
104 self.before()
104 self.before()
105
105
106 # pbranches may bring revisions from other branches (merge parents)
106 # pbranches may bring revisions from other branches (merge parents)
107 # Make sure we have them, or pull them.
107 # Make sure we have them, or pull them.
108 missings = {}
108 missings = {}
109 for b in pbranches:
109 for b in pbranches:
110 try:
110 try:
111 self.repo.lookup(b[0])
111 self.repo.lookup(b[0])
112 except Exception:
112 except Exception:
113 missings.setdefault(b[1], []).append(b[0])
113 missings.setdefault(b[1], []).append(b[0])
114
114
115 if missings:
115 if missings:
116 self.after()
116 self.after()
117 for pbranch, heads in sorted(missings.iteritems()):
117 for pbranch, heads in sorted(missings.iteritems()):
118 pbranchpath = os.path.join(self.path, pbranch)
118 pbranchpath = os.path.join(self.path, pbranch)
119 prepo = hg.peer(self.ui, {}, pbranchpath)
119 prepo = hg.peer(self.ui, {}, pbranchpath)
120 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
120 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
121 exchange.pull(self.repo, prepo,
121 exchange.pull(self.repo, prepo,
122 [prepo.lookup(h) for h in heads])
122 [prepo.lookup(h) for h in heads])
123 self.before()
123 self.before()
124
124
125 def _rewritetags(self, source, revmap, data):
125 def _rewritetags(self, source, revmap, data):
126 fp = cStringIO.StringIO()
126 fp = cStringIO.StringIO()
127 for line in data.splitlines():
127 for line in data.splitlines():
128 s = line.split(' ', 1)
128 s = line.split(' ', 1)
129 if len(s) != 2:
129 if len(s) != 2:
130 continue
130 continue
131 revid = revmap.get(source.lookuprev(s[0]))
131 revid = revmap.get(source.lookuprev(s[0]))
132 if not revid:
132 if not revid:
133 if s[0] == hex(nullid):
133 if s[0] == hex(nullid):
134 revid = s[0]
134 revid = s[0]
135 else:
135 else:
136 continue
136 continue
137 fp.write('%s %s\n' % (revid, s[1]))
137 fp.write('%s %s\n' % (revid, s[1]))
138 return fp.getvalue()
138 return fp.getvalue()
139
139
140 def _rewritesubstate(self, source, data):
140 def _rewritesubstate(self, source, data):
141 fp = cStringIO.StringIO()
141 fp = cStringIO.StringIO()
142 for line in data.splitlines():
142 for line in data.splitlines():
143 s = line.split(' ', 1)
143 s = line.split(' ', 1)
144 if len(s) != 2:
144 if len(s) != 2:
145 continue
145 continue
146
146
147 revid = s[0]
147 revid = s[0]
148 subpath = s[1]
148 subpath = s[1]
149 if revid != hex(nullid):
149 if revid != hex(nullid):
150 revmap = self.subrevmaps.get(subpath)
150 revmap = self.subrevmaps.get(subpath)
151 if revmap is None:
151 if revmap is None:
152 revmap = mapfile(self.ui,
152 revmap = mapfile(self.ui,
153 self.repo.wjoin(subpath, '.hg/shamap'))
153 self.repo.wjoin(subpath, '.hg/shamap'))
154 self.subrevmaps[subpath] = revmap
154 self.subrevmaps[subpath] = revmap
155
155
156 # It is reasonable that one or more of the subrepos don't
156 # It is reasonable that one or more of the subrepos don't
157 # need to be converted, in which case they can be cloned
157 # need to be converted, in which case they can be cloned
158 # into place instead of converted. Therefore, only warn
158 # into place instead of converted. Therefore, only warn
159 # once.
159 # once.
160 msg = _('no ".hgsubstate" updates will be made for "%s"\n')
160 msg = _('no ".hgsubstate" updates will be made for "%s"\n')
161 if len(revmap) == 0:
161 if len(revmap) == 0:
162 sub = self.repo.wvfs.reljoin(subpath, '.hg')
162 sub = self.repo.wvfs.reljoin(subpath, '.hg')
163
163
164 if self.repo.wvfs.exists(sub):
164 if self.repo.wvfs.exists(sub):
165 self.ui.warn(msg % subpath)
165 self.ui.warn(msg % subpath)
166
166
167 newid = revmap.get(revid)
167 newid = revmap.get(revid)
168 if not newid:
168 if not newid:
169 if len(revmap) > 0:
169 if len(revmap) > 0:
170 self.ui.warn(_("%s is missing from %s/.hg/shamap\n") %
170 self.ui.warn(_("%s is missing from %s/.hg/shamap\n") %
171 (revid, subpath))
171 (revid, subpath))
172 else:
172 else:
173 revid = newid
173 revid = newid
174
174
175 fp.write('%s %s\n' % (revid, subpath))
175 fp.write('%s %s\n' % (revid, subpath))
176
176
177 return fp.getvalue()
177 return fp.getvalue()
178
178
179 def putcommit(self, files, copies, parents, commit, source, revmap, full,
179 def putcommit(self, files, copies, parents, commit, source, revmap, full,
180 cleanp2):
180 cleanp2):
181 files = dict(files)
181 files = dict(files)
182
182
183 def getfilectx(repo, memctx, f):
183 def getfilectx(repo, memctx, f):
184 if p2ctx and f in cleanp2 and f not in copies:
184 if p2ctx and f in cleanp2 and f not in copies:
185 self.ui.debug('reusing %s from p2\n' % f)
185 self.ui.debug('reusing %s from p2\n' % f)
186 return p2ctx[f]
186 return p2ctx[f]
187 try:
187 try:
188 v = files[f]
188 v = files[f]
189 except KeyError:
189 except KeyError:
190 return None
190 return None
191 data, mode = source.getfile(f, v)
191 data, mode = source.getfile(f, v)
192 if data is None:
192 if data is None:
193 return None
193 return None
194 if f == '.hgtags':
194 if f == '.hgtags':
195 data = self._rewritetags(source, revmap, data)
195 data = self._rewritetags(source, revmap, data)
196 if f == '.hgsubstate':
196 if f == '.hgsubstate':
197 data = self._rewritesubstate(source, data)
197 data = self._rewritesubstate(source, data)
198 return context.memfilectx(self.repo, f, data, 'l' in mode,
198 return context.memfilectx(self.repo, f, data, 'l' in mode,
199 'x' in mode, copies.get(f))
199 'x' in mode, copies.get(f))
200
200
201 pl = []
201 pl = []
202 for p in parents:
202 for p in parents:
203 if p not in pl:
203 if p not in pl:
204 pl.append(p)
204 pl.append(p)
205 parents = pl
205 parents = pl
206 nparents = len(parents)
206 nparents = len(parents)
207 if self.filemapmode and nparents == 1:
207 if self.filemapmode and nparents == 1:
208 m1node = self.repo.changelog.read(bin(parents[0]))[0]
208 m1node = self.repo.changelog.read(bin(parents[0]))[0]
209 parent = parents[0]
209 parent = parents[0]
210
210
211 if len(parents) < 2:
211 if len(parents) < 2:
212 parents.append(nullid)
212 parents.append(nullid)
213 if len(parents) < 2:
213 if len(parents) < 2:
214 parents.append(nullid)
214 parents.append(nullid)
215 p2 = parents.pop(0)
215 p2 = parents.pop(0)
216
216
217 text = commit.desc
217 text = commit.desc
218
218
219 sha1s = re.findall(sha1re, text)
219 sha1s = re.findall(sha1re, text)
220 for sha1 in sha1s:
220 for sha1 in sha1s:
221 oldrev = source.lookuprev(sha1)
221 oldrev = source.lookuprev(sha1)
222 newrev = revmap.get(oldrev)
222 newrev = revmap.get(oldrev)
223 if newrev is not None:
223 if newrev is not None:
224 text = text.replace(sha1, newrev[:len(sha1)])
224 text = text.replace(sha1, newrev[:len(sha1)])
225
225
226 extra = commit.extra.copy()
226 extra = commit.extra.copy()
227
227
228 for label in ('source', 'transplant_source', 'rebase_source'):
228 for label in ('source', 'transplant_source', 'rebase_source',
229 'intermediate-source'):
229 node = extra.get(label)
230 node = extra.get(label)
230
231
231 if node is None:
232 if node is None:
232 continue
233 continue
233
234
234 # Only transplant stores its reference in binary
235 # Only transplant stores its reference in binary
235 if label == 'transplant_source':
236 if label == 'transplant_source':
236 node = hex(node)
237 node = hex(node)
237
238
238 newrev = revmap.get(node)
239 newrev = revmap.get(node)
239 if newrev is not None:
240 if newrev is not None:
240 if label == 'transplant_source':
241 if label == 'transplant_source':
241 newrev = bin(newrev)
242 newrev = bin(newrev)
242
243
243 extra[label] = newrev
244 extra[label] = newrev
244
245
245 if self.branchnames and commit.branch:
246 if self.branchnames and commit.branch:
246 extra['branch'] = commit.branch
247 extra['branch'] = commit.branch
247 if commit.rev and commit.saverev:
248 if commit.rev and commit.saverev:
248 extra['convert_revision'] = commit.rev
249 extra['convert_revision'] = commit.rev
249
250
250 while parents:
251 while parents:
251 p1 = p2
252 p1 = p2
252 p2 = parents.pop(0)
253 p2 = parents.pop(0)
253 p2ctx = None
254 p2ctx = None
254 if p2 != nullid:
255 if p2 != nullid:
255 p2ctx = self.repo[p2]
256 p2ctx = self.repo[p2]
256 fileset = set(files)
257 fileset = set(files)
257 if full:
258 if full:
258 fileset.update(self.repo[p1])
259 fileset.update(self.repo[p1])
259 fileset.update(self.repo[p2])
260 fileset.update(self.repo[p2])
260 ctx = context.memctx(self.repo, (p1, p2), text, fileset,
261 ctx = context.memctx(self.repo, (p1, p2), text, fileset,
261 getfilectx, commit.author, commit.date, extra)
262 getfilectx, commit.author, commit.date, extra)
262
263
263 # We won't know if the conversion changes the node until after the
264 # We won't know if the conversion changes the node until after the
264 # commit, so copy the source's phase for now.
265 # commit, so copy the source's phase for now.
265 self.repo.ui.setconfig('phases', 'new-commit',
266 self.repo.ui.setconfig('phases', 'new-commit',
266 phases.phasenames[commit.phase], 'convert')
267 phases.phasenames[commit.phase], 'convert')
267
268
268 tr = self.repo.transaction("convert")
269 tr = self.repo.transaction("convert")
269
270
270 try:
271 try:
271 node = hex(self.repo.commitctx(ctx))
272 node = hex(self.repo.commitctx(ctx))
272
273
273 # If the node value has changed, but the phase is lower than
274 # If the node value has changed, but the phase is lower than
274 # draft, set it back to draft since it hasn't been exposed
275 # draft, set it back to draft since it hasn't been exposed
275 # anywhere.
276 # anywhere.
276 if commit.rev != node:
277 if commit.rev != node:
277 ctx = self.repo[node]
278 ctx = self.repo[node]
278 if ctx.phase() < phases.draft:
279 if ctx.phase() < phases.draft:
279 phases.retractboundary(self.repo, tr, phases.draft,
280 phases.retractboundary(self.repo, tr, phases.draft,
280 [ctx.node()])
281 [ctx.node()])
281 tr.close()
282 tr.close()
282 finally:
283 finally:
283 tr.release()
284 tr.release()
284
285
285 text = "(octopus merge fixup)\n"
286 text = "(octopus merge fixup)\n"
286 p2 = hex(self.repo.changelog.tip())
287 p2 = hex(self.repo.changelog.tip())
287
288
288 if self.filemapmode and nparents == 1:
289 if self.filemapmode and nparents == 1:
289 man = self.repo.manifest
290 man = self.repo.manifest
290 mnode = self.repo.changelog.read(bin(p2))[0]
291 mnode = self.repo.changelog.read(bin(p2))[0]
291 closed = 'close' in commit.extra
292 closed = 'close' in commit.extra
292 if not closed and not man.cmp(m1node, man.revision(mnode)):
293 if not closed and not man.cmp(m1node, man.revision(mnode)):
293 self.ui.status(_("filtering out empty revision\n"))
294 self.ui.status(_("filtering out empty revision\n"))
294 self.repo.rollback(force=True)
295 self.repo.rollback(force=True)
295 return parent
296 return parent
296 return p2
297 return p2
297
298
298 def puttags(self, tags):
299 def puttags(self, tags):
299 try:
300 try:
300 parentctx = self.repo[self.tagsbranch]
301 parentctx = self.repo[self.tagsbranch]
301 tagparent = parentctx.node()
302 tagparent = parentctx.node()
302 except error.RepoError:
303 except error.RepoError:
303 parentctx = None
304 parentctx = None
304 tagparent = nullid
305 tagparent = nullid
305
306
306 oldlines = set()
307 oldlines = set()
307 for branch, heads in self.repo.branchmap().iteritems():
308 for branch, heads in self.repo.branchmap().iteritems():
308 for h in heads:
309 for h in heads:
309 if '.hgtags' in self.repo[h]:
310 if '.hgtags' in self.repo[h]:
310 oldlines.update(
311 oldlines.update(
311 set(self.repo[h]['.hgtags'].data().splitlines(True)))
312 set(self.repo[h]['.hgtags'].data().splitlines(True)))
312 oldlines = sorted(list(oldlines))
313 oldlines = sorted(list(oldlines))
313
314
314 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
315 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
315 if newlines == oldlines:
316 if newlines == oldlines:
316 return None, None
317 return None, None
317
318
318 # if the old and new tags match, then there is nothing to update
319 # if the old and new tags match, then there is nothing to update
319 oldtags = set()
320 oldtags = set()
320 newtags = set()
321 newtags = set()
321 for line in oldlines:
322 for line in oldlines:
322 s = line.strip().split(' ', 1)
323 s = line.strip().split(' ', 1)
323 if len(s) != 2:
324 if len(s) != 2:
324 continue
325 continue
325 oldtags.add(s[1])
326 oldtags.add(s[1])
326 for line in newlines:
327 for line in newlines:
327 s = line.strip().split(' ', 1)
328 s = line.strip().split(' ', 1)
328 if len(s) != 2:
329 if len(s) != 2:
329 continue
330 continue
330 if s[1] not in oldtags:
331 if s[1] not in oldtags:
331 newtags.add(s[1].strip())
332 newtags.add(s[1].strip())
332
333
333 if not newtags:
334 if not newtags:
334 return None, None
335 return None, None
335
336
336 data = "".join(newlines)
337 data = "".join(newlines)
337 def getfilectx(repo, memctx, f):
338 def getfilectx(repo, memctx, f):
338 return context.memfilectx(repo, f, data, False, False, None)
339 return context.memfilectx(repo, f, data, False, False, None)
339
340
340 self.ui.status(_("updating tags\n"))
341 self.ui.status(_("updating tags\n"))
341 date = "%s 0" % int(time.mktime(time.gmtime()))
342 date = "%s 0" % int(time.mktime(time.gmtime()))
342 extra = {'branch': self.tagsbranch}
343 extra = {'branch': self.tagsbranch}
343 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
344 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
344 [".hgtags"], getfilectx, "convert-repo", date,
345 [".hgtags"], getfilectx, "convert-repo", date,
345 extra)
346 extra)
346 self.repo.commitctx(ctx)
347 self.repo.commitctx(ctx)
347 return hex(self.repo.changelog.tip()), hex(tagparent)
348 return hex(self.repo.changelog.tip()), hex(tagparent)
348
349
349 def setfilemapmode(self, active):
350 def setfilemapmode(self, active):
350 self.filemapmode = active
351 self.filemapmode = active
351
352
352 def putbookmarks(self, updatedbookmark):
353 def putbookmarks(self, updatedbookmark):
353 if not len(updatedbookmark):
354 if not len(updatedbookmark):
354 return
355 return
355
356
356 self.ui.status(_("updating bookmarks\n"))
357 self.ui.status(_("updating bookmarks\n"))
357 destmarks = self.repo._bookmarks
358 destmarks = self.repo._bookmarks
358 for bookmark in updatedbookmark:
359 for bookmark in updatedbookmark:
359 destmarks[bookmark] = bin(updatedbookmark[bookmark])
360 destmarks[bookmark] = bin(updatedbookmark[bookmark])
360 destmarks.write()
361 destmarks.write()
361
362
362 def hascommitfrommap(self, rev):
363 def hascommitfrommap(self, rev):
363 # the exact semantics of clonebranches is unclear so we can't say no
364 # the exact semantics of clonebranches is unclear so we can't say no
364 return rev in self.repo or self.clonebranches
365 return rev in self.repo or self.clonebranches
365
366
366 def hascommitforsplicemap(self, rev):
367 def hascommitforsplicemap(self, rev):
367 if rev not in self.repo and self.clonebranches:
368 if rev not in self.repo and self.clonebranches:
368 raise util.Abort(_('revision %s not found in destination '
369 raise util.Abort(_('revision %s not found in destination '
369 'repository (lookups with clonebranches=true '
370 'repository (lookups with clonebranches=true '
370 'are not implemented)') % rev)
371 'are not implemented)') % rev)
371 return rev in self.repo
372 return rev in self.repo
372
373
373 class mercurial_source(converter_source):
374 class mercurial_source(converter_source):
374 def __init__(self, ui, path, rev=None):
375 def __init__(self, ui, path, rev=None):
375 converter_source.__init__(self, ui, path, rev)
376 converter_source.__init__(self, ui, path, rev)
376 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
377 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
377 self.ignored = set()
378 self.ignored = set()
378 self.saverev = ui.configbool('convert', 'hg.saverev', False)
379 self.saverev = ui.configbool('convert', 'hg.saverev', False)
379 try:
380 try:
380 self.repo = hg.repository(self.ui, path)
381 self.repo = hg.repository(self.ui, path)
381 # try to provoke an exception if this isn't really a hg
382 # try to provoke an exception if this isn't really a hg
382 # repo, but some other bogus compatible-looking url
383 # repo, but some other bogus compatible-looking url
383 if not self.repo.local():
384 if not self.repo.local():
384 raise error.RepoError
385 raise error.RepoError
385 except error.RepoError:
386 except error.RepoError:
386 ui.traceback()
387 ui.traceback()
387 raise NoRepo(_("%s is not a local Mercurial repository") % path)
388 raise NoRepo(_("%s is not a local Mercurial repository") % path)
388 self.lastrev = None
389 self.lastrev = None
389 self.lastctx = None
390 self.lastctx = None
390 self._changescache = None, None
391 self._changescache = None, None
391 self.convertfp = None
392 self.convertfp = None
392 # Restrict converted revisions to startrev descendants
393 # Restrict converted revisions to startrev descendants
393 startnode = ui.config('convert', 'hg.startrev')
394 startnode = ui.config('convert', 'hg.startrev')
394 hgrevs = ui.config('convert', 'hg.revs')
395 hgrevs = ui.config('convert', 'hg.revs')
395 if hgrevs is None:
396 if hgrevs is None:
396 if startnode is not None:
397 if startnode is not None:
397 try:
398 try:
398 startnode = self.repo.lookup(startnode)
399 startnode = self.repo.lookup(startnode)
399 except error.RepoError:
400 except error.RepoError:
400 raise util.Abort(_('%s is not a valid start revision')
401 raise util.Abort(_('%s is not a valid start revision')
401 % startnode)
402 % startnode)
402 startrev = self.repo.changelog.rev(startnode)
403 startrev = self.repo.changelog.rev(startnode)
403 children = {startnode: 1}
404 children = {startnode: 1}
404 for r in self.repo.changelog.descendants([startrev]):
405 for r in self.repo.changelog.descendants([startrev]):
405 children[self.repo.changelog.node(r)] = 1
406 children[self.repo.changelog.node(r)] = 1
406 self.keep = children.__contains__
407 self.keep = children.__contains__
407 else:
408 else:
408 self.keep = util.always
409 self.keep = util.always
409 if rev:
410 if rev:
410 self._heads = [self.repo[rev].node()]
411 self._heads = [self.repo[rev].node()]
411 else:
412 else:
412 self._heads = self.repo.heads()
413 self._heads = self.repo.heads()
413 else:
414 else:
414 if rev or startnode is not None:
415 if rev or startnode is not None:
415 raise util.Abort(_('hg.revs cannot be combined with '
416 raise util.Abort(_('hg.revs cannot be combined with '
416 'hg.startrev or --rev'))
417 'hg.startrev or --rev'))
417 nodes = set()
418 nodes = set()
418 parents = set()
419 parents = set()
419 for r in scmutil.revrange(self.repo, [hgrevs]):
420 for r in scmutil.revrange(self.repo, [hgrevs]):
420 ctx = self.repo[r]
421 ctx = self.repo[r]
421 nodes.add(ctx.node())
422 nodes.add(ctx.node())
422 parents.update(p.node() for p in ctx.parents())
423 parents.update(p.node() for p in ctx.parents())
423 self.keep = nodes.__contains__
424 self.keep = nodes.__contains__
424 self._heads = nodes - parents
425 self._heads = nodes - parents
425
426
426 def changectx(self, rev):
427 def changectx(self, rev):
427 if self.lastrev != rev:
428 if self.lastrev != rev:
428 self.lastctx = self.repo[rev]
429 self.lastctx = self.repo[rev]
429 self.lastrev = rev
430 self.lastrev = rev
430 return self.lastctx
431 return self.lastctx
431
432
432 def parents(self, ctx):
433 def parents(self, ctx):
433 return [p for p in ctx.parents() if p and self.keep(p.node())]
434 return [p for p in ctx.parents() if p and self.keep(p.node())]
434
435
435 def getheads(self):
436 def getheads(self):
436 return [hex(h) for h in self._heads if self.keep(h)]
437 return [hex(h) for h in self._heads if self.keep(h)]
437
438
438 def getfile(self, name, rev):
439 def getfile(self, name, rev):
439 try:
440 try:
440 fctx = self.changectx(rev)[name]
441 fctx = self.changectx(rev)[name]
441 return fctx.data(), fctx.flags()
442 return fctx.data(), fctx.flags()
442 except error.LookupError:
443 except error.LookupError:
443 return None, None
444 return None, None
444
445
445 def getchanges(self, rev, full):
446 def getchanges(self, rev, full):
446 ctx = self.changectx(rev)
447 ctx = self.changectx(rev)
447 parents = self.parents(ctx)
448 parents = self.parents(ctx)
448 if full or not parents:
449 if full or not parents:
449 files = copyfiles = ctx.manifest()
450 files = copyfiles = ctx.manifest()
450 if parents:
451 if parents:
451 if self._changescache[0] == rev:
452 if self._changescache[0] == rev:
452 m, a, r = self._changescache[1]
453 m, a, r = self._changescache[1]
453 else:
454 else:
454 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
455 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
455 if not full:
456 if not full:
456 files = m + a + r
457 files = m + a + r
457 copyfiles = m + a
458 copyfiles = m + a
458 # getcopies() is also run for roots and before filtering so missing
459 # getcopies() is also run for roots and before filtering so missing
459 # revlogs are detected early
460 # revlogs are detected early
460 copies = self.getcopies(ctx, parents, copyfiles)
461 copies = self.getcopies(ctx, parents, copyfiles)
461 cleanp2 = set()
462 cleanp2 = set()
462 if len(parents) == 2:
463 if len(parents) == 2:
463 cleanp2.update(self.repo.status(parents[1].node(), ctx.node(),
464 cleanp2.update(self.repo.status(parents[1].node(), ctx.node(),
464 clean=True).clean)
465 clean=True).clean)
465 changes = [(f, rev) for f in files if f not in self.ignored]
466 changes = [(f, rev) for f in files if f not in self.ignored]
466 changes.sort()
467 changes.sort()
467 return changes, copies, cleanp2
468 return changes, copies, cleanp2
468
469
469 def getcopies(self, ctx, parents, files):
470 def getcopies(self, ctx, parents, files):
470 copies = {}
471 copies = {}
471 for name in files:
472 for name in files:
472 if name in self.ignored:
473 if name in self.ignored:
473 continue
474 continue
474 try:
475 try:
475 copysource, _copynode = ctx.filectx(name).renamed()
476 copysource, _copynode = ctx.filectx(name).renamed()
476 if copysource in self.ignored:
477 if copysource in self.ignored:
477 continue
478 continue
478 # Ignore copy sources not in parent revisions
479 # Ignore copy sources not in parent revisions
479 found = False
480 found = False
480 for p in parents:
481 for p in parents:
481 if copysource in p:
482 if copysource in p:
482 found = True
483 found = True
483 break
484 break
484 if not found:
485 if not found:
485 continue
486 continue
486 copies[name] = copysource
487 copies[name] = copysource
487 except TypeError:
488 except TypeError:
488 pass
489 pass
489 except error.LookupError, e:
490 except error.LookupError, e:
490 if not self.ignoreerrors:
491 if not self.ignoreerrors:
491 raise
492 raise
492 self.ignored.add(name)
493 self.ignored.add(name)
493 self.ui.warn(_('ignoring: %s\n') % e)
494 self.ui.warn(_('ignoring: %s\n') % e)
494 return copies
495 return copies
495
496
496 def getcommit(self, rev):
497 def getcommit(self, rev):
497 ctx = self.changectx(rev)
498 ctx = self.changectx(rev)
498 parents = [p.hex() for p in self.parents(ctx)]
499 parents = [p.hex() for p in self.parents(ctx)]
499 crev = rev
500 crev = rev
500
501
501 return commit(author=ctx.user(),
502 return commit(author=ctx.user(),
502 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
503 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
503 desc=ctx.description(), rev=crev, parents=parents,
504 desc=ctx.description(), rev=crev, parents=parents,
504 branch=ctx.branch(), extra=ctx.extra(),
505 branch=ctx.branch(), extra=ctx.extra(),
505 sortkey=ctx.rev(), saverev=self.saverev,
506 sortkey=ctx.rev(), saverev=self.saverev,
506 phase=ctx.phase())
507 phase=ctx.phase())
507
508
508 def gettags(self):
509 def gettags(self):
509 # This will get written to .hgtags, filter non global tags out.
510 # This will get written to .hgtags, filter non global tags out.
510 tags = [t for t in self.repo.tagslist()
511 tags = [t for t in self.repo.tagslist()
511 if self.repo.tagtype(t[0]) == 'global']
512 if self.repo.tagtype(t[0]) == 'global']
512 return dict([(name, hex(node)) for name, node in tags
513 return dict([(name, hex(node)) for name, node in tags
513 if self.keep(node)])
514 if self.keep(node)])
514
515
515 def getchangedfiles(self, rev, i):
516 def getchangedfiles(self, rev, i):
516 ctx = self.changectx(rev)
517 ctx = self.changectx(rev)
517 parents = self.parents(ctx)
518 parents = self.parents(ctx)
518 if not parents and i is None:
519 if not parents and i is None:
519 i = 0
520 i = 0
520 changes = [], ctx.manifest().keys(), []
521 changes = [], ctx.manifest().keys(), []
521 else:
522 else:
522 i = i or 0
523 i = i or 0
523 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
524 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
524 changes = [[f for f in l if f not in self.ignored] for l in changes]
525 changes = [[f for f in l if f not in self.ignored] for l in changes]
525
526
526 if i == 0:
527 if i == 0:
527 self._changescache = (rev, changes)
528 self._changescache = (rev, changes)
528
529
529 return changes[0] + changes[1] + changes[2]
530 return changes[0] + changes[1] + changes[2]
530
531
531 def converted(self, rev, destrev):
532 def converted(self, rev, destrev):
532 if self.convertfp is None:
533 if self.convertfp is None:
533 self.convertfp = open(self.repo.join('shamap'), 'a')
534 self.convertfp = open(self.repo.join('shamap'), 'a')
534 self.convertfp.write('%s %s\n' % (destrev, rev))
535 self.convertfp.write('%s %s\n' % (destrev, rev))
535 self.convertfp.flush()
536 self.convertfp.flush()
536
537
537 def before(self):
538 def before(self):
538 self.ui.debug('run hg source pre-conversion action\n')
539 self.ui.debug('run hg source pre-conversion action\n')
539
540
540 def after(self):
541 def after(self):
541 self.ui.debug('run hg source post-conversion action\n')
542 self.ui.debug('run hg source post-conversion action\n')
542
543
543 def hasnativeorder(self):
544 def hasnativeorder(self):
544 return True
545 return True
545
546
546 def hasnativeclose(self):
547 def hasnativeclose(self):
547 return True
548 return True
548
549
549 def lookuprev(self, rev):
550 def lookuprev(self, rev):
550 try:
551 try:
551 return hex(self.repo.lookup(rev))
552 return hex(self.repo.lookup(rev))
552 except (error.RepoError, error.LookupError):
553 except (error.RepoError, error.LookupError):
553 return None
554 return None
554
555
555 def getbookmarks(self):
556 def getbookmarks(self):
556 return bookmarks.listbookmarks(self.repo)
557 return bookmarks.listbookmarks(self.repo)
557
558
558 def checkrevformat(self, revstr, mapname='splicemap'):
559 def checkrevformat(self, revstr, mapname='splicemap'):
559 """ Mercurial, revision string is a 40 byte hex """
560 """ Mercurial, revision string is a 40 byte hex """
560 self.checkhexformat(revstr, mapname)
561 self.checkhexformat(revstr, mapname)
@@ -1,769 +1,771
1 Create a repo with some stuff in it:
1 Create a repo with some stuff in it:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ echo a > d
6 $ echo a > d
7 $ echo a > e
7 $ echo a > e
8 $ hg ci -qAm0
8 $ hg ci -qAm0
9 $ echo b > a
9 $ echo b > a
10 $ hg ci -m1 -u bar
10 $ hg ci -m1 -u bar
11 $ hg mv a b
11 $ hg mv a b
12 $ hg ci -m2
12 $ hg ci -m2
13 $ hg cp b c
13 $ hg cp b c
14 $ hg ci -m3 -u baz
14 $ hg ci -m3 -u baz
15 $ echo b > d
15 $ echo b > d
16 $ echo f > e
16 $ echo f > e
17 $ hg ci -m4
17 $ hg ci -m4
18 $ hg up -q 3
18 $ hg up -q 3
19 $ echo b > e
19 $ echo b > e
20 $ hg branch -q stable
20 $ hg branch -q stable
21 $ hg ci -m5
21 $ hg ci -m5
22 $ hg merge -q default --tool internal:local
22 $ hg merge -q default --tool internal:local
23 $ hg branch -q default
23 $ hg branch -q default
24 $ hg ci -m6
24 $ hg ci -m6
25 $ hg phase --public 3
25 $ hg phase --public 3
26 $ hg phase --force --secret 6
26 $ hg phase --force --secret 6
27
27
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
29 @ test@6.secret: 6
29 @ test@6.secret: 6
30 |\
30 |\
31 | o test@5.draft: 5
31 | o test@5.draft: 5
32 | |
32 | |
33 o | test@4.draft: 4
33 o | test@4.draft: 4
34 |/
34 |/
35 o baz@3.public: 3
35 o baz@3.public: 3
36 |
36 |
37 o test@2.public: 2
37 o test@2.public: 2
38 |
38 |
39 o bar@1.public: 1
39 o bar@1.public: 1
40 |
40 |
41 o test@0.public: 0
41 o test@0.public: 0
42
42
43
43
44 Need to specify a rev:
44 Need to specify a rev:
45
45
46 $ hg graft
46 $ hg graft
47 abort: no revisions specified
47 abort: no revisions specified
48 [255]
48 [255]
49
49
50 Can't graft ancestor:
50 Can't graft ancestor:
51
51
52 $ hg graft 1 2
52 $ hg graft 1 2
53 skipping ancestor revision 1:5d205f8b35b6
53 skipping ancestor revision 1:5d205f8b35b6
54 skipping ancestor revision 2:5c095ad7e90f
54 skipping ancestor revision 2:5c095ad7e90f
55 [255]
55 [255]
56
56
57 Specify revisions with -r:
57 Specify revisions with -r:
58
58
59 $ hg graft -r 1 -r 2
59 $ hg graft -r 1 -r 2
60 skipping ancestor revision 1:5d205f8b35b6
60 skipping ancestor revision 1:5d205f8b35b6
61 skipping ancestor revision 2:5c095ad7e90f
61 skipping ancestor revision 2:5c095ad7e90f
62 [255]
62 [255]
63
63
64 $ hg graft -r 1 2
64 $ hg graft -r 1 2
65 skipping ancestor revision 2:5c095ad7e90f
65 skipping ancestor revision 2:5c095ad7e90f
66 skipping ancestor revision 1:5d205f8b35b6
66 skipping ancestor revision 1:5d205f8b35b6
67 [255]
67 [255]
68
68
69 Can't graft with dirty wd:
69 Can't graft with dirty wd:
70
70
71 $ hg up -q 0
71 $ hg up -q 0
72 $ echo foo > a
72 $ echo foo > a
73 $ hg graft 1
73 $ hg graft 1
74 abort: uncommitted changes
74 abort: uncommitted changes
75 [255]
75 [255]
76 $ hg revert a
76 $ hg revert a
77
77
78 Graft a rename:
78 Graft a rename:
79 (this also tests that editor is invoked if '--edit' is specified)
79 (this also tests that editor is invoked if '--edit' is specified)
80
80
81 $ hg status --rev "2^1" --rev 2
81 $ hg status --rev "2^1" --rev 2
82 A b
82 A b
83 R a
83 R a
84 $ HGEDITOR=cat hg graft 2 -u foo --edit
84 $ HGEDITOR=cat hg graft 2 -u foo --edit
85 grafting 2:5c095ad7e90f "2"
85 grafting 2:5c095ad7e90f "2"
86 merging a and b to b
86 merging a and b to b
87 2
87 2
88
88
89
89
90 HG: Enter commit message. Lines beginning with 'HG:' are removed.
90 HG: Enter commit message. Lines beginning with 'HG:' are removed.
91 HG: Leave message empty to abort commit.
91 HG: Leave message empty to abort commit.
92 HG: --
92 HG: --
93 HG: user: foo
93 HG: user: foo
94 HG: branch 'default'
94 HG: branch 'default'
95 HG: added b
95 HG: added b
96 HG: removed a
96 HG: removed a
97 $ hg export tip --git
97 $ hg export tip --git
98 # HG changeset patch
98 # HG changeset patch
99 # User foo
99 # User foo
100 # Date 0 0
100 # Date 0 0
101 # Thu Jan 01 00:00:00 1970 +0000
101 # Thu Jan 01 00:00:00 1970 +0000
102 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
102 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
103 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
103 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
104 2
104 2
105
105
106 diff --git a/a b/b
106 diff --git a/a b/b
107 rename from a
107 rename from a
108 rename to b
108 rename to b
109
109
110 Look for extra:source
110 Look for extra:source
111
111
112 $ hg log --debug -r tip
112 $ hg log --debug -r tip
113 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
113 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
114 tag: tip
114 tag: tip
115 phase: draft
115 phase: draft
116 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
116 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
117 parent: -1:0000000000000000000000000000000000000000
117 parent: -1:0000000000000000000000000000000000000000
118 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
118 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
119 user: foo
119 user: foo
120 date: Thu Jan 01 00:00:00 1970 +0000
120 date: Thu Jan 01 00:00:00 1970 +0000
121 files+: b
121 files+: b
122 files-: a
122 files-: a
123 extra: branch=default
123 extra: branch=default
124 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
124 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
125 description:
125 description:
126 2
126 2
127
127
128
128
129
129
130 Graft out of order, skipping a merge and a duplicate
130 Graft out of order, skipping a merge and a duplicate
131 (this also tests that editor is not invoked if '--edit' is not specified)
131 (this also tests that editor is not invoked if '--edit' is not specified)
132
132
133 $ hg graft 1 5 4 3 'merge()' 2 -n
133 $ hg graft 1 5 4 3 'merge()' 2 -n
134 skipping ungraftable merge revision 6
134 skipping ungraftable merge revision 6
135 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
135 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
136 grafting 1:5d205f8b35b6 "1"
136 grafting 1:5d205f8b35b6 "1"
137 grafting 5:97f8bfe72746 "5"
137 grafting 5:97f8bfe72746 "5"
138 grafting 4:9c233e8e184d "4"
138 grafting 4:9c233e8e184d "4"
139 grafting 3:4c60f11aa304 "3"
139 grafting 3:4c60f11aa304 "3"
140
140
141 $ HGEDITOR=cat hg graft 1 5 4 3 'merge()' 2 --debug
141 $ HGEDITOR=cat hg graft 1 5 4 3 'merge()' 2 --debug
142 skipping ungraftable merge revision 6
142 skipping ungraftable merge revision 6
143 scanning for duplicate grafts
143 scanning for duplicate grafts
144 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
144 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
145 grafting 1:5d205f8b35b6 "1"
145 grafting 1:5d205f8b35b6 "1"
146 searching for copies back to rev 1
146 searching for copies back to rev 1
147 unmatched files in local:
147 unmatched files in local:
148 b
148 b
149 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
149 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
150 src: 'a' -> dst: 'b' *
150 src: 'a' -> dst: 'b' *
151 checking for directory renames
151 checking for directory renames
152 resolving manifests
152 resolving manifests
153 branchmerge: True, force: True, partial: False
153 branchmerge: True, force: True, partial: False
154 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
154 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
155 preserving b for resolve of b
155 preserving b for resolve of b
156 b: local copied/moved from a -> m
156 b: local copied/moved from a -> m
157 picked tool 'internal:merge' for b (binary False symlink False)
157 picked tool 'internal:merge' for b (binary False symlink False)
158 merging b and a to b
158 merging b and a to b
159 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
159 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
160 premerge successful
160 premerge successful
161 committing files:
161 committing files:
162 b
162 b
163 committing manifest
163 committing manifest
164 committing changelog
164 committing changelog
165 grafting 5:97f8bfe72746 "5"
165 grafting 5:97f8bfe72746 "5"
166 searching for copies back to rev 1
166 searching for copies back to rev 1
167 resolving manifests
167 resolving manifests
168 branchmerge: True, force: True, partial: False
168 branchmerge: True, force: True, partial: False
169 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
169 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
170 e: remote is newer -> g
170 e: remote is newer -> g
171 getting e
171 getting e
172 b: remote unchanged -> k
172 b: remote unchanged -> k
173 committing files:
173 committing files:
174 e
174 e
175 committing manifest
175 committing manifest
176 committing changelog
176 committing changelog
177 grafting 4:9c233e8e184d "4"
177 grafting 4:9c233e8e184d "4"
178 searching for copies back to rev 1
178 searching for copies back to rev 1
179 resolving manifests
179 resolving manifests
180 branchmerge: True, force: True, partial: False
180 branchmerge: True, force: True, partial: False
181 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
181 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
182 preserving e for resolve of e
182 preserving e for resolve of e
183 d: remote is newer -> g
183 d: remote is newer -> g
184 getting d
184 getting d
185 b: remote unchanged -> k
185 b: remote unchanged -> k
186 e: versions differ -> m
186 e: versions differ -> m
187 picked tool 'internal:merge' for e (binary False symlink False)
187 picked tool 'internal:merge' for e (binary False symlink False)
188 merging e
188 merging e
189 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
189 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
190 warning: conflicts during merge.
190 warning: conflicts during merge.
191 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
191 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
192 abort: unresolved conflicts, can't continue
192 abort: unresolved conflicts, can't continue
193 (use hg resolve and hg graft --continue)
193 (use hg resolve and hg graft --continue)
194 [255]
194 [255]
195
195
196 Commit while interrupted should fail:
196 Commit while interrupted should fail:
197
197
198 $ hg ci -m 'commit interrupted graft'
198 $ hg ci -m 'commit interrupted graft'
199 abort: graft in progress
199 abort: graft in progress
200 (use 'hg graft --continue' or 'hg update' to abort)
200 (use 'hg graft --continue' or 'hg update' to abort)
201 [255]
201 [255]
202
202
203 Abort the graft and try committing:
203 Abort the graft and try committing:
204
204
205 $ hg up -C .
205 $ hg up -C .
206 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 $ echo c >> e
207 $ echo c >> e
208 $ hg ci -mtest
208 $ hg ci -mtest
209
209
210 $ hg strip . --config extensions.strip=
210 $ hg strip . --config extensions.strip=
211 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
212 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
212 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
213
213
214 Graft again:
214 Graft again:
215
215
216 $ hg graft 1 5 4 3 'merge()' 2
216 $ hg graft 1 5 4 3 'merge()' 2
217 skipping ungraftable merge revision 6
217 skipping ungraftable merge revision 6
218 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
218 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
219 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
219 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
220 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
220 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
221 grafting 4:9c233e8e184d "4"
221 grafting 4:9c233e8e184d "4"
222 merging e
222 merging e
223 warning: conflicts during merge.
223 warning: conflicts during merge.
224 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
224 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
225 abort: unresolved conflicts, can't continue
225 abort: unresolved conflicts, can't continue
226 (use hg resolve and hg graft --continue)
226 (use hg resolve and hg graft --continue)
227 [255]
227 [255]
228
228
229 Continue without resolve should fail:
229 Continue without resolve should fail:
230
230
231 $ hg graft -c
231 $ hg graft -c
232 grafting 4:9c233e8e184d "4"
232 grafting 4:9c233e8e184d "4"
233 abort: unresolved merge conflicts (see "hg help resolve")
233 abort: unresolved merge conflicts (see "hg help resolve")
234 [255]
234 [255]
235
235
236 Fix up:
236 Fix up:
237
237
238 $ echo b > e
238 $ echo b > e
239 $ hg resolve -m e
239 $ hg resolve -m e
240 (no more unresolved files)
240 (no more unresolved files)
241
241
242 Continue with a revision should fail:
242 Continue with a revision should fail:
243
243
244 $ hg graft -c 6
244 $ hg graft -c 6
245 abort: can't specify --continue and revisions
245 abort: can't specify --continue and revisions
246 [255]
246 [255]
247
247
248 $ hg graft -c -r 6
248 $ hg graft -c -r 6
249 abort: can't specify --continue and revisions
249 abort: can't specify --continue and revisions
250 [255]
250 [255]
251
251
252 Continue for real, clobber usernames
252 Continue for real, clobber usernames
253
253
254 $ hg graft -c -U
254 $ hg graft -c -U
255 grafting 4:9c233e8e184d "4"
255 grafting 4:9c233e8e184d "4"
256 grafting 3:4c60f11aa304 "3"
256 grafting 3:4c60f11aa304 "3"
257
257
258 Compare with original:
258 Compare with original:
259
259
260 $ hg diff -r 6
260 $ hg diff -r 6
261 $ hg status --rev 0:. -C
261 $ hg status --rev 0:. -C
262 M d
262 M d
263 M e
263 M e
264 A b
264 A b
265 a
265 a
266 A c
266 A c
267 a
267 a
268 R a
268 R a
269
269
270 View graph:
270 View graph:
271
271
272 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
272 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
273 @ test@11.draft: 3
273 @ test@11.draft: 3
274 |
274 |
275 o test@10.draft: 4
275 o test@10.draft: 4
276 |
276 |
277 o test@9.draft: 5
277 o test@9.draft: 5
278 |
278 |
279 o bar@8.draft: 1
279 o bar@8.draft: 1
280 |
280 |
281 o foo@7.draft: 2
281 o foo@7.draft: 2
282 |
282 |
283 | o test@6.secret: 6
283 | o test@6.secret: 6
284 | |\
284 | |\
285 | | o test@5.draft: 5
285 | | o test@5.draft: 5
286 | | |
286 | | |
287 | o | test@4.draft: 4
287 | o | test@4.draft: 4
288 | |/
288 | |/
289 | o baz@3.public: 3
289 | o baz@3.public: 3
290 | |
290 | |
291 | o test@2.public: 2
291 | o test@2.public: 2
292 | |
292 | |
293 | o bar@1.public: 1
293 | o bar@1.public: 1
294 |/
294 |/
295 o test@0.public: 0
295 o test@0.public: 0
296
296
297 Graft again onto another branch should preserve the original source
297 Graft again onto another branch should preserve the original source
298 $ hg up -q 0
298 $ hg up -q 0
299 $ echo 'g'>g
299 $ echo 'g'>g
300 $ hg add g
300 $ hg add g
301 $ hg ci -m 7
301 $ hg ci -m 7
302 created new head
302 created new head
303 $ hg graft 7
303 $ hg graft 7
304 grafting 7:ef0ef43d49e7 "2"
304 grafting 7:ef0ef43d49e7 "2"
305
305
306 $ hg log -r 7 --template '{rev}:{node}\n'
306 $ hg log -r 7 --template '{rev}:{node}\n'
307 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
307 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
308 $ hg log -r 2 --template '{rev}:{node}\n'
308 $ hg log -r 2 --template '{rev}:{node}\n'
309 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
309 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
310
310
311 $ hg log --debug -r tip
311 $ hg log --debug -r tip
312 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
312 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
313 tag: tip
313 tag: tip
314 phase: draft
314 phase: draft
315 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
315 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
316 parent: -1:0000000000000000000000000000000000000000
316 parent: -1:0000000000000000000000000000000000000000
317 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
317 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
318 user: foo
318 user: foo
319 date: Thu Jan 01 00:00:00 1970 +0000
319 date: Thu Jan 01 00:00:00 1970 +0000
320 files+: b
320 files+: b
321 files-: a
321 files-: a
322 extra: branch=default
322 extra: branch=default
323 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
323 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
324 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
324 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
325 description:
325 description:
326 2
326 2
327
327
328
328
329 Disallow grafting an already grafted cset onto its original branch
329 Disallow grafting an already grafted cset onto its original branch
330 $ hg up -q 6
330 $ hg up -q 6
331 $ hg graft 7
331 $ hg graft 7
332 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
332 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
333 [255]
333 [255]
334
334
335 Disallow grafting already grafted csets with the same origin onto each other
335 Disallow grafting already grafted csets with the same origin onto each other
336 $ hg up -q 13
336 $ hg up -q 13
337 $ hg graft 2
337 $ hg graft 2
338 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
338 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
339 [255]
339 [255]
340 $ hg graft 7
340 $ hg graft 7
341 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
341 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
342 [255]
342 [255]
343
343
344 $ hg up -q 7
344 $ hg up -q 7
345 $ hg graft 2
345 $ hg graft 2
346 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
346 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
347 [255]
347 [255]
348 $ hg graft tip
348 $ hg graft tip
349 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
349 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
350 [255]
350 [255]
351
351
352 Graft with --log
352 Graft with --log
353
353
354 $ hg up -Cq 1
354 $ hg up -Cq 1
355 $ hg graft 3 --log -u foo
355 $ hg graft 3 --log -u foo
356 grafting 3:4c60f11aa304 "3"
356 grafting 3:4c60f11aa304 "3"
357 warning: can't find ancestor for 'c' copied from 'b'!
357 warning: can't find ancestor for 'c' copied from 'b'!
358 $ hg log --template '{rev} {parents} {desc}\n' -r tip
358 $ hg log --template '{rev} {parents} {desc}\n' -r tip
359 14 1:5d205f8b35b6 3
359 14 1:5d205f8b35b6 3
360 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
360 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
361
361
362 Resolve conflicted graft
362 Resolve conflicted graft
363 $ hg up -q 0
363 $ hg up -q 0
364 $ echo b > a
364 $ echo b > a
365 $ hg ci -m 8
365 $ hg ci -m 8
366 created new head
366 created new head
367 $ echo c > a
367 $ echo c > a
368 $ hg ci -m 9
368 $ hg ci -m 9
369 $ hg graft 1 --tool internal:fail
369 $ hg graft 1 --tool internal:fail
370 grafting 1:5d205f8b35b6 "1"
370 grafting 1:5d205f8b35b6 "1"
371 abort: unresolved conflicts, can't continue
371 abort: unresolved conflicts, can't continue
372 (use hg resolve and hg graft --continue)
372 (use hg resolve and hg graft --continue)
373 [255]
373 [255]
374 $ hg resolve --all
374 $ hg resolve --all
375 merging a
375 merging a
376 warning: conflicts during merge.
376 warning: conflicts during merge.
377 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
377 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
378 [1]
378 [1]
379 $ cat a
379 $ cat a
380 <<<<<<< local: aaa4406d4f0a - test: 9
380 <<<<<<< local: aaa4406d4f0a - test: 9
381 c
381 c
382 =======
382 =======
383 b
383 b
384 >>>>>>> other: 5d205f8b35b6 - bar: 1
384 >>>>>>> other: 5d205f8b35b6 - bar: 1
385 $ echo b > a
385 $ echo b > a
386 $ hg resolve -m a
386 $ hg resolve -m a
387 (no more unresolved files)
387 (no more unresolved files)
388 $ hg graft -c
388 $ hg graft -c
389 grafting 1:5d205f8b35b6 "1"
389 grafting 1:5d205f8b35b6 "1"
390 $ hg export tip --git
390 $ hg export tip --git
391 # HG changeset patch
391 # HG changeset patch
392 # User bar
392 # User bar
393 # Date 0 0
393 # Date 0 0
394 # Thu Jan 01 00:00:00 1970 +0000
394 # Thu Jan 01 00:00:00 1970 +0000
395 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
395 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
396 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
396 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
397 1
397 1
398
398
399 diff --git a/a b/a
399 diff --git a/a b/a
400 --- a/a
400 --- a/a
401 +++ b/a
401 +++ b/a
402 @@ -1,1 +1,1 @@
402 @@ -1,1 +1,1 @@
403 -c
403 -c
404 +b
404 +b
405
405
406 Resolve conflicted graft with rename
406 Resolve conflicted graft with rename
407 $ echo c > a
407 $ echo c > a
408 $ hg ci -m 10
408 $ hg ci -m 10
409 $ hg graft 2 --tool internal:fail
409 $ hg graft 2 --tool internal:fail
410 grafting 2:5c095ad7e90f "2"
410 grafting 2:5c095ad7e90f "2"
411 abort: unresolved conflicts, can't continue
411 abort: unresolved conflicts, can't continue
412 (use hg resolve and hg graft --continue)
412 (use hg resolve and hg graft --continue)
413 [255]
413 [255]
414 $ hg resolve --all
414 $ hg resolve --all
415 merging a and b to b
415 merging a and b to b
416 (no more unresolved files)
416 (no more unresolved files)
417 $ hg graft -c
417 $ hg graft -c
418 grafting 2:5c095ad7e90f "2"
418 grafting 2:5c095ad7e90f "2"
419 $ hg export tip --git
419 $ hg export tip --git
420 # HG changeset patch
420 # HG changeset patch
421 # User test
421 # User test
422 # Date 0 0
422 # Date 0 0
423 # Thu Jan 01 00:00:00 1970 +0000
423 # Thu Jan 01 00:00:00 1970 +0000
424 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
424 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
425 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
425 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
426 2
426 2
427
427
428 diff --git a/a b/b
428 diff --git a/a b/b
429 rename from a
429 rename from a
430 rename to b
430 rename to b
431
431
432 Test simple origin(), with and without args
432 Test simple origin(), with and without args
433 $ hg log -r 'origin()'
433 $ hg log -r 'origin()'
434 changeset: 1:5d205f8b35b6
434 changeset: 1:5d205f8b35b6
435 user: bar
435 user: bar
436 date: Thu Jan 01 00:00:00 1970 +0000
436 date: Thu Jan 01 00:00:00 1970 +0000
437 summary: 1
437 summary: 1
438
438
439 changeset: 2:5c095ad7e90f
439 changeset: 2:5c095ad7e90f
440 user: test
440 user: test
441 date: Thu Jan 01 00:00:00 1970 +0000
441 date: Thu Jan 01 00:00:00 1970 +0000
442 summary: 2
442 summary: 2
443
443
444 changeset: 3:4c60f11aa304
444 changeset: 3:4c60f11aa304
445 user: baz
445 user: baz
446 date: Thu Jan 01 00:00:00 1970 +0000
446 date: Thu Jan 01 00:00:00 1970 +0000
447 summary: 3
447 summary: 3
448
448
449 changeset: 4:9c233e8e184d
449 changeset: 4:9c233e8e184d
450 user: test
450 user: test
451 date: Thu Jan 01 00:00:00 1970 +0000
451 date: Thu Jan 01 00:00:00 1970 +0000
452 summary: 4
452 summary: 4
453
453
454 changeset: 5:97f8bfe72746
454 changeset: 5:97f8bfe72746
455 branch: stable
455 branch: stable
456 parent: 3:4c60f11aa304
456 parent: 3:4c60f11aa304
457 user: test
457 user: test
458 date: Thu Jan 01 00:00:00 1970 +0000
458 date: Thu Jan 01 00:00:00 1970 +0000
459 summary: 5
459 summary: 5
460
460
461 $ hg log -r 'origin(7)'
461 $ hg log -r 'origin(7)'
462 changeset: 2:5c095ad7e90f
462 changeset: 2:5c095ad7e90f
463 user: test
463 user: test
464 date: Thu Jan 01 00:00:00 1970 +0000
464 date: Thu Jan 01 00:00:00 1970 +0000
465 summary: 2
465 summary: 2
466
466
467 Now transplant a graft to test following through copies
467 Now transplant a graft to test following through copies
468 $ hg up -q 0
468 $ hg up -q 0
469 $ hg branch -q dev
469 $ hg branch -q dev
470 $ hg ci -qm "dev branch"
470 $ hg ci -qm "dev branch"
471 $ hg --config extensions.transplant= transplant -q 7
471 $ hg --config extensions.transplant= transplant -q 7
472 $ hg log -r 'origin(.)'
472 $ hg log -r 'origin(.)'
473 changeset: 2:5c095ad7e90f
473 changeset: 2:5c095ad7e90f
474 user: test
474 user: test
475 date: Thu Jan 01 00:00:00 1970 +0000
475 date: Thu Jan 01 00:00:00 1970 +0000
476 summary: 2
476 summary: 2
477
477
478 Test that the graft and transplant markers in extra are converted, allowing
478 Test that the graft and transplant markers in extra are converted, allowing
479 origin() to still work. Note that these recheck the immediately preceeding two
479 origin() to still work. Note that these recheck the immediately preceeding two
480 tests.
480 tests.
481 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
481 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
482
482
483 The graft case
483 The graft case
484 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
484 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
485 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
485 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
486 branch=default
486 branch=default
487 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
487 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
488 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
488 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
489 $ hg -R ../converted log -r 'origin(7)'
489 $ hg -R ../converted log -r 'origin(7)'
490 changeset: 2:e0213322b2c1
490 changeset: 2:e0213322b2c1
491 user: test
491 user: test
492 date: Thu Jan 01 00:00:00 1970 +0000
492 date: Thu Jan 01 00:00:00 1970 +0000
493 summary: 2
493 summary: 2
494
494
495 Test that template correctly expands more than one 'extra' (issue4362)
495 Test that template correctly expands more than one 'extra' (issue4362), and that
496 $ hg -R ../converted log -r 7 --template "{extras % ' Extra: {extra}\n'}"
496 'intermediate-source' is converted.
497 $ hg -R ../converted log -r 13 --template "{extras % ' Extra: {extra}\n'}"
497 Extra: branch=default
498 Extra: branch=default
498 Extra: convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
499 Extra: convert_revision=7a4785234d87ec1aa420ed6b11afe40fa73e12a9
500 Extra: intermediate-source=7ae846e9111fc8f57745634250c7b9ac0a60689b
499 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
501 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
500
502
501 The transplant case
503 The transplant case
502 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
504 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
503 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
505 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
504 branch=dev
506 branch=dev
505 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
507 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
506 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
508 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
507 `h\x9b (esc)
509 `h\x9b (esc)
508 $ hg -R ../converted log -r 'origin(tip)'
510 $ hg -R ../converted log -r 'origin(tip)'
509 changeset: 2:e0213322b2c1
511 changeset: 2:e0213322b2c1
510 user: test
512 user: test
511 date: Thu Jan 01 00:00:00 1970 +0000
513 date: Thu Jan 01 00:00:00 1970 +0000
512 summary: 2
514 summary: 2
513
515
514
516
515 Test simple destination
517 Test simple destination
516 $ hg log -r 'destination()'
518 $ hg log -r 'destination()'
517 changeset: 7:ef0ef43d49e7
519 changeset: 7:ef0ef43d49e7
518 parent: 0:68795b066622
520 parent: 0:68795b066622
519 user: foo
521 user: foo
520 date: Thu Jan 01 00:00:00 1970 +0000
522 date: Thu Jan 01 00:00:00 1970 +0000
521 summary: 2
523 summary: 2
522
524
523 changeset: 8:6b9e5368ca4e
525 changeset: 8:6b9e5368ca4e
524 user: bar
526 user: bar
525 date: Thu Jan 01 00:00:00 1970 +0000
527 date: Thu Jan 01 00:00:00 1970 +0000
526 summary: 1
528 summary: 1
527
529
528 changeset: 9:1905859650ec
530 changeset: 9:1905859650ec
529 user: test
531 user: test
530 date: Thu Jan 01 00:00:00 1970 +0000
532 date: Thu Jan 01 00:00:00 1970 +0000
531 summary: 5
533 summary: 5
532
534
533 changeset: 10:52dc0b4c6907
535 changeset: 10:52dc0b4c6907
534 user: test
536 user: test
535 date: Thu Jan 01 00:00:00 1970 +0000
537 date: Thu Jan 01 00:00:00 1970 +0000
536 summary: 4
538 summary: 4
537
539
538 changeset: 11:882b35362a6b
540 changeset: 11:882b35362a6b
539 user: test
541 user: test
540 date: Thu Jan 01 00:00:00 1970 +0000
542 date: Thu Jan 01 00:00:00 1970 +0000
541 summary: 3
543 summary: 3
542
544
543 changeset: 13:7a4785234d87
545 changeset: 13:7a4785234d87
544 user: foo
546 user: foo
545 date: Thu Jan 01 00:00:00 1970 +0000
547 date: Thu Jan 01 00:00:00 1970 +0000
546 summary: 2
548 summary: 2
547
549
548 changeset: 14:f64defefacee
550 changeset: 14:f64defefacee
549 parent: 1:5d205f8b35b6
551 parent: 1:5d205f8b35b6
550 user: foo
552 user: foo
551 date: Thu Jan 01 00:00:00 1970 +0000
553 date: Thu Jan 01 00:00:00 1970 +0000
552 summary: 3
554 summary: 3
553
555
554 changeset: 17:f67661df0c48
556 changeset: 17:f67661df0c48
555 user: bar
557 user: bar
556 date: Thu Jan 01 00:00:00 1970 +0000
558 date: Thu Jan 01 00:00:00 1970 +0000
557 summary: 1
559 summary: 1
558
560
559 changeset: 19:9627f653b421
561 changeset: 19:9627f653b421
560 user: test
562 user: test
561 date: Thu Jan 01 00:00:00 1970 +0000
563 date: Thu Jan 01 00:00:00 1970 +0000
562 summary: 2
564 summary: 2
563
565
564 changeset: 21:7e61b508e709
566 changeset: 21:7e61b508e709
565 branch: dev
567 branch: dev
566 tag: tip
568 tag: tip
567 user: foo
569 user: foo
568 date: Thu Jan 01 00:00:00 1970 +0000
570 date: Thu Jan 01 00:00:00 1970 +0000
569 summary: 2
571 summary: 2
570
572
571 $ hg log -r 'destination(2)'
573 $ hg log -r 'destination(2)'
572 changeset: 7:ef0ef43d49e7
574 changeset: 7:ef0ef43d49e7
573 parent: 0:68795b066622
575 parent: 0:68795b066622
574 user: foo
576 user: foo
575 date: Thu Jan 01 00:00:00 1970 +0000
577 date: Thu Jan 01 00:00:00 1970 +0000
576 summary: 2
578 summary: 2
577
579
578 changeset: 13:7a4785234d87
580 changeset: 13:7a4785234d87
579 user: foo
581 user: foo
580 date: Thu Jan 01 00:00:00 1970 +0000
582 date: Thu Jan 01 00:00:00 1970 +0000
581 summary: 2
583 summary: 2
582
584
583 changeset: 19:9627f653b421
585 changeset: 19:9627f653b421
584 user: test
586 user: test
585 date: Thu Jan 01 00:00:00 1970 +0000
587 date: Thu Jan 01 00:00:00 1970 +0000
586 summary: 2
588 summary: 2
587
589
588 changeset: 21:7e61b508e709
590 changeset: 21:7e61b508e709
589 branch: dev
591 branch: dev
590 tag: tip
592 tag: tip
591 user: foo
593 user: foo
592 date: Thu Jan 01 00:00:00 1970 +0000
594 date: Thu Jan 01 00:00:00 1970 +0000
593 summary: 2
595 summary: 2
594
596
595 Transplants of grafts can find a destination...
597 Transplants of grafts can find a destination...
596 $ hg log -r 'destination(7)'
598 $ hg log -r 'destination(7)'
597 changeset: 21:7e61b508e709
599 changeset: 21:7e61b508e709
598 branch: dev
600 branch: dev
599 tag: tip
601 tag: tip
600 user: foo
602 user: foo
601 date: Thu Jan 01 00:00:00 1970 +0000
603 date: Thu Jan 01 00:00:00 1970 +0000
602 summary: 2
604 summary: 2
603
605
604 ... grafts of grafts unfortunately can't
606 ... grafts of grafts unfortunately can't
605 $ hg graft -q 13
607 $ hg graft -q 13
606 warning: can't find ancestor for 'b' copied from 'a'!
608 warning: can't find ancestor for 'b' copied from 'a'!
607 $ hg log -r 'destination(13)'
609 $ hg log -r 'destination(13)'
608 All copies of a cset
610 All copies of a cset
609 $ hg log -r 'origin(13) or destination(origin(13))'
611 $ hg log -r 'origin(13) or destination(origin(13))'
610 changeset: 2:5c095ad7e90f
612 changeset: 2:5c095ad7e90f
611 user: test
613 user: test
612 date: Thu Jan 01 00:00:00 1970 +0000
614 date: Thu Jan 01 00:00:00 1970 +0000
613 summary: 2
615 summary: 2
614
616
615 changeset: 7:ef0ef43d49e7
617 changeset: 7:ef0ef43d49e7
616 parent: 0:68795b066622
618 parent: 0:68795b066622
617 user: foo
619 user: foo
618 date: Thu Jan 01 00:00:00 1970 +0000
620 date: Thu Jan 01 00:00:00 1970 +0000
619 summary: 2
621 summary: 2
620
622
621 changeset: 13:7a4785234d87
623 changeset: 13:7a4785234d87
622 user: foo
624 user: foo
623 date: Thu Jan 01 00:00:00 1970 +0000
625 date: Thu Jan 01 00:00:00 1970 +0000
624 summary: 2
626 summary: 2
625
627
626 changeset: 19:9627f653b421
628 changeset: 19:9627f653b421
627 user: test
629 user: test
628 date: Thu Jan 01 00:00:00 1970 +0000
630 date: Thu Jan 01 00:00:00 1970 +0000
629 summary: 2
631 summary: 2
630
632
631 changeset: 21:7e61b508e709
633 changeset: 21:7e61b508e709
632 branch: dev
634 branch: dev
633 user: foo
635 user: foo
634 date: Thu Jan 01 00:00:00 1970 +0000
636 date: Thu Jan 01 00:00:00 1970 +0000
635 summary: 2
637 summary: 2
636
638
637 changeset: 22:d1cb6591fa4b
639 changeset: 22:d1cb6591fa4b
638 branch: dev
640 branch: dev
639 tag: tip
641 tag: tip
640 user: foo
642 user: foo
641 date: Thu Jan 01 00:00:00 1970 +0000
643 date: Thu Jan 01 00:00:00 1970 +0000
642 summary: 2
644 summary: 2
643
645
644
646
645 graft works on complex revset
647 graft works on complex revset
646
648
647 $ hg graft 'origin(13) or destination(origin(13))'
649 $ hg graft 'origin(13) or destination(origin(13))'
648 skipping ancestor revision 21:7e61b508e709
650 skipping ancestor revision 21:7e61b508e709
649 skipping ancestor revision 22:d1cb6591fa4b
651 skipping ancestor revision 22:d1cb6591fa4b
650 skipping revision 2:5c095ad7e90f (already grafted to 22:d1cb6591fa4b)
652 skipping revision 2:5c095ad7e90f (already grafted to 22:d1cb6591fa4b)
651 grafting 7:ef0ef43d49e7 "2"
653 grafting 7:ef0ef43d49e7 "2"
652 warning: can't find ancestor for 'b' copied from 'a'!
654 warning: can't find ancestor for 'b' copied from 'a'!
653 grafting 13:7a4785234d87 "2"
655 grafting 13:7a4785234d87 "2"
654 warning: can't find ancestor for 'b' copied from 'a'!
656 warning: can't find ancestor for 'b' copied from 'a'!
655 grafting 19:9627f653b421 "2"
657 grafting 19:9627f653b421 "2"
656 merging b
658 merging b
657 warning: can't find ancestor for 'b' copied from 'a'!
659 warning: can't find ancestor for 'b' copied from 'a'!
658
660
659 graft with --force (still doesn't graft merges)
661 graft with --force (still doesn't graft merges)
660
662
661 $ hg graft 19 0 6
663 $ hg graft 19 0 6
662 skipping ungraftable merge revision 6
664 skipping ungraftable merge revision 6
663 skipping ancestor revision 0:68795b066622
665 skipping ancestor revision 0:68795b066622
664 skipping already grafted revision 19:9627f653b421 (22:d1cb6591fa4b also has origin 2:5c095ad7e90f)
666 skipping already grafted revision 19:9627f653b421 (22:d1cb6591fa4b also has origin 2:5c095ad7e90f)
665 [255]
667 [255]
666 $ hg graft 19 0 6 --force
668 $ hg graft 19 0 6 --force
667 skipping ungraftable merge revision 6
669 skipping ungraftable merge revision 6
668 grafting 19:9627f653b421 "2"
670 grafting 19:9627f653b421 "2"
669 merging b
671 merging b
670 warning: can't find ancestor for 'b' copied from 'a'!
672 warning: can't find ancestor for 'b' copied from 'a'!
671 grafting 0:68795b066622 "0"
673 grafting 0:68795b066622 "0"
672
674
673 graft --force after backout
675 graft --force after backout
674
676
675 $ echo abc > a
677 $ echo abc > a
676 $ hg ci -m 28
678 $ hg ci -m 28
677 $ hg backout 28
679 $ hg backout 28
678 reverting a
680 reverting a
679 changeset 29:53177ba928f6 backs out changeset 28:50a516bb8b57
681 changeset 29:53177ba928f6 backs out changeset 28:50a516bb8b57
680 $ hg graft 28
682 $ hg graft 28
681 skipping ancestor revision 28:50a516bb8b57
683 skipping ancestor revision 28:50a516bb8b57
682 [255]
684 [255]
683 $ hg graft 28 --force
685 $ hg graft 28 --force
684 grafting 28:50a516bb8b57 "28"
686 grafting 28:50a516bb8b57 "28"
685 merging a
687 merging a
686 $ cat a
688 $ cat a
687 abc
689 abc
688
690
689 graft --continue after --force
691 graft --continue after --force
690
692
691 $ echo def > a
693 $ echo def > a
692 $ hg ci -m 31
694 $ hg ci -m 31
693 $ hg graft 28 --force --tool internal:fail
695 $ hg graft 28 --force --tool internal:fail
694 grafting 28:50a516bb8b57 "28"
696 grafting 28:50a516bb8b57 "28"
695 abort: unresolved conflicts, can't continue
697 abort: unresolved conflicts, can't continue
696 (use hg resolve and hg graft --continue)
698 (use hg resolve and hg graft --continue)
697 [255]
699 [255]
698 $ hg resolve --all
700 $ hg resolve --all
699 merging a
701 merging a
700 warning: conflicts during merge.
702 warning: conflicts during merge.
701 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
703 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
702 [1]
704 [1]
703 $ echo abc > a
705 $ echo abc > a
704 $ hg resolve -m a
706 $ hg resolve -m a
705 (no more unresolved files)
707 (no more unresolved files)
706 $ hg graft -c
708 $ hg graft -c
707 grafting 28:50a516bb8b57 "28"
709 grafting 28:50a516bb8b57 "28"
708 $ cat a
710 $ cat a
709 abc
711 abc
710
712
711 Continue testing same origin policy, using revision numbers from test above
713 Continue testing same origin policy, using revision numbers from test above
712 but do some destructive editing of the repo:
714 but do some destructive editing of the repo:
713
715
714 $ hg up -qC 7
716 $ hg up -qC 7
715 $ hg tag -l -r 13 tmp
717 $ hg tag -l -r 13 tmp
716 $ hg --config extensions.strip= strip 2
718 $ hg --config extensions.strip= strip 2
717 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg (glob)
719 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg (glob)
718 $ hg graft tmp
720 $ hg graft tmp
719 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
721 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
720 [255]
722 [255]
721
723
722 Empty graft
724 Empty graft
723
725
724 $ hg up -qr 26
726 $ hg up -qr 26
725 $ hg tag -f something
727 $ hg tag -f something
726 $ hg graft -qr 27
728 $ hg graft -qr 27
727 $ hg graft -f 27
729 $ hg graft -f 27
728 grafting 27:ed6c7e54e319 "28"
730 grafting 27:ed6c7e54e319 "28"
729 note: graft of 27:ed6c7e54e319 created no changes to commit
731 note: graft of 27:ed6c7e54e319 created no changes to commit
730
732
731 $ cd ..
733 $ cd ..
732
734
733 Graft to duplicate a commit
735 Graft to duplicate a commit
734
736
735 $ hg init graftsibling
737 $ hg init graftsibling
736 $ cd graftsibling
738 $ cd graftsibling
737 $ touch a
739 $ touch a
738 $ hg commit -qAm a
740 $ hg commit -qAm a
739 $ touch b
741 $ touch b
740 $ hg commit -qAm b
742 $ hg commit -qAm b
741 $ hg log -G -T '{rev}\n'
743 $ hg log -G -T '{rev}\n'
742 @ 1
744 @ 1
743 |
745 |
744 o 0
746 o 0
745
747
746 $ hg up -q 0
748 $ hg up -q 0
747 $ hg graft -r 1
749 $ hg graft -r 1
748 grafting 1:0e067c57feba "b" (tip)
750 grafting 1:0e067c57feba "b" (tip)
749 $ hg log -G -T '{rev}\n'
751 $ hg log -G -T '{rev}\n'
750 @ 2
752 @ 2
751 |
753 |
752 | o 1
754 | o 1
753 |/
755 |/
754 o 0
756 o 0
755
757
756 Graft to duplicate a commit twice
758 Graft to duplicate a commit twice
757
759
758 $ hg up -q 0
760 $ hg up -q 0
759 $ hg graft -r 2
761 $ hg graft -r 2
760 grafting 2:044ec77f6389 "b" (tip)
762 grafting 2:044ec77f6389 "b" (tip)
761 $ hg log -G -T '{rev}\n'
763 $ hg log -G -T '{rev}\n'
762 @ 3
764 @ 3
763 |
765 |
764 | o 2
766 | o 2
765 |/
767 |/
766 | o 1
768 | o 1
767 |/
769 |/
768 o 0
770 o 0
769
771
General Comments 0
You need to be logged in to leave comments. Login now