Mercurial > public > mercurial-scm > hg
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" |