diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -281,9 +281,11 @@ def copy(ui, repo, pats, opts, rename=Fa
                 if not os.path.isdir(targetdir):
                     os.makedirs(targetdir)
                 util.copyfile(src, target)
+                srcexists = True
             except IOError, inst:
                 if inst.errno == errno.ENOENT:
                     ui.warn(_('%s: deleted in working copy\n') % relsrc)
+                    srcexists = False
                 else:
                     ui.warn(_('%s: cannot copy - %s\n') %
                             (relsrc, inst.strerror))
@@ -301,7 +303,9 @@ def copy(ui, repo, pats, opts, rename=Fa
         scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
                              dryrun=dryrun, cwd=cwd)
         if rename and not dryrun:
-            wctx.remove([abssrc], not after)
+            if not after and srcexists:
+                util.unlinkpath(repo.wjoin(abssrc))
+            wctx.forget([abssrc])
 
     # pat: ossep
     # dest ossep
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -853,20 +853,6 @@ class workingctx(changectx):
             *[p.rev() for p in self._parents]):
             yield changectx(self._repo, a)
 
-    def remove(self, list, unlink=False):
-        wlock = self._repo.wlock()
-        try:
-            if unlink:
-                for f in list:
-                    try:
-                        util.unlinkpath(self._repo.wjoin(f))
-                    except OSError, inst:
-                        if inst.errno != errno.ENOENT:
-                            raise
-            self.forget(list)
-        finally:
-            wlock.release()
-
     def undelete(self, list):
         pctxs = self.parents()
         wlock = self._repo.wlock()