Skip to content

Commit ecb82f4

Browse files
committed
search: implement name like searches
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
1 parent 78db74b commit ecb82f4

6 files changed

Lines changed: 94 additions & 23 deletions

File tree

src/cps/search.cpp

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,49 @@ namespace cps::search {
7171
return out;
7272
}
7373

74-
const std::vector<fs::path> search_paths() {
74+
/// @brief Build a combination of all prefixes, subdirs, and name-like paths
75+
/// @param roots the prefix roots
76+
/// @param name the name of the package to find
77+
/// @return all of the search paths combined into concrete instances
78+
std::vector<fs::path> expand_search_paths(const std::vector<fs::path> & roots, std::string_view name) {
7579
// TODO: Windows paths
7680
// TODO: MacOS paths
81+
const std::vector<fs::path> segments{platform::libdir(), "share"};
82+
std::vector<fs::path> paths;
83+
84+
for (auto && root : roots) {
85+
for (auto && segment : segments) {
86+
if (const fs::path subdir = root / segment / "cps"; fs::is_directory(subdir)) {
87+
paths.emplace_back(subdir);
88+
if (const fs::path namedir = subdir / name; fs::is_directory(namedir)) {
89+
paths.emplace_back(namedir);
90+
for (const fs::path & name_subdir : fs::directory_iterator(namedir)) {
91+
if (fs::is_directory(name_subdir)) {
92+
paths.emplace_back(name_subdir);
93+
}
94+
}
95+
}
96+
}
97+
}
98+
}
99+
100+
return paths;
101+
}
102+
103+
/// @brief create concrete search paths for a specific package
104+
/// @param name the name of the package
105+
/// @return a vector of those paths
106+
std::vector<fs::path> search_paths(std::string_view name) {
107+
108+
// Build all of the roots to search
77109
std::vector<fs::path> roots;
78110
if (const char * env_c = std::getenv("CPS_PATH")) {
79111
auto && env = utils::split(env_c);
80112
roots.insert(roots.end(), env.begin(), env.end());
81113
}
82114
roots.emplace_back("/usr");
83115

84-
std::vector<fs::path> paths;
85-
for (auto && root : roots) {
86-
paths.emplace_back(root / platform::libdir() / "cps");
87-
paths.emplace_back(root / "share/cps");
88-
}
89-
return paths;
116+
return expand_search_paths(roots, name);
90117
}
91118

92119
/// @brief Find all possible paths for a given CPS name
@@ -99,19 +126,10 @@ namespace cps::search {
99126
}
100127

101128
// TODO: Need something like pkgconf's --personality option
102-
// TODO: we likely either need to return all possible files, or load
103-
// a file
104-
// TODO: what to do about finding multiple versions of the same
105-
// dependency?
106-
auto && paths = search_paths();
129+
auto && paths = search_paths(name);
107130
std::vector<fs::path> found{};
108131
for (auto && dir : paths) {
109-
// TODO: <prefix>/<libdir>/cps/<name-like>/
110-
// TODO: <prefix>/share/cps/<name-like>/
111-
// TODO: <prefix>/share/cps/
112-
113132
if (fs::is_directory(dir)) {
114-
// TODO: <name-like>
115133
const fs::path file = dir / fmt::format("{}.cps", name);
116134
if (fs::is_regular_file(file)) {
117135
found.push_back(file);
@@ -264,18 +282,31 @@ namespace cps::search {
264282
}
265283
}
266284

267-
fs::path calculate_prefix(const fs::path & path) {
285+
fs::path calculate_prefix(const fs::path & path, std::string_view name) {
268286
// TODO: Windows
269-
// TODO: /cps/<name-like>
287+
// TODO: Mac
288+
270289
std::vector<std::string> split = utils::split(std::string{path}, "/");
290+
// If the path ends in "/" then an empty string will be placed at
291+
// the end of the split paths
271292
if (split.back() == "") {
272293
split.pop_back();
273294
}
295+
// If split ends in name, ex: /usr/lib/cps/name/
296+
if (split.back() == name) {
297+
split.pop_back();
298+
}
299+
// If split ends in name/*, ex: /usr/lib/cps/name/*
300+
// Then drop both the */ and the name/
301+
if (*(split.end() - 2) == name) {
302+
split.pop_back();
303+
split.pop_back();
304+
}
274305
if (split.back() == "cps") {
275306
split.pop_back();
276307
}
277-
// Match only share or libdir, but not potentially an odd situation
278-
// like /opt/share/libdir/
308+
// Match only share or libdir, but not a potential odd situation
309+
// like `/opt/share/libdir/`
279310
if (split.back() == "share" || split.back() == platform::libdir()) {
280311
split.pop_back();
281312
}
@@ -354,7 +385,7 @@ namespace cps::search {
354385
// TODO: Windows…
355386
auto && split = utils::split(s, "/");
356387
if (split[0] == "@prefix@") {
357-
fs::path p = calculate_prefix(node->data.package.cps_path);
388+
fs::path p = calculate_prefix(node->data.package.cps_path, node->data.package.name);
358389
for (auto it = split.begin() + 1; it != split.end(); ++it) {
359390
p /= *it;
360391
}

tests/cases.toml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,19 @@
7777
expected = "-I/sentinel/err -l/sentinel/lib/libfoo.a"
7878

7979
[[case]]
80-
name = "prefix calculated"
80+
name = "prefix calculated (found in root)"
81+
cps = "cps-path-not-set-root"
82+
args = ["--cflags-only-I", "--libs-only-l"]
83+
expected = "-I{prefix}/err -l{prefix}/lib/libfoo.a"
84+
85+
[[case]]
86+
name = "prefix calculated (found in root/name)"
87+
cps = "cps-path-not-set-subdir"
88+
args = ["--cflags-only-I", "--libs-only-l"]
89+
expected = "-I{prefix}/err -l{prefix}/lib/libfoo.a"
90+
91+
[[case]]
92+
name = "prefix calculated (root/name/*/)"
8193
cps = "cps-path-not-set"
8294
args = ["--cflags-only-I", "--libs-only-l"]
8395
expected = "-I{prefix}/err -l{prefix}/lib/libfoo.a"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"Name": "cps-path-not-set-root",
3+
"Cps-Version": "0.9.0",
4+
"Version": "1.0.0",
5+
"Components": {
6+
"default": {
7+
"Type": "archive",
8+
"Includes": {"C": ["@prefix@/err"]},
9+
"Location": "@prefix@/lib/libfoo.a"
10+
}
11+
},
12+
"Default-Components": ["default"]
13+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"Name": "cps-path-not-set-subdir",
3+
"Cps-Version": "0.9.0",
4+
"Version": "1.0.0",
5+
"Components": {
6+
"default": {
7+
"Type": "archive",
8+
"Includes": {"C": ["@prefix@/err"]},
9+
"Location": "@prefix@/lib/libfoo.a"
10+
}
11+
},
12+
"Default-Components": ["default"]
13+
}
14+
15+

tests/cases/lib/cps/cps-path-not-set.cps renamed to tests/cases/lib/cps/cps-path-not-set/foo/cps-path-not-set.cps

File renamed without changes.

0 commit comments

Comments
 (0)