# HG changeset patch # User Vadim Gelfer # Date 1141278240 28800 # Node ID dca000ef7d52402cfec550fde5ac95430640cce5 # Parent adef8661c8f9587c41b16190db87ef2e78ef7dc1# Parent 0b3f4be5c5bf8258e4370c7755a2a1ab32ac07eb merge with crew. diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -825,7 +825,8 @@ def commit(ui, repo, *pats, **opts): except ValueError, inst: raise util.Abort(str(inst)) -def docopy(ui, repo, pats, opts): +def docopy(ui, repo, pats, opts, wlock): + # called with the repo lock held cwd = repo.getcwd() errors = 0 copied = [] @@ -871,8 +872,16 @@ def docopy(ui, repo, pats, opts): if not os.path.isdir(targetdir): os.makedirs(targetdir) try: - shutil.copyfile(relsrc, reltarget) - shutil.copymode(relsrc, reltarget) + restore = repo.dirstate.state(abstarget) == 'r' + if restore: + repo.undelete([abstarget], wlock) + try: + shutil.copyfile(relsrc, reltarget) + shutil.copymode(relsrc, reltarget) + restore = False + finally: + if restore: + repo.remove([abstarget], wlock) except shutil.Error, inst: raise util.Abort(str(inst)) except IOError, inst: @@ -886,7 +895,8 @@ def docopy(ui, repo, pats, opts): if ui.verbose or not exact: ui.status(_('copying %s to %s\n') % (relsrc, reltarget)) targets[abstarget] = abssrc - repo.copy(origsrc, abstarget) + if abstarget != origsrc: + repo.copy(origsrc, abstarget, wlock) copied.append((abssrc, relsrc, exact)) def targetpathfn(pat, dest, srcs): @@ -994,7 +1004,12 @@ def copy(ui, repo, *pats, **opts): should properly record copied files, this information is not yet fully used by merge, nor fully reported by log. """ - errs, copied = docopy(ui, repo, pats, opts) + try: + wlock = repo.wlock(0) + errs, copied = docopy(ui, repo, pats, opts, wlock) + except lock.LockHeld, inst: + ui.warn(_("repository lock held by %s\n") % inst.args[0]) + errs = 1 return errs def debugancestor(ui, index, rev1, rev2): @@ -1953,13 +1968,18 @@ def rename(ui, repo, *pats, **opts): should properly record rename files, this information is not yet fully used by merge, nor fully reported by log. """ - errs, copied = docopy(ui, repo, pats, opts) - names = [] - for abs, rel, exact in copied: - if ui.verbose or not exact: - ui.status(_('removing %s\n') % rel) - names.append(abs) - repo.remove(names, unlink=True) + try: + wlock = repo.wlock(0) + errs, copied = docopy(ui, repo, pats, opts, wlock) + names = [] + for abs, rel, exact in copied: + if ui.verbose or not exact: + ui.status(_('removing %s\n') % rel) + names.append(abs) + repo.remove(names, True, wlock) + except lock.LockHeld, inst: + ui.warn(_("repository lock held by %s\n") % inst.args[0]) + errs = 1 return errs def revert(ui, repo, *pats, **opts): diff --git a/tests/test-rename b/tests/test-rename --- a/tests/test-rename +++ b/tests/test-rename @@ -171,3 +171,11 @@ mv d1/bb d1/bc hg rename --after d1/bb d1/bc hg status hg update -C + +echo "# idempotent renames (d1/b -> d1/bb followed by d1/bb -> d1/b)" +hg rename d1/b d1/bb +echo "some stuff added to d1/bb" >> d1/bb +hg rename d1/bb d1/b +hg status +hg debugstate | grep copy +hg update -C diff --git a/tests/test-rename.out b/tests/test-rename.out --- a/tests/test-rename.out +++ b/tests/test-rename.out @@ -252,3 +252,5 @@ R d1/b # transitive rename --after A d1/bc R d1/b +# idempotent renames (d1/b -> d1/bb followed by d1/bb -> d1/b) +M d1/b