瀏覽代碼

file: add SIZE option

This commit adds the SIZE option to file(). It returns the file size of
the given path if it exists and produces an error if not.
Wouter Klouwen 7 年之前
父節點
當前提交
12b471e828

+ 11 - 0
Help/command/file.rst

@@ -25,6 +25,7 @@ Synopsis
     file({`REMOVE`_ | `REMOVE_RECURSE`_ } [<files>...])
     file(`MAKE_DIRECTORY`_ [<dir>...])
     file({`COPY`_ | `INSTALL`_} <file>... DESTINATION <dir> [...])
+    file(`SIZE`_ <filename> <out-var>)
 
   `Path Conversion`_
     file(`RELATIVE_PATH`_ <out-var> <directory> <file>)
@@ -333,6 +334,16 @@ and ``NO_SOURCE_PERMISSIONS`` is default.
 Installation scripts generated by the :command:`install` command
 use this signature (with some undocumented options for internal use).
 
+.. _SIZE:
+
+.. code-block:: cmake
+
+  file(SIZE <filename> <variable>)
+
+Determine the file size of the ``<filename>`` and put the result in
+``<variable>`` variable. Requires that ``<filename>`` is a valid path
+pointing to a file and is readable.
+
 Path Conversion
 ^^^^^^^^^^^^^^^
 

+ 5 - 0
Help/release/dev/file-size.rst

@@ -0,0 +1,5 @@
+file-size
+---------
+
+* The :command:`file` command gained a ``SIZE`` mode to get the size
+  of a file on disk.

+ 32 - 0
Source/cmFileCommand.cxx

@@ -176,6 +176,9 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
   if (subCommand == "LOCK") {
     return this->HandleLockCommand(args);
   }
+  if (subCommand == "SIZE") {
+    return this->HandleSizeCommand(args);
+  }
 
   std::string e = "does not recognize sub-command " + subCommand;
   this->SetError(e);
@@ -3605,3 +3608,32 @@ bool cmFileCommand::HandleTimestampCommand(
 
   return true;
 }
+
+bool cmFileCommand::HandleSizeCommand(std::vector<std::string> const& args)
+{
+  if (args.size() != 3) {
+    std::ostringstream e;
+    e << args[0] << " requires a file name and output variable";
+    this->SetError(e.str());
+    return false;
+  }
+
+  unsigned int argsIndex = 1;
+
+  const std::string& filename = args[argsIndex++];
+
+  const std::string& outputVariable = args[argsIndex++];
+
+  if (!cmSystemTools::FileExists(filename, true)) {
+    std::ostringstream e;
+    e << "SIZE requested of path that is not readable " << filename;
+    this->SetError(e.str());
+    return false;
+  }
+
+  this->Makefile->AddDefinition(
+    outputVariable,
+    std::to_string(cmSystemTools::FileLength(filename)).c_str());
+
+  return true;
+}

+ 1 - 0
Source/cmFileCommand.h

@@ -59,6 +59,7 @@ protected:
   bool HandleTimestampCommand(std::vector<std::string> const& args);
   bool HandleGenerateCommand(std::vector<std::string> const& args);
   bool HandleLockCommand(std::vector<std::string> const& args);
+  bool HandleSizeCommand(std::vector<std::string> const& args);
 
 private:
   void AddEvaluationFile(const std::string& inputName,

+ 2 - 0
Tests/RunCMake/file/RunCMakeTest.cmake

@@ -36,6 +36,8 @@ run_cmake(READ_ELF)
 run_cmake(GLOB)
 run_cmake(GLOB_RECURSE)
 run_cmake(GLOB_RECURSE-noexp-FOLLOW_SYMLINKS)
+run_cmake(SIZE)
+run_cmake(SIZE-error-does-not-exist)
 
 # tests are valid both for GLOB and GLOB_RECURSE
 run_cmake(GLOB-sort-dedup)

+ 1 - 0
Tests/RunCMake/file/SIZE-error-does-not-exist-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/file/SIZE-error-does-not-exist-stderr.txt

@@ -0,0 +1,5 @@
+^CMake Error at SIZE-error-does-not-exist.cmake:[0-9]+ \(file\):
+  file SIZE requested of path that is not readable
+  /a/file/that/does-not-exist
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)

+ 3 - 0
Tests/RunCMake/file/SIZE-error-does-not-exist.cmake

@@ -0,0 +1,3 @@
+set(file "/a/file/that/does-not-exist")
+
+file(SIZE "${file}" CALCULATED_SIZE)

+ 9 - 0
Tests/RunCMake/file/SIZE.cmake

@@ -0,0 +1,9 @@
+set(file "${CMAKE_CURRENT_BINARY_DIR}/a-test-file")
+
+file(WRITE "${file}" "test")
+
+file(SIZE "${file}" CALCULATED_SIZE)
+
+if (NOT CALCULATED_SIZE EQUAL 4)
+  message(FATAL_ERROR "Unexpected file size")
+endif()