Skip to content

Commit

Permalink
search: implement name like searches
Browse files Browse the repository at this point in the history
I think this is now implemented according to the current (what will be
0.10) spec. This is vaguely tested. This uncovers some limitations of
the prefix calculation code as well
  • Loading branch information
dcbaker committed Mar 6, 2024
1 parent 1e1222f commit 179b6cb
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 23 deletions.
75 changes: 53 additions & 22 deletions src/search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,49 @@ namespace search {
return out;
}

const std::vector<fs::path> search_paths() {
/// @brief Build a combination of all prefixes, subdirs, and name-like paths
/// @param roots the prefix roots
/// @param name the name of the package to find
/// @return all of the search paths combined into concrete instances
std::vector<fs::path> expand_search_paths(const std::vector<fs::path> & roots, std::string_view name) {
// TODO: Windows paths
// TODO: MacOS paths
const std::vector<fs::path> segments{platform::libdir(), "share"};
std::vector<fs::path> paths;

for (auto && root : roots) {
for (auto && segment : segments) {
if (const fs::path subdir = root / segment / "cps"; fs::is_directory(subdir)) {
paths.emplace_back(subdir);
if (const fs::path namedir = subdir / name; fs::is_directory(namedir)) {
paths.emplace_back(namedir);
for (const fs::path & name_subdir : fs::directory_iterator(namedir)) {
if (fs::is_directory(name_subdir)) {
paths.emplace_back(name_subdir);
}
}
}
}
}
}

return paths;
}

/// @brief create concrete search paths for a specific package
/// @param name the name of the package
/// @return a vector of those paths
std::vector<fs::path> search_paths(std::string_view name) {

// Build all of the roots to search
std::vector<fs::path> roots;
if (const char * env_c = std::getenv("CPS_PATH")) {
auto && env = utils::split(env_c);
roots.insert(roots.end(), env.begin(), env.end());
}
roots.emplace_back("/usr");

std::vector<fs::path> paths;
for (auto && root : roots) {
paths.emplace_back(root / platform::libdir() / "cps");
paths.emplace_back(root / "share/cps");
}
return paths;
return expand_search_paths(roots, name);
}

/// @brief Find all possible paths for a given CPS name
Expand All @@ -97,19 +124,10 @@ namespace search {
}

// TODO: Need something like pkgconf's --personality option
// TODO: we likely either need to return all possible files, or load
// a file
// TODO: what to do about finding multiple versions of the same
// dependency?
auto && paths = search_paths();
auto && paths = search_paths(name);
std::vector<fs::path> found{};
for (auto && dir : paths) {
// TODO: <prefix>/<libdir>/cps/<name-like>/
// TODO: <prefix>/share/cps/<name-like>/
// TODO: <prefix>/share/cps/

if (fs::is_directory(dir)) {
// TODO: <name-like>
const fs::path file = dir / fmt::format("{}.cps", name);
if (fs::is_regular_file(file)) {
found.push_back(file);
Expand Down Expand Up @@ -262,18 +280,31 @@ namespace search {
}
}

fs::path calculate_prefix(const fs::path & path) {
fs::path calculate_prefix(const fs::path & path, std::string_view name) {
// TODO: Windows
// TODO: /cps/<name-like>
// TODO: Mac

std::vector<std::string> split = utils::split(std::string{path}, "/");
// If the path ends in "/" then an empty string will be placed at
// the end of the split paths
if (split.back() == "") {
split.pop_back();
}
// If split ends in name, ex: /usr/lib/cps/name/
if (split.back() == name) {
split.pop_back();
}
// If split ends in name/*, ex: /usr/lib/cps/name/*
// Then drop both the */ and the name/
if (*(split.end() - 2) == name) {
split.pop_back();
split.pop_back();
}
if (split.back() == "cps") {
split.pop_back();
}
// Match only share or libdir, but not potentially an odd situation
// like /opt/share/libdir/
// Match only share or libdir, but not a potential odd situation
// like `/opt/share/libdir/`
if (split.back() == "share" || split.back() == platform::libdir()) {
split.pop_back();
}
Expand Down Expand Up @@ -352,7 +383,7 @@ namespace search {
// TODO: Windows…
auto && split = utils::split(s, "/");
if (split[0] == "@prefix@") {
fs::path p = calculate_prefix(node->data.package.cps_path);
fs::path p = calculate_prefix(node->data.package.cps_path, node->data.package.name);
for (auto it = split.begin() + 1; it != split.end(); ++it) {
p /= *it;
}
Expand Down
14 changes: 13 additions & 1 deletion tests/cases.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,19 @@
expected = "-I/sentinel/err -l/sentinel/lib/libfoo.a"

[[case]]
name = "prefix calculated"
name = "prefix calculated (found in root)"
cps = "cps-path-not-set-root"
args = ["--cflags-only-I", "--libs-only-l"]
expected = "-I{prefix}/err -l{prefix}/lib/libfoo.a"

[[case]]
name = "prefix calculated (found in root/name)"
cps = "cps-path-not-set-subdir"
args = ["--cflags-only-I", "--libs-only-l"]
expected = "-I{prefix}/err -l{prefix}/lib/libfoo.a"

[[case]]
name = "prefix calculated (root/name/*/)"
cps = "cps-path-not-set"
args = ["--cflags-only-I", "--libs-only-l"]
expected = "-I{prefix}/err -l{prefix}/lib/libfoo.a"
Expand Down
13 changes: 13 additions & 0 deletions tests/cases/lib/cps/cps-path-not-set-root.cps
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"Name": "cps-path-not-set-root",
"Cps-Version": "0.9.0",
"Version": "1.0.0",
"Components": {
"default": {
"Type": "archive",
"Includes": {"C": ["@prefix@/err"]},
"Location": "@prefix@/lib/libfoo.a"
}
},
"Default-Components": ["default"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"Name": "cps-path-not-set-subdir",
"Cps-Version": "0.9.0",
"Version": "1.0.0",
"Components": {
"default": {
"Type": "archive",
"Includes": {"C": ["@prefix@/err"]},
"Location": "@prefix@/lib/libfoo.a"
}
},
"Default-Components": ["default"]
}


File renamed without changes.
File renamed without changes.

0 comments on commit 179b6cb

Please sign in to comment.