[PATCH 1 of 1] Add rename/mv command

Bryan O'Sullivan bos at serpentine.com
Wed Sep 14 18:35:44 CDT 2005


# HG changeset patch
# User Bryan O'Sullivan <bos at serpentine.com>
# Node ID a45e717c61a8703ec880394f22a87347b98e9d70
# Parent  94f38724283f5b059a8c8cb1037c1b60efff3727
Add rename/mv command.
This is the logical equivalent of copy and remove, and is in fact
implemented as such.  It doesn't use the remove command directly.

diff -r 94f38724283f -r a45e717c61a8 doc/hg.1.txt
--- a/doc/hg.1.txt	Wed Sep 14 23:31:03 2005
+++ b/doc/hg.1.txt	Wed Sep 14 23:34:22 2005
@@ -173,13 +173,15 @@
     stand in the working directory.  If invoked with --after, the
     operation is recorded, but no copying is performed.
 
-    This command takes effect for the next commit.
+    This command takes effect in the next commit.
 
     Options:
     -A, --after        record a copy that has already occurred
     -f, --force        forcibly copy over an existing managed file
     -p, --parents      append source path to dest
     
+    aliases: cp
+
 diff [-a] [-r revision] [-r revision] [files ...]::
     Show differences between revisions for the specified files.
 
@@ -448,6 +450,24 @@
 
     aliases: rm
 
+rename <source ...> <dest>::
+    Mark dest as copies of sources; mark sources for deletion.  If
+    dest is a directory, copies are put in that directory.  If dest is
+    a file, there can only be one source.
+
+    By default, this command copies the contents of files as they
+    stand in the working directory.  If invoked with --after, the
+    operation is recorded, but no copying is performed.
+
+    This command takes effect in the next commit.
+
+    Options:
+    -A, --after        record a rename that has already occurred
+    -f, --force        forcibly copy over an existing managed file
+    -p, --parents      append source path to dest
+
+    aliases: mv
+
 revert [names ...]::
     Revert any uncommitted modifications made to the named files or
     directories.  This restores the contents of the affected files to
diff -r 94f38724283f -r a45e717c61a8 mercurial/commands.py
--- a/mercurial/commands.py	Wed Sep 14 23:31:03 2005
+++ b/mercurial/commands.py	Wed Sep 14 23:34:22 2005
@@ -696,8 +696,7 @@
     except ValueError, inst:
         raise util.Abort(str(inst))
 
-def copy(ui, repo, *pats, **opts):
-    """mark files as copied for the next commit"""
+def docopy(ui, repo, pats, opts):
     if not pats:
         raise util.Abort('no source or destination specified')
     elif len(pats) == 1:
@@ -735,7 +734,7 @@
         elif len(sources) > 1:
             raise util.Abort('with multiple sources, destination must be a '
                              'directory')
-    errs = 0
+    errs, copied = 0, []
     for abs, rel, exact in sources:
         if opts['parents']:
             mydest = os.path.join(dest, rel)
@@ -763,6 +762,8 @@
                 n = repo.manifest.tip()
                 mf = repo.manifest.readflags(n)
                 util.set_exec(myreldest, util.is_exec(rel, mf[abs]))
+            except shutil.Error, inst:
+                raise util.Abort(str(inst))
             except IOError, inst:
                 if inst.errno == errno.ENOENT:
                     ui.warn('%s: deleted in working copy\n' % rel)
@@ -771,8 +772,14 @@
                 errs += 1
                 continue
         repo.copy(abs, myabsdest)
+        copied.append((abs, rel, exact))
     if errs:
-        ui.warn('(consider using --after to record failed copies)\n')
+        ui.warn('(consider using --after)\n')
+    return errs, copied
+
+def copy(ui, repo, *pats, **opts):
+    """mark files as copied for the next commit"""
+    errs, copied = docopy(ui, repo, pats, opts)
     return errs
 
 def debugcheckstate(ui, repo):
