summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2021-04-26 15:30:50 (GMT)
committerKitware Robot <kwrobot@kitware.com>2021-04-26 15:30:57 (GMT)
commit6aabf2790c4e4f904aeaa166bf6a7abdd2f290e3 (patch)
tree9f50fc14b4aa9f030e7cd8019bd7e6f8c58c0e98
parent2fcd6a0242cba2d063aef2bc75c4d0f9982ca593 (diff)
parente4b793c614f2a499d4d235ec2267ad6bff56a697 (diff)
downloadCMake-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.rst3
-rw-r--r--Help/command/file.rst20
-rw-r--r--Help/release/dev/file-REAL_PATH-EXPAND_TILDE.rst5
-rw-r--r--Source/cmFileCommand.cxx23
-rw-r--r--Tests/RunCMake/file/REAL_PATH.cmake40
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake7
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(