From 4fd96434dd9afca5f446275fd037e28a09c85edd Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 18 May 2019 22:17:53 +0300 Subject: Add rep-info --deep option --- bpkg/rep-fetch.cxx | 141 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 124 insertions(+), 17 deletions(-) (limited to 'bpkg/rep-fetch.cxx') diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index 0c2ed89..fd47198 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -263,10 +263,47 @@ namespace bpkg return r; } + // Return contents of a file referenced by a *-file package manifest value. + // + static string + read_package_file (const path& f, + const string& name, + const dir_path& pkg, + const dir_path& repo, + const repository_location& rl, + const string& fragment) + { + path rp (pkg / f); + path fp (repo / rp); + + try + { + ifdstream is (fp); + string s (is.read_text ()); + + if (s.empty ()) + fail << name << " manifest value in " << pkg / manifest_file + << " references empty file " << rp << + info << "repository " << rl + << (!fragment.empty () ? " " + fragment : ""); + + return s; + } + catch (const io_error& e) + { + fail << "unable to read from " << rp << " referenced by " + << name << " manifest value in " << pkg / manifest_file << ": " + << e << + info << "repository " << rl + << (!fragment.empty () ? " " + fragment : "") << endf; + } + } + static rep_fetch_data rep_fetch_dir (const common_options& co, const repository_location& rl, - bool ignore_unknown) + bool iu, + bool ev) { assert (rl.absolute ()); @@ -276,23 +313,41 @@ namespace bpkg fr.repositories = parse_repository_manifests ( rd / repositories_file, - ignore_unknown, + iu, rl, string () /* fragment */); dir_package_manifests pms ( parse_directory_manifests ( rd / packages_file, - ignore_unknown, + iu, rl, string () /* fragment */)); fr.packages = parse_package_manifests (co, rd, move (pms), - ignore_unknown, + iu, rl, - string () /* fragment */); + empty_string /* fragment */); + + // Expand file-referencing package manifest values. + // + if (ev) + { + for (package_manifest& m: fr.packages) + m.load_files ( + [&m, &rd, &rl] (const string& n, const path& p) + { + return read_package_file (p, + n, + path_cast (*m.location), + rd, + rl, + empty_string /* fragment */); + }, + iu); + } return rep_fetch_data {{move (fr)}, nullopt /* cert_pem */, @@ -303,7 +358,8 @@ namespace bpkg rep_fetch_git (const common_options& co, const dir_path* conf, const repository_location& rl, - bool ignore_unknown) + bool iu, + bool ev) { if (conf != nullptr && conf->empty ()) conf = dir_exists (bpkg_dir) ? ¤t_dir : nullptr; @@ -388,7 +444,7 @@ namespace bpkg // fr.repositories = parse_repository_manifests ( td / repositories_file, - ignore_unknown, + iu, rl, fr.friendly_name); @@ -397,11 +453,23 @@ namespace bpkg git_package_manifests pms ( parse_directory_manifests ( td / packages_file, - ignore_unknown, + iu, rl, fr.friendly_name)); - // Checkout submodules, if required. + // Checkout submodules on the first call. + // + bool cs (true); + auto checkout_submodules = [&co, &rl, &td, &cs] () + { + if (cs) + { + git_checkout_submodules (co, rl, td); + cs = false; + } + }; + + // Checkout submodules to parse package manifests, if required. // for (const package_manifest& sm: pms) { @@ -409,7 +477,7 @@ namespace bpkg if (!exists (d) || empty (d)) { - git_checkout_submodules (co, rl, td); + checkout_submodules (); break; } } @@ -419,9 +487,41 @@ namespace bpkg fr.packages = parse_package_manifests (co, td, move (pms), - ignore_unknown, + iu, rl, fr.friendly_name); + + // Expand file-referencing package manifest values checking out + // submodules, if required. + // + if (ev) + { + for (package_manifest& m: fr.packages) + m.load_files ( + [&m, &td, &rl, &fr, &checkout_submodules] (const string& n, + const path& p) + { + // Note that this doesn't work for symlinks on Windows where git + // normally creates filesystem-agnostic symlinks that are + // indistinguishable from regular files (see fixup_worktree() + // for details). It seems like the only way to deal with that is + // to unconditionally checkout submodules on Windows. Let's not + // pessimize things for now (if someone really wants this to + // work, they can always enable real symlinks in git). + // + if (!exists (td / *m.location / p)) + checkout_submodules (); + + return read_package_file (p, + n, + path_cast (*m.location), + td, + rl, + fr.friendly_name); + }, + iu); + } + np += fr.packages.size (); r.fragments.push_back (move (fr)); @@ -452,13 +552,14 @@ namespace bpkg const dir_path* conf, const repository_location& rl, const optional& dt, - bool iu) + bool iu, + bool ev) { switch (rl.type ()) { case repository_type::pkg: return rep_fetch_pkg (co, conf, rl, dt, iu); - case repository_type::dir: return rep_fetch_dir (co, rl, iu); - case repository_type::git: return rep_fetch_git (co, conf, rl, iu); + case repository_type::dir: return rep_fetch_dir (co, rl, iu, ev); + case repository_type::git: return rep_fetch_git (co, conf, rl, iu, ev); } assert (false); // Can't be here. @@ -469,9 +570,10 @@ namespace bpkg rep_fetch (const common_options& co, const dir_path* conf, const repository_location& rl, - bool iu) + bool iu, + bool ev) { - return rep_fetch (co, conf, rl, nullopt /* dependent_trust */, iu); + return rep_fetch (co, conf, rl, nullopt /* dependent_trust */, iu, ev); } // Return an existing repository fragment or create a new one. Update the @@ -949,7 +1051,12 @@ namespace bpkg // repository sets. // rep_fetch_data rfd ( - rep_fetch (co, &conf, rl, dependent_trust, true /* ignore_unknow */)); + rep_fetch (co, + &conf, + rl, + dependent_trust, + true /* ignore_unknow */, + false /* expand_values */)); // Save for subsequent certificate authentication for repository use by // its dependents. -- cgit v1.1