172 for mf in match[of]: |
172 for mf in match[of]: |
173 checkpair(c, mf, m1) |
173 checkpair(c, mf, m1) |
174 |
174 |
175 return copy |
175 return copy |
176 |
176 |
177 def manifestmerge(ui, m1, m2, ma, copy, overwrite, backwards, partial): |
177 def manifestmerge(repo, p1, p2, pa, overwrite, partial): |
178 """ |
178 """ |
179 Merge manifest m1 with m2 using ancestor ma and generate merge action list |
179 Merge manifest m1 with m2 using ancestor ma and generate merge action list |
180 """ |
180 """ |
|
181 |
|
182 m1 = p1.manifest() |
|
183 m2 = p2.manifest() |
|
184 ma = pa.manifest() |
|
185 backwards = (pa == p2) |
181 |
186 |
182 def fmerge(f, f2=None, fa=None): |
187 def fmerge(f, f2=None, fa=None): |
183 """merge executable flags""" |
188 """merge executable flags""" |
184 if not f2: |
189 if not f2: |
185 f2 = f |
190 f2 = f |
188 return ((a^b) | (a^c)) ^ a |
193 return ((a^b) | (a^c)) ^ a |
189 |
194 |
190 action = [] |
195 action = [] |
191 |
196 |
192 def act(msg, f, m, *args): |
197 def act(msg, f, m, *args): |
193 ui.debug(" %s: %s -> %s\n" % (f, msg, m)) |
198 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m)) |
194 action.append((f, m) + args) |
199 action.append((f, m) + args) |
|
200 |
|
201 copy = {} |
|
202 if not (backwards or overwrite): |
|
203 copy = findcopies(repo, m1, m2, pa.rev()) |
195 |
204 |
196 # Compare manifests |
205 # Compare manifests |
197 for f, n in m1.iteritems(): |
206 for f, n in m1.iteritems(): |
198 if partial and not partial(f): |
207 if partial and not partial(f): |
199 continue |
208 continue |
228 else: # case 4,21 A/B/B |
237 else: # case 4,21 A/B/B |
229 act("local moved", |
238 act("local moved", |
230 f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False) |
239 f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False) |
231 elif f in ma: |
240 elif f in ma: |
232 if n != ma[f] and not overwrite: |
241 if n != ma[f] and not overwrite: |
233 if ui.prompt( |
242 if repo.ui.prompt( |
234 (_(" local changed %s which remote deleted\n") % f) + |
243 (_(" local changed %s which remote deleted\n") % f) + |
235 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"): |
244 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"): |
236 act("prompt delete", f, "r") |
245 act("prompt delete", f, "r") |
237 else: |
246 else: |
238 act("other deleted", f, "r") |
247 act("other deleted", f, "r") |
255 f2, "c", f, f, m1[f2], m2[f], fmerge(f2, f, f2), False) |
264 f2, "c", f, f, m1[f2], m2[f], fmerge(f2, f, f2), False) |
256 elif f in ma: |
265 elif f in ma: |
257 if overwrite or backwards: |
266 if overwrite or backwards: |
258 act("recreating", f, "g", m2.execf(f), n) |
267 act("recreating", f, "g", m2.execf(f), n) |
259 elif n != ma[f]: |
268 elif n != ma[f]: |
260 if ui.prompt( |
269 if repo.ui.prompt( |
261 (_("remote changed %s which local deleted\n") % f) + |
270 (_("remote changed %s which local deleted\n") % f) + |
262 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"): |
271 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"): |
263 act("prompt recreating", f, "g", m2.execf(f), n) |
272 act("prompt recreating", f, "g", m2.execf(f), n) |
264 else: |
273 else: |
265 act("remote created", f, "g", m2.execf(f), n) |
274 act("remote created", f, "g", m2.execf(f), n) |
379 raise util.Abort(_("outstanding uncommitted merges")) |
388 raise util.Abort(_("outstanding uncommitted merges")) |
380 |
389 |
381 p1, p2 = pl[0], repo.changectx(node) |
390 p1, p2 = pl[0], repo.changectx(node) |
382 pa = p1.ancestor(p2) |
391 pa = p1.ancestor(p2) |
383 |
392 |
384 # are we going backwards? |
|
385 backwards = (pa == p2) |
|
386 |
|
387 # is there a linear path from p1 to p2? |
393 # is there a linear path from p1 to p2? |
388 if pa == p1 or pa == p2: |
394 if pa == p1 or pa == p2: |
389 if branchmerge: |
395 if branchmerge: |
390 raise util.Abort(_("there is nothing to merge, just use " |
396 raise util.Abort(_("there is nothing to merge, just use " |
391 "'hg update' or look at 'hg heads'")) |
397 "'hg update' or look at 'hg heads'")) |
397 if wc.modified() or wc.added() or wc.removed(): |
403 if wc.modified() or wc.added() or wc.removed(): |
398 raise util.Abort(_("outstanding uncommitted changes")) |
404 raise util.Abort(_("outstanding uncommitted changes")) |
399 |
405 |
400 m1 = wc.manifest() |
406 m1 = wc.manifest() |
401 m2 = p2.manifest() |
407 m2 = p2.manifest() |
402 ma = pa.manifest() |
|
403 |
408 |
404 # resolve the manifest to determine which files |
409 # resolve the manifest to determine which files |
405 # we care about merging |
410 # we care about merging |
406 repo.ui.note(_("resolving manifests\n")) |
411 repo.ui.note(_("resolving manifests\n")) |
407 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s\n") % |
412 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s\n") % |
408 (overwrite, branchmerge, bool(partial))) |
413 (overwrite, branchmerge, bool(partial))) |
409 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (p1, p2, pa)) |
414 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (p1, p2, pa)) |
410 |
415 |
411 action = [] |
416 action = [] |
412 copy = {} |
|
413 |
417 |
414 if not force: |
418 if not force: |
415 checkunknown(repo, m2, wc) |
419 checkunknown(repo, m2, wc) |
416 if not branchmerge: |
420 if not branchmerge: |
417 action += forgetremoved(m2, wc) |
421 action += forgetremoved(m2, wc) |
418 if not (backwards or overwrite): |
422 |
419 copy = findcopies(repo, m1, m2, pa.rev()) |
423 action += manifestmerge(repo, wc, p2, pa, overwrite, partial) |
420 |
|
421 action += manifestmerge(repo.ui, m1, m2, ma, copy, |
|
422 overwrite, backwards, partial) |
|
423 |
424 |
424 ### apply phase |
425 ### apply phase |
425 |
426 |
426 if not branchmerge: |
427 if not branchmerge: |
427 # we don't need to do any magic, just jump to the new rev |
428 # we don't need to do any magic, just jump to the new rev |