cmake_path: Fix 'GET "foo/.." STEM' result

`cmake_path(GET "foo/.." STEM out)` is supposed to set `out` to `".."`,
the entire `cmake_path(GET "foo/.." FILENAME)` result.

However, the `GetNarrowStem()` logic in `cmCMakePath` was lacking
the `.` and `..` special-casing logic present in other methods.
As a result, it would erroneously trim the second `.` off of a stem
of `..` and return only `.`.

This caused the result of `cmake_path(GET "foo/.." STEM)` to be `"."`.

Making the standard empty-or-.-or-.. checks and bailing out early
fixes the result of `cmCMakePaths{".."}.GetNarrowStem()`.

Fixes: #26235
This commit is contained in:
FeRD (Frank Dana)
2024-08-21 14:33:52 -04:00
committed by Brad King
parent 8dcb35911c
commit b0be1bd9ca
2 changed files with 74 additions and 5 deletions

View File

@@ -57,11 +57,13 @@ cmCMakePath cmCMakePath::GetWideExtension() const
cmCMakePath cmCMakePath::GetNarrowStem() const
{
auto stem = this->Path.stem().string();
if (!stem.empty()) {
auto pos = stem.find('.', stem[0] == '.' ? 1 : 0);
if (pos != std::string::npos) {
return stem.substr(0, pos);
}
if (stem.empty() || stem == "." || stem == "..") {
return stem;
}
auto pos = stem.find('.', stem[0] == '.' ? 1 : 0);
if (pos != std::string::npos) {
return stem.substr(0, pos);
}
return stem;
}

View File

@@ -245,4 +245,71 @@ if (NOT output STREQUAL ".file")
list (APPEND errors "STEM returns bad data: ${output}")
endif()
##################################################
## tests for subcommands' handling of "." and ".."
##################################################
if (WIN32)
set (dot "C:/aa/bb/.")
set (dotdot "C:/ee/ff/..")
else()
set (dot "/aa/bb/.")
set (dotdot "/ee/ff/..")
endif()
cmake_path(GET dot FILENAME dot_out)
cmake_path(GET dotdot FILENAME dotdot_out)
if (NOT dot_out STREQUAL ".")
list(APPEND errors "FILENAME returns bad data for '<path>/.': ${dot_out}")
endif()
if (NOT dotdot_out STREQUAL "..")
list(APPEND errors "FILENAME returns bad data for '<path>/..': ${dotdot_out}")
endif()
cmake_path(GET dot STEM dot_out)
cmake_path(GET dotdot STEM dotdot_out)
if (NOT dot_out STREQUAL ".")
list(APPEND errors "STEM returns bad data for '<path>/.': ${dot_out}")
endif()
if (NOT dotdot_out STREQUAL "..")
list(APPEND errors "STEM returns bad data for '<path>/..': ${dotdot_out}")
endif()
cmake_path(GET dot STEM LAST_ONLY dot_out)
cmake_path(GET dotdot STEM LAST_ONLY dotdot_out)
if (NOT dot_out STREQUAL ".")
list(APPEND errors
"STEM LAST_ONLY returns bad data for '<path>/.': ${dot_out}")
endif()
if (NOT dotdot_out STREQUAL "..")
list(APPEND errors
"STEM LAST_ONLY returns bad data for '<path>/..': ${dotdot_out}")
endif()
cmake_path(GET dot EXTENSION dot_out)
cmake_path(GET dotdot EXTENSION dotdot_out)
if (NOT dot_out STREQUAL "")
list(APPEND errors
"EXTENSION returns bad data for '<path>/.': ${dot_out}")
endif()
if (NOT dotdot_out STREQUAL "")
list(APPEND errors
"EXTENSION returns bad data for '<path>/..': ${dotdot_out}")
endif()
cmake_path(GET dot EXTENSION LAST_ONLY dot_out)
cmake_path(GET dotdot EXTENSION LAST_ONLY dotdot_out)
if (NOT dot_out STREQUAL "")
list(APPEND errors
"EXTENSION LAST_ONLY returns bad data for '<path>/.': ${dot_out}")
endif()
if (NOT dotdot_out STREQUAL "")
list(APPEND errors
"EXTENSION LAST_ONLY returns bad data for '<path>/..': ${dotdot_out}")
endif()
check_errors (GET ${errors})