##// END OF EJS Templates
copies: when both sides made the same copy, report it as a copy...
Mads Kiilerich -
r20641:3db9e798 default
parent child Browse files
Show More
@@ -1,412 +1,424 b''
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 import util
8 import util
9 import heapq
9 import heapq
10
10
11 def _nonoverlap(d1, d2, d3):
11 def _nonoverlap(d1, d2, d3):
12 "Return list of elements in d1 not in d2 or d3"
12 "Return list of elements in d1 not in d2 or d3"
13 return sorted([d for d in d1 if d not in d3 and d not in d2])
13 return sorted([d for d in d1 if d not in d3 and d not in d2])
14
14
15 def _dirname(f):
15 def _dirname(f):
16 s = f.rfind("/")
16 s = f.rfind("/")
17 if s == -1:
17 if s == -1:
18 return ""
18 return ""
19 return f[:s]
19 return f[:s]
20
20
21 def _findlimit(repo, a, b):
21 def _findlimit(repo, a, b):
22 """Find the earliest revision that's an ancestor of a or b but not both,
22 """Find the earliest revision that's an ancestor of a or b but not both,
23 None if no such revision exists.
23 None if no such revision exists.
24 """
24 """
25 # basic idea:
25 # basic idea:
26 # - mark a and b with different sides
26 # - mark a and b with different sides
27 # - if a parent's children are all on the same side, the parent is
27 # - if a parent's children are all on the same side, the parent is
28 # on that side, otherwise it is on no side
28 # on that side, otherwise it is on no side
29 # - walk the graph in topological order with the help of a heap;
29 # - walk the graph in topological order with the help of a heap;
30 # - add unseen parents to side map
30 # - add unseen parents to side map
31 # - clear side of any parent that has children on different sides
31 # - clear side of any parent that has children on different sides
32 # - track number of interesting revs that might still be on a side
32 # - track number of interesting revs that might still be on a side
33 # - track the lowest interesting rev seen
33 # - track the lowest interesting rev seen
34 # - quit when interesting revs is zero
34 # - quit when interesting revs is zero
35
35
36 cl = repo.changelog
36 cl = repo.changelog
37 working = len(cl) # pseudo rev for the working directory
37 working = len(cl) # pseudo rev for the working directory
38 if a is None:
38 if a is None:
39 a = working
39 a = working
40 if b is None:
40 if b is None:
41 b = working
41 b = working
42
42
43 side = {a: -1, b: 1}
43 side = {a: -1, b: 1}
44 visit = [-a, -b]
44 visit = [-a, -b]
45 heapq.heapify(visit)
45 heapq.heapify(visit)
46 interesting = len(visit)
46 interesting = len(visit)
47 hascommonancestor = False
47 hascommonancestor = False
48 limit = working
48 limit = working
49
49
50 while interesting:
50 while interesting:
51 r = -heapq.heappop(visit)
51 r = -heapq.heappop(visit)
52 if r == working:
52 if r == working:
53 parents = [cl.rev(p) for p in repo.dirstate.parents()]
53 parents = [cl.rev(p) for p in repo.dirstate.parents()]
54 else:
54 else:
55 parents = cl.parentrevs(r)
55 parents = cl.parentrevs(r)
56 for p in parents:
56 for p in parents:
57 if p < 0:
57 if p < 0:
58 continue
58 continue
59 if p not in side:
59 if p not in side:
60 # first time we see p; add it to visit
60 # first time we see p; add it to visit
61 side[p] = side[r]
61 side[p] = side[r]
62 if side[p]:
62 if side[p]:
63 interesting += 1
63 interesting += 1
64 heapq.heappush(visit, -p)
64 heapq.heappush(visit, -p)
65 elif side[p] and side[p] != side[r]:
65 elif side[p] and side[p] != side[r]:
66 # p was interesting but now we know better
66 # p was interesting but now we know better
67 side[p] = 0
67 side[p] = 0
68 interesting -= 1
68 interesting -= 1
69 hascommonancestor = True
69 hascommonancestor = True
70 if side[r]:
70 if side[r]:
71 limit = r # lowest rev visited
71 limit = r # lowest rev visited
72 interesting -= 1
72 interesting -= 1
73
73
74 if not hascommonancestor:
74 if not hascommonancestor:
75 return None
75 return None
76 return limit
76 return limit
77
77
78 def _chain(src, dst, a, b):
78 def _chain(src, dst, a, b):
79 '''chain two sets of copies a->b'''
79 '''chain two sets of copies a->b'''
80 t = a.copy()
80 t = a.copy()
81 for k, v in b.iteritems():
81 for k, v in b.iteritems():
82 if v in t:
82 if v in t:
83 # found a chain
83 # found a chain
84 if t[v] != k:
84 if t[v] != k:
85 # file wasn't renamed back to itself
85 # file wasn't renamed back to itself
86 t[k] = t[v]
86 t[k] = t[v]
87 if v not in dst:
87 if v not in dst:
88 # chain was a rename, not a copy
88 # chain was a rename, not a copy
89 del t[v]
89 del t[v]
90 if v in src:
90 if v in src:
91 # file is a copy of an existing file
91 # file is a copy of an existing file
92 t[k] = v
92 t[k] = v
93
93
94 # remove criss-crossed copies
94 # remove criss-crossed copies
95 for k, v in t.items():
95 for k, v in t.items():
96 if k in src and v in dst:
96 if k in src and v in dst:
97 del t[k]
97 del t[k]
98
98
99 return t
99 return t
100
100
101 def _tracefile(fctx, am, limit=-1):
101 def _tracefile(fctx, am, limit=-1):
102 '''return file context that is the ancestor of fctx present in ancestor
102 '''return file context that is the ancestor of fctx present in ancestor
103 manifest am, stopping after the first ancestor lower than limit'''
103 manifest am, stopping after the first ancestor lower than limit'''
104
104
105 for f in fctx.ancestors():
105 for f in fctx.ancestors():
106 if am.get(f.path(), None) == f.filenode():
106 if am.get(f.path(), None) == f.filenode():
107 return f
107 return f
108 if f.rev() < limit:
108 if f.rev() < limit:
109 return None
109 return None
110
110
111 def _dirstatecopies(d):
111 def _dirstatecopies(d):
112 ds = d._repo.dirstate
112 ds = d._repo.dirstate
113 c = ds.copies().copy()
113 c = ds.copies().copy()
114 for k in c.keys():
114 for k in c.keys():
115 if ds[k] not in 'anm':
115 if ds[k] not in 'anm':
116 del c[k]
116 del c[k]
117 return c
117 return c
118
118
119 def _forwardcopies(a, b):
119 def _forwardcopies(a, b):
120 '''find {dst@b: src@a} copy mapping where a is an ancestor of b'''
120 '''find {dst@b: src@a} copy mapping where a is an ancestor of b'''
121
121
122 # check for working copy
122 # check for working copy
123 w = None
123 w = None
124 if b.rev() is None:
124 if b.rev() is None:
125 w = b
125 w = b
126 b = w.p1()
126 b = w.p1()
127 if a == b:
127 if a == b:
128 # short-circuit to avoid issues with merge states
128 # short-circuit to avoid issues with merge states
129 return _dirstatecopies(w)
129 return _dirstatecopies(w)
130
130
131 # files might have to be traced back to the fctx parent of the last
131 # files might have to be traced back to the fctx parent of the last
132 # one-side-only changeset, but not further back than that
132 # one-side-only changeset, but not further back than that
133 limit = _findlimit(a._repo, a.rev(), b.rev())
133 limit = _findlimit(a._repo, a.rev(), b.rev())
134 if limit is None:
134 if limit is None:
135 limit = -1
135 limit = -1
136 am = a.manifest()
136 am = a.manifest()
137
137
138 # find where new files came from
138 # find where new files came from
139 # we currently don't try to find where old files went, too expensive
139 # we currently don't try to find where old files went, too expensive
140 # this means we can miss a case like 'hg rm b; hg cp a b'
140 # this means we can miss a case like 'hg rm b; hg cp a b'
141 cm = {}
141 cm = {}
142 missing = set(b.manifest().iterkeys())
142 missing = set(b.manifest().iterkeys())
143 missing.difference_update(a.manifest().iterkeys())
143 missing.difference_update(a.manifest().iterkeys())
144
144
145 for f in missing:
145 for f in missing:
146 ofctx = _tracefile(b[f], am, limit)
146 ofctx = _tracefile(b[f], am, limit)
147 if ofctx:
147 if ofctx:
148 cm[f] = ofctx.path()
148 cm[f] = ofctx.path()
149
149
150 # combine copies from dirstate if necessary
150 # combine copies from dirstate if necessary
151 if w is not None:
151 if w is not None:
152 cm = _chain(a, w, cm, _dirstatecopies(w))
152 cm = _chain(a, w, cm, _dirstatecopies(w))
153
153
154 return cm
154 return cm
155
155
156 def _backwardrenames(a, b):
156 def _backwardrenames(a, b):
157 # Even though we're not taking copies into account, 1:n rename situations
157 # Even though we're not taking copies into account, 1:n rename situations
158 # can still exist (e.g. hg cp a b; hg mv a c). In those cases we
158 # can still exist (e.g. hg cp a b; hg mv a c). In those cases we
159 # arbitrarily pick one of the renames.
159 # arbitrarily pick one of the renames.
160 f = _forwardcopies(b, a)
160 f = _forwardcopies(b, a)
161 r = {}
161 r = {}
162 for k, v in sorted(f.iteritems()):
162 for k, v in sorted(f.iteritems()):
163 # remove copies
163 # remove copies
164 if v in a:
164 if v in a:
165 continue
165 continue
166 r[v] = k
166 r[v] = k
167 return r
167 return r
168
168
169 def pathcopies(x, y):
169 def pathcopies(x, y):
170 '''find {dst@y: src@x} copy mapping for directed compare'''
170 '''find {dst@y: src@x} copy mapping for directed compare'''
171 if x == y or not x or not y:
171 if x == y or not x or not y:
172 return {}
172 return {}
173 a = y.ancestor(x)
173 a = y.ancestor(x)
174 if a == x:
174 if a == x:
175 return _forwardcopies(x, y)
175 return _forwardcopies(x, y)
176 if a == y:
176 if a == y:
177 return _backwardrenames(x, y)
177 return _backwardrenames(x, y)
178 return _chain(x, y, _backwardrenames(x, a), _forwardcopies(a, y))
178 return _chain(x, y, _backwardrenames(x, a), _forwardcopies(a, y))
179
179
180 def mergecopies(repo, c1, c2, ca):
180 def mergecopies(repo, c1, c2, ca):
181 """
181 """
182 Find moves and copies between context c1 and c2 that are relevant
182 Find moves and copies between context c1 and c2 that are relevant
183 for merging.
183 for merging.
184
184
185 Returns four dicts: "copy", "movewithdir", "diverge", and
185 Returns four dicts: "copy", "movewithdir", "diverge", and
186 "renamedelete".
186 "renamedelete".
187
187
188 "copy" is a mapping from destination name -> source name,
188 "copy" is a mapping from destination name -> source name,
189 where source is in c1 and destination is in c2 or vice-versa.
189 where source is in c1 and destination is in c2 or vice-versa.
190
190
191 "movewithdir" is a mapping from source name -> destination name,
191 "movewithdir" is a mapping from source name -> destination name,
192 where the file at source present in one context but not the other
192 where the file at source present in one context but not the other
193 needs to be moved to destination by the merge process, because the
193 needs to be moved to destination by the merge process, because the
194 other context moved the directory it is in.
194 other context moved the directory it is in.
195
195
196 "diverge" is a mapping of source name -> list of destination names
196 "diverge" is a mapping of source name -> list of destination names
197 for divergent renames.
197 for divergent renames.
198
198
199 "renamedelete" is a mapping of source name -> list of destination
199 "renamedelete" is a mapping of source name -> list of destination
200 names for files deleted in c1 that were renamed in c2 or vice-versa.
200 names for files deleted in c1 that were renamed in c2 or vice-versa.
201 """
201 """
202 # avoid silly behavior for update from empty dir
202 # avoid silly behavior for update from empty dir
203 if not c1 or not c2 or c1 == c2:
203 if not c1 or not c2 or c1 == c2:
204 return {}, {}, {}, {}
204 return {}, {}, {}, {}
205
205
206 # avoid silly behavior for parent -> working dir
206 # avoid silly behavior for parent -> working dir
207 if c2.node() is None and c1.node() == repo.dirstate.p1():
207 if c2.node() is None and c1.node() == repo.dirstate.p1():
208 return repo.dirstate.copies(), {}, {}, {}
208 return repo.dirstate.copies(), {}, {}, {}
209
209
210 limit = _findlimit(repo, c1.rev(), c2.rev())
210 limit = _findlimit(repo, c1.rev(), c2.rev())
211 if limit is None:
211 if limit is None:
212 # no common ancestor, no copies
212 # no common ancestor, no copies
213 return {}, {}, {}, {}
213 return {}, {}, {}, {}
214 m1 = c1.manifest()
214 m1 = c1.manifest()
215 m2 = c2.manifest()
215 m2 = c2.manifest()
216 ma = ca.manifest()
216 ma = ca.manifest()
217
217
218 def makectx(f, n):
218 def makectx(f, n):
219 if len(n) != 20: # in a working context?
219 if len(n) != 20: # in a working context?
220 if c1.rev() is None:
220 if c1.rev() is None:
221 return c1.filectx(f)
221 return c1.filectx(f)
222 return c2.filectx(f)
222 return c2.filectx(f)
223 return repo.filectx(f, fileid=n)
223 return repo.filectx(f, fileid=n)
224
224
225 ctx = util.lrucachefunc(makectx)
225 ctx = util.lrucachefunc(makectx)
226 copy = {}
226 copy = {}
227 movewithdir = {}
227 movewithdir = {}
228 fullcopy = {}
228 fullcopy = {}
229 diverge = {}
229 diverge = {}
230
230
231 def _checkcopies(f, m1, m2):
231 def _checkcopies(f, m1, m2):
232 checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy)
232 checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy)
233
233
234 repo.ui.debug(" searching for copies back to rev %d\n" % limit)
234 repo.ui.debug(" searching for copies back to rev %d\n" % limit)
235
235
236 u1 = _nonoverlap(m1, m2, ma)
236 u1 = _nonoverlap(m1, m2, ma)
237 u2 = _nonoverlap(m2, m1, ma)
237 u2 = _nonoverlap(m2, m1, ma)
238
238
239 if u1:
239 if u1:
240 repo.ui.debug(" unmatched files in local:\n %s\n"
240 repo.ui.debug(" unmatched files in local:\n %s\n"
241 % "\n ".join(u1))
241 % "\n ".join(u1))
242 if u2:
242 if u2:
243 repo.ui.debug(" unmatched files in other:\n %s\n"
243 repo.ui.debug(" unmatched files in other:\n %s\n"
244 % "\n ".join(u2))
244 % "\n ".join(u2))
245
245
246 for f in u1:
246 for f in u1:
247 _checkcopies(f, m1, m2)
247 _checkcopies(f, m1, m2)
248 for f in u2:
248 for f in u2:
249 _checkcopies(f, m2, m1)
249 _checkcopies(f, m2, m1)
250
250
251 renamedelete = {}
251 renamedelete = {}
252 renamedelete2 = set()
252 renamedelete2 = set()
253 diverge2 = set()
253 diverge2 = set()
254 for of, fl in diverge.items():
254 for of, fl in diverge.items():
255 if len(fl) == 1 or of in c1 or of in c2:
255 if len(fl) == 1 or of in c1 or of in c2:
256 del diverge[of] # not actually divergent, or not a rename
256 del diverge[of] # not actually divergent, or not a rename
257 if of not in c1 and of not in c2:
257 if of not in c1 and of not in c2:
258 # renamed on one side, deleted on the other side, but filter
258 # renamed on one side, deleted on the other side, but filter
259 # out files that have been renamed and then deleted
259 # out files that have been renamed and then deleted
260 renamedelete[of] = [f for f in fl if f in c1 or f in c2]
260 renamedelete[of] = [f for f in fl if f in c1 or f in c2]
261 renamedelete2.update(fl) # reverse map for below
261 renamedelete2.update(fl) # reverse map for below
262 else:
262 else:
263 diverge2.update(fl) # reverse map for below
263 diverge2.update(fl) # reverse map for below
264
264
265 bothnew = sorted([d for d in m1 if d in m2 and d not in ma])
266 if bothnew:
267 repo.ui.debug(" unmatched files new in both:\n %s\n"
268 % "\n ".join(bothnew))
269 bothdiverge, _copy, _fullcopy = {}, {}, {}
270 for f in bothnew:
271 checkcopies(ctx, f, m1, m2, ca, limit, bothdiverge, _copy, _fullcopy)
272 checkcopies(ctx, f, m2, m1, ca, limit, bothdiverge, _copy, _fullcopy)
273 for of, fl in bothdiverge.items():
274 if len(fl) == 2 and fl[0] == fl[1]:
275 copy[fl[0]] = of # not actually divergent, just matching renames
276
265 if fullcopy:
277 if fullcopy:
266 repo.ui.debug(" all copies found (* = to merge, ! = divergent, "
278 repo.ui.debug(" all copies found (* = to merge, ! = divergent, "
267 "% = renamed and deleted):\n")
279 "% = renamed and deleted):\n")
268 for f in sorted(fullcopy):
280 for f in sorted(fullcopy):
269 note = ""
281 note = ""
270 if f in copy:
282 if f in copy:
271 note += "*"
283 note += "*"
272 if f in diverge2:
284 if f in diverge2:
273 note += "!"
285 note += "!"
274 if f in renamedelete2:
286 if f in renamedelete2:
275 note += "%"
287 note += "%"
276 repo.ui.debug(" src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f,
288 repo.ui.debug(" src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f,
277 note))
289 note))
278 del diverge2
290 del diverge2
279
291
280 if not fullcopy:
292 if not fullcopy:
281 return copy, movewithdir, diverge, renamedelete
293 return copy, movewithdir, diverge, renamedelete
282
294
283 repo.ui.debug(" checking for directory renames\n")
295 repo.ui.debug(" checking for directory renames\n")
284
296
285 # generate a directory move map
297 # generate a directory move map
286 d1, d2 = c1.dirs(), c2.dirs()
298 d1, d2 = c1.dirs(), c2.dirs()
287 d1.addpath('/')
299 d1.addpath('/')
288 d2.addpath('/')
300 d2.addpath('/')
289 invalid = set()
301 invalid = set()
290 dirmove = {}
302 dirmove = {}
291
303
292 # examine each file copy for a potential directory move, which is
304 # examine each file copy for a potential directory move, which is
293 # when all the files in a directory are moved to a new directory
305 # when all the files in a directory are moved to a new directory
294 for dst, src in fullcopy.iteritems():
306 for dst, src in fullcopy.iteritems():
295 dsrc, ddst = _dirname(src), _dirname(dst)
307 dsrc, ddst = _dirname(src), _dirname(dst)
296 if dsrc in invalid:
308 if dsrc in invalid:
297 # already seen to be uninteresting
309 # already seen to be uninteresting
298 continue
310 continue
299 elif dsrc in d1 and ddst in d1:
311 elif dsrc in d1 and ddst in d1:
300 # directory wasn't entirely moved locally
312 # directory wasn't entirely moved locally
301 invalid.add(dsrc)
313 invalid.add(dsrc)
302 elif dsrc in d2 and ddst in d2:
314 elif dsrc in d2 and ddst in d2:
303 # directory wasn't entirely moved remotely
315 # directory wasn't entirely moved remotely
304 invalid.add(dsrc)
316 invalid.add(dsrc)
305 elif dsrc in dirmove and dirmove[dsrc] != ddst:
317 elif dsrc in dirmove and dirmove[dsrc] != ddst:
306 # files from the same directory moved to two different places
318 # files from the same directory moved to two different places
307 invalid.add(dsrc)
319 invalid.add(dsrc)
308 else:
320 else:
309 # looks good so far
321 # looks good so far
310 dirmove[dsrc + "/"] = ddst + "/"
322 dirmove[dsrc + "/"] = ddst + "/"
311
323
312 for i in invalid:
324 for i in invalid:
313 if i in dirmove:
325 if i in dirmove:
314 del dirmove[i]
326 del dirmove[i]
315 del d1, d2, invalid
327 del d1, d2, invalid
316
328
317 if not dirmove:
329 if not dirmove:
318 return copy, movewithdir, diverge, renamedelete
330 return copy, movewithdir, diverge, renamedelete
319
331
320 for d in dirmove:
332 for d in dirmove:
321 repo.ui.debug(" discovered dir src: '%s' -> dst: '%s'\n" %
333 repo.ui.debug(" discovered dir src: '%s' -> dst: '%s'\n" %
322 (d, dirmove[d]))
334 (d, dirmove[d]))
323
335
324 # check unaccounted nonoverlapping files against directory moves
336 # check unaccounted nonoverlapping files against directory moves
325 for f in u1 + u2:
337 for f in u1 + u2:
326 if f not in fullcopy:
338 if f not in fullcopy:
327 for d in dirmove:
339 for d in dirmove:
328 if f.startswith(d):
340 if f.startswith(d):
329 # new file added in a directory that was moved, move it
341 # new file added in a directory that was moved, move it
330 df = dirmove[d] + f[len(d):]
342 df = dirmove[d] + f[len(d):]
331 if df not in copy:
343 if df not in copy:
332 movewithdir[f] = df
344 movewithdir[f] = df
333 repo.ui.debug((" pending file src: '%s' -> "
345 repo.ui.debug((" pending file src: '%s' -> "
334 "dst: '%s'\n") % (f, df))
346 "dst: '%s'\n") % (f, df))
335 break
347 break
336
348
337 return copy, movewithdir, diverge, renamedelete
349 return copy, movewithdir, diverge, renamedelete
338
350
339 def checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy):
351 def checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy):
340 """
352 """
341 check possible copies of f from m1 to m2
353 check possible copies of f from m1 to m2
342
354
343 ctx = function accepting (filename, node) that returns a filectx.
355 ctx = function accepting (filename, node) that returns a filectx.
344 f = the filename to check
356 f = the filename to check
345 m1 = the source manifest
357 m1 = the source manifest
346 m2 = the destination manifest
358 m2 = the destination manifest
347 ca = the changectx of the common ancestor
359 ca = the changectx of the common ancestor
348 limit = the rev number to not search beyond
360 limit = the rev number to not search beyond
349 diverge = record all diverges in this dict
361 diverge = record all diverges in this dict
350 copy = record all non-divergent copies in this dict
362 copy = record all non-divergent copies in this dict
351 fullcopy = record all copies in this dict
363 fullcopy = record all copies in this dict
352 """
364 """
353
365
354 ma = ca.manifest()
366 ma = ca.manifest()
355
367
356 def _related(f1, f2, limit):
368 def _related(f1, f2, limit):
357 # Walk back to common ancestor to see if the two files originate
369 # Walk back to common ancestor to see if the two files originate
358 # from the same file. Since workingfilectx's rev() is None it messes
370 # from the same file. Since workingfilectx's rev() is None it messes
359 # up the integer comparison logic, hence the pre-step check for
371 # up the integer comparison logic, hence the pre-step check for
360 # None (f1 and f2 can only be workingfilectx's initially).
372 # None (f1 and f2 can only be workingfilectx's initially).
361
373
362 if f1 == f2:
374 if f1 == f2:
363 return f1 # a match
375 return f1 # a match
364
376
365 g1, g2 = f1.ancestors(), f2.ancestors()
377 g1, g2 = f1.ancestors(), f2.ancestors()
366 try:
378 try:
367 f1r, f2r = f1.rev(), f2.rev()
379 f1r, f2r = f1.rev(), f2.rev()
368
380
369 if f1r is None:
381 if f1r is None:
370 f1 = g1.next()
382 f1 = g1.next()
371 if f2r is None:
383 if f2r is None:
372 f2 = g2.next()
384 f2 = g2.next()
373
385
374 while True:
386 while True:
375 f1r, f2r = f1.rev(), f2.rev()
387 f1r, f2r = f1.rev(), f2.rev()
376 if f1r > f2r:
388 if f1r > f2r:
377 f1 = g1.next()
389 f1 = g1.next()
378 elif f2r > f1r:
390 elif f2r > f1r:
379 f2 = g2.next()
391 f2 = g2.next()
380 elif f1 == f2:
392 elif f1 == f2:
381 return f1 # a match
393 return f1 # a match
382 elif f1r == f2r or f1r < limit or f2r < limit:
394 elif f1r == f2r or f1r < limit or f2r < limit:
383 return False # copy no longer relevant
395 return False # copy no longer relevant
384 except StopIteration:
396 except StopIteration:
385 return False
397 return False
386
398
387 of = None
399 of = None
388 seen = set([f])
400 seen = set([f])
389 for oc in ctx(f, m1[f]).ancestors():
401 for oc in ctx(f, m1[f]).ancestors():
390 ocr = oc.rev()
402 ocr = oc.rev()
391 of = oc.path()
403 of = oc.path()
392 if of in seen:
404 if of in seen:
393 # check limit late - grab last rename before
405 # check limit late - grab last rename before
394 if ocr < limit:
406 if ocr < limit:
395 break
407 break
396 continue
408 continue
397 seen.add(of)
409 seen.add(of)
398
410
399 fullcopy[f] = of # remember for dir rename detection
411 fullcopy[f] = of # remember for dir rename detection
400 if of not in m2:
412 if of not in m2:
401 continue # no match, keep looking
413 continue # no match, keep looking
402 if m2[of] == ma.get(of):
414 if m2[of] == ma.get(of):
403 break # no merge needed, quit early
415 break # no merge needed, quit early
404 c2 = ctx(of, m2[of])
416 c2 = ctx(of, m2[of])
405 cr = _related(oc, c2, ca.rev())
417 cr = _related(oc, c2, ca.rev())
406 if cr and (of == f or of == c2.path()): # non-divergent
418 if cr and (of == f or of == c2.path()): # non-divergent
407 copy[f] = of
419 copy[f] = of
408 of = None
420 of = None
409 break
421 break
410
422
411 if of in ma:
423 if of in ma:
412 diverge.setdefault(of, []).append(f)
424 diverge.setdefault(of, []).append(f)
@@ -1,949 +1,970 b''
1
1
2 $ mkdir -p t
2 $ mkdir -p t
3 $ cd t
3 $ cd t
4 $ cat <<EOF > merge
4 $ cat <<EOF > merge
5 > import sys, os
5 > import sys, os
6 > f = open(sys.argv[1], "wb")
6 > f = open(sys.argv[1], "wb")
7 > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3]))
7 > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3]))
8 > f.close()
8 > f.close()
9 > EOF
9 > EOF
10
10
11 perform a test merge with possible renaming
11 perform a test merge with possible renaming
12 args:
12 args:
13 $1 = action in local branch
13 $1 = action in local branch
14 $2 = action in remote branch
14 $2 = action in remote branch
15 $3 = action in working dir
15 $3 = action in working dir
16 $4 = expected result
16 $4 = expected result
17
17
18 $ tm()
18 $ tm()
19 > {
19 > {
20 > hg init t
20 > hg init t
21 > cd t
21 > cd t
22 > echo "[merge]" >> .hg/hgrc
22 > echo "[merge]" >> .hg/hgrc
23 > echo "followcopies = 1" >> .hg/hgrc
23 > echo "followcopies = 1" >> .hg/hgrc
24 >
24 >
25 > # base
25 > # base
26 > echo base > a
26 > echo base > a
27 > echo base > rev # used to force commits
27 > echo base > rev # used to force commits
28 > hg add a rev
28 > hg add a rev
29 > hg ci -m "base"
29 > hg ci -m "base"
30 >
30 >
31 > # remote
31 > # remote
32 > echo remote > rev
32 > echo remote > rev
33 > if [ "$2" != "" ] ; then $2 ; fi
33 > if [ "$2" != "" ] ; then $2 ; fi
34 > hg ci -m "remote"
34 > hg ci -m "remote"
35 >
35 >
36 > # local
36 > # local
37 > hg co -q 0
37 > hg co -q 0
38 > echo local > rev
38 > echo local > rev
39 > if [ "$1" != "" ] ; then $1 ; fi
39 > if [ "$1" != "" ] ; then $1 ; fi
40 > hg ci -m "local"
40 > hg ci -m "local"
41 >
41 >
42 > # working dir
42 > # working dir
43 > echo local > rev
43 > echo local > rev
44 > if [ "$3" != "" ] ; then $3 ; fi
44 > if [ "$3" != "" ] ; then $3 ; fi
45 >
45 >
46 > # merge
46 > # merge
47 > echo "--------------"
47 > echo "--------------"
48 > echo "test L:$1 R:$2 W:$3 - $4"
48 > echo "test L:$1 R:$2 W:$3 - $4"
49 > echo "--------------"
49 > echo "--------------"
50 > hg merge -y --debug --traceback --tool="python ../merge"
50 > hg merge -y --debug --traceback --tool="python ../merge"
51 >
51 >
52 > echo "--------------"
52 > echo "--------------"
53 > hg status -camC -X rev
53 > hg status -camC -X rev
54 >
54 >
55 > hg ci -m "merge"
55 > hg ci -m "merge"
56 >
56 >
57 > echo "--------------"
57 > echo "--------------"
58 > echo
58 > echo
59 >
59 >
60 > cd ..
60 > cd ..
61 > rm -r t
61 > rm -r t
62 > }
62 > }
63 $ up() {
63 $ up() {
64 > cp rev $1
64 > cp rev $1
65 > hg add $1 2> /dev/null
65 > hg add $1 2> /dev/null
66 > if [ "$2" != "" ] ; then
66 > if [ "$2" != "" ] ; then
67 > cp rev $2
67 > cp rev $2
68 > hg add $2 2> /dev/null
68 > hg add $2 2> /dev/null
69 > fi
69 > fi
70 > }
70 > }
71 $ uc() { up $1; hg cp $1 $2; } # update + copy
71 $ uc() { up $1; hg cp $1 $2; } # update + copy
72 $ um() { up $1; hg mv $1 $2; }
72 $ um() { up $1; hg mv $1 $2; }
73 $ nc() { hg cp $1 $2; } # just copy
73 $ nc() { hg cp $1 $2; } # just copy
74 $ nm() { hg mv $1 $2; } # just move
74 $ nm() { hg mv $1 $2; } # just move
75 $ tm "up a " "nc a b" " " "1 get local a to b"
75 $ tm "up a " "nc a b" " " "1 get local a to b"
76 created new head
76 created new head
77 --------------
77 --------------
78 test L:up a R:nc a b W: - 1 get local a to b
78 test L:up a R:nc a b W: - 1 get local a to b
79 --------------
79 --------------
80 searching for copies back to rev 1
80 searching for copies back to rev 1
81 unmatched files in other:
81 unmatched files in other:
82 b
82 b
83 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
83 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
84 src: 'a' -> dst: 'b' *
84 src: 'a' -> dst: 'b' *
85 checking for directory renames
85 checking for directory renames
86 resolving manifests
86 resolving manifests
87 branchmerge: True, force: False, partial: False
87 branchmerge: True, force: False, partial: False
88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
89 a: remote copied to b -> m
89 a: remote copied to b -> m
90 preserving a for resolve of b
90 preserving a for resolve of b
91 rev: versions differ -> m
91 rev: versions differ -> m
92 preserving rev for resolve of rev
92 preserving rev for resolve of rev
93 updating: a 1/2 files (50.00%)
93 updating: a 1/2 files (50.00%)
94 picked tool 'python ../merge' for b (binary False symlink False)
94 picked tool 'python ../merge' for b (binary False symlink False)
95 merging a and b to b
95 merging a and b to b
96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
97 premerge successful
97 premerge successful
98 updating: rev 2/2 files (100.00%)
98 updating: rev 2/2 files (100.00%)
99 picked tool 'python ../merge' for rev (binary False symlink False)
99 picked tool 'python ../merge' for rev (binary False symlink False)
100 merging rev
100 merging rev
101 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
101 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
102 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
102 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
103 (branch merge, don't forget to commit)
103 (branch merge, don't forget to commit)
104 --------------
104 --------------
105 M b
105 M b
106 a
106 a
107 C a
107 C a
108 --------------
108 --------------
109
109
110 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
110 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
111 created new head
111 created new head
112 --------------
112 --------------
113 test L:nc a b R:up a W: - 2 get rem change to a and b
113 test L:nc a b R:up a W: - 2 get rem change to a and b
114 --------------
114 --------------
115 searching for copies back to rev 1
115 searching for copies back to rev 1
116 unmatched files in local:
116 unmatched files in local:
117 b
117 b
118 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
118 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
119 src: 'a' -> dst: 'b' *
119 src: 'a' -> dst: 'b' *
120 checking for directory renames
120 checking for directory renames
121 resolving manifests
121 resolving manifests
122 branchmerge: True, force: False, partial: False
122 branchmerge: True, force: False, partial: False
123 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
123 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
124 a: remote is newer -> g
124 a: remote is newer -> g
125 b: local copied/moved to a -> m
125 b: local copied/moved to a -> m
126 preserving b for resolve of b
126 preserving b for resolve of b
127 rev: versions differ -> m
127 rev: versions differ -> m
128 preserving rev for resolve of rev
128 preserving rev for resolve of rev
129 getting a
129 getting a
130 updating: a 1/3 files (33.33%)
130 updating: a 1/3 files (33.33%)
131 updating: b 2/3 files (66.67%)
131 updating: b 2/3 files (66.67%)
132 picked tool 'python ../merge' for b (binary False symlink False)
132 picked tool 'python ../merge' for b (binary False symlink False)
133 merging b and a to b
133 merging b and a to b
134 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
134 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
135 premerge successful
135 premerge successful
136 updating: rev 3/3 files (100.00%)
136 updating: rev 3/3 files (100.00%)
137 picked tool 'python ../merge' for rev (binary False symlink False)
137 picked tool 'python ../merge' for rev (binary False symlink False)
138 merging rev
138 merging rev
139 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
139 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
140 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
140 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
141 (branch merge, don't forget to commit)
141 (branch merge, don't forget to commit)
142 --------------
142 --------------
143 M a
143 M a
144 M b
144 M b
145 a
145 a
146 --------------
146 --------------
147
147
148 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
148 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
149 created new head
149 created new head
150 --------------
150 --------------
151 test L:up a R:nm a b W: - 3 get local a change to b, remove a
151 test L:up a R:nm a b W: - 3 get local a change to b, remove a
152 --------------
152 --------------
153 searching for copies back to rev 1
153 searching for copies back to rev 1
154 unmatched files in other:
154 unmatched files in other:
155 b
155 b
156 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
156 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
157 src: 'a' -> dst: 'b' *
157 src: 'a' -> dst: 'b' *
158 checking for directory renames
158 checking for directory renames
159 resolving manifests
159 resolving manifests
160 branchmerge: True, force: False, partial: False
160 branchmerge: True, force: False, partial: False
161 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
161 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
162 a: remote moved to b -> m
162 a: remote moved to b -> m
163 preserving a for resolve of b
163 preserving a for resolve of b
164 rev: versions differ -> m
164 rev: versions differ -> m
165 preserving rev for resolve of rev
165 preserving rev for resolve of rev
166 removing a
166 removing a
167 updating: a 1/2 files (50.00%)
167 updating: a 1/2 files (50.00%)
168 picked tool 'python ../merge' for b (binary False symlink False)
168 picked tool 'python ../merge' for b (binary False symlink False)
169 merging a and b to b
169 merging a and b to b
170 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
170 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
171 premerge successful
171 premerge successful
172 updating: rev 2/2 files (100.00%)
172 updating: rev 2/2 files (100.00%)
173 picked tool 'python ../merge' for rev (binary False symlink False)
173 picked tool 'python ../merge' for rev (binary False symlink False)
174 merging rev
174 merging rev
175 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
175 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
176 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
176 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
177 (branch merge, don't forget to commit)
177 (branch merge, don't forget to commit)
178 --------------
178 --------------
179 M b
179 M b
180 a
180 a
181 --------------
181 --------------
182
182
183 $ tm "nm a b" "up a " " " "4 get remote change to b"
183 $ tm "nm a b" "up a " " " "4 get remote change to b"
184 created new head
184 created new head
185 --------------
185 --------------
186 test L:nm a b R:up a W: - 4 get remote change to b
186 test L:nm a b R:up a W: - 4 get remote change to b
187 --------------
187 --------------
188 searching for copies back to rev 1
188 searching for copies back to rev 1
189 unmatched files in local:
189 unmatched files in local:
190 b
190 b
191 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
191 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
192 src: 'a' -> dst: 'b' *
192 src: 'a' -> dst: 'b' *
193 checking for directory renames
193 checking for directory renames
194 resolving manifests
194 resolving manifests
195 branchmerge: True, force: False, partial: False
195 branchmerge: True, force: False, partial: False
196 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
196 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
197 b: local copied/moved to a -> m
197 b: local copied/moved to a -> m
198 preserving b for resolve of b
198 preserving b for resolve of b
199 rev: versions differ -> m
199 rev: versions differ -> m
200 preserving rev for resolve of rev
200 preserving rev for resolve of rev
201 updating: b 1/2 files (50.00%)
201 updating: b 1/2 files (50.00%)
202 picked tool 'python ../merge' for b (binary False symlink False)
202 picked tool 'python ../merge' for b (binary False symlink False)
203 merging b and a to b
203 merging b and a to b
204 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
204 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
205 premerge successful
205 premerge successful
206 updating: rev 2/2 files (100.00%)
206 updating: rev 2/2 files (100.00%)
207 picked tool 'python ../merge' for rev (binary False symlink False)
207 picked tool 'python ../merge' for rev (binary False symlink False)
208 merging rev
208 merging rev
209 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
209 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
210 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
210 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
211 (branch merge, don't forget to commit)
211 (branch merge, don't forget to commit)
212 --------------
212 --------------
213 M b
213 M b
214 a
214 a
215 --------------
215 --------------
216
216
217 $ tm " " "nc a b" " " "5 get b"
217 $ tm " " "nc a b" " " "5 get b"
218 created new head
218 created new head
219 --------------
219 --------------
220 test L: R:nc a b W: - 5 get b
220 test L: R:nc a b W: - 5 get b
221 --------------
221 --------------
222 searching for copies back to rev 1
222 searching for copies back to rev 1
223 unmatched files in other:
223 unmatched files in other:
224 b
224 b
225 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
225 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
226 src: 'a' -> dst: 'b'
226 src: 'a' -> dst: 'b'
227 checking for directory renames
227 checking for directory renames
228 resolving manifests
228 resolving manifests
229 branchmerge: True, force: False, partial: False
229 branchmerge: True, force: False, partial: False
230 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
230 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
231 b: remote created -> g
231 b: remote created -> g
232 rev: versions differ -> m
232 rev: versions differ -> m
233 preserving rev for resolve of rev
233 preserving rev for resolve of rev
234 getting b
234 getting b
235 updating: b 1/2 files (50.00%)
235 updating: b 1/2 files (50.00%)
236 updating: rev 2/2 files (100.00%)
236 updating: rev 2/2 files (100.00%)
237 picked tool 'python ../merge' for rev (binary False symlink False)
237 picked tool 'python ../merge' for rev (binary False symlink False)
238 merging rev
238 merging rev
239 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
239 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
240 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
240 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
241 (branch merge, don't forget to commit)
241 (branch merge, don't forget to commit)
242 --------------
242 --------------
243 M b
243 M b
244 C a
244 C a
245 --------------
245 --------------
246
246
247 $ tm "nc a b" " " " " "6 nothing"
247 $ tm "nc a b" " " " " "6 nothing"
248 created new head
248 created new head
249 --------------
249 --------------
250 test L:nc a b R: W: - 6 nothing
250 test L:nc a b R: W: - 6 nothing
251 --------------
251 --------------
252 searching for copies back to rev 1
252 searching for copies back to rev 1
253 unmatched files in local:
253 unmatched files in local:
254 b
254 b
255 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
255 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
256 src: 'a' -> dst: 'b'
256 src: 'a' -> dst: 'b'
257 checking for directory renames
257 checking for directory renames
258 resolving manifests
258 resolving manifests
259 branchmerge: True, force: False, partial: False
259 branchmerge: True, force: False, partial: False
260 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
260 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
261 rev: versions differ -> m
261 rev: versions differ -> m
262 preserving rev for resolve of rev
262 preserving rev for resolve of rev
263 updating: rev 1/1 files (100.00%)
263 updating: rev 1/1 files (100.00%)
264 picked tool 'python ../merge' for rev (binary False symlink False)
264 picked tool 'python ../merge' for rev (binary False symlink False)
265 merging rev
265 merging rev
266 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
266 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
267 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
267 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
268 (branch merge, don't forget to commit)
268 (branch merge, don't forget to commit)
269 --------------
269 --------------
270 C a
270 C a
271 C b
271 C b
272 --------------
272 --------------
273
273
274 $ tm " " "nm a b" " " "7 get b"
274 $ tm " " "nm a b" " " "7 get b"
275 created new head
275 created new head
276 --------------
276 --------------
277 test L: R:nm a b W: - 7 get b
277 test L: R:nm a b W: - 7 get b
278 --------------
278 --------------
279 searching for copies back to rev 1
279 searching for copies back to rev 1
280 unmatched files in other:
280 unmatched files in other:
281 b
281 b
282 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
282 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
283 src: 'a' -> dst: 'b'
283 src: 'a' -> dst: 'b'
284 checking for directory renames
284 checking for directory renames
285 resolving manifests
285 resolving manifests
286 branchmerge: True, force: False, partial: False
286 branchmerge: True, force: False, partial: False
287 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
287 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
288 a: other deleted -> r
288 a: other deleted -> r
289 b: remote created -> g
289 b: remote created -> g
290 rev: versions differ -> m
290 rev: versions differ -> m
291 preserving rev for resolve of rev
291 preserving rev for resolve of rev
292 removing a
292 removing a
293 updating: a 1/3 files (33.33%)
293 updating: a 1/3 files (33.33%)
294 getting b
294 getting b
295 updating: b 2/3 files (66.67%)
295 updating: b 2/3 files (66.67%)
296 updating: rev 3/3 files (100.00%)
296 updating: rev 3/3 files (100.00%)
297 picked tool 'python ../merge' for rev (binary False symlink False)
297 picked tool 'python ../merge' for rev (binary False symlink False)
298 merging rev
298 merging rev
299 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
299 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
300 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
300 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
301 (branch merge, don't forget to commit)
301 (branch merge, don't forget to commit)
302 --------------
302 --------------
303 M b
303 M b
304 --------------
304 --------------
305
305
306 $ tm "nm a b" " " " " "8 nothing"
306 $ tm "nm a b" " " " " "8 nothing"
307 created new head
307 created new head
308 --------------
308 --------------
309 test L:nm a b R: W: - 8 nothing
309 test L:nm a b R: W: - 8 nothing
310 --------------
310 --------------
311 searching for copies back to rev 1
311 searching for copies back to rev 1
312 unmatched files in local:
312 unmatched files in local:
313 b
313 b
314 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
314 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
315 src: 'a' -> dst: 'b'
315 src: 'a' -> dst: 'b'
316 checking for directory renames
316 checking for directory renames
317 resolving manifests
317 resolving manifests
318 branchmerge: True, force: False, partial: False
318 branchmerge: True, force: False, partial: False
319 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
319 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
320 rev: versions differ -> m
320 rev: versions differ -> m
321 preserving rev for resolve of rev
321 preserving rev for resolve of rev
322 updating: rev 1/1 files (100.00%)
322 updating: rev 1/1 files (100.00%)
323 picked tool 'python ../merge' for rev (binary False symlink False)
323 picked tool 'python ../merge' for rev (binary False symlink False)
324 merging rev
324 merging rev
325 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
325 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
326 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
326 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
327 (branch merge, don't forget to commit)
327 (branch merge, don't forget to commit)
328 --------------
328 --------------
329 C b
329 C b
330 --------------
330 --------------
331
331
332 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
332 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
333 created new head
333 created new head
334 --------------
334 --------------
335 test L:um a b R:um a b W: - 9 do merge with ancestor in a
335 test L:um a b R:um a b W: - 9 do merge with ancestor in a
336 --------------
336 --------------
337 searching for copies back to rev 1
337 searching for copies back to rev 1
338 unmatched files new in both:
339 b
338 resolving manifests
340 resolving manifests
339 branchmerge: True, force: False, partial: False
341 branchmerge: True, force: False, partial: False
340 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
342 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
341 b: versions differ -> m
343 b: versions differ -> m
342 preserving b for resolve of b
344 preserving b for resolve of b
343 rev: versions differ -> m
345 rev: versions differ -> m
344 preserving rev for resolve of rev
346 preserving rev for resolve of rev
345 updating: b 1/2 files (50.00%)
347 updating: b 1/2 files (50.00%)
346 picked tool 'python ../merge' for b (binary False symlink False)
348 picked tool 'python ../merge' for b (binary False symlink False)
347 merging b
349 merging b
348 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
350 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
349 updating: rev 2/2 files (100.00%)
351 updating: rev 2/2 files (100.00%)
350 picked tool 'python ../merge' for rev (binary False symlink False)
352 picked tool 'python ../merge' for rev (binary False symlink False)
351 merging rev
353 merging rev
352 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
354 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
353 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
355 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
354 (branch merge, don't forget to commit)
356 (branch merge, don't forget to commit)
355 --------------
357 --------------
356 M b
358 M b
357 --------------
359 --------------
358
360
359
361
360 m "um a c" "um x c" " " "10 do merge with no ancestor"
362 m "um a c" "um x c" " " "10 do merge with no ancestor"
361
363
362 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
364 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
363 created new head
365 created new head
364 --------------
366 --------------
365 test L:nm a b R:nm a c W: - 11 get c, keep b
367 test L:nm a b R:nm a c W: - 11 get c, keep b
366 --------------
368 --------------
367 searching for copies back to rev 1
369 searching for copies back to rev 1
368 unmatched files in local:
370 unmatched files in local:
369 b
371 b
370 unmatched files in other:
372 unmatched files in other:
371 c
373 c
372 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
374 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
373 src: 'a' -> dst: 'b' !
375 src: 'a' -> dst: 'b' !
374 src: 'a' -> dst: 'c' !
376 src: 'a' -> dst: 'c' !
375 checking for directory renames
377 checking for directory renames
376 resolving manifests
378 resolving manifests
377 branchmerge: True, force: False, partial: False
379 branchmerge: True, force: False, partial: False
378 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
380 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
379 a: divergent renames -> dr
381 a: divergent renames -> dr
380 c: remote created -> g
382 c: remote created -> g
381 rev: versions differ -> m
383 rev: versions differ -> m
382 preserving rev for resolve of rev
384 preserving rev for resolve of rev
383 getting c
385 getting c
384 updating: c 1/3 files (33.33%)
386 updating: c 1/3 files (33.33%)
385 updating: a 2/3 files (66.67%)
387 updating: a 2/3 files (66.67%)
386 note: possible conflict - a was renamed multiple times to:
388 note: possible conflict - a was renamed multiple times to:
387 b
389 b
388 c
390 c
389 updating: rev 3/3 files (100.00%)
391 updating: rev 3/3 files (100.00%)
390 picked tool 'python ../merge' for rev (binary False symlink False)
392 picked tool 'python ../merge' for rev (binary False symlink False)
391 merging rev
393 merging rev
392 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
394 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
393 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
395 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
394 (branch merge, don't forget to commit)
396 (branch merge, don't forget to commit)
395 --------------
397 --------------
396 M c
398 M c
397 C b
399 C b
398 --------------
400 --------------
399
401
400 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
402 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
401 created new head
403 created new head
402 --------------
404 --------------
403 test L:nc a b R:up b W: - 12 merge b no ancestor
405 test L:nc a b R:up b W: - 12 merge b no ancestor
404 --------------
406 --------------
405 searching for copies back to rev 1
407 searching for copies back to rev 1
408 unmatched files new in both:
409 b
406 resolving manifests
410 resolving manifests
407 branchmerge: True, force: False, partial: False
411 branchmerge: True, force: False, partial: False
408 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
412 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
409 b: versions differ -> m
413 b: versions differ -> m
410 preserving b for resolve of b
414 preserving b for resolve of b
411 rev: versions differ -> m
415 rev: versions differ -> m
412 preserving rev for resolve of rev
416 preserving rev for resolve of rev
413 updating: b 1/2 files (50.00%)
417 updating: b 1/2 files (50.00%)
414 picked tool 'python ../merge' for b (binary False symlink False)
418 picked tool 'python ../merge' for b (binary False symlink False)
415 merging b
419 merging b
416 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
420 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
417 updating: rev 2/2 files (100.00%)
421 updating: rev 2/2 files (100.00%)
418 picked tool 'python ../merge' for rev (binary False symlink False)
422 picked tool 'python ../merge' for rev (binary False symlink False)
419 merging rev
423 merging rev
420 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
424 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
421 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
425 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
422 (branch merge, don't forget to commit)
426 (branch merge, don't forget to commit)
423 --------------
427 --------------
424 M b
428 M b
425 C a
429 C a
426 --------------
430 --------------
427
431
428 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
432 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
429 created new head
433 created new head
430 --------------
434 --------------
431 test L:up b R:nm a b W: - 13 merge b no ancestor
435 test L:up b R:nm a b W: - 13 merge b no ancestor
432 --------------
436 --------------
433 searching for copies back to rev 1
437 searching for copies back to rev 1
438 unmatched files new in both:
439 b
434 resolving manifests
440 resolving manifests
435 branchmerge: True, force: False, partial: False
441 branchmerge: True, force: False, partial: False
436 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
442 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
437 a: other deleted -> r
443 a: other deleted -> r
438 b: versions differ -> m
444 b: versions differ -> m
439 preserving b for resolve of b
445 preserving b for resolve of b
440 rev: versions differ -> m
446 rev: versions differ -> m
441 preserving rev for resolve of rev
447 preserving rev for resolve of rev
442 removing a
448 removing a
443 updating: a 1/3 files (33.33%)
449 updating: a 1/3 files (33.33%)
444 updating: b 2/3 files (66.67%)
450 updating: b 2/3 files (66.67%)
445 picked tool 'python ../merge' for b (binary False symlink False)
451 picked tool 'python ../merge' for b (binary False symlink False)
446 merging b
452 merging b
447 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
453 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
448 updating: rev 3/3 files (100.00%)
454 updating: rev 3/3 files (100.00%)
449 picked tool 'python ../merge' for rev (binary False symlink False)
455 picked tool 'python ../merge' for rev (binary False symlink False)
450 merging rev
456 merging rev
451 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
457 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
452 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
458 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
453 (branch merge, don't forget to commit)
459 (branch merge, don't forget to commit)
454 --------------
460 --------------
455 M b
461 M b
456 --------------
462 --------------
457
463
458 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
464 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
459 created new head
465 created new head
460 --------------
466 --------------
461 test L:nc a b R:up a b W: - 14 merge b no ancestor
467 test L:nc a b R:up a b W: - 14 merge b no ancestor
462 --------------
468 --------------
463 searching for copies back to rev 1
469 searching for copies back to rev 1
470 unmatched files new in both:
471 b
464 resolving manifests
472 resolving manifests
465 branchmerge: True, force: False, partial: False
473 branchmerge: True, force: False, partial: False
466 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
474 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
467 a: remote is newer -> g
475 a: remote is newer -> g
468 b: versions differ -> m
476 b: versions differ -> m
469 preserving b for resolve of b
477 preserving b for resolve of b
470 rev: versions differ -> m
478 rev: versions differ -> m
471 preserving rev for resolve of rev
479 preserving rev for resolve of rev
472 getting a
480 getting a
473 updating: a 1/3 files (33.33%)
481 updating: a 1/3 files (33.33%)
474 updating: b 2/3 files (66.67%)
482 updating: b 2/3 files (66.67%)
475 picked tool 'python ../merge' for b (binary False symlink False)
483 picked tool 'python ../merge' for b (binary False symlink False)
476 merging b
484 merging b
477 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
485 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
478 updating: rev 3/3 files (100.00%)
486 updating: rev 3/3 files (100.00%)
479 picked tool 'python ../merge' for rev (binary False symlink False)
487 picked tool 'python ../merge' for rev (binary False symlink False)
480 merging rev
488 merging rev
481 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
489 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
482 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
490 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
483 (branch merge, don't forget to commit)
491 (branch merge, don't forget to commit)
484 --------------
492 --------------
485 M a
493 M a
486 M b
494 M b
487 --------------
495 --------------
488
496
489 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
497 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
490 created new head
498 created new head
491 --------------
499 --------------
492 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
500 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
493 --------------
501 --------------
494 searching for copies back to rev 1
502 searching for copies back to rev 1
503 unmatched files new in both:
504 b
495 resolving manifests
505 resolving manifests
496 branchmerge: True, force: False, partial: False
506 branchmerge: True, force: False, partial: False
497 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
507 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
498 a: other deleted -> r
508 a: other deleted -> r
499 b: versions differ -> m
509 b: versions differ -> m
500 preserving b for resolve of b
510 preserving b for resolve of b
501 rev: versions differ -> m
511 rev: versions differ -> m
502 preserving rev for resolve of rev
512 preserving rev for resolve of rev
503 removing a
513 removing a
504 updating: a 1/3 files (33.33%)
514 updating: a 1/3 files (33.33%)
505 updating: b 2/3 files (66.67%)
515 updating: b 2/3 files (66.67%)
506 picked tool 'python ../merge' for b (binary False symlink False)
516 picked tool 'python ../merge' for b (binary False symlink False)
507 merging b
517 merging b
508 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
518 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
509 updating: rev 3/3 files (100.00%)
519 updating: rev 3/3 files (100.00%)
510 picked tool 'python ../merge' for rev (binary False symlink False)
520 picked tool 'python ../merge' for rev (binary False symlink False)
511 merging rev
521 merging rev
512 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
522 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
513 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
523 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
514 (branch merge, don't forget to commit)
524 (branch merge, don't forget to commit)
515 --------------
525 --------------
516 M b
526 M b
517 --------------
527 --------------
518
528
519 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
529 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
520 created new head
530 created new head
521 --------------
531 --------------
522 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
532 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
523 --------------
533 --------------
524 searching for copies back to rev 1
534 searching for copies back to rev 1
535 unmatched files new in both:
536 b
525 resolving manifests
537 resolving manifests
526 branchmerge: True, force: False, partial: False
538 branchmerge: True, force: False, partial: False
527 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
539 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
528 a: remote is newer -> g
540 a: remote is newer -> g
529 b: versions differ -> m
541 b: versions differ -> m
530 preserving b for resolve of b
542 preserving b for resolve of b
531 rev: versions differ -> m
543 rev: versions differ -> m
532 preserving rev for resolve of rev
544 preserving rev for resolve of rev
533 getting a
545 getting a
534 updating: a 1/3 files (33.33%)
546 updating: a 1/3 files (33.33%)
535 updating: b 2/3 files (66.67%)
547 updating: b 2/3 files (66.67%)
536 picked tool 'python ../merge' for b (binary False symlink False)
548 picked tool 'python ../merge' for b (binary False symlink False)
537 merging b
549 merging b
538 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
550 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
539 updating: rev 3/3 files (100.00%)
551 updating: rev 3/3 files (100.00%)
540 picked tool 'python ../merge' for rev (binary False symlink False)
552 picked tool 'python ../merge' for rev (binary False symlink False)
541 merging rev
553 merging rev
542 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
554 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
543 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
555 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
544 (branch merge, don't forget to commit)
556 (branch merge, don't forget to commit)
545 --------------
557 --------------
546 M a
558 M a
547 M b
559 M b
548 --------------
560 --------------
549
561
550 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
562 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
551 created new head
563 created new head
552 --------------
564 --------------
553 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
565 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
554 --------------
566 --------------
555 searching for copies back to rev 1
567 searching for copies back to rev 1
568 unmatched files new in both:
569 b
556 resolving manifests
570 resolving manifests
557 branchmerge: True, force: False, partial: False
571 branchmerge: True, force: False, partial: False
558 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
572 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
559 b: versions differ -> m
573 b: versions differ -> m
560 preserving b for resolve of b
574 preserving b for resolve of b
561 rev: versions differ -> m
575 rev: versions differ -> m
562 preserving rev for resolve of rev
576 preserving rev for resolve of rev
563 updating: b 1/2 files (50.00%)
577 updating: b 1/2 files (50.00%)
564 picked tool 'python ../merge' for b (binary False symlink False)
578 picked tool 'python ../merge' for b (binary False symlink False)
565 merging b
579 merging b
566 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
580 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
567 updating: rev 2/2 files (100.00%)
581 updating: rev 2/2 files (100.00%)
568 picked tool 'python ../merge' for rev (binary False symlink False)
582 picked tool 'python ../merge' for rev (binary False symlink False)
569 merging rev
583 merging rev
570 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
584 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
571 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
585 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
572 (branch merge, don't forget to commit)
586 (branch merge, don't forget to commit)
573 --------------
587 --------------
574 M b
588 M b
575 C a
589 C a
576 --------------
590 --------------
577
591
578 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
592 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
579 created new head
593 created new head
580 --------------
594 --------------
581 test L:nm a b R:up a b W: - 18 merge b no ancestor
595 test L:nm a b R:up a b W: - 18 merge b no ancestor
582 --------------
596 --------------
583 searching for copies back to rev 1
597 searching for copies back to rev 1
598 unmatched files new in both:
599 b
584 resolving manifests
600 resolving manifests
585 branchmerge: True, force: False, partial: False
601 branchmerge: True, force: False, partial: False
586 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
602 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
587 remote changed a which local deleted
603 remote changed a which local deleted
588 use (c)hanged version or leave (d)eleted? c
604 use (c)hanged version or leave (d)eleted? c
589 a: prompt recreating -> g
605 a: prompt recreating -> g
590 b: versions differ -> m
606 b: versions differ -> m
591 preserving b for resolve of b
607 preserving b for resolve of b
592 rev: versions differ -> m
608 rev: versions differ -> m
593 preserving rev for resolve of rev
609 preserving rev for resolve of rev
594 getting a
610 getting a
595 updating: a 1/3 files (33.33%)
611 updating: a 1/3 files (33.33%)
596 updating: b 2/3 files (66.67%)
612 updating: b 2/3 files (66.67%)
597 picked tool 'python ../merge' for b (binary False symlink False)
613 picked tool 'python ../merge' for b (binary False symlink False)
598 merging b
614 merging b
599 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
615 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
600 updating: rev 3/3 files (100.00%)
616 updating: rev 3/3 files (100.00%)
601 picked tool 'python ../merge' for rev (binary False symlink False)
617 picked tool 'python ../merge' for rev (binary False symlink False)
602 merging rev
618 merging rev
603 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
619 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
604 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
620 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
605 (branch merge, don't forget to commit)
621 (branch merge, don't forget to commit)
606 --------------
622 --------------
607 M a
623 M a
608 M b
624 M b
609 --------------
625 --------------
610
626
611 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
627 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
612 created new head
628 created new head
613 --------------
629 --------------
614 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
630 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
615 --------------
631 --------------
616 searching for copies back to rev 1
632 searching for copies back to rev 1
633 unmatched files new in both:
634 b
617 resolving manifests
635 resolving manifests
618 branchmerge: True, force: False, partial: False
636 branchmerge: True, force: False, partial: False
619 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
637 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
620 local changed a which remote deleted
638 local changed a which remote deleted
621 use (c)hanged version or (d)elete? c
639 use (c)hanged version or (d)elete? c
622 a: prompt keep -> a
640 a: prompt keep -> a
623 b: versions differ -> m
641 b: versions differ -> m
624 preserving b for resolve of b
642 preserving b for resolve of b
625 rev: versions differ -> m
643 rev: versions differ -> m
626 preserving rev for resolve of rev
644 preserving rev for resolve of rev
627 updating: a 1/3 files (33.33%)
645 updating: a 1/3 files (33.33%)
628 updating: b 2/3 files (66.67%)
646 updating: b 2/3 files (66.67%)
629 picked tool 'python ../merge' for b (binary False symlink False)
647 picked tool 'python ../merge' for b (binary False symlink False)
630 merging b
648 merging b
631 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
649 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
632 updating: rev 3/3 files (100.00%)
650 updating: rev 3/3 files (100.00%)
633 picked tool 'python ../merge' for rev (binary False symlink False)
651 picked tool 'python ../merge' for rev (binary False symlink False)
634 merging rev
652 merging rev
635 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
653 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
636 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
654 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
637 (branch merge, don't forget to commit)
655 (branch merge, don't forget to commit)
638 --------------
656 --------------
639 M b
657 M b
640 C a
658 C a
641 --------------
659 --------------
642
660
643 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
661 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
644 created new head
662 created new head
645 --------------
663 --------------
646 test L:up a R:um a b W: - 20 merge a and b to b, remove a
664 test L:up a R:um a b W: - 20 merge a and b to b, remove a
647 --------------
665 --------------
648 searching for copies back to rev 1
666 searching for copies back to rev 1
649 unmatched files in other:
667 unmatched files in other:
650 b
668 b
651 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
669 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
652 src: 'a' -> dst: 'b' *
670 src: 'a' -> dst: 'b' *
653 checking for directory renames
671 checking for directory renames
654 resolving manifests
672 resolving manifests
655 branchmerge: True, force: False, partial: False
673 branchmerge: True, force: False, partial: False
656 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
674 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
657 a: remote moved to b -> m
675 a: remote moved to b -> m
658 preserving a for resolve of b
676 preserving a for resolve of b
659 rev: versions differ -> m
677 rev: versions differ -> m
660 preserving rev for resolve of rev
678 preserving rev for resolve of rev
661 removing a
679 removing a
662 updating: a 1/2 files (50.00%)
680 updating: a 1/2 files (50.00%)
663 picked tool 'python ../merge' for b (binary False symlink False)
681 picked tool 'python ../merge' for b (binary False symlink False)
664 merging a and b to b
682 merging a and b to b
665 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
683 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
666 updating: rev 2/2 files (100.00%)
684 updating: rev 2/2 files (100.00%)
667 picked tool 'python ../merge' for rev (binary False symlink False)
685 picked tool 'python ../merge' for rev (binary False symlink False)
668 merging rev
686 merging rev
669 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
687 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
670 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
688 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
671 (branch merge, don't forget to commit)
689 (branch merge, don't forget to commit)
672 --------------
690 --------------
673 M b
691 M b
674 a
692 a
675 --------------
693 --------------
676
694
677 $ tm "um a b" "up a " " " "21 merge a and b to b"
695 $ tm "um a b" "up a " " " "21 merge a and b to b"
678 created new head
696 created new head
679 --------------
697 --------------
680 test L:um a b R:up a W: - 21 merge a and b to b
698 test L:um a b R:up a W: - 21 merge a and b to b
681 --------------
699 --------------
682 searching for copies back to rev 1
700 searching for copies back to rev 1
683 unmatched files in local:
701 unmatched files in local:
684 b
702 b
685 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
703 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
686 src: 'a' -> dst: 'b' *
704 src: 'a' -> dst: 'b' *
687 checking for directory renames
705 checking for directory renames
688 resolving manifests
706 resolving manifests
689 branchmerge: True, force: False, partial: False
707 branchmerge: True, force: False, partial: False
690 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
708 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
691 b: local copied/moved to a -> m
709 b: local copied/moved to a -> m
692 preserving b for resolve of b
710 preserving b for resolve of b
693 rev: versions differ -> m
711 rev: versions differ -> m
694 preserving rev for resolve of rev
712 preserving rev for resolve of rev
695 updating: b 1/2 files (50.00%)
713 updating: b 1/2 files (50.00%)
696 picked tool 'python ../merge' for b (binary False symlink False)
714 picked tool 'python ../merge' for b (binary False symlink False)
697 merging b and a to b
715 merging b and a to b
698 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
716 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
699 updating: rev 2/2 files (100.00%)
717 updating: rev 2/2 files (100.00%)
700 picked tool 'python ../merge' for rev (binary False symlink False)
718 picked tool 'python ../merge' for rev (binary False symlink False)
701 merging rev
719 merging rev
702 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
720 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
703 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
721 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
704 (branch merge, don't forget to commit)
722 (branch merge, don't forget to commit)
705 --------------
723 --------------
706 M b
724 M b
707 a
725 a
708 --------------
726 --------------
709
727
710
728
711 m "nm a b" "um x a" " " "22 get a, keep b"
729 m "nm a b" "um x a" " " "22 get a, keep b"
712
730
713 $ tm "nm a b" "up a c" " " "23 get c, keep b"
731 $ tm "nm a b" "up a c" " " "23 get c, keep b"
714 created new head
732 created new head
715 --------------
733 --------------
716 test L:nm a b R:up a c W: - 23 get c, keep b
734 test L:nm a b R:up a c W: - 23 get c, keep b
717 --------------
735 --------------
718 searching for copies back to rev 1
736 searching for copies back to rev 1
719 unmatched files in local:
737 unmatched files in local:
720 b
738 b
721 unmatched files in other:
739 unmatched files in other:
722 c
740 c
723 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
741 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
724 src: 'a' -> dst: 'b' *
742 src: 'a' -> dst: 'b' *
725 checking for directory renames
743 checking for directory renames
726 resolving manifests
744 resolving manifests
727 branchmerge: True, force: False, partial: False
745 branchmerge: True, force: False, partial: False
728 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
746 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
729 b: local copied/moved to a -> m
747 b: local copied/moved to a -> m
730 preserving b for resolve of b
748 preserving b for resolve of b
731 c: remote created -> g
749 c: remote created -> g
732 rev: versions differ -> m
750 rev: versions differ -> m
733 preserving rev for resolve of rev
751 preserving rev for resolve of rev
734 getting c
752 getting c
735 updating: c 1/3 files (33.33%)
753 updating: c 1/3 files (33.33%)
736 updating: b 2/3 files (66.67%)
754 updating: b 2/3 files (66.67%)
737 picked tool 'python ../merge' for b (binary False symlink False)
755 picked tool 'python ../merge' for b (binary False symlink False)
738 merging b and a to b
756 merging b and a to b
739 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
757 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
740 premerge successful
758 premerge successful
741 updating: rev 3/3 files (100.00%)
759 updating: rev 3/3 files (100.00%)
742 picked tool 'python ../merge' for rev (binary False symlink False)
760 picked tool 'python ../merge' for rev (binary False symlink False)
743 merging rev
761 merging rev
744 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
762 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
745 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
763 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
746 (branch merge, don't forget to commit)
764 (branch merge, don't forget to commit)
747 --------------
765 --------------
748 M b
766 M b
749 a
767 a
750 M c
768 M c
751 --------------
769 --------------
752
770
753
771
754 $ cd ..
772 $ cd ..
755
773
756
774
757 Systematic and terse testing of merge merges and ancestor calculation:
775 Systematic and terse testing of merge merges and ancestor calculation:
758
776
759 Excpected result:
777 Excpected result:
760
778
761 \ a m1 m2 dst
779 \ a m1 m2 dst
762 0 - f f f "versions differ"
780 0 - f f f "versions differ"
763 1 f g g g "versions differ"
781 1 f g g g "versions differ"
764 2 f f f f "versions differ"
782 2 f f f f "versions differ"
765 3 f f g f+g "remote copied to " + f
783 3 f f g f+g "remote copied to " + f
766 4 f f g g "remote moved to " + f
784 4 f f g g "remote moved to " + f
767 5 f g f f+g "local copied to " + f2
785 5 f g f f+g "local copied to " + f2
768 6 f g f g "local moved to " + f2
786 6 f g f g "local moved to " + f2
769 7 - (f) f f "remote differs from untracked local"
787 7 - (f) f f "remote differs from untracked local"
770 8 f (f) f f "remote differs from untracked local"
788 8 f (f) f f "remote differs from untracked local"
771
789
772 $ hg init ancestortest
790 $ hg init ancestortest
773 $ cd ancestortest
791 $ cd ancestortest
774 $ for x in 1 2 3 4 5 6 8; do mkdir $x; echo a > $x/f; done
792 $ for x in 1 2 3 4 5 6 8; do mkdir $x; echo a > $x/f; done
775 $ hg ci -Aqm "a"
793 $ hg ci -Aqm "a"
776 $ mkdir 0
794 $ mkdir 0
777 $ touch 0/f
795 $ touch 0/f
778 $ hg mv 1/f 1/g
796 $ hg mv 1/f 1/g
779 $ hg cp 5/f 5/g
797 $ hg cp 5/f 5/g
780 $ hg mv 6/f 6/g
798 $ hg mv 6/f 6/g
781 $ hg rm 8/f
799 $ hg rm 8/f
782 $ for x in */*; do echo m1 > $x; done
800 $ for x in */*; do echo m1 > $x; done
783 $ hg ci -Aqm "m1"
801 $ hg ci -Aqm "m1"
784 $ hg up -qr0
802 $ hg up -qr0
785 $ mkdir 0 7
803 $ mkdir 0 7
786 $ touch 0/f 7/f
804 $ touch 0/f 7/f
787 $ hg mv 1/f 1/g
805 $ hg mv 1/f 1/g
788 $ hg cp 3/f 3/g
806 $ hg cp 3/f 3/g
789 $ hg mv 4/f 4/g
807 $ hg mv 4/f 4/g
790 $ for x in */*; do echo m2 > $x; done
808 $ for x in */*; do echo m2 > $x; done
791 $ hg ci -Aqm "m2"
809 $ hg ci -Aqm "m2"
792 $ hg up -qr1
810 $ hg up -qr1
793 $ mkdir 7 8
811 $ mkdir 7 8
794 $ echo m > 7/f
812 $ echo m > 7/f
795 $ echo m > 8/f
813 $ echo m > 8/f
796 $ hg merge -f --tool internal:dump -v --debug -r2 | sed '/^updating:/,$d' 2> /dev/null
814 $ hg merge -f --tool internal:dump -v --debug -r2 | sed '/^updating:/,$d' 2> /dev/null
797 searching for copies back to rev 1
815 searching for copies back to rev 1
798 unmatched files in local:
816 unmatched files in local:
799 5/g
817 5/g
800 6/g
818 6/g
801 unmatched files in other:
819 unmatched files in other:
802 3/g
820 3/g
803 4/g
821 4/g
804 7/f
822 7/f
823 unmatched files new in both:
824 0/f
825 1/g
805 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
826 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
806 src: '3/f' -> dst: '3/g' *
827 src: '3/f' -> dst: '3/g' *
807 src: '4/f' -> dst: '4/g' *
828 src: '4/f' -> dst: '4/g' *
808 src: '5/f' -> dst: '5/g' *
829 src: '5/f' -> dst: '5/g' *
809 src: '6/f' -> dst: '6/g' *
830 src: '6/f' -> dst: '6/g' *
810 checking for directory renames
831 checking for directory renames
811 resolving manifests
832 resolving manifests
812 branchmerge: True, force: True, partial: False
833 branchmerge: True, force: True, partial: False
813 ancestor: e6cb3cf11019, local: ec44bf929ab5+, remote: c62e34d0b898
834 ancestor: e6cb3cf11019, local: ec44bf929ab5+, remote: c62e34d0b898
814 remote changed 8/f which local deleted
835 remote changed 8/f which local deleted
815 use (c)hanged version or leave (d)eleted? c
836 use (c)hanged version or leave (d)eleted? c
816 0/f: versions differ -> m
837 0/f: versions differ -> m
817 preserving 0/f for resolve of 0/f
838 preserving 0/f for resolve of 0/f
818 1/g: versions differ -> m
839 1/g: versions differ -> m
819 preserving 1/g for resolve of 1/g
840 preserving 1/g for resolve of 1/g
820 2/f: versions differ -> m
841 2/f: versions differ -> m
821 preserving 2/f for resolve of 2/f
842 preserving 2/f for resolve of 2/f
822 3/f: versions differ -> m
843 3/f: versions differ -> m
823 preserving 3/f for resolve of 3/f
844 preserving 3/f for resolve of 3/f
824 3/f: remote copied to 3/g -> m
845 3/f: remote copied to 3/g -> m
825 preserving 3/f for resolve of 3/g
846 preserving 3/f for resolve of 3/g
826 4/f: remote moved to 4/g -> m
847 4/f: remote moved to 4/g -> m
827 preserving 4/f for resolve of 4/g
848 preserving 4/f for resolve of 4/g
828 5/f: versions differ -> m
849 5/f: versions differ -> m
829 preserving 5/f for resolve of 5/f
850 preserving 5/f for resolve of 5/f
830 5/g: local copied/moved to 5/f -> m
851 5/g: local copied/moved to 5/f -> m
831 preserving 5/g for resolve of 5/g
852 preserving 5/g for resolve of 5/g
832 6/g: local copied/moved to 6/f -> m
853 6/g: local copied/moved to 6/f -> m
833 preserving 6/g for resolve of 6/g
854 preserving 6/g for resolve of 6/g
834 7/f: remote differs from untracked local -> m
855 7/f: remote differs from untracked local -> m
835 preserving 7/f for resolve of 7/f
856 preserving 7/f for resolve of 7/f
836 8/f: prompt recreating -> g
857 8/f: prompt recreating -> g
837 removing 4/f
858 removing 4/f
838 getting 8/f
859 getting 8/f
839 $ hg mani
860 $ hg mani
840 0/f
861 0/f
841 1/g
862 1/g
842 2/f
863 2/f
843 3/f
864 3/f
844 4/f
865 4/f
845 5/f
866 5/f
846 5/g
867 5/g
847 6/g
868 6/g
848 $ for f in */*; do echo $f:; cat $f; done
869 $ for f in */*; do echo $f:; cat $f; done
849 0/f:
870 0/f:
850 m1
871 m1
851 0/f.base:
872 0/f.base:
852 0/f.local:
873 0/f.local:
853 m1
874 m1
854 0/f.orig:
875 0/f.orig:
855 m1
876 m1
856 0/f.other:
877 0/f.other:
857 m2
878 m2
858 1/g:
879 1/g:
859 m1
880 m1
860 1/g.base:
881 1/g.base:
861 a
882 a
862 1/g.local:
883 1/g.local:
863 m1
884 m1
864 1/g.orig:
885 1/g.orig:
865 m1
886 m1
866 1/g.other:
887 1/g.other:
867 m2
888 m2
868 2/f:
889 2/f:
869 m1
890 m1
870 2/f.base:
891 2/f.base:
871 a
892 a
872 2/f.local:
893 2/f.local:
873 m1
894 m1
874 2/f.orig:
895 2/f.orig:
875 m1
896 m1
876 2/f.other:
897 2/f.other:
877 m2
898 m2
878 3/f:
899 3/f:
879 m1
900 m1
880 3/f.base:
901 3/f.base:
881 a
902 a
882 3/f.local:
903 3/f.local:
883 m1
904 m1
884 3/f.orig:
905 3/f.orig:
885 m1
906 m1
886 3/f.other:
907 3/f.other:
887 m2
908 m2
888 3/g:
909 3/g:
889 m1
910 m1
890 3/g.base:
911 3/g.base:
891 a
912 a
892 3/g.local:
913 3/g.local:
893 m1
914 m1
894 3/g.orig:
915 3/g.orig:
895 m1
916 m1
896 3/g.other:
917 3/g.other:
897 m2
918 m2
898 4/g:
919 4/g:
899 m1
920 m1
900 4/g.base:
921 4/g.base:
901 a
922 a
902 4/g.local:
923 4/g.local:
903 m1
924 m1
904 4/g.orig:
925 4/g.orig:
905 m1
926 m1
906 4/g.other:
927 4/g.other:
907 m2
928 m2
908 5/f:
929 5/f:
909 m1
930 m1
910 5/f.base:
931 5/f.base:
911 a
932 a
912 5/f.local:
933 5/f.local:
913 m1
934 m1
914 5/f.orig:
935 5/f.orig:
915 m1
936 m1
916 5/f.other:
937 5/f.other:
917 m2
938 m2
918 5/g:
939 5/g:
919 m1
940 m1
920 5/g.base:
941 5/g.base:
921 a
942 a
922 5/g.local:
943 5/g.local:
923 m1
944 m1
924 5/g.orig:
945 5/g.orig:
925 m1
946 m1
926 5/g.other:
947 5/g.other:
927 m2
948 m2
928 6/g:
949 6/g:
929 m1
950 m1
930 6/g.base:
951 6/g.base:
931 a
952 a
932 6/g.local:
953 6/g.local:
933 m1
954 m1
934 6/g.orig:
955 6/g.orig:
935 m1
956 m1
936 6/g.other:
957 6/g.other:
937 m2
958 m2
938 7/f:
959 7/f:
939 m
960 m
940 7/f.base:
961 7/f.base:
941 7/f.local:
962 7/f.local:
942 m
963 m
943 7/f.orig:
964 7/f.orig:
944 m
965 m
945 7/f.other:
966 7/f.other:
946 m2
967 m2
947 8/f:
968 8/f:
948 m2
969 m2
949 $ cd ..
970 $ cd ..
@@ -1,239 +1,241 b''
1 $ HGMERGE=true; export HGMERGE
1 $ HGMERGE=true; export HGMERGE
2
2
3 $ hg init r1
3 $ hg init r1
4 $ cd r1
4 $ cd r1
5 $ echo a > a
5 $ echo a > a
6 $ hg addremove
6 $ hg addremove
7 adding a
7 adding a
8 $ hg commit -m "1"
8 $ hg commit -m "1"
9
9
10 $ hg clone . ../r2
10 $ hg clone . ../r2
11 updating to branch default
11 updating to branch default
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 $ cd ../r2
13 $ cd ../r2
14 $ hg up
14 $ hg up
15 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 $ echo abc > a
16 $ echo abc > a
17 $ hg diff --nodates
17 $ hg diff --nodates
18 diff -r c19d34741b0a a
18 diff -r c19d34741b0a a
19 --- a/a
19 --- a/a
20 +++ b/a
20 +++ b/a
21 @@ -1,1 +1,1 @@
21 @@ -1,1 +1,1 @@
22 -a
22 -a
23 +abc
23 +abc
24
24
25 $ cd ../r1
25 $ cd ../r1
26 $ echo b > b
26 $ echo b > b
27 $ echo a2 > a
27 $ echo a2 > a
28 $ hg addremove
28 $ hg addremove
29 adding b
29 adding b
30 $ hg commit -m "2"
30 $ hg commit -m "2"
31
31
32 $ cd ../r2
32 $ cd ../r2
33 $ hg -q pull ../r1
33 $ hg -q pull ../r1
34 $ hg status
34 $ hg status
35 M a
35 M a
36 $ hg parents
36 $ hg parents
37 changeset: 0:c19d34741b0a
37 changeset: 0:c19d34741b0a
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 1
40 summary: 1
41
41
42 $ hg --debug up
42 $ hg --debug up
43 searching for copies back to rev 1
43 searching for copies back to rev 1
44 unmatched files in other:
44 unmatched files in other:
45 b
45 b
46 resolving manifests
46 resolving manifests
47 branchmerge: False, force: False, partial: False
47 branchmerge: False, force: False, partial: False
48 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
48 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
49 a: versions differ -> m
49 a: versions differ -> m
50 preserving a for resolve of a
50 preserving a for resolve of a
51 b: remote created -> g
51 b: remote created -> g
52 getting b
52 getting b
53 updating: b 1/2 files (50.00%)
53 updating: b 1/2 files (50.00%)
54 updating: a 2/2 files (100.00%)
54 updating: a 2/2 files (100.00%)
55 picked tool 'true' for a (binary False symlink False)
55 picked tool 'true' for a (binary False symlink False)
56 merging a
56 merging a
57 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
57 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
58 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
58 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
59 $ hg parents
59 $ hg parents
60 changeset: 1:1e71731e6fbb
60 changeset: 1:1e71731e6fbb
61 tag: tip
61 tag: tip
62 user: test
62 user: test
63 date: Thu Jan 01 00:00:00 1970 +0000
63 date: Thu Jan 01 00:00:00 1970 +0000
64 summary: 2
64 summary: 2
65
65
66 $ hg --debug up 0
66 $ hg --debug up 0
67 resolving manifests
67 resolving manifests
68 branchmerge: False, force: False, partial: False
68 branchmerge: False, force: False, partial: False
69 ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
69 ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
70 b: other deleted -> r
70 b: other deleted -> r
71 a: versions differ -> m
71 a: versions differ -> m
72 preserving a for resolve of a
72 preserving a for resolve of a
73 removing b
73 removing b
74 updating: b 1/2 files (50.00%)
74 updating: b 1/2 files (50.00%)
75 updating: a 2/2 files (100.00%)
75 updating: a 2/2 files (100.00%)
76 picked tool 'true' for a (binary False symlink False)
76 picked tool 'true' for a (binary False symlink False)
77 merging a
77 merging a
78 my a@1e71731e6fbb+ other a@c19d34741b0a ancestor a@1e71731e6fbb
78 my a@1e71731e6fbb+ other a@c19d34741b0a ancestor a@1e71731e6fbb
79 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
79 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
80 $ hg parents
80 $ hg parents
81 changeset: 0:c19d34741b0a
81 changeset: 0:c19d34741b0a
82 user: test
82 user: test
83 date: Thu Jan 01 00:00:00 1970 +0000
83 date: Thu Jan 01 00:00:00 1970 +0000
84 summary: 1
84 summary: 1
85
85
86 $ hg --debug merge
86 $ hg --debug merge
87 abort: nothing to merge
87 abort: nothing to merge
88 (use 'hg update' instead)
88 (use 'hg update' instead)
89 [255]
89 [255]
90 $ hg parents
90 $ hg parents
91 changeset: 0:c19d34741b0a
91 changeset: 0:c19d34741b0a
92 user: test
92 user: test
93 date: Thu Jan 01 00:00:00 1970 +0000
93 date: Thu Jan 01 00:00:00 1970 +0000
94 summary: 1
94 summary: 1
95
95
96 $ hg --debug up
96 $ hg --debug up
97 searching for copies back to rev 1
97 searching for copies back to rev 1
98 unmatched files in other:
98 unmatched files in other:
99 b
99 b
100 resolving manifests
100 resolving manifests
101 branchmerge: False, force: False, partial: False
101 branchmerge: False, force: False, partial: False
102 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
102 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
103 a: versions differ -> m
103 a: versions differ -> m
104 preserving a for resolve of a
104 preserving a for resolve of a
105 b: remote created -> g
105 b: remote created -> g
106 getting b
106 getting b
107 updating: b 1/2 files (50.00%)
107 updating: b 1/2 files (50.00%)
108 updating: a 2/2 files (100.00%)
108 updating: a 2/2 files (100.00%)
109 picked tool 'true' for a (binary False symlink False)
109 picked tool 'true' for a (binary False symlink False)
110 merging a
110 merging a
111 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
111 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
112 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
112 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
113 $ hg parents
113 $ hg parents
114 changeset: 1:1e71731e6fbb
114 changeset: 1:1e71731e6fbb
115 tag: tip
115 tag: tip
116 user: test
116 user: test
117 date: Thu Jan 01 00:00:00 1970 +0000
117 date: Thu Jan 01 00:00:00 1970 +0000
118 summary: 2
118 summary: 2
119
119
120 $ hg -v history
120 $ hg -v history
121 changeset: 1:1e71731e6fbb
121 changeset: 1:1e71731e6fbb
122 tag: tip
122 tag: tip
123 user: test
123 user: test
124 date: Thu Jan 01 00:00:00 1970 +0000
124 date: Thu Jan 01 00:00:00 1970 +0000
125 files: a b
125 files: a b
126 description:
126 description:
127 2
127 2
128
128
129
129
130 changeset: 0:c19d34741b0a
130 changeset: 0:c19d34741b0a
131 user: test
131 user: test
132 date: Thu Jan 01 00:00:00 1970 +0000
132 date: Thu Jan 01 00:00:00 1970 +0000
133 files: a
133 files: a
134 description:
134 description:
135 1
135 1
136
136
137
137
138 $ hg diff --nodates
138 $ hg diff --nodates
139 diff -r 1e71731e6fbb a
139 diff -r 1e71731e6fbb a
140 --- a/a
140 --- a/a
141 +++ b/a
141 +++ b/a
142 @@ -1,1 +1,1 @@
142 @@ -1,1 +1,1 @@
143 -a2
143 -a2
144 +abc
144 +abc
145
145
146
146
147 create a second head
147 create a second head
148
148
149 $ cd ../r1
149 $ cd ../r1
150 $ hg up 0
150 $ hg up 0
151 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
151 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
152 $ echo b2 > b
152 $ echo b2 > b
153 $ echo a3 > a
153 $ echo a3 > a
154 $ hg addremove
154 $ hg addremove
155 adding b
155 adding b
156 $ hg commit -m "3"
156 $ hg commit -m "3"
157 created new head
157 created new head
158
158
159 $ cd ../r2
159 $ cd ../r2
160 $ hg -q pull ../r1
160 $ hg -q pull ../r1
161 $ hg status
161 $ hg status
162 M a
162 M a
163 $ hg parents
163 $ hg parents
164 changeset: 1:1e71731e6fbb
164 changeset: 1:1e71731e6fbb
165 user: test
165 user: test
166 date: Thu Jan 01 00:00:00 1970 +0000
166 date: Thu Jan 01 00:00:00 1970 +0000
167 summary: 2
167 summary: 2
168
168
169 $ hg --debug up
169 $ hg --debug up
170 abort: uncommitted changes
170 abort: uncommitted changes
171 (commit and merge, or update --clean to discard changes)
171 (commit and merge, or update --clean to discard changes)
172 [255]
172 [255]
173 $ hg --debug merge
173 $ hg --debug merge
174 abort: uncommitted changes
174 abort: uncommitted changes
175 (use 'hg status' to list changes)
175 (use 'hg status' to list changes)
176 [255]
176 [255]
177 $ hg --debug merge -f
177 $ hg --debug merge -f
178 searching for copies back to rev 1
178 searching for copies back to rev 1
179 unmatched files new in both:
180 b
179 resolving manifests
181 resolving manifests
180 branchmerge: True, force: True, partial: False
182 branchmerge: True, force: True, partial: False
181 ancestor: c19d34741b0a, local: 1e71731e6fbb+, remote: 83c51d0caff4
183 ancestor: c19d34741b0a, local: 1e71731e6fbb+, remote: 83c51d0caff4
182 a: versions differ -> m
184 a: versions differ -> m
183 preserving a for resolve of a
185 preserving a for resolve of a
184 b: versions differ -> m
186 b: versions differ -> m
185 preserving b for resolve of b
187 preserving b for resolve of b
186 updating: a 1/2 files (50.00%)
188 updating: a 1/2 files (50.00%)
187 picked tool 'true' for a (binary False symlink False)
189 picked tool 'true' for a (binary False symlink False)
188 merging a
190 merging a
189 my a@1e71731e6fbb+ other a@83c51d0caff4 ancestor a@c19d34741b0a
191 my a@1e71731e6fbb+ other a@83c51d0caff4 ancestor a@c19d34741b0a
190 updating: b 2/2 files (100.00%)
192 updating: b 2/2 files (100.00%)
191 picked tool 'true' for b (binary False symlink False)
193 picked tool 'true' for b (binary False symlink False)
192 merging b
194 merging b
193 my b@1e71731e6fbb+ other b@83c51d0caff4 ancestor b@000000000000
195 my b@1e71731e6fbb+ other b@83c51d0caff4 ancestor b@000000000000
194 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
196 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
195 (branch merge, don't forget to commit)
197 (branch merge, don't forget to commit)
196 $ hg parents
198 $ hg parents
197 changeset: 1:1e71731e6fbb
199 changeset: 1:1e71731e6fbb
198 user: test
200 user: test
199 date: Thu Jan 01 00:00:00 1970 +0000
201 date: Thu Jan 01 00:00:00 1970 +0000
200 summary: 2
202 summary: 2
201
203
202 changeset: 2:83c51d0caff4
204 changeset: 2:83c51d0caff4
203 tag: tip
205 tag: tip
204 parent: 0:c19d34741b0a
206 parent: 0:c19d34741b0a
205 user: test
207 user: test
206 date: Thu Jan 01 00:00:00 1970 +0000
208 date: Thu Jan 01 00:00:00 1970 +0000
207 summary: 3
209 summary: 3
208
210
209 $ hg diff --nodates
211 $ hg diff --nodates
210 diff -r 1e71731e6fbb a
212 diff -r 1e71731e6fbb a
211 --- a/a
213 --- a/a
212 +++ b/a
214 +++ b/a
213 @@ -1,1 +1,1 @@
215 @@ -1,1 +1,1 @@
214 -a2
216 -a2
215 +abc
217 +abc
216
218
217
219
218 test a local add
220 test a local add
219
221
220 $ cd ..
222 $ cd ..
221 $ hg init a
223 $ hg init a
222 $ hg init b
224 $ hg init b
223 $ echo a > a/a
225 $ echo a > a/a
224 $ echo a > b/a
226 $ echo a > b/a
225 $ hg --cwd a commit -A -m a
227 $ hg --cwd a commit -A -m a
226 adding a
228 adding a
227 $ cd b
229 $ cd b
228 $ hg add a
230 $ hg add a
229 $ hg pull -u ../a
231 $ hg pull -u ../a
230 pulling from ../a
232 pulling from ../a
231 requesting all changes
233 requesting all changes
232 adding changesets
234 adding changesets
233 adding manifests
235 adding manifests
234 adding file changes
236 adding file changes
235 added 1 changesets with 1 changes to 1 files
237 added 1 changesets with 1 changes to 1 files
236 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
237 $ hg st
239 $ hg st
238
240
239 $ cd ..
241 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now