Browse Source

ENH: Create file(RENAME) command mode

This creates command "file(RENAME <oldname> <newname>)" to rename a file
or directory within a single disk volume.
Brad King 16 years ago
parent
commit
0d92350bb6
3 changed files with 51 additions and 1 deletions
  1. 43 0
      Source/cmFileCommand.cxx
  2. 5 0
      Source/cmFileCommand.h
  3. 3 1
      Tests/StringFileTest/CMakeLists.txt

+ 43 - 0
Source/cmFileCommand.cxx

@@ -100,6 +100,10 @@ bool cmFileCommand
     {
     return this->HandleMakeDirectoryCommand(args);
     }
+  else if ( subCommand == "RENAME" )
+    {
+    return this->HandleRename(args);
+    }
   else if ( subCommand == "REMOVE" )
     {
     return this->HandleRemove(args, false);
@@ -2174,6 +2178,45 @@ bool cmFileCommand::HandleRelativePathCommand(
 }
 
 
+//----------------------------------------------------------------------------
+bool cmFileCommand::HandleRename(std::vector<std::string> const& args)
+{
+  if(args.size() != 3)
+    {
+    this->SetError("given incorrect number of arguments.");
+    return false;
+    }
+
+  // Compute full path for old and new names.
+  std::string oldname = args[1];
+  if(!cmsys::SystemTools::FileIsFullPath(oldname.c_str()))
+    {
+    oldname = this->Makefile->GetCurrentDirectory();
+    oldname += "/" + args[1];
+    }
+  std::string newname = args[2];
+  if(!cmsys::SystemTools::FileIsFullPath(newname.c_str()))
+    {
+    newname = this->Makefile->GetCurrentDirectory();
+    newname += "/" + args[2];
+    }
+
+  if(!cmSystemTools::RenameFile(oldname.c_str(), newname.c_str()))
+    {
+    std::string err = cmSystemTools::GetLastSystemError();
+    cmOStringStream e;
+    e << "RENAME failed to rename\n"
+      << "  " << oldname << "\n"
+      << "to\n"
+      << "  " << newname << "\n"
+      << "because: " << err << "\n";
+    this->SetError(e.str().c_str());
+    return false;
+    }
+  return true;
+}
+
+
 //----------------------------------------------------------------------------
 bool cmFileCommand::HandleRemove(std::vector<std::string> const& args,
                                  bool recurse)

+ 5 - 0
Source/cmFileCommand.h

@@ -78,6 +78,7 @@ public:
       "  file(GLOB variable [RELATIVE path] [globbing expressions]...)\n"
       "  file(GLOB_RECURSE variable [RELATIVE path] \n"
       "       [FOLLOW_SYMLINKS] [globbing expressions]...)\n"
+      "  file(RENAME <oldname> <newname>)\n"
       "  file(REMOVE [file1 ...])\n"
       "  file(REMOVE_RECURSE [file1 ...])\n"
       "  file(MAKE_DIRECTORY [directory1 directory2 ...])\n"
@@ -133,6 +134,9 @@ public:
       "   /dir/*.py  - match all python files in /dir and subdirectories\n"
       "MAKE_DIRECTORY will create the given directories, also if their parent "
       "directories don't exist yet\n"
+      "RENAME moves a file or directory within a filesystem, "
+      "replacing the destination atomically."
+      "\n"
       "REMOVE will remove the given files, also in subdirectories\n"
       "REMOVE_RECURSE will remove the given files and directories, also "
       "non-empty directories\n"
@@ -159,6 +163,7 @@ public:
   cmTypeMacro(cmFileCommand, cmCommand);
 
 protected:
+  bool HandleRename(std::vector<std::string> const& args);
   bool HandleRemove(std::vector<std::string> const& args, bool recurse);
   bool HandleWriteCommand(std::vector<std::string> const& args, bool append);
   bool HandleReadCommand(std::vector<std::string> const& args);

+ 3 - 1
Tests/StringFileTest/CMakeLists.txt

@@ -184,7 +184,9 @@ SET(infile "${infile+-/out}")
 
 # Write include file to a file
 STRING(REGEX REPLACE "includefile" "${file}" outfile "${infile}")
-FILE(WRITE "${CMAKE_CURRENT_BINARY_DIR}/OutputFile.h" "${outfile}")
+FILE(WRITE "${CMAKE_CURRENT_BINARY_DIR}/OutputFile.h-tmp" "${outfile}")
+FILE(RENAME "${CMAKE_CURRENT_BINARY_DIR}/OutputFile.h-tmp"
+            "${CMAKE_CURRENT_BINARY_DIR}/OutputFile.h")
 
 # Test file glob
 FILE(GLOB_RECURSE src_files "${CMAKE_CURRENT_SOURCE_DIR}/*")