From b51954dc7c88372f861ba2911e7270d39337d2dc Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 23 Aug 2024 11:55:47 -0700 Subject: [PATCH] search: Be smarter about removing datadir and libdir to calculate a prefix There are two corrections here: 1) only remove one, either the datadir or the libdir 2) only remove the directory if the whole directory can be removed, for example: the prefix is `/usr/lib/foo/x86_64-linux-gnu`, and the libdir is `lib/x86_64-linux-gnu`, we don't want to take off just the `x86_64-linux-gnu`, we want to leave the whole thing since we couldn't remove the entire libdir. --- src/cps/search.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/cps/search.cpp b/src/cps/search.cpp index a4ad449..43a78d5 100644 --- a/src/cps/search.cpp +++ b/src/cps/search.cpp @@ -332,21 +332,31 @@ namespace cps::search { } fs::path p = filename.parent_path(); + + const auto reducer = [&p](fs::path dir) -> std::optional { + fs::path np = p; + + // remove a trailing slash + if (dir.stem() == "") { + dir = dir.parent_path(); + } + + while (dir.stem() == np.stem()) { + dir = dir.parent_path(); + np = np.parent_path(); + } + + // If our new path has changed and we have consumed the entire + // directory, then return that, otherwise this was not + // successful. + return np != p && dir == dir.root_path() ? std::optional{np} : std::nullopt; + }; + if (p.stem() == "cps") { p = p.parent_path(); } - fs::path dir = platform::datadir(); - while (dir.stem() == p.stem()) { - dir = dir.parent_path(); - p = p.parent_path(); - } - dir = platform::libdir(); - while (dir.stem() == p.stem()) { - dir = dir.parent_path(); - p = p.parent_path(); - } - return p; + return reducer(platform::libdir()).value_or(reducer(platform::datadir()).value_or(p)); } /// @brief Calculate the required components in the graph