diff options
author | Brad King <brad.king@kitware.com> | 2021-04-26 15:30:50 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2021-04-26 15:30:57 (GMT) |
commit | 6aabf2790c4e4f904aeaa166bf6a7abdd2f290e3 (patch) | |
tree | 9f50fc14b4aa9f030e7cd8019bd7e6f8c58c0e98 | |
parent | 2fcd6a0242cba2d063aef2bc75c4d0f9982ca593 (diff) | |
parent | e4b793c614f2a499d4d235ec2267ad6bff56a697 (diff) | |
download | CMake-6aabf2790c4e4f904aeaa166bf6a7abdd2f290e3.zip CMake-6aabf2790c4e4f904aeaa166bf6a7abdd2f290e3.tar.gz CMake-6aabf2790c4e4f904aeaa166bf6a7abdd2f290e3.tar.bz2 |
Merge topic 'file-REAL_PATH-EXPAND_TILDE'
e4b793c614 file(REAL_PATH): add option EXPAND_TILDE
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Michael Hirsch <michael@scivision.dev>
Merge-request: !6033
-rw-r--r-- | Help/command/cmake_path.rst | 3 | ||||
-rw-r--r-- | Help/command/file.rst | 20 | ||||
-rw-r--r-- | Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst | 5 | ||||
-rw-r--r-- | Source/cmFileCommand.cxx | 23 | ||||
-rw-r--r-- | Tests/RunCMake/file/REAL_PATH.cmake | 40 | ||||
-rw-r--r-- | Tests/RunCMake/file/RunCMakeTest.cmake | 7 |
6 files changed, 77 insertions, 21 deletions
diff --git a/Help/command/cmake_path.rst b/Help/command/cmake_path.rst index a8999f3..193180d 100644 --- a/Help/command/cmake_path.rst +++ b/Help/command/cmake_path.rst @@ -687,7 +687,8 @@ When the ``NORMALIZE`` option is specified, the path is :ref:`normalized <Normalization>` after the path computation. Because ``cmake_path()`` does not access the filesystem, symbolic links are -not resolved. To compute a real path with symbolic links resolved, use the +not resolved and any leading tilde is not expanded. To compute a real path +with symbolic links resolved and leading tildes expanded, use the :command:`file(REAL_PATH)` command instead. Native Conversion diff --git a/Help/command/file.rst b/Help/command/file.rst index 62642cf..e170526 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -50,7 +50,7 @@ Synopsis file(`CHMOD_RECURSE`_ <files>... <directories>... PERMISSIONS <permissions>... [...]) `Path Conversion`_ - file(`REAL_PATH`_ <path> <out-var> [BASE_DIRECTORY <dir>]) + file(`REAL_PATH`_ <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE]) file(`RELATIVE_PATH`_ <out-var> <directory> <file>) file({`TO_CMAKE_PATH`_ | `TO_NATIVE_PATH`_} <path> <out-var>) @@ -924,16 +924,26 @@ Path Conversion .. code-block:: cmake - file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>]) + file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE]) .. versionadded:: 3.19 Compute the absolute path to an existing file or directory with symlinks resolved. -If the provided ``<path>`` is a relative path, it is evaluated relative to the -given base directory ``<dir>``. If no base directory is provided, the default -base directory will be :variable:`CMAKE_CURRENT_SOURCE_DIR`. +``BASE_DIRECTORY <dir>`` + If the provided ``<path>`` is a relative path, it is evaluated relative to the + given base directory ``<dir>``. If no base directory is provided, the default + base directory will be :variable:`CMAKE_CURRENT_SOURCE_DIR`. + +``EXPAND_TILDE`` + .. versionadded:: 3.21 + + If the ``<path>`` is ``~`` or starts with ``~/``, the ``~`` is replaced by + the user's home directory. The path to the home directory is obtained from + environment variables. On Windows, the ``USERPROFILE`` environment variable + is used, falling back to the ``HOME`` environment variable if ``USERPROFILE`` + is not defined. On all other platforms, only ``HOME`` is used. .. _RELATIVE_PATH: diff --git a/Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst b/Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst new file mode 100644 index 0000000..cdf1efa --- /dev/null +++ b/Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst @@ -0,0 +1,5 @@ +file-REAL_PATH-EXPAND_TILDE +--------------------------- + +* The :command:`file(REAL_PATH)` command gained the option ``EXPAND_TILDE`` to + replace any leading tilde with the path to the user's home directory. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 05ebcca..a943258 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1246,9 +1246,12 @@ bool HandleRealPathCommand(std::vector<std::string> const& args, struct Arguments { std::string BaseDirectory; + bool ExpandTilde = false; }; - static auto const parser = cmArgumentParser<Arguments>{}.Bind( - "BASE_DIRECTORY"_s, &Arguments::BaseDirectory); + static auto const parser = + cmArgumentParser<Arguments>{} + .Bind("BASE_DIRECTORY"_s, &Arguments::BaseDirectory) + .Bind("EXPAND_TILDE"_s, &Arguments::ExpandTilde); std::vector<std::string> unparsedArguments; std::vector<std::string> keywordsMissingValue; @@ -1270,7 +1273,21 @@ bool HandleRealPathCommand(std::vector<std::string> const& args, arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory(); } - cmCMakePath path(args[1]); + auto input = args[1]; + if (arguments.ExpandTilde && !input.empty()) { + if (input[0] == '~' && (input.length() == 1 || input[1] == '/')) { + std::string home; + if ( +#if defined(_WIN32) && !defined(__CYGWIN__) + cmSystemTools::GetEnv("USERPROFILE", home) || +#endif + cmSystemTools::GetEnv("HOME", home)) { + input.replace(0, 1, home); + } + } + } + + cmCMakePath path(input, cmCMakePath::auto_format); path = path.Absolute(arguments.BaseDirectory).Normal(); auto realPath = cmSystemTools::GetRealPath(path.GenericString()); diff --git a/Tests/RunCMake/file/REAL_PATH.cmake b/Tests/RunCMake/file/REAL_PATH.cmake index be25706..0b5d3c0 100644 --- a/Tests/RunCMake/file/REAL_PATH.cmake +++ b/Tests/RunCMake/file/REAL_PATH.cmake @@ -1,14 +1,36 @@ -file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/test.txt") -file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/test.sym") -file(CREATE_LINK "test.txt" "${CMAKE_CURRENT_BINARY_DIR}/test.sym" SYMBOLIC) +if (NOT WIN32 OR CYGWIN) + file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/test.txt") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/test.sym") + file(CREATE_LINK "test.txt" "${CMAKE_CURRENT_BINARY_DIR}/test.sym" SYMBOLIC) -file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/test.sym" real_path) -if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") - message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") + file(REAL_PATH "${CMAKE_CURRENT_BINARY_DIR}/test.sym" real_path) + if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") + endif() + + file(REAL_PATH "test.sym" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") + endif() +endif() + + +If (WIN32) + cmake_path(SET HOME_DIR "$ENV{USERPROFILE}") + if (NOT HOME_DIR) + cmake_path(SET HOME_DIR "$ENV{HOME}") + endif() +else() + set(HOME_DIR "$ENV{HOME}") +endif() + +file(REAL_PATH "~" real_path EXPAND_TILDE) +if (NOT real_path STREQUAL "${HOME_DIR}") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${HOME_DIR}\"") endif() -file(REAL_PATH "test.sym" real_path BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -if (NOT real_path STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/test.txt") - message(SEND_ERROR "real path is \"${real_path}\", should be \"${CMAKE_CURRENT_BINARY_DIR}/test.txt\"") +file(REAL_PATH "~/test.txt" real_path EXPAND_TILDE) +if (NOT real_path STREQUAL "${HOME_DIR}/test.txt") + message(SEND_ERROR "real path is \"${real_path}\", should be \"${HOME_DIR}/test.txt\"") endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index b4ea9ba..6d1109a 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -96,11 +96,12 @@ if(NOT WIN32 OR CYGWIN) run_cmake(READ_SYMLINK-noexist) run_cmake(READ_SYMLINK-notsymlink) run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN) - run_cmake(REAL_PATH-unexpected-arg) - run_cmake(REAL_PATH-no-base-dir) - run_cmake(REAL_PATH) endif() +run_cmake(REAL_PATH-unexpected-arg) +run_cmake(REAL_PATH-no-base-dir) +run_cmake(REAL_PATH) + if(RunCMake_GENERATOR MATCHES "Ninja") # Detect ninja version so we know what tests can be supported. execute_process( |