218 backwards = (pa == p2) |
218 backwards = (pa == p2) |
219 action = [] |
219 action = [] |
220 copy = {} |
220 copy = {} |
221 |
221 |
222 def fmerge(f, f2=None, fa=None): |
222 def fmerge(f, f2=None, fa=None): |
223 """merge executable flags""" |
223 """merge flags""" |
224 if not f2: |
224 if not f2: |
225 f2 = f |
225 f2 = f |
226 fa = f |
226 fa = f |
227 a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2) |
227 a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2) |
228 return ((a^b) | (a^c)) ^ a |
228 if ((a^b) | (a^c)) ^ a: |
|
229 return 'x' |
|
230 a, b, c = ma.linkf(fa), m1.linkf(f), m2.linkf(f2) |
|
231 if ((a^b) | (a^c)) ^ a: |
|
232 return 'l' |
|
233 return '' |
229 |
234 |
230 def act(msg, m, f, *args): |
235 def act(msg, m, f, *args): |
231 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m)) |
236 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m)) |
232 action.append((f, m) + args) |
237 action.append((f, m) + args) |
233 |
238 |
248 act("versions differ", "m", f, f, f, fmerge(f), False) |
253 act("versions differ", "m", f, f, f, fmerge(f), False) |
249 # are we clobbering? |
254 # are we clobbering? |
250 # is remote's version newer? |
255 # is remote's version newer? |
251 # or are we going back in time and clean? |
256 # or are we going back in time and clean? |
252 elif overwrite or m2[f] != a or (backwards and not n[20:]): |
257 elif overwrite or m2[f] != a or (backwards and not n[20:]): |
253 act("remote is newer", "g", f, m2.execf(f)) |
258 act("remote is newer", "g", f, m2.flags(f)) |
254 # local is newer, not overwrite, check mode bits |
259 # local is newer, not overwrite, check mode bits |
255 elif fmerge(f) != m1.execf(f): |
260 elif fmerge(f) != m1.flags(f): |
256 act("update permissions", "e", f, m2.execf(f)) |
261 act("update permissions", "e", f, m2.flags(f)) |
257 # contents same, check mode bits |
262 # contents same, check mode bits |
258 elif m1.execf(f) != m2.execf(f): |
263 elif m1.flags(f) != m2.flags(f): |
259 if overwrite or fmerge(f) != m1.execf(f): |
264 if overwrite or fmerge(f) != m1.flags(f): |
260 act("update permissions", "e", f, m2.execf(f)) |
265 act("update permissions", "e", f, m2.flags(f)) |
261 elif f in copied: |
266 elif f in copied: |
262 continue |
267 continue |
263 elif f in copy: |
268 elif f in copy: |
264 f2 = copy[f] |
269 f2 = copy[f] |
265 if f2 not in m2: # directory rename |
270 if f2 not in m2: # directory rename |
266 act("remote renamed directory to " + f2, "d", |
271 act("remote renamed directory to " + f2, "d", |
267 f, None, f2, m1.execf(f)) |
272 f, None, f2, m1.flags(f)) |
268 elif f2 in m1: # case 2 A,B/B/B |
273 elif f2 in m1: # case 2 A,B/B/B |
269 act("local copied to " + f2, "m", |
274 act("local copied to " + f2, "m", |
270 f, f2, f, fmerge(f, f2, f2), False) |
275 f, f2, f, fmerge(f, f2, f2), False) |
271 else: # case 4,21 A/B/B |
276 else: # case 4,21 A/B/B |
272 act("local moved to " + f2, "m", |
277 act("local moved to " + f2, "m", |
293 continue |
298 continue |
294 if f in copy: |
299 if f in copy: |
295 f2 = copy[f] |
300 f2 = copy[f] |
296 if f2 not in m1: # directory rename |
301 if f2 not in m1: # directory rename |
297 act("local renamed directory to " + f2, "d", |
302 act("local renamed directory to " + f2, "d", |
298 None, f, f2, m2.execf(f)) |
303 None, f, f2, m2.flags(f)) |
299 elif f2 in m2: # rename case 1, A/A,B/A |
304 elif f2 in m2: # rename case 1, A/A,B/A |
300 act("remote copied to " + f, "m", |
305 act("remote copied to " + f, "m", |
301 f2, f, f, fmerge(f2, f, f2), False) |
306 f2, f, f, fmerge(f2, f, f2), False) |
302 else: # case 3,20 A/B/A |
307 else: # case 3,20 A/B/A |
303 act("remote moved to " + f, "m", |
308 act("remote moved to " + f, "m", |
304 f2, f, f, fmerge(f2, f, f2), True) |
309 f2, f, f, fmerge(f2, f, f2), True) |
305 elif f in ma: |
310 elif f in ma: |
306 if overwrite or backwards: |
311 if overwrite or backwards: |
307 act("recreating", "g", f, m2.execf(f)) |
312 act("recreating", "g", f, m2.flags(f)) |
308 elif n != ma[f]: |
313 elif n != ma[f]: |
309 if repo.ui.prompt( |
314 if repo.ui.prompt( |
310 (_("remote changed %s which local deleted\n") % f) + |
315 (_("remote changed %s which local deleted\n") % f) + |
311 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"): |
316 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"): |
312 act("prompt recreating", "g", f, m2.execf(f)) |
317 act("prompt recreating", "g", f, m2.flags(f)) |
313 else: |
318 else: |
314 act("remote created", "g", f, m2.execf(f)) |
319 act("remote created", "g", f, m2.flags(f)) |
315 |
320 |
316 return action |
321 return action |
317 |
322 |
318 def applyupdates(repo, action, wctx, mctx): |
323 def applyupdates(repo, action, wctx, mctx): |
319 "apply the merge action list to the working directory" |
324 "apply the merge action list to the working directory" |
333 if inst.errno != errno.ENOENT: |
338 if inst.errno != errno.ENOENT: |
334 repo.ui.warn(_("update failed to remove %s: %s!\n") % |
339 repo.ui.warn(_("update failed to remove %s: %s!\n") % |
335 (f, inst.strerror)) |
340 (f, inst.strerror)) |
336 removed += 1 |
341 removed += 1 |
337 elif m == "m": # merge |
342 elif m == "m": # merge |
338 f2, fd, flag, move = a[2:] |
343 f2, fd, flags, move = a[2:] |
339 r = filemerge(repo, f, f2, wctx, mctx) |
344 r = filemerge(repo, f, f2, wctx, mctx) |
340 if r > 0: |
345 if r > 0: |
341 unresolved += 1 |
346 unresolved += 1 |
342 else: |
347 else: |
343 if r is None: |
348 if r is None: |
344 updated += 1 |
349 updated += 1 |
345 else: |
350 else: |
346 merged += 1 |
351 merged += 1 |
347 if f != fd: |
352 if f != fd: |
348 repo.ui.debug(_("copying %s to %s\n") % (f, fd)) |
353 repo.ui.debug(_("copying %s to %s\n") % (f, fd)) |
349 repo.wwrite(fd, repo.wread(f), flag and 'x' or '') |
354 repo.wwrite(fd, repo.wread(f), flags) |
350 if move: |
355 if move: |
351 repo.ui.debug(_("removing %s\n") % f) |
356 repo.ui.debug(_("removing %s\n") % f) |
352 os.unlink(repo.wjoin(f)) |
357 os.unlink(repo.wjoin(f)) |
353 util.set_exec(repo.wjoin(fd), flag) |
358 util.set_exec(repo.wjoin(fd), "x" in flags) |
354 elif m == "g": # get |
359 elif m == "g": # get |
355 flag = a[2] |
360 flags = a[2] |
356 repo.ui.note(_("getting %s\n") % f) |
361 repo.ui.note(_("getting %s\n") % f) |
357 t = mctx.filectx(f).data() |
362 t = mctx.filectx(f).data() |
358 repo.wwrite(f, t, flag and 'x' or '') |
363 repo.wwrite(f, t, flags) |
359 updated += 1 |
364 updated += 1 |
360 elif m == "d": # directory rename |
365 elif m == "d": # directory rename |
361 f2, fd, flag = a[2:] |
366 f2, fd, flags = a[2:] |
362 if f: |
367 if f: |
363 repo.ui.note(_("moving %s to %s\n") % (f, fd)) |
368 repo.ui.note(_("moving %s to %s\n") % (f, fd)) |
364 t = wctx.filectx(f).data() |
369 t = wctx.filectx(f).data() |
365 repo.wwrite(fd, t, flag and 'x' or '') |
370 repo.wwrite(fd, t, flags) |
366 util.unlink(repo.wjoin(f)) |
371 util.unlink(repo.wjoin(f)) |
367 if f2: |
372 if f2: |
368 repo.ui.note(_("getting %s to %s\n") % (f2, fd)) |
373 repo.ui.note(_("getting %s to %s\n") % (f2, fd)) |
369 t = mctx.filectx(f2).data() |
374 t = mctx.filectx(f2).data() |
370 repo.wwrite(fd, t, flag and 'x' or '') |
375 repo.wwrite(fd, t, flags) |
371 updated += 1 |
376 updated += 1 |
372 elif m == "e": # exec |
377 elif m == "e": # exec |
373 flag = a[2] |
378 flags = a[2] |
374 util.set_exec(repo.wjoin(f), flag) |
379 util.set_exec(repo.wjoin(f), flags) |
375 |
380 |
376 return updated, merged, removed, unresolved |
381 return updated, merged, removed, unresolved |
377 |
382 |
378 def recordupdates(repo, action, branchmerge): |
383 def recordupdates(repo, action, branchmerge): |
379 "record merge actions to the dirstate" |
384 "record merge actions to the dirstate" |