@@ -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 }
0 commit comments