##// END OF EJS Templates
checkcopies: handle divergences contained entirely in tca::ctx...
Gábor Stefanik -
r30201:856ead83 default
parent child Browse files
Show More
@@ -1,630 +1,635
1 # copies.py - copy detection for Mercurial
1 # copies.py - copy detection for Mercurial
2 #
2 #
3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import heapq
10 import heapq
11
11
12 from . import (
12 from . import (
13 node,
13 node,
14 pathutil,
14 pathutil,
15 scmutil,
15 scmutil,
16 util,
16 util,
17 )
17 )
18
18
19 def _findlimit(repo, a, b):
19 def _findlimit(repo, a, b):
20 """
20 """
21 Find the last revision that needs to be checked to ensure that a full
21 Find the last revision that needs to be checked to ensure that a full
22 transitive closure for file copies can be properly calculated.
22 transitive closure for file copies can be properly calculated.
23 Generally, this means finding the earliest revision number that's an
23 Generally, this means finding the earliest revision number that's an
24 ancestor of a or b but not both, except when a or b is a direct descendent
24 ancestor of a or b but not both, except when a or b is a direct descendent
25 of the other, in which case we can return the minimum revnum of a and b.
25 of the other, in which case we can return the minimum revnum of a and b.
26 None if no such revision exists.
26 None if no such revision exists.
27 """
27 """
28
28
29 # basic idea:
29 # basic idea:
30 # - mark a and b with different sides
30 # - mark a and b with different sides
31 # - if a parent's children are all on the same side, the parent is
31 # - if a parent's children are all on the same side, the parent is
32 # on that side, otherwise it is on no side
32 # on that side, otherwise it is on no side
33 # - walk the graph in topological order with the help of a heap;
33 # - walk the graph in topological order with the help of a heap;
34 # - add unseen parents to side map
34 # - add unseen parents to side map
35 # - clear side of any parent that has children on different sides
35 # - clear side of any parent that has children on different sides
36 # - track number of interesting revs that might still be on a side
36 # - track number of interesting revs that might still be on a side
37 # - track the lowest interesting rev seen
37 # - track the lowest interesting rev seen
38 # - quit when interesting revs is zero
38 # - quit when interesting revs is zero
39
39
40 cl = repo.changelog
40 cl = repo.changelog
41 working = len(cl) # pseudo rev for the working directory
41 working = len(cl) # pseudo rev for the working directory
42 if a is None:
42 if a is None:
43 a = working
43 a = working
44 if b is None:
44 if b is None:
45 b = working
45 b = working
46
46
47 side = {a: -1, b: 1}
47 side = {a: -1, b: 1}
48 visit = [-a, -b]
48 visit = [-a, -b]
49 heapq.heapify(visit)
49 heapq.heapify(visit)
50 interesting = len(visit)
50 interesting = len(visit)
51 hascommonancestor = False
51 hascommonancestor = False
52 limit = working
52 limit = working
53
53
54 while interesting:
54 while interesting:
55 r = -heapq.heappop(visit)
55 r = -heapq.heappop(visit)
56 if r == working:
56 if r == working:
57 parents = [cl.rev(p) for p in repo.dirstate.parents()]
57 parents = [cl.rev(p) for p in repo.dirstate.parents()]
58 else:
58 else:
59 parents = cl.parentrevs(r)
59 parents = cl.parentrevs(r)
60 for p in parents:
60 for p in parents:
61 if p < 0:
61 if p < 0:
62 continue
62 continue
63 if p not in side:
63 if p not in side:
64 # first time we see p; add it to visit
64 # first time we see p; add it to visit
65 side[p] = side[r]
65 side[p] = side[r]
66 if side[p]:
66 if side[p]:
67 interesting += 1
67 interesting += 1
68 heapq.heappush(visit, -p)
68 heapq.heappush(visit, -p)
69 elif side[p] and side[p] != side[r]:
69 elif side[p] and side[p] != side[r]:
70 # p was interesting but now we know better
70 # p was interesting but now we know better
71 side[p] = 0
71 side[p] = 0
72 interesting -= 1
72 interesting -= 1
73 hascommonancestor = True
73 hascommonancestor = True
74 if side[r]:
74 if side[r]:
75 limit = r # lowest rev visited
75 limit = r # lowest rev visited
76 interesting -= 1
76 interesting -= 1
77
77
78 if not hascommonancestor:
78 if not hascommonancestor:
79 return None
79 return None
80
80
81 # Consider the following flow (see test-commit-amend.t under issue4405):
81 # Consider the following flow (see test-commit-amend.t under issue4405):
82 # 1/ File 'a0' committed
82 # 1/ File 'a0' committed
83 # 2/ File renamed from 'a0' to 'a1' in a new commit (call it 'a1')
83 # 2/ File renamed from 'a0' to 'a1' in a new commit (call it 'a1')
84 # 3/ Move back to first commit
84 # 3/ Move back to first commit
85 # 4/ Create a new commit via revert to contents of 'a1' (call it 'a1-amend')
85 # 4/ Create a new commit via revert to contents of 'a1' (call it 'a1-amend')
86 # 5/ Rename file from 'a1' to 'a2' and commit --amend 'a1-msg'
86 # 5/ Rename file from 'a1' to 'a2' and commit --amend 'a1-msg'
87 #
87 #
88 # During the amend in step five, we will be in this state:
88 # During the amend in step five, we will be in this state:
89 #
89 #
90 # @ 3 temporary amend commit for a1-amend
90 # @ 3 temporary amend commit for a1-amend
91 # |
91 # |
92 # o 2 a1-amend
92 # o 2 a1-amend
93 # |
93 # |
94 # | o 1 a1
94 # | o 1 a1
95 # |/
95 # |/
96 # o 0 a0
96 # o 0 a0
97 #
97 #
98 # When _findlimit is called, a and b are revs 3 and 0, so limit will be 2,
98 # When _findlimit is called, a and b are revs 3 and 0, so limit will be 2,
99 # yet the filelog has the copy information in rev 1 and we will not look
99 # yet the filelog has the copy information in rev 1 and we will not look
100 # back far enough unless we also look at the a and b as candidates.
100 # back far enough unless we also look at the a and b as candidates.
101 # This only occurs when a is a descendent of b or visa-versa.
101 # This only occurs when a is a descendent of b or visa-versa.
102 return min(limit, a, b)
102 return min(limit, a, b)
103
103
104 def _chain(src, dst, a, b):
104 def _chain(src, dst, a, b):
105 '''chain two sets of copies a->b'''
105 '''chain two sets of copies a->b'''
106 t = a.copy()
106 t = a.copy()
107 for k, v in b.iteritems():
107 for k, v in b.iteritems():
108 if v in t:
108 if v in t:
109 # found a chain
109 # found a chain
110 if t[v] != k:
110 if t[v] != k:
111 # file wasn't renamed back to itself
111 # file wasn't renamed back to itself
112 t[k] = t[v]
112 t[k] = t[v]
113 if v not in dst:
113 if v not in dst:
114 # chain was a rename, not a copy
114 # chain was a rename, not a copy
115 del t[v]
115 del t[v]
116 if v in src:
116 if v in src:
117 # file is a copy of an existing file
117 # file is a copy of an existing file
118 t[k] = v
118 t[k] = v
119
119
120 # remove criss-crossed copies
120 # remove criss-crossed copies
121 for k, v in t.items():
121 for k, v in t.items():
122 if k in src and v in dst:
122 if k in src and v in dst:
123 del t[k]
123 del t[k]
124
124
125 return t
125 return t
126
126
127 def _tracefile(fctx, am, limit=-1):
127 def _tracefile(fctx, am, limit=-1):
128 '''return file context that is the ancestor of fctx present in ancestor
128 '''return file context that is the ancestor of fctx present in ancestor
129 manifest am, stopping after the first ancestor lower than limit'''
129 manifest am, stopping after the first ancestor lower than limit'''
130
130
131 for f in fctx.ancestors():
131 for f in fctx.ancestors():
132 if am.get(f.path(), None) == f.filenode():
132 if am.get(f.path(), None) == f.filenode():
133 return f
133 return f
134 if limit >= 0 and f.linkrev() < limit and f.rev() < limit:
134 if limit >= 0 and f.linkrev() < limit and f.rev() < limit:
135 return None
135 return None
136
136
137 def _dirstatecopies(d):
137 def _dirstatecopies(d):
138 ds = d._repo.dirstate
138 ds = d._repo.dirstate
139 c = ds.copies().copy()
139 c = ds.copies().copy()
140 for k in c.keys():
140 for k in c.keys():
141 if ds[k] not in 'anm':
141 if ds[k] not in 'anm':
142 del c[k]
142 del c[k]
143 return c
143 return c
144
144
145 def _computeforwardmissing(a, b, match=None):
145 def _computeforwardmissing(a, b, match=None):
146 """Computes which files are in b but not a.
146 """Computes which files are in b but not a.
147 This is its own function so extensions can easily wrap this call to see what
147 This is its own function so extensions can easily wrap this call to see what
148 files _forwardcopies is about to process.
148 files _forwardcopies is about to process.
149 """
149 """
150 ma = a.manifest()
150 ma = a.manifest()
151 mb = b.manifest()
151 mb = b.manifest()
152 if match:
152 if match:
153 ma = ma.matches(match)
153 ma = ma.matches(match)
154 mb = mb.matches(match)
154 mb = mb.matches(match)
155 return mb.filesnotin(ma)
155 return mb.filesnotin(ma)
156
156
157 def _forwardcopies(a, b, match=None):
157 def _forwardcopies(a, b, match=None):
158 '''find {dst@b: src@a} copy mapping where a is an ancestor of b'''
158 '''find {dst@b: src@a} copy mapping where a is an ancestor of b'''
159
159
160 # check for working copy
160 # check for working copy
161 w = None
161 w = None
162 if b.rev() is None:
162 if b.rev() is None:
163 w = b
163 w = b
164 b = w.p1()
164 b = w.p1()
165 if a == b:
165 if a == b:
166 # short-circuit to avoid issues with merge states
166 # short-circuit to avoid issues with merge states
167 return _dirstatecopies(w)
167 return _dirstatecopies(w)
168
168
169 # files might have to be traced back to the fctx parent of the last
169 # files might have to be traced back to the fctx parent of the last
170 # one-side-only changeset, but not further back than that
170 # one-side-only changeset, but not further back than that
171 limit = _findlimit(a._repo, a.rev(), b.rev())
171 limit = _findlimit(a._repo, a.rev(), b.rev())
172 if limit is None:
172 if limit is None:
173 limit = -1
173 limit = -1
174 am = a.manifest()
174 am = a.manifest()
175
175
176 # find where new files came from
176 # find where new files came from
177 # we currently don't try to find where old files went, too expensive
177 # we currently don't try to find where old files went, too expensive
178 # this means we can miss a case like 'hg rm b; hg cp a b'
178 # this means we can miss a case like 'hg rm b; hg cp a b'
179 cm = {}
179 cm = {}
180
180
181 # Computing the forward missing is quite expensive on large manifests, since
181 # Computing the forward missing is quite expensive on large manifests, since
182 # it compares the entire manifests. We can optimize it in the common use
182 # it compares the entire manifests. We can optimize it in the common use
183 # case of computing what copies are in a commit versus its parent (like
183 # case of computing what copies are in a commit versus its parent (like
184 # during a rebase or histedit). Note, we exclude merge commits from this
184 # during a rebase or histedit). Note, we exclude merge commits from this
185 # optimization, since the ctx.files() for a merge commit is not correct for
185 # optimization, since the ctx.files() for a merge commit is not correct for
186 # this comparison.
186 # this comparison.
187 forwardmissingmatch = match
187 forwardmissingmatch = match
188 if not match and b.p1() == a and b.p2().node() == node.nullid:
188 if not match and b.p1() == a and b.p2().node() == node.nullid:
189 forwardmissingmatch = scmutil.matchfiles(a._repo, b.files())
189 forwardmissingmatch = scmutil.matchfiles(a._repo, b.files())
190 missing = _computeforwardmissing(a, b, match=forwardmissingmatch)
190 missing = _computeforwardmissing(a, b, match=forwardmissingmatch)
191
191
192 ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True)
192 ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True)
193 for f in missing:
193 for f in missing:
194 fctx = b[f]
194 fctx = b[f]
195 fctx._ancestrycontext = ancestrycontext
195 fctx._ancestrycontext = ancestrycontext
196 ofctx = _tracefile(fctx, am, limit)
196 ofctx = _tracefile(fctx, am, limit)
197 if ofctx:
197 if ofctx:
198 cm[f] = ofctx.path()
198 cm[f] = ofctx.path()
199
199
200 # combine copies from dirstate if necessary
200 # combine copies from dirstate if necessary
201 if w is not None:
201 if w is not None:
202 cm = _chain(a, w, cm, _dirstatecopies(w))
202 cm = _chain(a, w, cm, _dirstatecopies(w))
203
203
204 return cm
204 return cm
205
205
206 def _backwardrenames(a, b):
206 def _backwardrenames(a, b):
207 if a._repo.ui.configbool('experimental', 'disablecopytrace'):
207 if a._repo.ui.configbool('experimental', 'disablecopytrace'):
208 return {}
208 return {}
209
209
210 # Even though we're not taking copies into account, 1:n rename situations
210 # Even though we're not taking copies into account, 1:n rename situations
211 # can still exist (e.g. hg cp a b; hg mv a c). In those cases we
211 # can still exist (e.g. hg cp a b; hg mv a c). In those cases we
212 # arbitrarily pick one of the renames.
212 # arbitrarily pick one of the renames.
213 f = _forwardcopies(b, a)
213 f = _forwardcopies(b, a)
214 r = {}
214 r = {}
215 for k, v in sorted(f.iteritems()):
215 for k, v in sorted(f.iteritems()):
216 # remove copies
216 # remove copies
217 if v in a:
217 if v in a:
218 continue
218 continue
219 r[v] = k
219 r[v] = k
220 return r
220 return r
221
221
222 def pathcopies(x, y, match=None):
222 def pathcopies(x, y, match=None):
223 '''find {dst@y: src@x} copy mapping for directed compare'''
223 '''find {dst@y: src@x} copy mapping for directed compare'''
224 if x == y or not x or not y:
224 if x == y or not x or not y:
225 return {}
225 return {}
226 a = y.ancestor(x)
226 a = y.ancestor(x)
227 if a == x:
227 if a == x:
228 return _forwardcopies(x, y, match=match)
228 return _forwardcopies(x, y, match=match)
229 if a == y:
229 if a == y:
230 return _backwardrenames(x, y)
230 return _backwardrenames(x, y)
231 return _chain(x, y, _backwardrenames(x, a),
231 return _chain(x, y, _backwardrenames(x, a),
232 _forwardcopies(a, y, match=match))
232 _forwardcopies(a, y, match=match))
233
233
234 def _computenonoverlap(repo, c1, c2, addedinm1, addedinm2, baselabel=''):
234 def _computenonoverlap(repo, c1, c2, addedinm1, addedinm2, baselabel=''):
235 """Computes, based on addedinm1 and addedinm2, the files exclusive to c1
235 """Computes, based on addedinm1 and addedinm2, the files exclusive to c1
236 and c2. This is its own function so extensions can easily wrap this call
236 and c2. This is its own function so extensions can easily wrap this call
237 to see what files mergecopies is about to process.
237 to see what files mergecopies is about to process.
238
238
239 Even though c1 and c2 are not used in this function, they are useful in
239 Even though c1 and c2 are not used in this function, they are useful in
240 other extensions for being able to read the file nodes of the changed files.
240 other extensions for being able to read the file nodes of the changed files.
241
241
242 "baselabel" can be passed to help distinguish the multiple computations
242 "baselabel" can be passed to help distinguish the multiple computations
243 done in the graft case.
243 done in the graft case.
244 """
244 """
245 u1 = sorted(addedinm1 - addedinm2)
245 u1 = sorted(addedinm1 - addedinm2)
246 u2 = sorted(addedinm2 - addedinm1)
246 u2 = sorted(addedinm2 - addedinm1)
247
247
248 header = " unmatched files in %s"
248 header = " unmatched files in %s"
249 if baselabel:
249 if baselabel:
250 header += ' (from %s)' % baselabel
250 header += ' (from %s)' % baselabel
251 if u1:
251 if u1:
252 repo.ui.debug("%s:\n %s\n" % (header % 'local', "\n ".join(u1)))
252 repo.ui.debug("%s:\n %s\n" % (header % 'local', "\n ".join(u1)))
253 if u2:
253 if u2:
254 repo.ui.debug("%s:\n %s\n" % (header % 'other', "\n ".join(u2)))
254 repo.ui.debug("%s:\n %s\n" % (header % 'other', "\n ".join(u2)))
255 return u1, u2
255 return u1, u2
256
256
257 def _makegetfctx(ctx):
257 def _makegetfctx(ctx):
258 """return a 'getfctx' function suitable for _checkcopies usage
258 """return a 'getfctx' function suitable for _checkcopies usage
259
259
260 We have to re-setup the function building 'filectx' for each
260 We have to re-setup the function building 'filectx' for each
261 '_checkcopies' to ensure the linkrev adjustment is properly setup for
261 '_checkcopies' to ensure the linkrev adjustment is properly setup for
262 each. Linkrev adjustment is important to avoid bug in rename
262 each. Linkrev adjustment is important to avoid bug in rename
263 detection. Moreover, having a proper '_ancestrycontext' setup ensures
263 detection. Moreover, having a proper '_ancestrycontext' setup ensures
264 the performance impact of this adjustment is kept limited. Without it,
264 the performance impact of this adjustment is kept limited. Without it,
265 each file could do a full dag traversal making the time complexity of
265 each file could do a full dag traversal making the time complexity of
266 the operation explode (see issue4537).
266 the operation explode (see issue4537).
267
267
268 This function exists here mostly to limit the impact on stable. Feel
268 This function exists here mostly to limit the impact on stable. Feel
269 free to refactor on default.
269 free to refactor on default.
270 """
270 """
271 rev = ctx.rev()
271 rev = ctx.rev()
272 repo = ctx._repo
272 repo = ctx._repo
273 ac = getattr(ctx, '_ancestrycontext', None)
273 ac = getattr(ctx, '_ancestrycontext', None)
274 if ac is None:
274 if ac is None:
275 revs = [rev]
275 revs = [rev]
276 if rev is None:
276 if rev is None:
277 revs = [p.rev() for p in ctx.parents()]
277 revs = [p.rev() for p in ctx.parents()]
278 ac = repo.changelog.ancestors(revs, inclusive=True)
278 ac = repo.changelog.ancestors(revs, inclusive=True)
279 ctx._ancestrycontext = ac
279 ctx._ancestrycontext = ac
280 def makectx(f, n):
280 def makectx(f, n):
281 if len(n) != 20: # in a working context?
281 if len(n) != 20: # in a working context?
282 if ctx.rev() is None:
282 if ctx.rev() is None:
283 return ctx.filectx(f)
283 return ctx.filectx(f)
284 return repo[None][f]
284 return repo[None][f]
285 fctx = repo.filectx(f, fileid=n)
285 fctx = repo.filectx(f, fileid=n)
286 # setup only needed for filectx not create from a changectx
286 # setup only needed for filectx not create from a changectx
287 fctx._ancestrycontext = ac
287 fctx._ancestrycontext = ac
288 fctx._descendantrev = rev
288 fctx._descendantrev = rev
289 return fctx
289 return fctx
290 return util.lrucachefunc(makectx)
290 return util.lrucachefunc(makectx)
291
291
292 def mergecopies(repo, c1, c2, base):
292 def mergecopies(repo, c1, c2, base):
293 """
293 """
294 Find moves and copies between context c1 and c2 that are relevant
294 Find moves and copies between context c1 and c2 that are relevant
295 for merging. 'base' will be used as the merge base.
295 for merging. 'base' will be used as the merge base.
296
296
297 Returns four dicts: "copy", "movewithdir", "diverge", and
297 Returns four dicts: "copy", "movewithdir", "diverge", and
298 "renamedelete".
298 "renamedelete".
299
299
300 "copy" is a mapping from destination name -> source name,
300 "copy" is a mapping from destination name -> source name,
301 where source is in c1 and destination is in c2 or vice-versa.
301 where source is in c1 and destination is in c2 or vice-versa.
302
302
303 "movewithdir" is a mapping from source name -> destination name,
303 "movewithdir" is a mapping from source name -> destination name,
304 where the file at source present in one context but not the other
304 where the file at source present in one context but not the other
305 needs to be moved to destination by the merge process, because the
305 needs to be moved to destination by the merge process, because the
306 other context moved the directory it is in.
306 other context moved the directory it is in.
307
307
308 "diverge" is a mapping of source name -> list of destination names
308 "diverge" is a mapping of source name -> list of destination names
309 for divergent renames.
309 for divergent renames.
310
310
311 "renamedelete" is a mapping of source name -> list of destination
311 "renamedelete" is a mapping of source name -> list of destination
312 names for files deleted in c1 that were renamed in c2 or vice-versa.
312 names for files deleted in c1 that were renamed in c2 or vice-versa.
313 """
313 """
314 # avoid silly behavior for update from empty dir
314 # avoid silly behavior for update from empty dir
315 if not c1 or not c2 or c1 == c2:
315 if not c1 or not c2 or c1 == c2:
316 return {}, {}, {}, {}
316 return {}, {}, {}, {}
317
317
318 # avoid silly behavior for parent -> working dir
318 # avoid silly behavior for parent -> working dir
319 if c2.node() is None and c1.node() == repo.dirstate.p1():
319 if c2.node() is None and c1.node() == repo.dirstate.p1():
320 return repo.dirstate.copies(), {}, {}, {}
320 return repo.dirstate.copies(), {}, {}, {}
321
321
322 # Copy trace disabling is explicitly below the node == p1 logic above
322 # Copy trace disabling is explicitly below the node == p1 logic above
323 # because the logic above is required for a simple copy to be kept across a
323 # because the logic above is required for a simple copy to be kept across a
324 # rebase.
324 # rebase.
325 if repo.ui.configbool('experimental', 'disablecopytrace'):
325 if repo.ui.configbool('experimental', 'disablecopytrace'):
326 return {}, {}, {}, {}
326 return {}, {}, {}, {}
327
327
328 # In certain scenarios (e.g. graft, update or rebase), base can be
328 # In certain scenarios (e.g. graft, update or rebase), base can be
329 # overridden We still need to know a real common ancestor in this case We
329 # overridden We still need to know a real common ancestor in this case We
330 # can't just compute _c1.ancestor(_c2) and compare it to ca, because there
330 # can't just compute _c1.ancestor(_c2) and compare it to ca, because there
331 # can be multiple common ancestors, e.g. in case of bidmerge. Because our
331 # can be multiple common ancestors, e.g. in case of bidmerge. Because our
332 # caller may not know if the revision passed in lieu of the CA is a genuine
332 # caller may not know if the revision passed in lieu of the CA is a genuine
333 # common ancestor or not without explicitly checking it, it's better to
333 # common ancestor or not without explicitly checking it, it's better to
334 # determine that here.
334 # determine that here.
335 #
335 #
336 # base.descendant(wc) and base.descendant(base) are False, work around that
336 # base.descendant(wc) and base.descendant(base) are False, work around that
337 _c1 = c1.p1() if c1.rev() is None else c1
337 _c1 = c1.p1() if c1.rev() is None else c1
338 _c2 = c2.p1() if c2.rev() is None else c2
338 _c2 = c2.p1() if c2.rev() is None else c2
339 # an endpoint is "dirty" if it isn't a descendant of the merge base
339 # an endpoint is "dirty" if it isn't a descendant of the merge base
340 # if we have a dirty endpoint, we need to trigger graft logic, and also
340 # if we have a dirty endpoint, we need to trigger graft logic, and also
341 # keep track of which endpoint is dirty
341 # keep track of which endpoint is dirty
342 dirtyc1 = not (base == _c1 or base.descendant(_c1))
342 dirtyc1 = not (base == _c1 or base.descendant(_c1))
343 dirtyc2 = not (base== _c2 or base.descendant(_c2))
343 dirtyc2 = not (base== _c2 or base.descendant(_c2))
344 graft = dirtyc1 or dirtyc2
344 graft = dirtyc1 or dirtyc2
345 tca = base
345 tca = base
346 if graft:
346 if graft:
347 tca = _c1.ancestor(_c2)
347 tca = _c1.ancestor(_c2)
348
348
349 limit = _findlimit(repo, c1.rev(), c2.rev())
349 limit = _findlimit(repo, c1.rev(), c2.rev())
350 if limit is None:
350 if limit is None:
351 # no common ancestor, no copies
351 # no common ancestor, no copies
352 return {}, {}, {}, {}
352 return {}, {}, {}, {}
353 repo.ui.debug(" searching for copies back to rev %d\n" % limit)
353 repo.ui.debug(" searching for copies back to rev %d\n" % limit)
354
354
355 m1 = c1.manifest()
355 m1 = c1.manifest()
356 m2 = c2.manifest()
356 m2 = c2.manifest()
357 mb = base.manifest()
357 mb = base.manifest()
358
358
359 # gather data from _checkcopies:
359 # gather data from _checkcopies:
360 # - diverge = record all diverges in this dict
360 # - diverge = record all diverges in this dict
361 # - copy = record all non-divergent copies in this dict
361 # - copy = record all non-divergent copies in this dict
362 # - fullcopy = record all copies in this dict
362 # - fullcopy = record all copies in this dict
363 diverge = {} # divergence data is shared
363 diverge = {} # divergence data is shared
364 data1 = {'copy': {},
364 data1 = {'copy': {},
365 'fullcopy': {},
365 'fullcopy': {},
366 'diverge': diverge,
366 'diverge': diverge,
367 }
367 }
368 data2 = {'copy': {},
368 data2 = {'copy': {},
369 'fullcopy': {},
369 'fullcopy': {},
370 'diverge': diverge,
370 'diverge': diverge,
371 }
371 }
372
372
373 # find interesting file sets from manifests
373 # find interesting file sets from manifests
374 addedinm1 = m1.filesnotin(mb)
374 addedinm1 = m1.filesnotin(mb)
375 addedinm2 = m2.filesnotin(mb)
375 addedinm2 = m2.filesnotin(mb)
376 bothnew = sorted(addedinm1 & addedinm2)
376 bothnew = sorted(addedinm1 & addedinm2)
377 if tca == base:
377 if tca == base:
378 # unmatched file from base
378 # unmatched file from base
379 u1r, u2r = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
379 u1r, u2r = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
380 u1u, u2u = u1r, u2r
380 u1u, u2u = u1r, u2r
381 else:
381 else:
382 # unmatched file from base (DAG rotation in the graft case)
382 # unmatched file from base (DAG rotation in the graft case)
383 u1r, u2r = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2,
383 u1r, u2r = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2,
384 baselabel='base')
384 baselabel='base')
385 # unmatched file from topological common ancestors (no DAG rotation)
385 # unmatched file from topological common ancestors (no DAG rotation)
386 # need to recompute this for directory move handling when grafting
386 # need to recompute this for directory move handling when grafting
387 mta = tca.manifest()
387 mta = tca.manifest()
388 u1u, u2u = _computenonoverlap(repo, c1, c2, m1.filesnotin(mta),
388 u1u, u2u = _computenonoverlap(repo, c1, c2, m1.filesnotin(mta),
389 m2.filesnotin(mta),
389 m2.filesnotin(mta),
390 baselabel='topological common ancestor')
390 baselabel='topological common ancestor')
391
391
392 for f in u1u:
392 for f in u1u:
393 _checkcopies(c1, f, m1, m2, base, tca, limit, data1)
393 _checkcopies(c1, f, m1, m2, base, tca, limit, data1)
394
394
395 for f in u2u:
395 for f in u2u:
396 _checkcopies(c2, f, m2, m1, base, tca, limit, data2)
396 _checkcopies(c2, f, m2, m1, base, tca, limit, data2)
397
397
398 copy = dict(data1['copy'].items() + data2['copy'].items())
398 copy = dict(data1['copy'].items() + data2['copy'].items())
399 fullcopy = dict(data1['fullcopy'].items() + data2['fullcopy'].items())
399 fullcopy = dict(data1['fullcopy'].items() + data2['fullcopy'].items())
400
400
401 renamedelete = {}
401 renamedelete = {}
402 renamedeleteset = set()
402 renamedeleteset = set()
403 divergeset = set()
403 divergeset = set()
404 for of, fl in diverge.items():
404 for of, fl in diverge.items():
405 if len(fl) == 1 or of in c1 or of in c2:
405 if len(fl) == 1 or of in c1 or of in c2:
406 del diverge[of] # not actually divergent, or not a rename
406 del diverge[of] # not actually divergent, or not a rename
407 if of not in c1 and of not in c2:
407 if of not in c1 and of not in c2:
408 # renamed on one side, deleted on the other side, but filter
408 # renamed on one side, deleted on the other side, but filter
409 # out files that have been renamed and then deleted
409 # out files that have been renamed and then deleted
410 renamedelete[of] = [f for f in fl if f in c1 or f in c2]
410 renamedelete[of] = [f for f in fl if f in c1 or f in c2]
411 renamedeleteset.update(fl) # reverse map for below
411 renamedeleteset.update(fl) # reverse map for below
412 else:
412 else:
413 divergeset.update(fl) # reverse map for below
413 divergeset.update(fl) # reverse map for below
414
414
415 if bothnew:
415 if bothnew:
416 repo.ui.debug(" unmatched files new in both:\n %s\n"
416 repo.ui.debug(" unmatched files new in both:\n %s\n"
417 % "\n ".join(bothnew))
417 % "\n ".join(bothnew))
418 bothdiverge = {}
418 bothdiverge = {}
419 bothdata = {'copy': {},
419 bothdata = {'copy': {},
420 'fullcopy': {},
420 'fullcopy': {},
421 'diverge': bothdiverge,
421 'diverge': bothdiverge,
422 }
422 }
423 for f in bothnew:
423 for f in bothnew:
424 _checkcopies(c1, f, m1, m2, base, tca, limit, bothdata)
424 _checkcopies(c1, f, m1, m2, base, tca, limit, bothdata)
425 _checkcopies(c2, f, m2, m1, base, tca, limit, bothdata)
425 _checkcopies(c2, f, m2, m1, base, tca, limit, bothdata)
426 for of, fl in bothdiverge.items():
426 for of, fl in bothdiverge.items():
427 if len(fl) == 2 and fl[0] == fl[1]:
427 if len(fl) == 2 and fl[0] == fl[1]:
428 copy[fl[0]] = of # not actually divergent, just matching renames
428 copy[fl[0]] = of # not actually divergent, just matching renames
429
429
430 if fullcopy and repo.ui.debugflag:
430 if fullcopy and repo.ui.debugflag:
431 repo.ui.debug(" all copies found (* = to merge, ! = divergent, "
431 repo.ui.debug(" all copies found (* = to merge, ! = divergent, "
432 "% = renamed and deleted):\n")
432 "% = renamed and deleted):\n")
433 for f in sorted(fullcopy):
433 for f in sorted(fullcopy):
434 note = ""
434 note = ""
435 if f in copy:
435 if f in copy:
436 note += "*"
436 note += "*"
437 if f in divergeset:
437 if f in divergeset:
438 note += "!"
438 note += "!"
439 if f in renamedeleteset:
439 if f in renamedeleteset:
440 note += "%"
440 note += "%"
441 repo.ui.debug(" src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f,
441 repo.ui.debug(" src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f,
442 note))
442 note))
443 del divergeset
443 del divergeset
444
444
445 if not fullcopy:
445 if not fullcopy:
446 return copy, {}, diverge, renamedelete
446 return copy, {}, diverge, renamedelete
447
447
448 repo.ui.debug(" checking for directory renames\n")
448 repo.ui.debug(" checking for directory renames\n")
449
449
450 # generate a directory move map
450 # generate a directory move map
451 d1, d2 = c1.dirs(), c2.dirs()
451 d1, d2 = c1.dirs(), c2.dirs()
452 # Hack for adding '', which is not otherwise added, to d1 and d2
452 # Hack for adding '', which is not otherwise added, to d1 and d2
453 d1.addpath('/')
453 d1.addpath('/')
454 d2.addpath('/')
454 d2.addpath('/')
455 invalid = set()
455 invalid = set()
456 dirmove = {}
456 dirmove = {}
457
457
458 # examine each file copy for a potential directory move, which is
458 # examine each file copy for a potential directory move, which is
459 # when all the files in a directory are moved to a new directory
459 # when all the files in a directory are moved to a new directory
460 for dst, src in fullcopy.iteritems():
460 for dst, src in fullcopy.iteritems():
461 dsrc, ddst = pathutil.dirname(src), pathutil.dirname(dst)
461 dsrc, ddst = pathutil.dirname(src), pathutil.dirname(dst)
462 if dsrc in invalid:
462 if dsrc in invalid:
463 # already seen to be uninteresting
463 # already seen to be uninteresting
464 continue
464 continue
465 elif dsrc in d1 and ddst in d1:
465 elif dsrc in d1 and ddst in d1:
466 # directory wasn't entirely moved locally
466 # directory wasn't entirely moved locally
467 invalid.add(dsrc + "/")
467 invalid.add(dsrc + "/")
468 elif dsrc in d2 and ddst in d2:
468 elif dsrc in d2 and ddst in d2:
469 # directory wasn't entirely moved remotely
469 # directory wasn't entirely moved remotely
470 invalid.add(dsrc + "/")
470 invalid.add(dsrc + "/")
471 elif dsrc + "/" in dirmove and dirmove[dsrc + "/"] != ddst + "/":
471 elif dsrc + "/" in dirmove and dirmove[dsrc + "/"] != ddst + "/":
472 # files from the same directory moved to two different places
472 # files from the same directory moved to two different places
473 invalid.add(dsrc + "/")
473 invalid.add(dsrc + "/")
474 else:
474 else:
475 # looks good so far
475 # looks good so far
476 dirmove[dsrc + "/"] = ddst + "/"
476 dirmove[dsrc + "/"] = ddst + "/"
477
477
478 for i in invalid:
478 for i in invalid:
479 if i in dirmove:
479 if i in dirmove:
480 del dirmove[i]
480 del dirmove[i]
481 del d1, d2, invalid
481 del d1, d2, invalid
482
482
483 if not dirmove:
483 if not dirmove:
484 return copy, {}, diverge, renamedelete
484 return copy, {}, diverge, renamedelete
485
485
486 for d in dirmove:
486 for d in dirmove:
487 repo.ui.debug(" discovered dir src: '%s' -> dst: '%s'\n" %
487 repo.ui.debug(" discovered dir src: '%s' -> dst: '%s'\n" %
488 (d, dirmove[d]))
488 (d, dirmove[d]))
489
489
490 movewithdir = {}
490 movewithdir = {}
491 # check unaccounted nonoverlapping files against directory moves
491 # check unaccounted nonoverlapping files against directory moves
492 for f in u1r + u2r:
492 for f in u1r + u2r:
493 if f not in fullcopy:
493 if f not in fullcopy:
494 for d in dirmove:
494 for d in dirmove:
495 if f.startswith(d):
495 if f.startswith(d):
496 # new file added in a directory that was moved, move it
496 # new file added in a directory that was moved, move it
497 df = dirmove[d] + f[len(d):]
497 df = dirmove[d] + f[len(d):]
498 if df not in copy:
498 if df not in copy:
499 movewithdir[f] = df
499 movewithdir[f] = df
500 repo.ui.debug((" pending file src: '%s' -> "
500 repo.ui.debug((" pending file src: '%s' -> "
501 "dst: '%s'\n") % (f, df))
501 "dst: '%s'\n") % (f, df))
502 break
502 break
503
503
504 return copy, movewithdir, diverge, renamedelete
504 return copy, movewithdir, diverge, renamedelete
505
505
506 def _related(f1, f2, limit):
506 def _related(f1, f2, limit):
507 """return True if f1 and f2 filectx have a common ancestor
507 """return True if f1 and f2 filectx have a common ancestor
508
508
509 Walk back to common ancestor to see if the two files originate
509 Walk back to common ancestor to see if the two files originate
510 from the same file. Since workingfilectx's rev() is None it messes
510 from the same file. Since workingfilectx's rev() is None it messes
511 up the integer comparison logic, hence the pre-step check for
511 up the integer comparison logic, hence the pre-step check for
512 None (f1 and f2 can only be workingfilectx's initially).
512 None (f1 and f2 can only be workingfilectx's initially).
513 """
513 """
514
514
515 if f1 == f2:
515 if f1 == f2:
516 return f1 # a match
516 return f1 # a match
517
517
518 g1, g2 = f1.ancestors(), f2.ancestors()
518 g1, g2 = f1.ancestors(), f2.ancestors()
519 try:
519 try:
520 f1r, f2r = f1.linkrev(), f2.linkrev()
520 f1r, f2r = f1.linkrev(), f2.linkrev()
521
521
522 if f1r is None:
522 if f1r is None:
523 f1 = next(g1)
523 f1 = next(g1)
524 if f2r is None:
524 if f2r is None:
525 f2 = next(g2)
525 f2 = next(g2)
526
526
527 while True:
527 while True:
528 f1r, f2r = f1.linkrev(), f2.linkrev()
528 f1r, f2r = f1.linkrev(), f2.linkrev()
529 if f1r > f2r:
529 if f1r > f2r:
530 f1 = next(g1)
530 f1 = next(g1)
531 elif f2r > f1r:
531 elif f2r > f1r:
532 f2 = next(g2)
532 f2 = next(g2)
533 elif f1 == f2:
533 elif f1 == f2:
534 return f1 # a match
534 return f1 # a match
535 elif f1r == f2r or f1r < limit or f2r < limit:
535 elif f1r == f2r or f1r < limit or f2r < limit:
536 return False # copy no longer relevant
536 return False # copy no longer relevant
537 except StopIteration:
537 except StopIteration:
538 return False
538 return False
539
539
540 def _checkcopies(ctx, f, m1, m2, base, tca, limit, data):
540 def _checkcopies(ctx, f, m1, m2, base, tca, limit, data):
541 """
541 """
542 check possible copies of f from m1 to m2
542 check possible copies of f from m1 to m2
543
543
544 ctx = starting context for f in m1
544 ctx = starting context for f in m1
545 f = the filename to check (as in m1)
545 f = the filename to check (as in m1)
546 m1 = the source manifest
546 m1 = the source manifest
547 m2 = the destination manifest
547 m2 = the destination manifest
548 base = the changectx used as a merge base
548 base = the changectx used as a merge base
549 tca = topological common ancestor for graft-like scenarios
549 tca = topological common ancestor for graft-like scenarios
550 limit = the rev number to not search beyond
550 limit = the rev number to not search beyond
551 data = dictionary of dictionary to store copy data. (see mergecopies)
551 data = dictionary of dictionary to store copy data. (see mergecopies)
552
552
553 note: limit is only an optimization, and there is no guarantee that
553 note: limit is only an optimization, and there is no guarantee that
554 irrelevant revisions will not be limited
554 irrelevant revisions will not be limited
555 there is no easy way to make this algorithm stop in a guaranteed way
555 there is no easy way to make this algorithm stop in a guaranteed way
556 once it "goes behind a certain revision".
556 once it "goes behind a certain revision".
557 """
557 """
558
558
559 mb = base.manifest()
559 mb = base.manifest()
560 # Might be true if this call is about finding backward renames,
560 # Might be true if this call is about finding backward renames,
561 # This happens in the case of grafts because the DAG is then rotated.
561 # This happens in the case of grafts because the DAG is then rotated.
562 # If the file exists in both the base and the source, we are not looking
562 # If the file exists in both the base and the source, we are not looking
563 # for a rename on the source side, but on the part of the DAG that is
563 # for a rename on the source side, but on the part of the DAG that is
564 # traversed backwards.
564 # traversed backwards.
565 #
565 #
566 # In the case there is both backward and forward renames (before and after
566 # In the case there is both backward and forward renames (before and after
567 # the base) this is more complicated as we must detect a divergence. This
567 # the base) this is more complicated as we must detect a divergence.
568 # is currently broken and hopefully some later code update will make that
568 # We use 'backwards = False' in that case.
569 # work (we use 'backwards = False' in that case)
570 backwards = base != tca and f in mb
569 backwards = base != tca and f in mb
571 getfctx = _makegetfctx(ctx)
570 getfctx = _makegetfctx(ctx)
572
571
573 of = None
572 of = None
574 seen = set([f])
573 seen = set([f])
575 for oc in getfctx(f, m1[f]).ancestors():
574 for oc in getfctx(f, m1[f]).ancestors():
576 ocr = oc.linkrev()
575 ocr = oc.linkrev()
577 of = oc.path()
576 of = oc.path()
578 if of in seen:
577 if of in seen:
579 # check limit late - grab last rename before
578 # check limit late - grab last rename before
580 if ocr < limit:
579 if ocr < limit:
581 break
580 break
582 continue
581 continue
583 seen.add(of)
582 seen.add(of)
584
583
585 # remember for dir rename detection
584 # remember for dir rename detection
586 if backwards:
585 if backwards:
587 data['fullcopy'][of] = f # grafting backwards through renames
586 data['fullcopy'][of] = f # grafting backwards through renames
588 else:
587 else:
589 data['fullcopy'][f] = of
588 data['fullcopy'][f] = of
590 if of not in m2:
589 if of not in m2:
591 continue # no match, keep looking
590 continue # no match, keep looking
592 if m2[of] == mb.get(of):
591 if m2[of] == mb.get(of):
593 return # no merge needed, quit early
592 return # no merge needed, quit early
594 c2 = getfctx(of, m2[of])
593 c2 = getfctx(of, m2[of])
595 # c2 might be a plain new file on added on destination side that is
594 # c2 might be a plain new file on added on destination side that is
596 # unrelated to the droids we are looking for.
595 # unrelated to the droids we are looking for.
597 cr = _related(oc, c2, tca.rev())
596 cr = _related(oc, c2, tca.rev())
598 if cr and (of == f or of == c2.path()): # non-divergent
597 if cr and (of == f or of == c2.path()): # non-divergent
599 if backwards:
598 if backwards:
600 data['copy'][of] = f
599 data['copy'][of] = f
601 elif of in mb:
600 elif of in mb:
602 data['copy'][f] = of
601 data['copy'][f] = of
602 else: # divergence w.r.t. graft CA on one side of topological CA
603 for sf in seen:
604 if sf in mb:
605 assert sf not in data['diverge']
606 data['diverge'][sf] = [f, of]
607 break
603 return
608 return
604
609
605 if of in mb:
610 if of in mb:
606 data['diverge'].setdefault(of, []).append(f)
611 data['diverge'].setdefault(of, []).append(f)
607
612
608 def duplicatecopies(repo, rev, fromrev, skiprev=None):
613 def duplicatecopies(repo, rev, fromrev, skiprev=None):
609 '''reproduce copies from fromrev to rev in the dirstate
614 '''reproduce copies from fromrev to rev in the dirstate
610
615
611 If skiprev is specified, it's a revision that should be used to
616 If skiprev is specified, it's a revision that should be used to
612 filter copy records. Any copies that occur between fromrev and
617 filter copy records. Any copies that occur between fromrev and
613 skiprev will not be duplicated, even if they appear in the set of
618 skiprev will not be duplicated, even if they appear in the set of
614 copies between fromrev and rev.
619 copies between fromrev and rev.
615 '''
620 '''
616 exclude = {}
621 exclude = {}
617 if (skiprev is not None and
622 if (skiprev is not None and
618 not repo.ui.configbool('experimental', 'disablecopytrace')):
623 not repo.ui.configbool('experimental', 'disablecopytrace')):
619 # disablecopytrace skips this line, but not the entire function because
624 # disablecopytrace skips this line, but not the entire function because
620 # the line below is O(size of the repo) during a rebase, while the rest
625 # the line below is O(size of the repo) during a rebase, while the rest
621 # of the function is much faster (and is required for carrying copy
626 # of the function is much faster (and is required for carrying copy
622 # metadata across the rebase anyway).
627 # metadata across the rebase anyway).
623 exclude = pathcopies(repo[fromrev], repo[skiprev])
628 exclude = pathcopies(repo[fromrev], repo[skiprev])
624 for dst, src in pathcopies(repo[fromrev], repo[rev]).iteritems():
629 for dst, src in pathcopies(repo[fromrev], repo[rev]).iteritems():
625 # copies.pathcopies returns backward renames, so dst might not
630 # copies.pathcopies returns backward renames, so dst might not
626 # actually be in the dirstate
631 # actually be in the dirstate
627 if dst in exclude:
632 if dst in exclude:
628 continue
633 continue
629 if repo.dirstate[dst] in "nma":
634 if repo.dirstate[dst] in "nma":
630 repo.dirstate.copy(src, dst)
635 repo.dirstate.copy(src, dst)
@@ -1,1333 +1,1336
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extdiff]
2 > [extdiff]
3 > # for portability:
3 > # for portability:
4 > pdiff = sh "$RUNTESTDIR/pdiff"
4 > pdiff = sh "$RUNTESTDIR/pdiff"
5 > EOF
5 > EOF
6
6
7 Create a repo with some stuff in it:
7 Create a repo with some stuff in it:
8
8
9 $ hg init a
9 $ hg init a
10 $ cd a
10 $ cd a
11 $ echo a > a
11 $ echo a > a
12 $ echo a > d
12 $ echo a > d
13 $ echo a > e
13 $ echo a > e
14 $ hg ci -qAm0
14 $ hg ci -qAm0
15 $ echo b > a
15 $ echo b > a
16 $ hg ci -m1 -u bar
16 $ hg ci -m1 -u bar
17 $ hg mv a b
17 $ hg mv a b
18 $ hg ci -m2
18 $ hg ci -m2
19 $ hg cp b c
19 $ hg cp b c
20 $ hg ci -m3 -u baz
20 $ hg ci -m3 -u baz
21 $ echo b > d
21 $ echo b > d
22 $ echo f > e
22 $ echo f > e
23 $ hg ci -m4
23 $ hg ci -m4
24 $ hg up -q 3
24 $ hg up -q 3
25 $ echo b > e
25 $ echo b > e
26 $ hg branch -q stable
26 $ hg branch -q stable
27 $ hg ci -m5
27 $ hg ci -m5
28 $ hg merge -q default --tool internal:local
28 $ hg merge -q default --tool internal:local
29 $ hg branch -q default
29 $ hg branch -q default
30 $ hg ci -m6
30 $ hg ci -m6
31 $ hg phase --public 3
31 $ hg phase --public 3
32 $ hg phase --force --secret 6
32 $ hg phase --force --secret 6
33
33
34 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
34 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
35 @ test@6.secret: 6
35 @ test@6.secret: 6
36 |\
36 |\
37 | o test@5.draft: 5
37 | o test@5.draft: 5
38 | |
38 | |
39 o | test@4.draft: 4
39 o | test@4.draft: 4
40 |/
40 |/
41 o baz@3.public: 3
41 o baz@3.public: 3
42 |
42 |
43 o test@2.public: 2
43 o test@2.public: 2
44 |
44 |
45 o bar@1.public: 1
45 o bar@1.public: 1
46 |
46 |
47 o test@0.public: 0
47 o test@0.public: 0
48
48
49 Can't continue without starting:
49 Can't continue without starting:
50
50
51 $ hg rm -q e
51 $ hg rm -q e
52 $ hg graft --continue
52 $ hg graft --continue
53 abort: no graft in progress
53 abort: no graft in progress
54 [255]
54 [255]
55 $ hg revert -r . -q e
55 $ hg revert -r . -q e
56
56
57 Need to specify a rev:
57 Need to specify a rev:
58
58
59 $ hg graft
59 $ hg graft
60 abort: no revisions specified
60 abort: no revisions specified
61 [255]
61 [255]
62
62
63 Can't graft ancestor:
63 Can't graft ancestor:
64
64
65 $ hg graft 1 2
65 $ hg graft 1 2
66 skipping ancestor revision 1:5d205f8b35b6
66 skipping ancestor revision 1:5d205f8b35b6
67 skipping ancestor revision 2:5c095ad7e90f
67 skipping ancestor revision 2:5c095ad7e90f
68 [255]
68 [255]
69
69
70 Specify revisions with -r:
70 Specify revisions with -r:
71
71
72 $ hg graft -r 1 -r 2
72 $ hg graft -r 1 -r 2
73 skipping ancestor revision 1:5d205f8b35b6
73 skipping ancestor revision 1:5d205f8b35b6
74 skipping ancestor revision 2:5c095ad7e90f
74 skipping ancestor revision 2:5c095ad7e90f
75 [255]
75 [255]
76
76
77 $ hg graft -r 1 2
77 $ hg graft -r 1 2
78 warning: inconsistent use of --rev might give unexpected revision ordering!
78 warning: inconsistent use of --rev might give unexpected revision ordering!
79 skipping ancestor revision 2:5c095ad7e90f
79 skipping ancestor revision 2:5c095ad7e90f
80 skipping ancestor revision 1:5d205f8b35b6
80 skipping ancestor revision 1:5d205f8b35b6
81 [255]
81 [255]
82
82
83 Can't graft with dirty wd:
83 Can't graft with dirty wd:
84
84
85 $ hg up -q 0
85 $ hg up -q 0
86 $ echo foo > a
86 $ echo foo > a
87 $ hg graft 1
87 $ hg graft 1
88 abort: uncommitted changes
88 abort: uncommitted changes
89 [255]
89 [255]
90 $ hg revert a
90 $ hg revert a
91
91
92 Graft a rename:
92 Graft a rename:
93 (this also tests that editor is invoked if '--edit' is specified)
93 (this also tests that editor is invoked if '--edit' is specified)
94
94
95 $ hg status --rev "2^1" --rev 2
95 $ hg status --rev "2^1" --rev 2
96 A b
96 A b
97 R a
97 R a
98 $ HGEDITOR=cat hg graft 2 -u foo --edit
98 $ HGEDITOR=cat hg graft 2 -u foo --edit
99 grafting 2:5c095ad7e90f "2"
99 grafting 2:5c095ad7e90f "2"
100 merging a and b to b
100 merging a and b to b
101 2
101 2
102
102
103
103
104 HG: Enter commit message. Lines beginning with 'HG:' are removed.
104 HG: Enter commit message. Lines beginning with 'HG:' are removed.
105 HG: Leave message empty to abort commit.
105 HG: Leave message empty to abort commit.
106 HG: --
106 HG: --
107 HG: user: foo
107 HG: user: foo
108 HG: branch 'default'
108 HG: branch 'default'
109 HG: added b
109 HG: added b
110 HG: removed a
110 HG: removed a
111 $ hg export tip --git
111 $ hg export tip --git
112 # HG changeset patch
112 # HG changeset patch
113 # User foo
113 # User foo
114 # Date 0 0
114 # Date 0 0
115 # Thu Jan 01 00:00:00 1970 +0000
115 # Thu Jan 01 00:00:00 1970 +0000
116 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
116 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
117 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
117 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
118 2
118 2
119
119
120 diff --git a/a b/b
120 diff --git a/a b/b
121 rename from a
121 rename from a
122 rename to b
122 rename to b
123
123
124 Look for extra:source
124 Look for extra:source
125
125
126 $ hg log --debug -r tip
126 $ hg log --debug -r tip
127 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
127 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
128 tag: tip
128 tag: tip
129 phase: draft
129 phase: draft
130 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
130 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
131 parent: -1:0000000000000000000000000000000000000000
131 parent: -1:0000000000000000000000000000000000000000
132 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
132 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
133 user: foo
133 user: foo
134 date: Thu Jan 01 00:00:00 1970 +0000
134 date: Thu Jan 01 00:00:00 1970 +0000
135 files+: b
135 files+: b
136 files-: a
136 files-: a
137 extra: branch=default
137 extra: branch=default
138 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
138 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
139 description:
139 description:
140 2
140 2
141
141
142
142
143
143
144 Graft out of order, skipping a merge and a duplicate
144 Graft out of order, skipping a merge and a duplicate
145 (this also tests that editor is not invoked if '--edit' is not specified)
145 (this also tests that editor is not invoked if '--edit' is not specified)
146
146
147 $ hg graft 1 5 4 3 'merge()' 2 -n
147 $ hg graft 1 5 4 3 'merge()' 2 -n
148 skipping ungraftable merge revision 6
148 skipping ungraftable merge revision 6
149 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
149 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
150 grafting 1:5d205f8b35b6 "1"
150 grafting 1:5d205f8b35b6 "1"
151 grafting 5:97f8bfe72746 "5"
151 grafting 5:97f8bfe72746 "5"
152 grafting 4:9c233e8e184d "4"
152 grafting 4:9c233e8e184d "4"
153 grafting 3:4c60f11aa304 "3"
153 grafting 3:4c60f11aa304 "3"
154
154
155 $ HGEDITOR=cat hg graft 1 5 'merge()' 2 --debug
155 $ HGEDITOR=cat hg graft 1 5 'merge()' 2 --debug
156 skipping ungraftable merge revision 6
156 skipping ungraftable merge revision 6
157 scanning for duplicate grafts
157 scanning for duplicate grafts
158 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
158 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
159 grafting 1:5d205f8b35b6 "1"
159 grafting 1:5d205f8b35b6 "1"
160 searching for copies back to rev 1
160 searching for copies back to rev 1
161 unmatched files in local:
161 unmatched files in local:
162 b
162 b
163 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
163 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
164 src: 'a' -> dst: 'b' *
164 src: 'a' -> dst: 'b' *
165 checking for directory renames
165 checking for directory renames
166 resolving manifests
166 resolving manifests
167 branchmerge: True, force: True, partial: False
167 branchmerge: True, force: True, partial: False
168 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
168 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
169 preserving b for resolve of b
169 preserving b for resolve of b
170 starting 4 threads for background file closing (?)
170 starting 4 threads for background file closing (?)
171 b: local copied/moved from a -> m (premerge)
171 b: local copied/moved from a -> m (premerge)
172 picked tool ':merge' for b (binary False symlink False changedelete False)
172 picked tool ':merge' for b (binary False symlink False changedelete False)
173 merging b and a to b
173 merging b and a to b
174 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
174 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
175 premerge successful
175 premerge successful
176 committing files:
176 committing files:
177 b
177 b
178 committing manifest
178 committing manifest
179 committing changelog
179 committing changelog
180 grafting 5:97f8bfe72746 "5"
180 grafting 5:97f8bfe72746 "5"
181 searching for copies back to rev 1
181 searching for copies back to rev 1
182 unmatched files in other (from topological common ancestor):
182 unmatched files in other (from topological common ancestor):
183 c
183 c
184 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
184 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
185 src: 'c' -> dst: 'b' *
185 src: 'c' -> dst: 'b' *
186 checking for directory renames
186 checking for directory renames
187 resolving manifests
187 resolving manifests
188 branchmerge: True, force: True, partial: False
188 branchmerge: True, force: True, partial: False
189 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
189 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
190 e: remote is newer -> g
190 e: remote is newer -> g
191 getting e
191 getting e
192 b: remote unchanged -> k
192 b: remote unchanged -> k
193 committing files:
193 committing files:
194 e
194 e
195 committing manifest
195 committing manifest
196 committing changelog
196 committing changelog
197 $ HGEDITOR=cat hg graft 4 3 --log --debug
197 $ HGEDITOR=cat hg graft 4 3 --log --debug
198 scanning for duplicate grafts
198 scanning for duplicate grafts
199 grafting 4:9c233e8e184d "4"
199 grafting 4:9c233e8e184d "4"
200 searching for copies back to rev 1
200 searching for copies back to rev 1
201 unmatched files in other (from topological common ancestor):
201 unmatched files in other (from topological common ancestor):
202 c
202 c
203 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
203 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
204 src: 'c' -> dst: 'b' *
204 src: 'c' -> dst: 'b' *
205 checking for directory renames
205 checking for directory renames
206 resolving manifests
206 resolving manifests
207 branchmerge: True, force: True, partial: False
207 branchmerge: True, force: True, partial: False
208 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
208 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
209 preserving e for resolve of e
209 preserving e for resolve of e
210 d: remote is newer -> g
210 d: remote is newer -> g
211 getting d
211 getting d
212 b: remote unchanged -> k
212 b: remote unchanged -> k
213 e: versions differ -> m (premerge)
213 e: versions differ -> m (premerge)
214 picked tool ':merge' for e (binary False symlink False changedelete False)
214 picked tool ':merge' for e (binary False symlink False changedelete False)
215 merging e
215 merging e
216 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
216 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
217 e: versions differ -> m (merge)
217 e: versions differ -> m (merge)
218 picked tool ':merge' for e (binary False symlink False changedelete False)
218 picked tool ':merge' for e (binary False symlink False changedelete False)
219 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
219 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
220 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
220 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
221 abort: unresolved conflicts, can't continue
221 abort: unresolved conflicts, can't continue
222 (use 'hg resolve' and 'hg graft --continue --log')
222 (use 'hg resolve' and 'hg graft --continue --log')
223 [255]
223 [255]
224
224
225 Summary should mention graft:
225 Summary should mention graft:
226
226
227 $ hg summary |grep graft
227 $ hg summary |grep graft
228 commit: 2 modified, 2 unknown, 1 unresolved (graft in progress)
228 commit: 2 modified, 2 unknown, 1 unresolved (graft in progress)
229
229
230 Commit while interrupted should fail:
230 Commit while interrupted should fail:
231
231
232 $ hg ci -m 'commit interrupted graft'
232 $ hg ci -m 'commit interrupted graft'
233 abort: graft in progress
233 abort: graft in progress
234 (use 'hg graft --continue' or 'hg update' to abort)
234 (use 'hg graft --continue' or 'hg update' to abort)
235 [255]
235 [255]
236
236
237 Abort the graft and try committing:
237 Abort the graft and try committing:
238
238
239 $ hg up -C .
239 $ hg up -C .
240 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
240 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
241 $ echo c >> e
241 $ echo c >> e
242 $ hg ci -mtest
242 $ hg ci -mtest
243
243
244 $ hg strip . --config extensions.strip=
244 $ hg strip . --config extensions.strip=
245 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
245 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
246 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
246 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
247
247
248 Graft again:
248 Graft again:
249
249
250 $ hg graft 1 5 4 3 'merge()' 2
250 $ hg graft 1 5 4 3 'merge()' 2
251 skipping ungraftable merge revision 6
251 skipping ungraftable merge revision 6
252 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
252 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
253 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
253 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
254 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
254 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
255 grafting 4:9c233e8e184d "4"
255 grafting 4:9c233e8e184d "4"
256 merging e
256 merging e
257 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
257 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
258 abort: unresolved conflicts, can't continue
258 abort: unresolved conflicts, can't continue
259 (use 'hg resolve' and 'hg graft --continue')
259 (use 'hg resolve' and 'hg graft --continue')
260 [255]
260 [255]
261
261
262 Continue without resolve should fail:
262 Continue without resolve should fail:
263
263
264 $ hg graft -c
264 $ hg graft -c
265 grafting 4:9c233e8e184d "4"
265 grafting 4:9c233e8e184d "4"
266 abort: unresolved merge conflicts (see 'hg help resolve')
266 abort: unresolved merge conflicts (see 'hg help resolve')
267 [255]
267 [255]
268
268
269 Fix up:
269 Fix up:
270
270
271 $ echo b > e
271 $ echo b > e
272 $ hg resolve -m e
272 $ hg resolve -m e
273 (no more unresolved files)
273 (no more unresolved files)
274 continue: hg graft --continue
274 continue: hg graft --continue
275
275
276 Continue with a revision should fail:
276 Continue with a revision should fail:
277
277
278 $ hg graft -c 6
278 $ hg graft -c 6
279 abort: can't specify --continue and revisions
279 abort: can't specify --continue and revisions
280 [255]
280 [255]
281
281
282 $ hg graft -c -r 6
282 $ hg graft -c -r 6
283 abort: can't specify --continue and revisions
283 abort: can't specify --continue and revisions
284 [255]
284 [255]
285
285
286 Continue for real, clobber usernames
286 Continue for real, clobber usernames
287
287
288 $ hg graft -c -U
288 $ hg graft -c -U
289 grafting 4:9c233e8e184d "4"
289 grafting 4:9c233e8e184d "4"
290 grafting 3:4c60f11aa304 "3"
290 grafting 3:4c60f11aa304 "3"
291
291
292 Compare with original:
292 Compare with original:
293
293
294 $ hg diff -r 6
294 $ hg diff -r 6
295 $ hg status --rev 0:. -C
295 $ hg status --rev 0:. -C
296 M d
296 M d
297 M e
297 M e
298 A b
298 A b
299 a
299 a
300 A c
300 A c
301 a
301 a
302 R a
302 R a
303
303
304 View graph:
304 View graph:
305
305
306 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
306 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
307 @ test@11.draft: 3
307 @ test@11.draft: 3
308 |
308 |
309 o test@10.draft: 4
309 o test@10.draft: 4
310 |
310 |
311 o test@9.draft: 5
311 o test@9.draft: 5
312 |
312 |
313 o bar@8.draft: 1
313 o bar@8.draft: 1
314 |
314 |
315 o foo@7.draft: 2
315 o foo@7.draft: 2
316 |
316 |
317 | o test@6.secret: 6
317 | o test@6.secret: 6
318 | |\
318 | |\
319 | | o test@5.draft: 5
319 | | o test@5.draft: 5
320 | | |
320 | | |
321 | o | test@4.draft: 4
321 | o | test@4.draft: 4
322 | |/
322 | |/
323 | o baz@3.public: 3
323 | o baz@3.public: 3
324 | |
324 | |
325 | o test@2.public: 2
325 | o test@2.public: 2
326 | |
326 | |
327 | o bar@1.public: 1
327 | o bar@1.public: 1
328 |/
328 |/
329 o test@0.public: 0
329 o test@0.public: 0
330
330
331 Graft again onto another branch should preserve the original source
331 Graft again onto another branch should preserve the original source
332 $ hg up -q 0
332 $ hg up -q 0
333 $ echo 'g'>g
333 $ echo 'g'>g
334 $ hg add g
334 $ hg add g
335 $ hg ci -m 7
335 $ hg ci -m 7
336 created new head
336 created new head
337 $ hg graft 7
337 $ hg graft 7
338 grafting 7:ef0ef43d49e7 "2"
338 grafting 7:ef0ef43d49e7 "2"
339
339
340 $ hg log -r 7 --template '{rev}:{node}\n'
340 $ hg log -r 7 --template '{rev}:{node}\n'
341 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
341 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
342 $ hg log -r 2 --template '{rev}:{node}\n'
342 $ hg log -r 2 --template '{rev}:{node}\n'
343 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
343 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
344
344
345 $ hg log --debug -r tip
345 $ hg log --debug -r tip
346 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
346 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
347 tag: tip
347 tag: tip
348 phase: draft
348 phase: draft
349 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
349 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
350 parent: -1:0000000000000000000000000000000000000000
350 parent: -1:0000000000000000000000000000000000000000
351 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
351 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
352 user: foo
352 user: foo
353 date: Thu Jan 01 00:00:00 1970 +0000
353 date: Thu Jan 01 00:00:00 1970 +0000
354 files+: b
354 files+: b
355 files-: a
355 files-: a
356 extra: branch=default
356 extra: branch=default
357 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
357 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
358 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
358 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
359 description:
359 description:
360 2
360 2
361
361
362
362
363 Disallow grafting an already grafted cset onto its original branch
363 Disallow grafting an already grafted cset onto its original branch
364 $ hg up -q 6
364 $ hg up -q 6
365 $ hg graft 7
365 $ hg graft 7
366 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
366 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
367 [255]
367 [255]
368
368
369 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13
369 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13
370 --- */hg-5c095ad7e90f.patch * (glob)
370 --- */hg-5c095ad7e90f.patch * (glob)
371 +++ */hg-7a4785234d87.patch * (glob)
371 +++ */hg-7a4785234d87.patch * (glob)
372 @@ -1,18 +1,18 @@
372 @@ -1,18 +1,18 @@
373 # HG changeset patch
373 # HG changeset patch
374 -# User test
374 -# User test
375 +# User foo
375 +# User foo
376 # Date 0 0
376 # Date 0 0
377 # Thu Jan 01 00:00:00 1970 +0000
377 # Thu Jan 01 00:00:00 1970 +0000
378 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
378 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
379 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
379 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
380 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
380 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
381 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
381 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
382 2
382 2
383
383
384 -diff -r 5d205f8b35b6 -r 5c095ad7e90f a
384 -diff -r 5d205f8b35b6 -r 5c095ad7e90f a
385 +diff -r b592ea63bb0c -r 7a4785234d87 a
385 +diff -r b592ea63bb0c -r 7a4785234d87 a
386 --- a/a Thu Jan 01 00:00:00 1970 +0000
386 --- a/a Thu Jan 01 00:00:00 1970 +0000
387 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
387 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
388 @@ -1,1 +0,0 @@
388 @@ -1,1 +0,0 @@
389 --b
389 --b
390 -diff -r 5d205f8b35b6 -r 5c095ad7e90f b
390 -diff -r 5d205f8b35b6 -r 5c095ad7e90f b
391 +-a
391 +-a
392 +diff -r b592ea63bb0c -r 7a4785234d87 b
392 +diff -r b592ea63bb0c -r 7a4785234d87 b
393 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
393 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
394 +++ b/b Thu Jan 01 00:00:00 1970 +0000
394 +++ b/b Thu Jan 01 00:00:00 1970 +0000
395 @@ -0,0 +1,1 @@
395 @@ -0,0 +1,1 @@
396 -+b
396 -+b
397 ++a
397 ++a
398 [1]
398 [1]
399
399
400 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13 -X .
400 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13 -X .
401 --- */hg-5c095ad7e90f.patch * (glob)
401 --- */hg-5c095ad7e90f.patch * (glob)
402 +++ */hg-7a4785234d87.patch * (glob)
402 +++ */hg-7a4785234d87.patch * (glob)
403 @@ -1,8 +1,8 @@
403 @@ -1,8 +1,8 @@
404 # HG changeset patch
404 # HG changeset patch
405 -# User test
405 -# User test
406 +# User foo
406 +# User foo
407 # Date 0 0
407 # Date 0 0
408 # Thu Jan 01 00:00:00 1970 +0000
408 # Thu Jan 01 00:00:00 1970 +0000
409 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
409 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
410 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
410 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
411 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
411 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
412 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
412 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
413 2
413 2
414
414
415 [1]
415 [1]
416
416
417 Disallow grafting already grafted csets with the same origin onto each other
417 Disallow grafting already grafted csets with the same origin onto each other
418 $ hg up -q 13
418 $ hg up -q 13
419 $ hg graft 2
419 $ hg graft 2
420 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
420 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
421 [255]
421 [255]
422 $ hg graft 7
422 $ hg graft 7
423 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
423 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
424 [255]
424 [255]
425
425
426 $ hg up -q 7
426 $ hg up -q 7
427 $ hg graft 2
427 $ hg graft 2
428 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
428 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
429 [255]
429 [255]
430 $ hg graft tip
430 $ hg graft tip
431 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
431 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
432 [255]
432 [255]
433
433
434 Graft with --log
434 Graft with --log
435
435
436 $ hg up -Cq 1
436 $ hg up -Cq 1
437 $ hg graft 3 --log -u foo
437 $ hg graft 3 --log -u foo
438 grafting 3:4c60f11aa304 "3"
438 grafting 3:4c60f11aa304 "3"
439 warning: can't find ancestor for 'c' copied from 'b'!
439 warning: can't find ancestor for 'c' copied from 'b'!
440 $ hg log --template '{rev}:{node|short} {parents} {desc}\n' -r tip
440 $ hg log --template '{rev}:{node|short} {parents} {desc}\n' -r tip
441 14:0c921c65ef1e 1:5d205f8b35b6 3
441 14:0c921c65ef1e 1:5d205f8b35b6 3
442 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
442 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
443
443
444 Resolve conflicted graft
444 Resolve conflicted graft
445 $ hg up -q 0
445 $ hg up -q 0
446 $ echo b > a
446 $ echo b > a
447 $ hg ci -m 8
447 $ hg ci -m 8
448 created new head
448 created new head
449 $ echo c > a
449 $ echo c > a
450 $ hg ci -m 9
450 $ hg ci -m 9
451 $ hg graft 1 --tool internal:fail
451 $ hg graft 1 --tool internal:fail
452 grafting 1:5d205f8b35b6 "1"
452 grafting 1:5d205f8b35b6 "1"
453 abort: unresolved conflicts, can't continue
453 abort: unresolved conflicts, can't continue
454 (use 'hg resolve' and 'hg graft --continue')
454 (use 'hg resolve' and 'hg graft --continue')
455 [255]
455 [255]
456 $ hg resolve --all
456 $ hg resolve --all
457 merging a
457 merging a
458 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
458 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
459 [1]
459 [1]
460 $ cat a
460 $ cat a
461 <<<<<<< local: aaa4406d4f0a - test: 9
461 <<<<<<< local: aaa4406d4f0a - test: 9
462 c
462 c
463 =======
463 =======
464 b
464 b
465 >>>>>>> graft: 5d205f8b35b6 - bar: 1
465 >>>>>>> graft: 5d205f8b35b6 - bar: 1
466 $ echo b > a
466 $ echo b > a
467 $ hg resolve -m a
467 $ hg resolve -m a
468 (no more unresolved files)
468 (no more unresolved files)
469 continue: hg graft --continue
469 continue: hg graft --continue
470 $ hg graft -c
470 $ hg graft -c
471 grafting 1:5d205f8b35b6 "1"
471 grafting 1:5d205f8b35b6 "1"
472 $ hg export tip --git
472 $ hg export tip --git
473 # HG changeset patch
473 # HG changeset patch
474 # User bar
474 # User bar
475 # Date 0 0
475 # Date 0 0
476 # Thu Jan 01 00:00:00 1970 +0000
476 # Thu Jan 01 00:00:00 1970 +0000
477 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
477 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
478 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
478 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
479 1
479 1
480
480
481 diff --git a/a b/a
481 diff --git a/a b/a
482 --- a/a
482 --- a/a
483 +++ b/a
483 +++ b/a
484 @@ -1,1 +1,1 @@
484 @@ -1,1 +1,1 @@
485 -c
485 -c
486 +b
486 +b
487
487
488 Resolve conflicted graft with rename
488 Resolve conflicted graft with rename
489 $ echo c > a
489 $ echo c > a
490 $ hg ci -m 10
490 $ hg ci -m 10
491 $ hg graft 2 --tool internal:fail
491 $ hg graft 2 --tool internal:fail
492 grafting 2:5c095ad7e90f "2"
492 grafting 2:5c095ad7e90f "2"
493 abort: unresolved conflicts, can't continue
493 abort: unresolved conflicts, can't continue
494 (use 'hg resolve' and 'hg graft --continue')
494 (use 'hg resolve' and 'hg graft --continue')
495 [255]
495 [255]
496 $ hg resolve --all
496 $ hg resolve --all
497 merging a and b to b
497 merging a and b to b
498 (no more unresolved files)
498 (no more unresolved files)
499 continue: hg graft --continue
499 continue: hg graft --continue
500 $ hg graft -c
500 $ hg graft -c
501 grafting 2:5c095ad7e90f "2"
501 grafting 2:5c095ad7e90f "2"
502 $ hg export tip --git
502 $ hg export tip --git
503 # HG changeset patch
503 # HG changeset patch
504 # User test
504 # User test
505 # Date 0 0
505 # Date 0 0
506 # Thu Jan 01 00:00:00 1970 +0000
506 # Thu Jan 01 00:00:00 1970 +0000
507 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
507 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
508 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
508 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
509 2
509 2
510
510
511 diff --git a/a b/b
511 diff --git a/a b/b
512 rename from a
512 rename from a
513 rename to b
513 rename to b
514
514
515 Test simple origin(), with and without args
515 Test simple origin(), with and without args
516 $ hg log -r 'origin()'
516 $ hg log -r 'origin()'
517 changeset: 1:5d205f8b35b6
517 changeset: 1:5d205f8b35b6
518 user: bar
518 user: bar
519 date: Thu Jan 01 00:00:00 1970 +0000
519 date: Thu Jan 01 00:00:00 1970 +0000
520 summary: 1
520 summary: 1
521
521
522 changeset: 2:5c095ad7e90f
522 changeset: 2:5c095ad7e90f
523 user: test
523 user: test
524 date: Thu Jan 01 00:00:00 1970 +0000
524 date: Thu Jan 01 00:00:00 1970 +0000
525 summary: 2
525 summary: 2
526
526
527 changeset: 3:4c60f11aa304
527 changeset: 3:4c60f11aa304
528 user: baz
528 user: baz
529 date: Thu Jan 01 00:00:00 1970 +0000
529 date: Thu Jan 01 00:00:00 1970 +0000
530 summary: 3
530 summary: 3
531
531
532 changeset: 4:9c233e8e184d
532 changeset: 4:9c233e8e184d
533 user: test
533 user: test
534 date: Thu Jan 01 00:00:00 1970 +0000
534 date: Thu Jan 01 00:00:00 1970 +0000
535 summary: 4
535 summary: 4
536
536
537 changeset: 5:97f8bfe72746
537 changeset: 5:97f8bfe72746
538 branch: stable
538 branch: stable
539 parent: 3:4c60f11aa304
539 parent: 3:4c60f11aa304
540 user: test
540 user: test
541 date: Thu Jan 01 00:00:00 1970 +0000
541 date: Thu Jan 01 00:00:00 1970 +0000
542 summary: 5
542 summary: 5
543
543
544 $ hg log -r 'origin(7)'
544 $ hg log -r 'origin(7)'
545 changeset: 2:5c095ad7e90f
545 changeset: 2:5c095ad7e90f
546 user: test
546 user: test
547 date: Thu Jan 01 00:00:00 1970 +0000
547 date: Thu Jan 01 00:00:00 1970 +0000
548 summary: 2
548 summary: 2
549
549
550 Now transplant a graft to test following through copies
550 Now transplant a graft to test following through copies
551 $ hg up -q 0
551 $ hg up -q 0
552 $ hg branch -q dev
552 $ hg branch -q dev
553 $ hg ci -qm "dev branch"
553 $ hg ci -qm "dev branch"
554 $ hg --config extensions.transplant= transplant -q 7
554 $ hg --config extensions.transplant= transplant -q 7
555 $ hg log -r 'origin(.)'
555 $ hg log -r 'origin(.)'
556 changeset: 2:5c095ad7e90f
556 changeset: 2:5c095ad7e90f
557 user: test
557 user: test
558 date: Thu Jan 01 00:00:00 1970 +0000
558 date: Thu Jan 01 00:00:00 1970 +0000
559 summary: 2
559 summary: 2
560
560
561 Test that the graft and transplant markers in extra are converted, allowing
561 Test that the graft and transplant markers in extra are converted, allowing
562 origin() to still work. Note that these recheck the immediately preceeding two
562 origin() to still work. Note that these recheck the immediately preceeding two
563 tests.
563 tests.
564 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
564 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
565
565
566 The graft case
566 The graft case
567 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
567 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
568 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
568 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
569 branch=default
569 branch=default
570 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
570 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
571 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
571 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
572 $ hg -R ../converted log -r 'origin(7)'
572 $ hg -R ../converted log -r 'origin(7)'
573 changeset: 2:e0213322b2c1
573 changeset: 2:e0213322b2c1
574 user: test
574 user: test
575 date: Thu Jan 01 00:00:00 1970 +0000
575 date: Thu Jan 01 00:00:00 1970 +0000
576 summary: 2
576 summary: 2
577
577
578 Test that template correctly expands more than one 'extra' (issue4362), and that
578 Test that template correctly expands more than one 'extra' (issue4362), and that
579 'intermediate-source' is converted.
579 'intermediate-source' is converted.
580 $ hg -R ../converted log -r 13 --template "{extras % ' Extra: {extra}\n'}"
580 $ hg -R ../converted log -r 13 --template "{extras % ' Extra: {extra}\n'}"
581 Extra: branch=default
581 Extra: branch=default
582 Extra: convert_revision=7a4785234d87ec1aa420ed6b11afe40fa73e12a9
582 Extra: convert_revision=7a4785234d87ec1aa420ed6b11afe40fa73e12a9
583 Extra: intermediate-source=7ae846e9111fc8f57745634250c7b9ac0a60689b
583 Extra: intermediate-source=7ae846e9111fc8f57745634250c7b9ac0a60689b
584 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
584 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
585
585
586 The transplant case
586 The transplant case
587 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
587 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
588 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
588 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
589 branch=dev
589 branch=dev
590 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
590 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
591 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
591 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
592 `h\x9b (esc)
592 `h\x9b (esc)
593 $ hg -R ../converted log -r 'origin(tip)'
593 $ hg -R ../converted log -r 'origin(tip)'
594 changeset: 2:e0213322b2c1
594 changeset: 2:e0213322b2c1
595 user: test
595 user: test
596 date: Thu Jan 01 00:00:00 1970 +0000
596 date: Thu Jan 01 00:00:00 1970 +0000
597 summary: 2
597 summary: 2
598
598
599
599
600 Test simple destination
600 Test simple destination
601 $ hg log -r 'destination()'
601 $ hg log -r 'destination()'
602 changeset: 7:ef0ef43d49e7
602 changeset: 7:ef0ef43d49e7
603 parent: 0:68795b066622
603 parent: 0:68795b066622
604 user: foo
604 user: foo
605 date: Thu Jan 01 00:00:00 1970 +0000
605 date: Thu Jan 01 00:00:00 1970 +0000
606 summary: 2
606 summary: 2
607
607
608 changeset: 8:6b9e5368ca4e
608 changeset: 8:6b9e5368ca4e
609 user: bar
609 user: bar
610 date: Thu Jan 01 00:00:00 1970 +0000
610 date: Thu Jan 01 00:00:00 1970 +0000
611 summary: 1
611 summary: 1
612
612
613 changeset: 9:1905859650ec
613 changeset: 9:1905859650ec
614 user: test
614 user: test
615 date: Thu Jan 01 00:00:00 1970 +0000
615 date: Thu Jan 01 00:00:00 1970 +0000
616 summary: 5
616 summary: 5
617
617
618 changeset: 10:52dc0b4c6907
618 changeset: 10:52dc0b4c6907
619 user: test
619 user: test
620 date: Thu Jan 01 00:00:00 1970 +0000
620 date: Thu Jan 01 00:00:00 1970 +0000
621 summary: 4
621 summary: 4
622
622
623 changeset: 11:882b35362a6b
623 changeset: 11:882b35362a6b
624 user: test
624 user: test
625 date: Thu Jan 01 00:00:00 1970 +0000
625 date: Thu Jan 01 00:00:00 1970 +0000
626 summary: 3
626 summary: 3
627
627
628 changeset: 13:7a4785234d87
628 changeset: 13:7a4785234d87
629 user: foo
629 user: foo
630 date: Thu Jan 01 00:00:00 1970 +0000
630 date: Thu Jan 01 00:00:00 1970 +0000
631 summary: 2
631 summary: 2
632
632
633 changeset: 14:0c921c65ef1e
633 changeset: 14:0c921c65ef1e
634 parent: 1:5d205f8b35b6
634 parent: 1:5d205f8b35b6
635 user: foo
635 user: foo
636 date: Thu Jan 01 00:00:00 1970 +0000
636 date: Thu Jan 01 00:00:00 1970 +0000
637 summary: 3
637 summary: 3
638
638
639 changeset: 17:f67661df0c48
639 changeset: 17:f67661df0c48
640 user: bar
640 user: bar
641 date: Thu Jan 01 00:00:00 1970 +0000
641 date: Thu Jan 01 00:00:00 1970 +0000
642 summary: 1
642 summary: 1
643
643
644 changeset: 19:9627f653b421
644 changeset: 19:9627f653b421
645 user: test
645 user: test
646 date: Thu Jan 01 00:00:00 1970 +0000
646 date: Thu Jan 01 00:00:00 1970 +0000
647 summary: 2
647 summary: 2
648
648
649 changeset: 21:7e61b508e709
649 changeset: 21:7e61b508e709
650 branch: dev
650 branch: dev
651 tag: tip
651 tag: tip
652 user: foo
652 user: foo
653 date: Thu Jan 01 00:00:00 1970 +0000
653 date: Thu Jan 01 00:00:00 1970 +0000
654 summary: 2
654 summary: 2
655
655
656 $ hg log -r 'destination(2)'
656 $ hg log -r 'destination(2)'
657 changeset: 7:ef0ef43d49e7
657 changeset: 7:ef0ef43d49e7
658 parent: 0:68795b066622
658 parent: 0:68795b066622
659 user: foo
659 user: foo
660 date: Thu Jan 01 00:00:00 1970 +0000
660 date: Thu Jan 01 00:00:00 1970 +0000
661 summary: 2
661 summary: 2
662
662
663 changeset: 13:7a4785234d87
663 changeset: 13:7a4785234d87
664 user: foo
664 user: foo
665 date: Thu Jan 01 00:00:00 1970 +0000
665 date: Thu Jan 01 00:00:00 1970 +0000
666 summary: 2
666 summary: 2
667
667
668 changeset: 19:9627f653b421
668 changeset: 19:9627f653b421
669 user: test
669 user: test
670 date: Thu Jan 01 00:00:00 1970 +0000
670 date: Thu Jan 01 00:00:00 1970 +0000
671 summary: 2
671 summary: 2
672
672
673 changeset: 21:7e61b508e709
673 changeset: 21:7e61b508e709
674 branch: dev
674 branch: dev
675 tag: tip
675 tag: tip
676 user: foo
676 user: foo
677 date: Thu Jan 01 00:00:00 1970 +0000
677 date: Thu Jan 01 00:00:00 1970 +0000
678 summary: 2
678 summary: 2
679
679
680 Transplants of grafts can find a destination...
680 Transplants of grafts can find a destination...
681 $ hg log -r 'destination(7)'
681 $ hg log -r 'destination(7)'
682 changeset: 21:7e61b508e709
682 changeset: 21:7e61b508e709
683 branch: dev
683 branch: dev
684 tag: tip
684 tag: tip
685 user: foo
685 user: foo
686 date: Thu Jan 01 00:00:00 1970 +0000
686 date: Thu Jan 01 00:00:00 1970 +0000
687 summary: 2
687 summary: 2
688
688
689 ... grafts of grafts unfortunately can't
689 ... grafts of grafts unfortunately can't
690 $ hg graft -q 13
690 $ hg graft -q 13
691 warning: can't find ancestor for 'b' copied from 'a'!
691 warning: can't find ancestor for 'b' copied from 'a'!
692 $ hg log -r 'destination(13)'
692 $ hg log -r 'destination(13)'
693 All copies of a cset
693 All copies of a cset
694 $ hg log -r 'origin(13) or destination(origin(13))'
694 $ hg log -r 'origin(13) or destination(origin(13))'
695 changeset: 2:5c095ad7e90f
695 changeset: 2:5c095ad7e90f
696 user: test
696 user: test
697 date: Thu Jan 01 00:00:00 1970 +0000
697 date: Thu Jan 01 00:00:00 1970 +0000
698 summary: 2
698 summary: 2
699
699
700 changeset: 7:ef0ef43d49e7
700 changeset: 7:ef0ef43d49e7
701 parent: 0:68795b066622
701 parent: 0:68795b066622
702 user: foo
702 user: foo
703 date: Thu Jan 01 00:00:00 1970 +0000
703 date: Thu Jan 01 00:00:00 1970 +0000
704 summary: 2
704 summary: 2
705
705
706 changeset: 13:7a4785234d87
706 changeset: 13:7a4785234d87
707 user: foo
707 user: foo
708 date: Thu Jan 01 00:00:00 1970 +0000
708 date: Thu Jan 01 00:00:00 1970 +0000
709 summary: 2
709 summary: 2
710
710
711 changeset: 19:9627f653b421
711 changeset: 19:9627f653b421
712 user: test
712 user: test
713 date: Thu Jan 01 00:00:00 1970 +0000
713 date: Thu Jan 01 00:00:00 1970 +0000
714 summary: 2
714 summary: 2
715
715
716 changeset: 21:7e61b508e709
716 changeset: 21:7e61b508e709
717 branch: dev
717 branch: dev
718 user: foo
718 user: foo
719 date: Thu Jan 01 00:00:00 1970 +0000
719 date: Thu Jan 01 00:00:00 1970 +0000
720 summary: 2
720 summary: 2
721
721
722 changeset: 22:d1cb6591fa4b
722 changeset: 22:d1cb6591fa4b
723 branch: dev
723 branch: dev
724 tag: tip
724 tag: tip
725 user: foo
725 user: foo
726 date: Thu Jan 01 00:00:00 1970 +0000
726 date: Thu Jan 01 00:00:00 1970 +0000
727 summary: 2
727 summary: 2
728
728
729
729
730 graft works on complex revset
730 graft works on complex revset
731
731
732 $ hg graft 'origin(13) or destination(origin(13))'
732 $ hg graft 'origin(13) or destination(origin(13))'
733 skipping ancestor revision 21:7e61b508e709
733 skipping ancestor revision 21:7e61b508e709
734 skipping ancestor revision 22:d1cb6591fa4b
734 skipping ancestor revision 22:d1cb6591fa4b
735 skipping revision 2:5c095ad7e90f (already grafted to 22:d1cb6591fa4b)
735 skipping revision 2:5c095ad7e90f (already grafted to 22:d1cb6591fa4b)
736 grafting 7:ef0ef43d49e7 "2"
736 grafting 7:ef0ef43d49e7 "2"
737 warning: can't find ancestor for 'b' copied from 'a'!
737 warning: can't find ancestor for 'b' copied from 'a'!
738 grafting 13:7a4785234d87 "2"
738 grafting 13:7a4785234d87 "2"
739 warning: can't find ancestor for 'b' copied from 'a'!
739 warning: can't find ancestor for 'b' copied from 'a'!
740 grafting 19:9627f653b421 "2"
740 grafting 19:9627f653b421 "2"
741 merging b
741 merging b
742 warning: can't find ancestor for 'b' copied from 'a'!
742 warning: can't find ancestor for 'b' copied from 'a'!
743
743
744 graft with --force (still doesn't graft merges)
744 graft with --force (still doesn't graft merges)
745
745
746 $ hg graft 19 0 6
746 $ hg graft 19 0 6
747 skipping ungraftable merge revision 6
747 skipping ungraftable merge revision 6
748 skipping ancestor revision 0:68795b066622
748 skipping ancestor revision 0:68795b066622
749 skipping already grafted revision 19:9627f653b421 (22:d1cb6591fa4b also has origin 2:5c095ad7e90f)
749 skipping already grafted revision 19:9627f653b421 (22:d1cb6591fa4b also has origin 2:5c095ad7e90f)
750 [255]
750 [255]
751 $ hg graft 19 0 6 --force
751 $ hg graft 19 0 6 --force
752 skipping ungraftable merge revision 6
752 skipping ungraftable merge revision 6
753 grafting 19:9627f653b421 "2"
753 grafting 19:9627f653b421 "2"
754 merging b
754 merging b
755 warning: can't find ancestor for 'b' copied from 'a'!
755 warning: can't find ancestor for 'b' copied from 'a'!
756 grafting 0:68795b066622 "0"
756 grafting 0:68795b066622 "0"
757
757
758 graft --force after backout
758 graft --force after backout
759
759
760 $ echo abc > a
760 $ echo abc > a
761 $ hg ci -m 28
761 $ hg ci -m 28
762 $ hg backout 28
762 $ hg backout 28
763 reverting a
763 reverting a
764 changeset 29:53177ba928f6 backs out changeset 28:50a516bb8b57
764 changeset 29:53177ba928f6 backs out changeset 28:50a516bb8b57
765 $ hg graft 28
765 $ hg graft 28
766 skipping ancestor revision 28:50a516bb8b57
766 skipping ancestor revision 28:50a516bb8b57
767 [255]
767 [255]
768 $ hg graft 28 --force
768 $ hg graft 28 --force
769 grafting 28:50a516bb8b57 "28"
769 grafting 28:50a516bb8b57 "28"
770 merging a
770 merging a
771 $ cat a
771 $ cat a
772 abc
772 abc
773
773
774 graft --continue after --force
774 graft --continue after --force
775
775
776 $ echo def > a
776 $ echo def > a
777 $ hg ci -m 31
777 $ hg ci -m 31
778 $ hg graft 28 --force --tool internal:fail
778 $ hg graft 28 --force --tool internal:fail
779 grafting 28:50a516bb8b57 "28"
779 grafting 28:50a516bb8b57 "28"
780 abort: unresolved conflicts, can't continue
780 abort: unresolved conflicts, can't continue
781 (use 'hg resolve' and 'hg graft --continue')
781 (use 'hg resolve' and 'hg graft --continue')
782 [255]
782 [255]
783 $ hg resolve --all
783 $ hg resolve --all
784 merging a
784 merging a
785 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
785 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
786 [1]
786 [1]
787 $ echo abc > a
787 $ echo abc > a
788 $ hg resolve -m a
788 $ hg resolve -m a
789 (no more unresolved files)
789 (no more unresolved files)
790 continue: hg graft --continue
790 continue: hg graft --continue
791 $ hg graft -c
791 $ hg graft -c
792 grafting 28:50a516bb8b57 "28"
792 grafting 28:50a516bb8b57 "28"
793 $ cat a
793 $ cat a
794 abc
794 abc
795
795
796 Continue testing same origin policy, using revision numbers from test above
796 Continue testing same origin policy, using revision numbers from test above
797 but do some destructive editing of the repo:
797 but do some destructive editing of the repo:
798
798
799 $ hg up -qC 7
799 $ hg up -qC 7
800 $ hg tag -l -r 13 tmp
800 $ hg tag -l -r 13 tmp
801 $ hg --config extensions.strip= strip 2
801 $ hg --config extensions.strip= strip 2
802 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg (glob)
802 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg (glob)
803 $ hg graft tmp
803 $ hg graft tmp
804 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
804 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
805 [255]
805 [255]
806
806
807 Empty graft
807 Empty graft
808
808
809 $ hg up -qr 26
809 $ hg up -qr 26
810 $ hg tag -f something
810 $ hg tag -f something
811 $ hg graft -qr 27
811 $ hg graft -qr 27
812 $ hg graft -f 27
812 $ hg graft -f 27
813 grafting 27:ed6c7e54e319 "28"
813 grafting 27:ed6c7e54e319 "28"
814 note: graft of 27:ed6c7e54e319 created no changes to commit
814 note: graft of 27:ed6c7e54e319 created no changes to commit
815
815
816 $ cd ..
816 $ cd ..
817
817
818 Graft to duplicate a commit
818 Graft to duplicate a commit
819
819
820 $ hg init graftsibling
820 $ hg init graftsibling
821 $ cd graftsibling
821 $ cd graftsibling
822 $ touch a
822 $ touch a
823 $ hg commit -qAm a
823 $ hg commit -qAm a
824 $ touch b
824 $ touch b
825 $ hg commit -qAm b
825 $ hg commit -qAm b
826 $ hg log -G -T '{rev}\n'
826 $ hg log -G -T '{rev}\n'
827 @ 1
827 @ 1
828 |
828 |
829 o 0
829 o 0
830
830
831 $ hg up -q 0
831 $ hg up -q 0
832 $ hg graft -r 1
832 $ hg graft -r 1
833 grafting 1:0e067c57feba "b" (tip)
833 grafting 1:0e067c57feba "b" (tip)
834 $ hg log -G -T '{rev}\n'
834 $ hg log -G -T '{rev}\n'
835 @ 2
835 @ 2
836 |
836 |
837 | o 1
837 | o 1
838 |/
838 |/
839 o 0
839 o 0
840
840
841 Graft to duplicate a commit twice
841 Graft to duplicate a commit twice
842
842
843 $ hg up -q 0
843 $ hg up -q 0
844 $ hg graft -r 2
844 $ hg graft -r 2
845 grafting 2:044ec77f6389 "b" (tip)
845 grafting 2:044ec77f6389 "b" (tip)
846 $ hg log -G -T '{rev}\n'
846 $ hg log -G -T '{rev}\n'
847 @ 3
847 @ 3
848 |
848 |
849 | o 2
849 | o 2
850 |/
850 |/
851 | o 1
851 | o 1
852 |/
852 |/
853 o 0
853 o 0
854
854
855 Graft from behind a move or rename
855 Graft from behind a move or rename
856 ==================================
856 ==================================
857
857
858 NOTE: This is affected by issue5343, and will need updating when it's fixed
858 NOTE: This is affected by issue5343, and will need updating when it's fixed
859
859
860 Possible cases during a regular graft (when ca is between cta and c2):
860 Possible cases during a regular graft (when ca is between cta and c2):
861
861
862 name | c1<-cta | cta<->ca | ca->c2
862 name | c1<-cta | cta<->ca | ca->c2
863 A.0 | | |
863 A.0 | | |
864 A.1 | X | |
864 A.1 | X | |
865 A.2 | | X |
865 A.2 | | X |
866 A.3 | | | X
866 A.3 | | | X
867 A.4 | X | X |
867 A.4 | X | X |
868 A.5 | X | | X
868 A.5 | X | | X
869 A.6 | | X | X
869 A.6 | | X | X
870 A.7 | X | X | X
870 A.7 | X | X | X
871
871
872 A.0 is trivial, and doesn't need copy tracking.
872 A.0 is trivial, and doesn't need copy tracking.
873 For A.1, a forward rename is recorded in the c1 pass, to be followed later.
873 For A.1, a forward rename is recorded in the c1 pass, to be followed later.
874 In A.2, the rename is recorded in the c2 pass and followed backwards.
874 In A.2, the rename is recorded in the c2 pass and followed backwards.
875 A.3 is recorded in the c2 pass as a forward rename to be duplicated on target.
875 A.3 is recorded in the c2 pass as a forward rename to be duplicated on target.
876 In A.4, both passes of checkcopies record incomplete renames, which are
876 In A.4, both passes of checkcopies record incomplete renames, which are
877 then joined in mergecopies to record a rename to be followed.
877 then joined in mergecopies to record a rename to be followed.
878 In A.5 and A.7, the c1 pass records an incomplete rename, while the c2 pass
878 In A.5 and A.7, the c1 pass records an incomplete rename, while the c2 pass
879 records an incomplete divergence. The incomplete rename is then joined to the
879 records an incomplete divergence. The incomplete rename is then joined to the
880 appropriate side of the incomplete divergence, and the result is recorded as a
880 appropriate side of the incomplete divergence, and the result is recorded as a
881 divergence. The code doesn't distinguish at all between these two cases, since
881 divergence. The code doesn't distinguish at all between these two cases, since
882 the end result of them is the same: an incomplete divergence joined with an
882 the end result of them is the same: an incomplete divergence joined with an
883 incomplete rename into a divergence.
883 incomplete rename into a divergence.
884 Finally, A.6 records a divergence entirely in the c2 pass.
884 Finally, A.6 records a divergence entirely in the c2 pass.
885
885
886 A.4 has a degenerate case a<-b<-a->a, where checkcopies isn't needed at all.
886 A.4 has a degenerate case a<-b<-a->a, where checkcopies isn't needed at all.
887 A.5 has a special case a<-b<-b->a, which is treated like a<-b->a in a merge.
887 A.5 has a special case a<-b<-b->a, which is treated like a<-b->a in a merge.
888 A.6 has a special case a<-a<-b->a. Here, checkcopies will find a spurious
888 A.6 has a special case a<-a<-b->a. Here, checkcopies will find a spurious
889 incomplete divergence, which is in fact complete. This is handled later in
889 incomplete divergence, which is in fact complete. This is handled later in
890 mergecopies.
890 mergecopies.
891 A.7 has 4 special cases: a<-b<-a->b (the "ping-pong" case), a<-b<-c->b,
891 A.7 has 4 special cases: a<-b<-a->b (the "ping-pong" case), a<-b<-c->b,
892 a<-b<-a->c and a<-b<-c->a. Of these, only the "ping-pong" case is interesting,
892 a<-b<-a->c and a<-b<-c->a. Of these, only the "ping-pong" case is interesting,
893 the others are fairly trivial (a<-b<-c->b and a<-b<-a->c proceed like the base
893 the others are fairly trivial (a<-b<-c->b and a<-b<-a->c proceed like the base
894 case, a<-b<-c->a is treated the same as a<-b<-b->a).
894 case, a<-b<-c->a is treated the same as a<-b<-b->a).
895
895
896 f5a therefore tests the "ping-pong" rename case, where a file is renamed to the
896 f5a therefore tests the "ping-pong" rename case, where a file is renamed to the
897 same name on both branches, then the rename is backed out on one branch, and
897 same name on both branches, then the rename is backed out on one branch, and
898 the backout is grafted to the other branch. This creates a challenging rename
898 the backout is grafted to the other branch. This creates a challenging rename
899 sequence of a<-b<-a->b in the graft target, topological CA, graft CA and graft
899 sequence of a<-b<-a->b in the graft target, topological CA, graft CA and graft
900 source, respectively. Since rename detection will run on the c1 side for such a
900 source, respectively. Since rename detection will run on the c1 side for such a
901 sequence (as for technical reasons, we split the c1 and c2 sides not at the
901 sequence (as for technical reasons, we split the c1 and c2 sides not at the
902 graft CA, but rather at the topological CA), it will pick up a false rename,
902 graft CA, but rather at the topological CA), it will pick up a false rename,
903 and cause a spurious merge conflict. This false rename is always exactly the
903 and cause a spurious merge conflict. This false rename is always exactly the
904 reverse of the true rename that would be detected on the c2 side, so we can
904 reverse of the true rename that would be detected on the c2 side, so we can
905 correct for it by detecting this condition and reversing as necessary.
905 correct for it by detecting this condition and reversing as necessary.
906
906
907 First, set up the repository with commits to be grafted
907 First, set up the repository with commits to be grafted
908
908
909 $ hg init ../graftmove
909 $ hg init ../graftmove
910 $ cd ../graftmove
910 $ cd ../graftmove
911 $ echo c1a > f1a
911 $ echo c1a > f1a
912 $ echo c2a > f2a
912 $ echo c2a > f2a
913 $ echo c3a > f3a
913 $ echo c3a > f3a
914 $ echo c4a > f4a
914 $ echo c4a > f4a
915 $ echo c5a > f5a
915 $ echo c5a > f5a
916 $ hg ci -qAm A0
916 $ hg ci -qAm A0
917 $ hg mv f1a f1b
917 $ hg mv f1a f1b
918 $ hg mv f3a f3b
918 $ hg mv f3a f3b
919 $ hg mv f5a f5b
919 $ hg mv f5a f5b
920 $ hg ci -qAm B0
920 $ hg ci -qAm B0
921 $ echo c1c > f1b
921 $ echo c1c > f1b
922 $ hg mv f2a f2c
922 $ hg mv f2a f2c
923 $ hg mv f5b f5a
923 $ hg mv f5b f5a
924 $ echo c5c > f5a
924 $ echo c5c > f5a
925 $ hg ci -qAm C0
925 $ hg ci -qAm C0
926 $ hg mv f3b f3d
926 $ hg mv f3b f3d
927 $ echo c4d > f4a
927 $ echo c4d > f4a
928 $ hg ci -qAm D0
928 $ hg ci -qAm D0
929 $ hg log -G
929 $ hg log -G
930 @ changeset: 3:b69f5839d2d9
930 @ changeset: 3:b69f5839d2d9
931 | tag: tip
931 | tag: tip
932 | user: test
932 | user: test
933 | date: Thu Jan 01 00:00:00 1970 +0000
933 | date: Thu Jan 01 00:00:00 1970 +0000
934 | summary: D0
934 | summary: D0
935 |
935 |
936 o changeset: 2:f58c7e2b28fa
936 o changeset: 2:f58c7e2b28fa
937 | user: test
937 | user: test
938 | date: Thu Jan 01 00:00:00 1970 +0000
938 | date: Thu Jan 01 00:00:00 1970 +0000
939 | summary: C0
939 | summary: C0
940 |
940 |
941 o changeset: 1:3d7bba921b5d
941 o changeset: 1:3d7bba921b5d
942 | user: test
942 | user: test
943 | date: Thu Jan 01 00:00:00 1970 +0000
943 | date: Thu Jan 01 00:00:00 1970 +0000
944 | summary: B0
944 | summary: B0
945 |
945 |
946 o changeset: 0:11f7a1b56675
946 o changeset: 0:11f7a1b56675
947 user: test
947 user: test
948 date: Thu Jan 01 00:00:00 1970 +0000
948 date: Thu Jan 01 00:00:00 1970 +0000
949 summary: A0
949 summary: A0
950
950
951
951
952 Test the cases A.2 (f1x), A.3 (f2x) and a special case of A.6 (f5x) where the
952 Test the cases A.2 (f1x), A.3 (f2x) and a special case of A.6 (f5x) where the
953 two renames actually converge to the same name (thus no actual divergence).
953 two renames actually converge to the same name (thus no actual divergence).
954
954
955 $ hg up -q 'desc("A0")'
955 $ hg up -q 'desc("A0")'
956 $ HGEDITOR="echo C1 >" hg graft -r 'desc("C0")' --edit
956 $ HGEDITOR="echo C1 >" hg graft -r 'desc("C0")' --edit
957 grafting 2:f58c7e2b28fa "C0"
957 grafting 2:f58c7e2b28fa "C0"
958 merging f1a and f1b to f1a
958 merging f1a and f1b to f1a
959 merging f5a
959 merging f5a
960 warning: conflicts while merging f5a! (edit, then use 'hg resolve --mark')
960 warning: conflicts while merging f5a! (edit, then use 'hg resolve --mark')
961 abort: unresolved conflicts, can't continue
961 abort: unresolved conflicts, can't continue
962 (use 'hg resolve' and 'hg graft --continue')
962 (use 'hg resolve' and 'hg graft --continue')
963 [255]
963 [255]
964 $ hg resolve f5a -t ':other' # XXX work around failure
964 $ hg resolve f5a -t ':other' # XXX work around failure
965 (no more unresolved files)
965 (no more unresolved files)
966 continue: hg graft --continue
966 continue: hg graft --continue
967 $ hg graft --continue # XXX work around failure
967 $ hg graft --continue # XXX work around failure
968 grafting 2:f58c7e2b28fa "C0"
968 grafting 2:f58c7e2b28fa "C0"
969 warning: can't find ancestor for 'f5a' copied from 'f5b'!
969 warning: can't find ancestor for 'f5a' copied from 'f5b'!
970 $ hg status --change .
970 $ hg status --change .
971 M f1a
971 M f1a
972 M f5a
972 M f5a
973 A f2c
973 A f2c
974 R f2a
974 R f2a
975 $ hg cat f1a
975 $ hg cat f1a
976 c1c
976 c1c
977 $ hg cat f1b
977 $ hg cat f1b
978 f1b: no such file in rev 43e4b415492d
978 f1b: no such file in rev 43e4b415492d
979 [1]
979 [1]
980
980
981 Test the cases A.0 (f4x) and A.6 (f3x)
981 Test the cases A.0 (f4x) and A.6 (f3x)
982
982
983 $ HGEDITOR="echo D1 >" hg graft -r 'desc("D0")' --edit
983 $ HGEDITOR="echo D1 >" hg graft -r 'desc("D0")' --edit
984 grafting 3:b69f5839d2d9 "D0"
984 grafting 3:b69f5839d2d9 "D0"
985 note: possible conflict - f3b was renamed multiple times to:
986 f3d
987 f3a
985 warning: can't find ancestor for 'f3d' copied from 'f3b'!
988 warning: can't find ancestor for 'f3d' copied from 'f3b'!
986
989
987 Set up the repository for some further tests
990 Set up the repository for some further tests
988
991
989 $ hg up -q "min(desc("A0"))"
992 $ hg up -q "min(desc("A0"))"
990 $ hg mv f1a f1e
993 $ hg mv f1a f1e
991 $ echo c2e > f2a
994 $ echo c2e > f2a
992 $ hg mv f3a f3e
995 $ hg mv f3a f3e
993 $ hg mv f4a f4e
996 $ hg mv f4a f4e
994 $ hg mv f5a f5b
997 $ hg mv f5a f5b
995 $ hg ci -qAm "E0"
998 $ hg ci -qAm "E0"
996 $ hg log -G
999 $ hg log -G
997 @ changeset: 6:ebba59d1fb02
1000 @ changeset: 6:ebba59d1fb02
998 | tag: tip
1001 | tag: tip
999 | parent: 0:11f7a1b56675
1002 | parent: 0:11f7a1b56675
1000 | user: test
1003 | user: test
1001 | date: Thu Jan 01 00:00:00 1970 +0000
1004 | date: Thu Jan 01 00:00:00 1970 +0000
1002 | summary: E0
1005 | summary: E0
1003 |
1006 |
1004 | o changeset: 5:4f4ba7a6e606
1007 | o changeset: 5:4f4ba7a6e606
1005 | | user: test
1008 | | user: test
1006 | | date: Thu Jan 01 00:00:00 1970 +0000
1009 | | date: Thu Jan 01 00:00:00 1970 +0000
1007 | | summary: D1
1010 | | summary: D1
1008 | |
1011 | |
1009 | o changeset: 4:43e4b415492d
1012 | o changeset: 4:43e4b415492d
1010 |/ parent: 0:11f7a1b56675
1013 |/ parent: 0:11f7a1b56675
1011 | user: test
1014 | user: test
1012 | date: Thu Jan 01 00:00:00 1970 +0000
1015 | date: Thu Jan 01 00:00:00 1970 +0000
1013 | summary: C0
1016 | summary: C0
1014 |
1017 |
1015 | o changeset: 3:b69f5839d2d9
1018 | o changeset: 3:b69f5839d2d9
1016 | | user: test
1019 | | user: test
1017 | | date: Thu Jan 01 00:00:00 1970 +0000
1020 | | date: Thu Jan 01 00:00:00 1970 +0000
1018 | | summary: D0
1021 | | summary: D0
1019 | |
1022 | |
1020 | o changeset: 2:f58c7e2b28fa
1023 | o changeset: 2:f58c7e2b28fa
1021 | | user: test
1024 | | user: test
1022 | | date: Thu Jan 01 00:00:00 1970 +0000
1025 | | date: Thu Jan 01 00:00:00 1970 +0000
1023 | | summary: C0
1026 | | summary: C0
1024 | |
1027 | |
1025 | o changeset: 1:3d7bba921b5d
1028 | o changeset: 1:3d7bba921b5d
1026 |/ user: test
1029 |/ user: test
1027 | date: Thu Jan 01 00:00:00 1970 +0000
1030 | date: Thu Jan 01 00:00:00 1970 +0000
1028 | summary: B0
1031 | summary: B0
1029 |
1032 |
1030 o changeset: 0:11f7a1b56675
1033 o changeset: 0:11f7a1b56675
1031 user: test
1034 user: test
1032 date: Thu Jan 01 00:00:00 1970 +0000
1035 date: Thu Jan 01 00:00:00 1970 +0000
1033 summary: A0
1036 summary: A0
1034
1037
1035
1038
1036 Test the cases A.4 (f1x), the "ping-pong" special case of A.7 (f5x),
1039 Test the cases A.4 (f1x), the "ping-pong" special case of A.7 (f5x),
1037 and A.3 with a local content change to be preserved (f2x).
1040 and A.3 with a local content change to be preserved (f2x).
1038
1041
1039 $ HGEDITOR="echo C2 >" hg graft -r 'desc("C0")' --edit
1042 $ HGEDITOR="echo C2 >" hg graft -r 'desc("C0")' --edit
1040 grafting 2:f58c7e2b28fa "C0"
1043 grafting 2:f58c7e2b28fa "C0"
1041 other [graft] changed f1b which local [local] deleted
1044 other [graft] changed f1b which local [local] deleted
1042 use (c)hanged version, leave (d)eleted, or leave (u)nresolved? u
1045 use (c)hanged version, leave (d)eleted, or leave (u)nresolved? u
1043 merging f2a and f2c to f2c
1046 merging f2a and f2c to f2c
1044 merging f5b and f5a to f5a
1047 merging f5b and f5a to f5a
1045 abort: unresolved conflicts, can't continue
1048 abort: unresolved conflicts, can't continue
1046 (use 'hg resolve' and 'hg graft --continue')
1049 (use 'hg resolve' and 'hg graft --continue')
1047 [255]
1050 [255]
1048 $ hg resolve f1b -t ':other' # XXX work around failure
1051 $ hg resolve f1b -t ':other' # XXX work around failure
1049 (no more unresolved files)
1052 (no more unresolved files)
1050 continue: hg graft --continue
1053 continue: hg graft --continue
1051 $ hg graft --continue # XXX work around failure
1054 $ hg graft --continue # XXX work around failure
1052 grafting 2:f58c7e2b28fa "C0"
1055 grafting 2:f58c7e2b28fa "C0"
1053 grafting 4:43e4b415492d "C0"
1056 grafting 4:43e4b415492d "C0"
1054 merging f1e and f1a to f1e
1057 merging f1e and f1a to f1e
1055 merging f2c
1058 merging f2c
1056 warning: can't find ancestor for 'f2c' copied from 'f2a'!
1059 warning: can't find ancestor for 'f2c' copied from 'f2a'!
1057
1060
1058 Test the cases A.1 (f4x) and A.7 (f3x).
1061 Test the cases A.1 (f4x) and A.7 (f3x).
1059
1062
1060 $ HGEDITOR="echo D2 >" hg graft -r 'desc("D0")' --edit
1063 $ HGEDITOR="echo D2 >" hg graft -r 'desc("D0")' --edit
1061 grafting 3:b69f5839d2d9 "D0"
1064 grafting 3:b69f5839d2d9 "D0"
1062 merging f4e and f4a to f4e
1065 merging f4e and f4a to f4e
1063 warning: can't find ancestor for 'f3d' copied from 'f3b'!
1066 warning: can't find ancestor for 'f3d' copied from 'f3b'!
1064
1067
1065 Check the results of the grafts tested
1068 Check the results of the grafts tested
1066
1069
1067 $ hg log -CGv --patch --git
1070 $ hg log -CGv --patch --git
1068 @ changeset: 9:100f4d78e056
1071 @ changeset: 9:100f4d78e056
1069 | tag: tip
1072 | tag: tip
1070 | user: test
1073 | user: test
1071 | date: Thu Jan 01 00:00:00 1970 +0000
1074 | date: Thu Jan 01 00:00:00 1970 +0000
1072 | files: f3d f4e
1075 | files: f3d f4e
1073 | description:
1076 | description:
1074 | D2
1077 | D2
1075 |
1078 |
1076 |
1079 |
1077 | diff --git a/f3d b/f3d
1080 | diff --git a/f3d b/f3d
1078 | new file mode 100644
1081 | new file mode 100644
1079 | --- /dev/null
1082 | --- /dev/null
1080 | +++ b/f3d
1083 | +++ b/f3d
1081 | @@ -0,0 +1,1 @@
1084 | @@ -0,0 +1,1 @@
1082 | +c3a
1085 | +c3a
1083 | diff --git a/f4e b/f4e
1086 | diff --git a/f4e b/f4e
1084 | --- a/f4e
1087 | --- a/f4e
1085 | +++ b/f4e
1088 | +++ b/f4e
1086 | @@ -1,1 +1,1 @@
1089 | @@ -1,1 +1,1 @@
1087 | -c4a
1090 | -c4a
1088 | +c4d
1091 | +c4d
1089 |
1092 |
1090 o changeset: 8:84915a7da133
1093 o changeset: 8:84915a7da133
1091 | user: test
1094 | user: test
1092 | date: Thu Jan 01 00:00:00 1970 +0000
1095 | date: Thu Jan 01 00:00:00 1970 +0000
1093 | files: f1e f5a.orig
1096 | files: f1e f5a.orig
1094 | description:
1097 | description:
1095 | C0
1098 | C0
1096 |
1099 |
1097 |
1100 |
1098 | diff --git a/f1e b/f1e
1101 | diff --git a/f1e b/f1e
1099 | --- a/f1e
1102 | --- a/f1e
1100 | +++ b/f1e
1103 | +++ b/f1e
1101 | @@ -1,1 +1,1 @@
1104 | @@ -1,1 +1,1 @@
1102 | -c1a
1105 | -c1a
1103 | +c1c
1106 | +c1c
1104 | diff --git a/f5a.orig b/f5a.orig
1107 | diff --git a/f5a.orig b/f5a.orig
1105 | deleted file mode 100644
1108 | deleted file mode 100644
1106 | --- a/f5a.orig
1109 | --- a/f5a.orig
1107 | +++ /dev/null
1110 | +++ /dev/null
1108 | @@ -1,5 +0,0 @@
1111 | @@ -1,5 +0,0 @@
1109 | -<<<<<<< local: 11f7a1b56675 - test: A0
1112 | -<<<<<<< local: 11f7a1b56675 - test: A0
1110 | -c5a
1113 | -c5a
1111 | -=======
1114 | -=======
1112 | -c5c
1115 | -c5c
1113 | ->>>>>>> graft: f58c7e2b28fa - test: C0
1116 | ->>>>>>> graft: f58c7e2b28fa - test: C0
1114 |
1117 |
1115 o changeset: 7:dc778749ee9a
1118 o changeset: 7:dc778749ee9a
1116 | user: test
1119 | user: test
1117 | date: Thu Jan 01 00:00:00 1970 +0000
1120 | date: Thu Jan 01 00:00:00 1970 +0000
1118 | files: f1b f2a f2c f5a f5b
1121 | files: f1b f2a f2c f5a f5b
1119 | copies: f2c (f2a) f5a (f5b)
1122 | copies: f2c (f2a) f5a (f5b)
1120 | description:
1123 | description:
1121 | C0
1124 | C0
1122 |
1125 |
1123 |
1126 |
1124 | diff --git a/f1b b/f1b
1127 | diff --git a/f1b b/f1b
1125 | new file mode 100644
1128 | new file mode 100644
1126 | --- /dev/null
1129 | --- /dev/null
1127 | +++ b/f1b
1130 | +++ b/f1b
1128 | @@ -0,0 +1,1 @@
1131 | @@ -0,0 +1,1 @@
1129 | +c1c
1132 | +c1c
1130 | diff --git a/f2a b/f2c
1133 | diff --git a/f2a b/f2c
1131 | rename from f2a
1134 | rename from f2a
1132 | rename to f2c
1135 | rename to f2c
1133 | diff --git a/f5b b/f5a
1136 | diff --git a/f5b b/f5a
1134 | rename from f5b
1137 | rename from f5b
1135 | rename to f5a
1138 | rename to f5a
1136 | --- a/f5b
1139 | --- a/f5b
1137 | +++ b/f5a
1140 | +++ b/f5a
1138 | @@ -1,1 +1,1 @@
1141 | @@ -1,1 +1,1 @@
1139 | -c5a
1142 | -c5a
1140 | +c5c
1143 | +c5c
1141 |
1144 |
1142 o changeset: 6:ebba59d1fb02
1145 o changeset: 6:ebba59d1fb02
1143 | parent: 0:11f7a1b56675
1146 | parent: 0:11f7a1b56675
1144 | user: test
1147 | user: test
1145 | date: Thu Jan 01 00:00:00 1970 +0000
1148 | date: Thu Jan 01 00:00:00 1970 +0000
1146 | files: f1a f1e f2a f3a f3e f4a f4e f5a f5a.orig f5b
1149 | files: f1a f1e f2a f3a f3e f4a f4e f5a f5a.orig f5b
1147 | copies: f1e (f1a) f3e (f3a) f4e (f4a) f5b (f5a)
1150 | copies: f1e (f1a) f3e (f3a) f4e (f4a) f5b (f5a)
1148 | description:
1151 | description:
1149 | E0
1152 | E0
1150 |
1153 |
1151 |
1154 |
1152 | diff --git a/f1a b/f1e
1155 | diff --git a/f1a b/f1e
1153 | rename from f1a
1156 | rename from f1a
1154 | rename to f1e
1157 | rename to f1e
1155 | diff --git a/f2a b/f2a
1158 | diff --git a/f2a b/f2a
1156 | --- a/f2a
1159 | --- a/f2a
1157 | +++ b/f2a
1160 | +++ b/f2a
1158 | @@ -1,1 +1,1 @@
1161 | @@ -1,1 +1,1 @@
1159 | -c2a
1162 | -c2a
1160 | +c2e
1163 | +c2e
1161 | diff --git a/f3a b/f3e
1164 | diff --git a/f3a b/f3e
1162 | rename from f3a
1165 | rename from f3a
1163 | rename to f3e
1166 | rename to f3e
1164 | diff --git a/f4a b/f4e
1167 | diff --git a/f4a b/f4e
1165 | rename from f4a
1168 | rename from f4a
1166 | rename to f4e
1169 | rename to f4e
1167 | diff --git a/f5a.orig b/f5a.orig
1170 | diff --git a/f5a.orig b/f5a.orig
1168 | new file mode 100644
1171 | new file mode 100644
1169 | --- /dev/null
1172 | --- /dev/null
1170 | +++ b/f5a.orig
1173 | +++ b/f5a.orig
1171 | @@ -0,0 +1,5 @@
1174 | @@ -0,0 +1,5 @@
1172 | +<<<<<<< local: 11f7a1b56675 - test: A0
1175 | +<<<<<<< local: 11f7a1b56675 - test: A0
1173 | +c5a
1176 | +c5a
1174 | +=======
1177 | +=======
1175 | +c5c
1178 | +c5c
1176 | +>>>>>>> graft: f58c7e2b28fa - test: C0
1179 | +>>>>>>> graft: f58c7e2b28fa - test: C0
1177 | diff --git a/f5a b/f5b
1180 | diff --git a/f5a b/f5b
1178 | rename from f5a
1181 | rename from f5a
1179 | rename to f5b
1182 | rename to f5b
1180 |
1183 |
1181 | o changeset: 5:4f4ba7a6e606
1184 | o changeset: 5:4f4ba7a6e606
1182 | | user: test
1185 | | user: test
1183 | | date: Thu Jan 01 00:00:00 1970 +0000
1186 | | date: Thu Jan 01 00:00:00 1970 +0000
1184 | | files: f3d f4a
1187 | | files: f3d f4a
1185 | | description:
1188 | | description:
1186 | | D1
1189 | | D1
1187 | |
1190 | |
1188 | |
1191 | |
1189 | | diff --git a/f3d b/f3d
1192 | | diff --git a/f3d b/f3d
1190 | | new file mode 100644
1193 | | new file mode 100644
1191 | | --- /dev/null
1194 | | --- /dev/null
1192 | | +++ b/f3d
1195 | | +++ b/f3d
1193 | | @@ -0,0 +1,1 @@
1196 | | @@ -0,0 +1,1 @@
1194 | | +c3a
1197 | | +c3a
1195 | | diff --git a/f4a b/f4a
1198 | | diff --git a/f4a b/f4a
1196 | | --- a/f4a
1199 | | --- a/f4a
1197 | | +++ b/f4a
1200 | | +++ b/f4a
1198 | | @@ -1,1 +1,1 @@
1201 | | @@ -1,1 +1,1 @@
1199 | | -c4a
1202 | | -c4a
1200 | | +c4d
1203 | | +c4d
1201 | |
1204 | |
1202 | o changeset: 4:43e4b415492d
1205 | o changeset: 4:43e4b415492d
1203 |/ parent: 0:11f7a1b56675
1206 |/ parent: 0:11f7a1b56675
1204 | user: test
1207 | user: test
1205 | date: Thu Jan 01 00:00:00 1970 +0000
1208 | date: Thu Jan 01 00:00:00 1970 +0000
1206 | files: f1a f2a f2c f5a
1209 | files: f1a f2a f2c f5a
1207 | copies: f2c (f2a)
1210 | copies: f2c (f2a)
1208 | description:
1211 | description:
1209 | C0
1212 | C0
1210 |
1213 |
1211 |
1214 |
1212 | diff --git a/f1a b/f1a
1215 | diff --git a/f1a b/f1a
1213 | --- a/f1a
1216 | --- a/f1a
1214 | +++ b/f1a
1217 | +++ b/f1a
1215 | @@ -1,1 +1,1 @@
1218 | @@ -1,1 +1,1 @@
1216 | -c1a
1219 | -c1a
1217 | +c1c
1220 | +c1c
1218 | diff --git a/f2a b/f2c
1221 | diff --git a/f2a b/f2c
1219 | rename from f2a
1222 | rename from f2a
1220 | rename to f2c
1223 | rename to f2c
1221 | diff --git a/f5a b/f5a
1224 | diff --git a/f5a b/f5a
1222 | --- a/f5a
1225 | --- a/f5a
1223 | +++ b/f5a
1226 | +++ b/f5a
1224 | @@ -1,1 +1,1 @@
1227 | @@ -1,1 +1,1 @@
1225 | -c5a
1228 | -c5a
1226 | +c5c
1229 | +c5c
1227 |
1230 |
1228 | o changeset: 3:b69f5839d2d9
1231 | o changeset: 3:b69f5839d2d9
1229 | | user: test
1232 | | user: test
1230 | | date: Thu Jan 01 00:00:00 1970 +0000
1233 | | date: Thu Jan 01 00:00:00 1970 +0000
1231 | | files: f3b f3d f4a
1234 | | files: f3b f3d f4a
1232 | | copies: f3d (f3b)
1235 | | copies: f3d (f3b)
1233 | | description:
1236 | | description:
1234 | | D0
1237 | | D0
1235 | |
1238 | |
1236 | |
1239 | |
1237 | | diff --git a/f3b b/f3d
1240 | | diff --git a/f3b b/f3d
1238 | | rename from f3b
1241 | | rename from f3b
1239 | | rename to f3d
1242 | | rename to f3d
1240 | | diff --git a/f4a b/f4a
1243 | | diff --git a/f4a b/f4a
1241 | | --- a/f4a
1244 | | --- a/f4a
1242 | | +++ b/f4a
1245 | | +++ b/f4a
1243 | | @@ -1,1 +1,1 @@
1246 | | @@ -1,1 +1,1 @@
1244 | | -c4a
1247 | | -c4a
1245 | | +c4d
1248 | | +c4d
1246 | |
1249 | |
1247 | o changeset: 2:f58c7e2b28fa
1250 | o changeset: 2:f58c7e2b28fa
1248 | | user: test
1251 | | user: test
1249 | | date: Thu Jan 01 00:00:00 1970 +0000
1252 | | date: Thu Jan 01 00:00:00 1970 +0000
1250 | | files: f1b f2a f2c f5a f5b
1253 | | files: f1b f2a f2c f5a f5b
1251 | | copies: f2c (f2a) f5a (f5b)
1254 | | copies: f2c (f2a) f5a (f5b)
1252 | | description:
1255 | | description:
1253 | | C0
1256 | | C0
1254 | |
1257 | |
1255 | |
1258 | |
1256 | | diff --git a/f1b b/f1b
1259 | | diff --git a/f1b b/f1b
1257 | | --- a/f1b
1260 | | --- a/f1b
1258 | | +++ b/f1b
1261 | | +++ b/f1b
1259 | | @@ -1,1 +1,1 @@
1262 | | @@ -1,1 +1,1 @@
1260 | | -c1a
1263 | | -c1a
1261 | | +c1c
1264 | | +c1c
1262 | | diff --git a/f2a b/f2c
1265 | | diff --git a/f2a b/f2c
1263 | | rename from f2a
1266 | | rename from f2a
1264 | | rename to f2c
1267 | | rename to f2c
1265 | | diff --git a/f5b b/f5a
1268 | | diff --git a/f5b b/f5a
1266 | | rename from f5b
1269 | | rename from f5b
1267 | | rename to f5a
1270 | | rename to f5a
1268 | | --- a/f5b
1271 | | --- a/f5b
1269 | | +++ b/f5a
1272 | | +++ b/f5a
1270 | | @@ -1,1 +1,1 @@
1273 | | @@ -1,1 +1,1 @@
1271 | | -c5a
1274 | | -c5a
1272 | | +c5c
1275 | | +c5c
1273 | |
1276 | |
1274 | o changeset: 1:3d7bba921b5d
1277 | o changeset: 1:3d7bba921b5d
1275 |/ user: test
1278 |/ user: test
1276 | date: Thu Jan 01 00:00:00 1970 +0000
1279 | date: Thu Jan 01 00:00:00 1970 +0000
1277 | files: f1a f1b f3a f3b f5a f5b
1280 | files: f1a f1b f3a f3b f5a f5b
1278 | copies: f1b (f1a) f3b (f3a) f5b (f5a)
1281 | copies: f1b (f1a) f3b (f3a) f5b (f5a)
1279 | description:
1282 | description:
1280 | B0
1283 | B0
1281 |
1284 |
1282 |
1285 |
1283 | diff --git a/f1a b/f1b
1286 | diff --git a/f1a b/f1b
1284 | rename from f1a
1287 | rename from f1a
1285 | rename to f1b
1288 | rename to f1b
1286 | diff --git a/f3a b/f3b
1289 | diff --git a/f3a b/f3b
1287 | rename from f3a
1290 | rename from f3a
1288 | rename to f3b
1291 | rename to f3b
1289 | diff --git a/f5a b/f5b
1292 | diff --git a/f5a b/f5b
1290 | rename from f5a
1293 | rename from f5a
1291 | rename to f5b
1294 | rename to f5b
1292 |
1295 |
1293 o changeset: 0:11f7a1b56675
1296 o changeset: 0:11f7a1b56675
1294 user: test
1297 user: test
1295 date: Thu Jan 01 00:00:00 1970 +0000
1298 date: Thu Jan 01 00:00:00 1970 +0000
1296 files: f1a f2a f3a f4a f5a
1299 files: f1a f2a f3a f4a f5a
1297 description:
1300 description:
1298 A0
1301 A0
1299
1302
1300
1303
1301 diff --git a/f1a b/f1a
1304 diff --git a/f1a b/f1a
1302 new file mode 100644
1305 new file mode 100644
1303 --- /dev/null
1306 --- /dev/null
1304 +++ b/f1a
1307 +++ b/f1a
1305 @@ -0,0 +1,1 @@
1308 @@ -0,0 +1,1 @@
1306 +c1a
1309 +c1a
1307 diff --git a/f2a b/f2a
1310 diff --git a/f2a b/f2a
1308 new file mode 100644
1311 new file mode 100644
1309 --- /dev/null
1312 --- /dev/null
1310 +++ b/f2a
1313 +++ b/f2a
1311 @@ -0,0 +1,1 @@
1314 @@ -0,0 +1,1 @@
1312 +c2a
1315 +c2a
1313 diff --git a/f3a b/f3a
1316 diff --git a/f3a b/f3a
1314 new file mode 100644
1317 new file mode 100644
1315 --- /dev/null
1318 --- /dev/null
1316 +++ b/f3a
1319 +++ b/f3a
1317 @@ -0,0 +1,1 @@
1320 @@ -0,0 +1,1 @@
1318 +c3a
1321 +c3a
1319 diff --git a/f4a b/f4a
1322 diff --git a/f4a b/f4a
1320 new file mode 100644
1323 new file mode 100644
1321 --- /dev/null
1324 --- /dev/null
1322 +++ b/f4a
1325 +++ b/f4a
1323 @@ -0,0 +1,1 @@
1326 @@ -0,0 +1,1 @@
1324 +c4a
1327 +c4a
1325 diff --git a/f5a b/f5a
1328 diff --git a/f5a b/f5a
1326 new file mode 100644
1329 new file mode 100644
1327 --- /dev/null
1330 --- /dev/null
1328 +++ b/f5a
1331 +++ b/f5a
1329 @@ -0,0 +1,1 @@
1332 @@ -0,0 +1,1 @@
1330 +c5a
1333 +c5a
1331
1334
1332 $ hg cat f2c
1335 $ hg cat f2c
1333 c2e
1336 c2e
General Comments 0
You need to be logged in to leave comments. Login now