diff mercurial/commands.py @ 1822:64df4220b349

copy/rename to a removed destination file When the destination of a copy or rename operation has been marked for removal, we need to restore it before we overwrite it with the new content. This also handles the case of idempotent renames, i.e. hg rename "a" "b" hg rename "b" "a"
author Robin Farine <robin.farine@terminus.org>
date Tue, 28 Feb 2006 23:47:40 -0800
parents a81f99dfaa2a
children adef8661c8f9
line wrap: on
line diff
--- a/mercurial/commands.py	Wed Mar 01 01:45:05 2006 +0100
+++ b/mercurial/commands.py	Tue Feb 28 23:47:40 2006 -0800
@@ -825,7 +825,8 @@
     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 @@
             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 @@
         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 @@
     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 @@
     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):