From cd315fecaf4c7473950c1610e06417634b416954 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 16 Aug 2021 18:54:15 +0300 Subject: Optimize rep-fetch for dir and git repos quering projects info in single call --- bpkg/rep-fetch.cxx | 89 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 30 deletions(-) (limited to 'bpkg/rep-fetch.cxx') diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index f6165b7..80598c5 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -195,76 +195,105 @@ namespace bpkg static vector parse_package_manifests (const common_options& co, const dir_path& repo_dir, - vector&& sms, + vector&& pms, bool iu, const repository_location& rl, const optional& fragment) // For diagnostics. { - vector r; - r.reserve (sms.size ()); + auto package_info = [&rl, &fragment] (const package_manifest& pm, + diag_record& dr) + { + dr << "package "; + + if (!pm.location->current ()) + dr << "'" << pm.location->string () << "' "; // Strip trailing '/'. + + dr << "in repository " << rl; + + if (fragment) + dr << ' ' << *fragment; + }; - for (package_manifest& sm: sms) + // Verify that all the package directories contain the package manifest + // files and retrieve the package versions via the single `b info` call. + // While at it cache the manifest paths for the future use. + // + paths mfs; + vector> pvs; { - assert (sm.location); + mfs.reserve (pms.size ()); - auto package_info = [&sm, &rl, &fragment] (diag_record& dr) + dir_paths pds; + pds.reserve (pms.size ()); + + for (const package_manifest& pm: pms) { - dr << "package "; + assert (pm.location); - if (!sm.location->current ()) - dr << "'" << sm.location->string () << "' "; // Strip trailing '/'. + dir_path d (repo_dir / path_cast (*pm.location)); + d.normalize (); // In case location is './'. - dr << "in repository " << rl; + path f (d / manifest_file); + if (!exists (f)) + { + diag_record dr (fail); + dr << "no manifest file for "; + package_info (pm, dr); + } - if (fragment) - dr << ' ' << *fragment; - }; + mfs.push_back (move (f)); + pds.push_back (move (d)); + } - auto failure = [&package_info] (const char* desc) - { - diag_record dr (fail); - dr << desc << " for "; - package_info (dr); - }; + pvs = package_versions (co, pds); + } - dir_path d (repo_dir / path_cast (*sm.location)); - d.normalize (); // In case location is './'. + // Parse package manifests, fixing up their versions. + // + vector r; + r.reserve (pms.size ()); + + for (size_t i (0); i != pms.size (); ++i) + { + package_manifest& pm (pms[i]); - path f (d / manifest_file); - if (!exists (f)) - failure ("no manifest file"); + assert (pm.location); + + const path& f (mfs[i]); try { ifdstream ifs (f); manifest_parser mp (ifs, f.string ()); + optional& pv (pvs[i]); + package_manifest m ( mp, - [&co, &d] (version& v) + [&pv] (version& v) { - if (optional pv = package_version (co, d)) + if (pv) v = move (*pv); }, iu); // Save the package manifest, preserving its location. // - m.location = move (*sm.location); - sm = move (m); + m.location = move (*pm.location); + pm = move (m); } catch (const manifest_parsing& e) { diag_record dr (fail (e.name, e.line, e.column)); dr << e.description << info; - package_info (dr); + package_info (pm, dr); } catch (const io_error& e) { fail << "unable to read from " << f << ": " << e; } - r.emplace_back (move (sm)); + r.emplace_back (move (pm)); } return r; -- cgit v1.1