From 98a39be6cfb7b229ff78f7045c6d5bcd6b6c7509 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Wed, 5 Dec 2018 15:27:08 -0500 Subject: file: Add READ_SYMLINK sub-command --- Help/command/file.rst | 24 +++++++++++++++++ Help/release/dev/file-read_symlink.rst | 5 ++++ Source/cmFileCommand.cxx | 30 ++++++++++++++++++++++ Source/cmFileCommand.h | 1 + .../RunCMake/file/READ_SYMLINK-noexist-result.txt | 1 + .../RunCMake/file/READ_SYMLINK-noexist-stderr.txt | 6 +++++ Tests/RunCMake/file/READ_SYMLINK-noexist.cmake | 1 + .../file/READ_SYMLINK-notsymlink-result.txt | 1 + .../file/READ_SYMLINK-notsymlink-stderr.txt | 6 +++++ Tests/RunCMake/file/READ_SYMLINK-notsymlink.cmake | 2 ++ Tests/RunCMake/file/READ_SYMLINK.cmake | 13 ++++++++++ Tests/RunCMake/file/RunCMakeTest.cmake | 3 +++ 12 files changed, 93 insertions(+) create mode 100644 Help/release/dev/file-read_symlink.rst create mode 100644 Tests/RunCMake/file/READ_SYMLINK-noexist-result.txt create mode 100644 Tests/RunCMake/file/READ_SYMLINK-noexist-stderr.txt create mode 100644 Tests/RunCMake/file/READ_SYMLINK-noexist.cmake create mode 100644 Tests/RunCMake/file/READ_SYMLINK-notsymlink-result.txt create mode 100644 Tests/RunCMake/file/READ_SYMLINK-notsymlink-stderr.txt create mode 100644 Tests/RunCMake/file/READ_SYMLINK-notsymlink.cmake create mode 100644 Tests/RunCMake/file/READ_SYMLINK.cmake diff --git a/Help/command/file.rst b/Help/command/file.rst index 26a9ae2..6e2a6dd 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -26,6 +26,7 @@ Synopsis file(`MAKE_DIRECTORY`_ [...]) file({`COPY`_ | `INSTALL`_} ... DESTINATION [...]) file(`SIZE`_ ) + file(`READ_SYMLINK`_ ) `Path Conversion`_ file(`RELATIVE_PATH`_ ) @@ -344,6 +345,29 @@ Determine the file size of the ```` and put the result in ```` variable. Requires that ```` is a valid path pointing to a file and is readable. +.. _READ_SYMLINK: + +.. code-block:: cmake + + file(READ_SYMLINK ) + +Read the symlink at ```` and put the result in ````. +Requires that ```` is a valid path pointing to a symlink. If +```` does not exist, or is not a symlink, an error is thrown. + +Note that this command returns the raw symlink path and does not resolve +relative symlinks. If you want to resolve the relative symlink yourself, you +could do something like this: + +.. code-block:: cmake + + set(filename "/path/to/foo.sym") + file(READ_SYMLINK "${filename}" result) + if(NOT IS_ABSOLUTE "${result}") + get_filename_component(dir "${filename}" DIRECTORY) + set(result "${dir}/${result}") + endif() + Path Conversion ^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/file-read_symlink.rst b/Help/release/dev/file-read_symlink.rst new file mode 100644 index 0000000..718802e --- /dev/null +++ b/Help/release/dev/file-read_symlink.rst @@ -0,0 +1,5 @@ +file-read_symlink +----------------- + +* The :command:`file` command learned a new sub-command, ``READ_SYMLINK``, + which can be used to determine the path that a symlink points to. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 73ff5a1..7fc717d 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -180,6 +180,9 @@ bool cmFileCommand::InitialPass(std::vector const& args, if (subCommand == "SIZE") { return this->HandleSizeCommand(args); } + if (subCommand == "READ_SYMLINK") { + return this->HandleReadSymlinkCommand(args); + } std::string e = "does not recognize sub-command " + subCommand; this->SetError(e); @@ -3638,3 +3641,30 @@ bool cmFileCommand::HandleSizeCommand(std::vector const& args) return true; } + +bool cmFileCommand::HandleReadSymlinkCommand( + std::vector 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; + } + + const std::string& filename = args[1]; + const std::string& outputVariable = args[2]; + + std::string result; + if (!cmSystemTools::ReadSymlink(filename, result)) { + std::ostringstream e; + e << "READ_SYMLINK requested of path that is not a symlink:\n " + << filename; + this->SetError(e.str()); + return false; + } + + this->Makefile->AddDefinition(outputVariable, result.c_str()); + + return true; +} diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 01e007d..fe05c98 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -60,6 +60,7 @@ protected: bool HandleGenerateCommand(std::vector const& args); bool HandleLockCommand(std::vector const& args); bool HandleSizeCommand(std::vector const& args); + bool HandleReadSymlinkCommand(std::vector const& args); private: void AddEvaluationFile(const std::string& inputName, diff --git a/Tests/RunCMake/file/READ_SYMLINK-noexist-result.txt b/Tests/RunCMake/file/READ_SYMLINK-noexist-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/READ_SYMLINK-noexist-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/READ_SYMLINK-noexist-stderr.txt b/Tests/RunCMake/file/READ_SYMLINK-noexist-stderr.txt new file mode 100644 index 0000000..32b3e85 --- /dev/null +++ b/Tests/RunCMake/file/READ_SYMLINK-noexist-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at READ_SYMLINK-noexist\.cmake:[0-9]+ \(file\): + file READ_SYMLINK requested of path that is not a symlink: + + .*/Tests/RunCMake/file/READ_SYMLINK-noexist-build/rel\.sym +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/READ_SYMLINK-noexist.cmake b/Tests/RunCMake/file/READ_SYMLINK-noexist.cmake new file mode 100644 index 0000000..9e57e4b --- /dev/null +++ b/Tests/RunCMake/file/READ_SYMLINK-noexist.cmake @@ -0,0 +1 @@ +file(READ_SYMLINK "${CMAKE_CURRENT_BINARY_DIR}/rel.sym" result) diff --git a/Tests/RunCMake/file/READ_SYMLINK-notsymlink-result.txt b/Tests/RunCMake/file/READ_SYMLINK-notsymlink-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/READ_SYMLINK-notsymlink-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/READ_SYMLINK-notsymlink-stderr.txt b/Tests/RunCMake/file/READ_SYMLINK-notsymlink-stderr.txt new file mode 100644 index 0000000..63e32ed --- /dev/null +++ b/Tests/RunCMake/file/READ_SYMLINK-notsymlink-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at READ_SYMLINK-notsymlink\.cmake:[0-9]+ \(file\): + file READ_SYMLINK requested of path that is not a symlink: + + .*/Tests/RunCMake/file/READ_SYMLINK-notsymlink-build/rel\.sym +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/READ_SYMLINK-notsymlink.cmake b/Tests/RunCMake/file/READ_SYMLINK-notsymlink.cmake new file mode 100644 index 0000000..a9798b6 --- /dev/null +++ b/Tests/RunCMake/file/READ_SYMLINK-notsymlink.cmake @@ -0,0 +1,2 @@ +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/rel.sym" "") +file(READ_SYMLINK "${CMAKE_CURRENT_BINARY_DIR}/rel.sym" result) diff --git a/Tests/RunCMake/file/READ_SYMLINK.cmake b/Tests/RunCMake/file/READ_SYMLINK.cmake new file mode 100644 index 0000000..865a2e9 --- /dev/null +++ b/Tests/RunCMake/file/READ_SYMLINK.cmake @@ -0,0 +1,13 @@ +execute_process(COMMAND + ${CMAKE_COMMAND} -E create_symlink "test.txt" "${CMAKE_CURRENT_BINARY_DIR}/rel.sym") +file(READ_SYMLINK "${CMAKE_CURRENT_BINARY_DIR}/rel.sym" result) +if(NOT result STREQUAL "test.txt") + message(SEND_ERROR "Relative symlink is \"${result}\", should be \"test.txt\"") +endif() + +execute_process(COMMAND + ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_BINARY_DIR}/test.txt" "${CMAKE_CURRENT_BINARY_DIR}/abs.sym") +file(READ_SYMLINK "${CMAKE_CURRENT_BINARY_DIR}/abs.sym" result) +if(NOT result MATCHES "^.*/Tests/RunCMake/file/READ_SYMLINK-build/test\\.txt$") + message(SEND_ERROR "Absolute symlink is \"${result}\", should be \"*/Tests/RunCMake/file/READ_SYMLINK-build/test.txt\"") +endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index b9d76bf..b872824 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -55,6 +55,9 @@ run_cmake_command(GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE ${CMAKE_COMMAND} -P if(NOT WIN32 OR CYGWIN) run_cmake(GLOB_RECURSE-cyclic-recursion) run_cmake(INSTALL-SYMLINK) + run_cmake(READ_SYMLINK) + run_cmake(READ_SYMLINK-noexist) + run_cmake(READ_SYMLINK-notsymlink) endif() if(RunCMake_GENERATOR STREQUAL "Ninja") -- cgit v0.12