PathResolver: Add mode to collapse paths naively and look up on-disk case
In CMake 3.31 and below, `CollapseFullPath` did this on Windows. KWSys has since stopped looking up the on-disk case in `CollapseFullPath` to avoid disk access when most callers only need an in-memory operation. We currently call `GetActualCaseForPath` explicitly when needed. Add a mode to `cm::PathResolver` to combine these operations and cache disk access behind the `System::ReadName` callback. We will use this to restore the way CMake 3.31 and below normalized input paths on Windows. Issue: #26750 Issue: #20214
This commit is contained in:
parent
75913fe430
commit
8dfc725cdb
@ -492,6 +492,14 @@ struct NaivePath
|
||||
static constexpr Options::Symlinks Symlinks = Options::Symlinks::None;
|
||||
static constexpr Options::Existence Existence = Options::Existence::Agnostic;
|
||||
};
|
||||
struct CasePath
|
||||
{
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
static constexpr Options::ActualCase ActualCase = Options::ActualCase::Yes;
|
||||
#endif
|
||||
static constexpr Options::Symlinks Symlinks = Options::Symlinks::None;
|
||||
static constexpr Options::Existence Existence = Options::Existence::Agnostic;
|
||||
};
|
||||
struct RealPath
|
||||
{
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
@ -512,6 +520,8 @@ struct LogicalPath
|
||||
#if defined(__SUNPRO_CC)
|
||||
constexpr Options::Symlinks NaivePath::Symlinks;
|
||||
constexpr Options::Existence NaivePath::Existence;
|
||||
constexpr Options::Symlinks CasePath::Symlinks;
|
||||
constexpr Options::Existence CasePath::Existence;
|
||||
constexpr Options::Symlinks RealPath::Symlinks;
|
||||
constexpr Options::Existence RealPath::Existence;
|
||||
constexpr Options::Symlinks LogicalPath::Symlinks;
|
||||
@ -535,6 +545,7 @@ System::~System() = default;
|
||||
|
||||
template class Resolver<Policies::LogicalPath>;
|
||||
template class Resolver<Policies::RealPath>;
|
||||
template class Resolver<Policies::CasePath>;
|
||||
template class Resolver<Policies::NaivePath>;
|
||||
|
||||
}
|
||||
|
@ -85,6 +85,11 @@ struct LogicalPath;
|
||||
and reads their on-disk case (on Windows and macOS). */
|
||||
struct RealPath;
|
||||
|
||||
/** Normalizes paths while assuming components followed by '..'
|
||||
components are not symlinks. Does not require paths to exist, but
|
||||
reads on-disk case of paths that do exist (on Windows and macOS). */
|
||||
struct CasePath;
|
||||
|
||||
/** Normalizes paths in memory without disk access.
|
||||
Assumes components followed by '..' components are not symlinks. */
|
||||
struct NaivePath;
|
||||
@ -94,6 +99,7 @@ struct NaivePath;
|
||||
|
||||
extern template class Resolver<Policies::LogicalPath>;
|
||||
extern template class Resolver<Policies::RealPath>;
|
||||
extern template class Resolver<Policies::CasePath>;
|
||||
extern template class Resolver<Policies::NaivePath>;
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
// IWYU pragma: no_forward_declare cm::PathResolver::Policies::LogicalPath
|
||||
// IWYU pragma: no_forward_declare cm::PathResolver::Policies::NaivePath
|
||||
// IWYU pragma: no_forward_declare cm::PathResolver::Policies::CasePath
|
||||
// IWYU pragma: no_forward_declare cm::PathResolver::Policies::RealPath
|
||||
|
||||
namespace {
|
||||
@ -212,6 +213,22 @@ bool posixSymlink()
|
||||
{ "/1/2/3", { {}, {} } },
|
||||
});
|
||||
|
||||
{
|
||||
Resolver<Policies::CasePath> const r(os);
|
||||
EXPECT_RESOLVE("/link-a", "/link-a");
|
||||
EXPECT_RESOLVE("/link-a-excess", "/link-a-excess");
|
||||
EXPECT_RESOLVE("/link-a-excess/b", "/link-a-excess/b");
|
||||
EXPECT_RESOLVE("/link-broken", "/link-broken");
|
||||
EXPECT_RESOLVE("/link-a/../missing", "/missing");
|
||||
EXPECT_RESOLVE("/a/b/link-c", "/a/b/link-c");
|
||||
EXPECT_RESOLVE("/a/link-b/c", "/a/link-b/c");
|
||||
EXPECT_RESOLVE("/a/link-b/link-c/..", "/a/link-b");
|
||||
EXPECT_RESOLVE("/a/b/c/link-..|..", "/a/b/c/link-..|..");
|
||||
EXPECT_RESOLVE("/a/b/c/link-..|../link-b", "/a/b/c/link-..|../link-b");
|
||||
EXPECT_RESOLVE("/a/link-|1|2/3", "/a/link-|1|2/3");
|
||||
EXPECT_RESOLVE("/a/link-|1|2/../2/3", "/a/2/3");
|
||||
}
|
||||
|
||||
{
|
||||
Resolver<Policies::LogicalPath> const r(os);
|
||||
EXPECT_RESOLVE("/link-a", "/link-a");
|
||||
@ -263,6 +280,16 @@ bool macosActualCase()
|
||||
{ "/upper/link-c-upper", { "LINK-C-UPPER", "/upper" } },
|
||||
});
|
||||
|
||||
{
|
||||
Resolver<Policies::CasePath> const r(os);
|
||||
EXPECT_RESOLVE("/mIxEd/MiSsInG", "/MiXeD/MiSsInG");
|
||||
EXPECT_RESOLVE("/mIxEd/link-MiXeD", "/MiXeD/LiNk-MiXeD");
|
||||
EXPECT_RESOLVE("/mIxEd/link-c-MiXeD", "/MiXeD/LiNk-C-MiXeD");
|
||||
EXPECT_RESOLVE("/upper/mIsSiNg", "/UPPER/mIsSiNg");
|
||||
EXPECT_RESOLVE("/upper/link-upper", "/UPPER/LINK-UPPER");
|
||||
EXPECT_RESOLVE("/upper/link-c-upper", "/UPPER/LINK-C-UPPER");
|
||||
}
|
||||
|
||||
{
|
||||
Resolver<Policies::LogicalPath> const r(os);
|
||||
EXPECT_RESOLVE("/mIxEd/MiSsInG", "/MiXeD/MiSsInG");
|
||||
@ -302,6 +329,16 @@ bool windowsRoot()
|
||||
EXPECT_RESOLVE("C:/..", "C:/");
|
||||
EXPECT_RESOLVE("c:/../", "c:/");
|
||||
}
|
||||
{
|
||||
Resolver<Policies::CasePath> const r(os);
|
||||
EXPECT_RESOLVE("c:/", "C:/");
|
||||
EXPECT_RESOLVE("C:/", "C:/");
|
||||
EXPECT_RESOLVE("c://", "C:/");
|
||||
EXPECT_RESOLVE("C:/.", "C:/");
|
||||
EXPECT_RESOLVE("c:/./", "C:/");
|
||||
EXPECT_RESOLVE("C:/..", "C:/");
|
||||
EXPECT_RESOLVE("c:/../", "C:/");
|
||||
}
|
||||
os.SetPaths({
|
||||
{ "c:/", { {}, {} } },
|
||||
{ "//host/", { {}, {} } },
|
||||
@ -360,6 +397,16 @@ bool windowsActualCase()
|
||||
{ "c:/upper/link-c-upper", { "LINK-C-UPPER", "c:/upper" } },
|
||||
});
|
||||
|
||||
{
|
||||
Resolver<Policies::CasePath> const r(os);
|
||||
EXPECT_RESOLVE("c:/mIxEd/MiSsInG", "C:/MiXeD/MiSsInG");
|
||||
EXPECT_RESOLVE("c:/mIxEd/link-MiXeD", "C:/MiXeD/LiNk-MiXeD");
|
||||
EXPECT_RESOLVE("c:/mIxEd/link-c-MiXeD", "C:/MiXeD/LiNk-C-MiXeD");
|
||||
EXPECT_RESOLVE("c:/upper/mIsSiNg", "C:/UPPER/mIsSiNg");
|
||||
EXPECT_RESOLVE("c:/upper/link-upper", "C:/UPPER/LINK-UPPER");
|
||||
EXPECT_RESOLVE("c:/upper/link-c-upper", "C:/UPPER/LINK-C-UPPER");
|
||||
}
|
||||
|
||||
{
|
||||
Resolver<Policies::LogicalPath> const r(os);
|
||||
EXPECT_RESOLVE("c:/mIxEd/MiSsInG", "C:/MiXeD/MiSsInG");
|
||||
@ -441,6 +488,27 @@ bool windowsWorkingDirectoryOnDrive()
|
||||
EXPECT_RESOLVE("E:.", "E:/");
|
||||
EXPECT_RESOLVE("E:..", "E:/");
|
||||
}
|
||||
{
|
||||
Resolver<Policies::CasePath> const r(os);
|
||||
EXPECT_RESOLVE("c:", "C:/cwd");
|
||||
EXPECT_RESOLVE("c:.", "C:/cwd");
|
||||
EXPECT_RESOLVE("c:..", "C:/");
|
||||
EXPECT_RESOLVE("C:", "C:/cwd");
|
||||
EXPECT_RESOLVE("C:.", "C:/cwd");
|
||||
EXPECT_RESOLVE("C:..", "C:/");
|
||||
EXPECT_RESOLVE("d:", "D:/cwd-d");
|
||||
EXPECT_RESOLVE("d:.", "D:/cwd-d");
|
||||
EXPECT_RESOLVE("d:..", "D:/");
|
||||
EXPECT_RESOLVE("D:", "D:/cwd-d");
|
||||
EXPECT_RESOLVE("D:.", "D:/cwd-d");
|
||||
EXPECT_RESOLVE("D:..", "D:/");
|
||||
EXPECT_RESOLVE("e:", "E:/");
|
||||
EXPECT_RESOLVE("e:.", "E:/");
|
||||
EXPECT_RESOLVE("e:..", "E:/");
|
||||
EXPECT_RESOLVE("E:", "E:/");
|
||||
EXPECT_RESOLVE("E:.", "E:/");
|
||||
EXPECT_RESOLVE("E:..", "E:/");
|
||||
}
|
||||
os.SetPaths({
|
||||
{ "c:/", { {}, {} } },
|
||||
{ "c:/cwd", { {}, {} } },
|
||||
@ -496,6 +564,13 @@ bool windowsNetworkShare()
|
||||
EXPECT_RESOLVE("link-to-host-share/..", "//host/");
|
||||
EXPECT_RESOLVE("link-to-host-share/../missing", "//host/missing");
|
||||
}
|
||||
|
||||
{
|
||||
Resolver<Policies::CasePath> const r(os);
|
||||
EXPECT_RESOLVE("link-to-host-share", "C:/cwd/link-to-host-share");
|
||||
EXPECT_RESOLVE("link-to-host-share/..", "C:/cwd");
|
||||
EXPECT_RESOLVE("link-to-host-share/../missing", "C:/cwd/missing");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user