@@ -1390,14 +1397,14 @@
         reason = None
         if c: reason = 'is modified'
         elif a: reason = 'has been marked for add'
-        elif u: reason = 'not managed'
+        elif u: reason = 'is not managed'
         if reason and exact:
             ui.warn('not removing %s: file %s\n' % (rel, reason))
         else:
             return True
     for src, abs, rel, exact in walk(repo, (pat,) + pats, opts):
         if okaytoremove(abs, rel, exact):
-            if not exact: ui.status('removing %s\n' % rel)
+            if ui.verbose or not exact: ui.status('removing %s\n' % rel)
             names.append(abs)
     for name in names:
         try:
@@ -1405,6 +1412,20 @@
         except OSError, inst:
             if inst.errno != errno.ENOENT: raise
     repo.remove(names)
+
+def rename(ui, repo, *pats, **opts):
+    """rename files; equivalent of copy + remove"""
+    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)
+        try:
+            os.unlink(rel)
+        except OSError, inst:
+            if inst.errno != errno.ENOENT: raise
+        names.append(abs)
+    repo.remove(names)
+    return errs
 
 def revert(ui, repo, *names, **opts):
     """revert modified files or dirs back to their unmodified states"""
@@ -1823,7 +1844,7 @@
           ('f', 'force', None, 'skip check for outstanding changes'),
           ('b', 'base', "", 'base path')],
          "hg import [-f] [-p NUM] [-b BASE] PATCH..."),
-    "incoming|in": (incoming, 
+    "incoming|in": (incoming,
          [('p', 'patch', None, 'show patch')],
          'hg incoming [-p] [SOURCE]'),
     "^init": (init, [], 'hg init [DEST]'),
@@ -1844,7 +1865,7 @@
           ('p', 'patch', None, 'show patch')],
          'hg log [-I] [-X] [-r REV]... [-p] [FILE]'),
     "manifest": (manifest, [], 'hg manifest [REV]'),
-    "outgoing|out": (outgoing, 
+    "outgoing|out": (outgoing,
          [('p', 'patch', None, 'show patch')],
          'hg outgoing [-p] [DEST]'),
     "parents": (parents, [], 'hg parents [REV]'),
@@ -1876,6 +1897,13 @@
                    [('I', 'include', [], 'include path in search'),
                     ('X', 'exclude', [], 'exclude path from search')],
                    "hg remove [OPTION]... FILE..."),
+    "rename|mv": (rename,
+                  [('I', 'include', [], 'include path in search'),
+                   ('X', 'exclude', [], 'exclude path from search'),
+                   ('A', 'after', None, 'record a copy after it has happened'),
+                   ('f', 'force', None, 'replace destination if it exists'),
+                   ('p', 'parents', None, 'append source path to dest')],
+                  'hg rename [OPTION]... [SOURCE]... DEST'),
     "^revert":
         (revert,
          [("n", "nonrecursive", None, "don't recurse into subdirs"),
diff -r 94f38724283f -r a45e717c61a8 tests/test-help.out
--- a/tests/test-help.out	Wed Sep 14 23:31:03 2005
+++ b/tests/test-help.out	Wed Sep 14 23:34:22 2005
@@ -65,6 +65,7 @@
  rawcommit   raw commit interface
  recover     roll back an interrupted transaction
  remove      remove the specified files on the next commit
+ rename      rename files; equivalent of copy + remove
  revert      revert modified files or dirs back to their unmodified states
  root        print the root (top) of the current working dir
  serve       export the repository via HTTP
@@ -106,6 +107,7 @@
  rawcommit   raw commit interface
  recover     roll back an interrupted transaction
  remove      remove the specified files on the next commit
+ rename      rename files; equivalent of copy + remove
  revert      revert modified files or dirs back to their unmodified states
  root        print the root (top) of the current working dir
  serve       export the repository via HTTP


More information about the Mercurial mailing list