comparison mercurial/merge.py @ 4007:20da40cc1c73

symlinks: minimal support for symlinks in merge/update This will get angry, confused, and sad if you try to merge a symlink with a regular file.
author Matt Mackall <mpm@selenic.com>
date Fri, 29 Dec 2006 20:04:31 -0600
parents 67982d3ee76c
children bb70d5fa02ae
comparison
equal deleted inserted replaced
4006:67982d3ee76c 4007:20da40cc1c73
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"