diff options
Diffstat (limited to 'bpkg/pkg-command.cxx')
-rw-r--r-- | bpkg/pkg-command.cxx | 164 |
1 files changed, 140 insertions, 24 deletions
diff --git a/bpkg/pkg-command.cxx b/bpkg/pkg-command.cxx index 0828118..20e5230 100644 --- a/bpkg/pkg-command.cxx +++ b/bpkg/pkg-command.cxx @@ -3,6 +3,11 @@ #include <bpkg/pkg-command.hxx> +#include <libbutl/path-pattern.hxx> + +#include <libbuild2/file.hxx> +#include <libbuild2/context.hxx> + #include <bpkg/package.hxx> #include <bpkg/package-odb.hxx> #include <bpkg/database.hxx> @@ -16,7 +21,6 @@ namespace bpkg { void pkg_command (const string& cmd, - const dir_path& c, const common_options& o, const string& cmd_v, const strings& cvars, @@ -53,6 +57,8 @@ namespace bpkg } }; + unique_ptr<build2::context> ctx; // Create lazily. + for (const pkg_command_vars& pv: ps) { if (!pv.vars.empty () || pv.cwd) @@ -73,12 +79,49 @@ namespace bpkg const shared_ptr<selected_package>& p (pv.pkg); - assert (p->state == package_state::configured); - assert (p->out_root); // Should be present since configured. + assert (p->state == package_state::configured && + p->substate != package_substate::system); + assert (p->out_root && + p->src_root); // Should be present since configured, not system. - dir_path out_root (p->effective_out_root (c)); + dir_path out_root (p->effective_out_root (pv.config_orig)); l4 ([&]{trace << p->name << " out_root: " << out_root;}); + // Figure out if the source directory is forwarded to this out_root. If + // it is, then we need to build via src_root. Failed that, backlinks + // won't be created. + // + if (*p->out_root != *p->src_root) + { + dir_path src_root (p->effective_src_root (pv.config_orig)); + + // For us to switch to src_root, it should not only be configured as + // forwarded, but also be forwarded to our out_root. So we actually + // need to first check if the build/bootstrap/out-root.build (or its + // alt naming equivalent) exists and, if so, extract the out_root + // value and compare it to ours. This is all done by bootstrap_fwd() + // from libbuild2 so seeing that we act as a special build system + // driver, we might as well use that. Note that this could potentially + // be improved by only creating context if the file exists. + // + try + { + if (ctx == nullptr) + ctx.reset (new build2::context ()); + + optional<bool> altn; + if (build2::bootstrap_fwd (*ctx, src_root, altn) == out_root) + { + out_root = move (src_root); + l4 ([&]{trace << p->name << " src_root: " << out_root;}); + } + } + catch (const build2::failed&) + { + throw failed (); // Assume the diagnostics has already been issued. + } + } + if (bspec.back () != '(') bspec += ' '; @@ -113,10 +156,19 @@ namespace bpkg collect_dependencies (const shared_ptr<selected_package>& p, bool recursive, bool package_cwd, - vector<pkg_command_vars>& ps) + vector<pkg_command_vars>& ps, + bool allow_host_type) { for (const auto& pr: p->prerequisites) { + if (!allow_host_type) + { + database& db (pr.first.database ()); + + if (db.type == host_config_type || db.type == build2_config_type) + continue; + } + shared_ptr<selected_package> d (pr.first.load ()); // The selected package can only be configured if all its dependencies @@ -131,14 +183,24 @@ namespace bpkg [&d] (const pkg_command_vars& i) {return i.pkg == d;}) == ps.end ()) { + database& db (pr.first.database ()); + // Note: no package-specific variables (global ones still apply). // - ps.push_back (pkg_command_vars {d, - strings () /* vars */, - package_cwd}); + ps.push_back ( + pkg_command_vars { + db.config_orig, + db.main (), + d, + strings () /* vars */, + package_cwd}); if (recursive) - collect_dependencies (d, recursive, package_cwd, ps); + collect_dependencies (d, + recursive, + package_cwd, + ps, + allow_host_type); } } } @@ -150,7 +212,9 @@ namespace bpkg bool recursive, bool immediate, bool all, + const strings& all_patterns, bool package_cwd, + bool allow_host_type, cli::group_scanner& args) { tracer trace ("pkg_command"); @@ -191,7 +255,7 @@ namespace bpkg if (args.group ().more ()) fail << "unexpected options group for variable '" << a << "'"; - cvars.push_back (move (a)); + cvars.push_back (move (trim (a))); } else { @@ -206,7 +270,7 @@ namespace bpkg if (a.find ('=') == string::npos) fail << "unexpected group argument '" << a << "'"; - vars.push_back (move (a)); + vars.push_back (move (trim (a))); } pkg_args.push_back (pkg_arg {move (n), move (vars)}); @@ -216,7 +280,7 @@ namespace bpkg // Check that options and arguments are consistent. // // Note that we can as well count on the option names that correspond to - // the immediate, recursive, and all parameters. + // the immediate, recursive, all, and all_patterns parameters. // { diag_record dr; @@ -225,9 +289,17 @@ namespace bpkg dr << fail << "both --immediate|-i and --recursive|-r specified"; else if (all) { + if (!all_patterns.empty ()) + dr << fail << "both --all|-a and --all-pattern specified"; + if (!pkg_args.empty ()) dr << fail << "both --all|-a and package argument specified"; } + else if (!all_patterns.empty ()) + { + if (!pkg_args.empty ()) + dr << fail << "both --all-pattern and package argument specified"; + } else if (pkg_args.empty ()) dr << fail << "package name argument expected"; @@ -237,7 +309,16 @@ namespace bpkg vector<pkg_command_vars> ps; { - database db (open (c, trace)); + database db (c, trace, true /* pre_attach */); + + if (!allow_host_type && (db.type == host_config_type || + db.type == build2_config_type)) + { + fail << "unable to " << cmd << " from " << db.type + << " configuration" << + info << "use target configuration instead"; + } + transaction t (db); // We need to suppress duplicate dependencies for the recursive command @@ -245,23 +326,33 @@ namespace bpkg // session ses; - auto add = [&ps, recursive, immediate, package_cwd] ( + auto add = + [&db, &ps, allow_host_type, recursive, immediate, package_cwd] ( const shared_ptr<selected_package>& p, strings vars) { - ps.push_back (pkg_command_vars {p, move (vars), package_cwd}); + ps.push_back ( + pkg_command_vars {db.config_orig, + db.main (), + p, + move (vars), + package_cwd}); // Note that it can only be recursive or immediate but not both. // if (recursive || immediate) - collect_dependencies (p, recursive, package_cwd, ps); + collect_dependencies (p, + recursive, + package_cwd, + ps, + allow_host_type); }; - if (all) + if (all || !all_patterns.empty ()) { using query = query<selected_package>; - query q (query::hold_package && + query q (query::hold_package && query::state == "configured" && query::substate != "system"); @@ -270,7 +361,19 @@ namespace bpkg { l4 ([&]{trace << *p;}); - add (p, strings ()); + if (!all_patterns.empty ()) + { + for (const string& pat: all_patterns) + { + if (path_match (p->name.string (), pat)) + { + add (p, strings ()); + break; + } + } + } + else // --all + add (p, strings ()); } if (ps.empty ()) @@ -287,13 +390,13 @@ namespace bpkg << "configuration " << c; if (p->state != package_state::configured) - fail << "package " << a.name << " is " << p->state << + fail << "package " << a.name << db << " is " << p->state << info << "expected it to be configured"; if (p->substate == package_substate::system) - fail << "cannot " << cmd << " system package " << a.name; + fail << "cannot " << cmd << " system package " << a.name << db; - l4 ([&]{trace << *p;}); + l4 ([&]{trace << *p << db;}); add (p, move (a.vars)); } @@ -302,14 +405,27 @@ namespace bpkg t.commit (); } - pkg_command (cmd, c, o, cmd_v, cvars, ps); + pkg_command (cmd, o, cmd_v, cvars, ps); if (verb && !o.no_result ()) { for (const pkg_command_vars& pv: ps) - text << cmd << (cmd.back () != 'e' ? "ed " : "d ") << *pv.pkg; + text << cmd << (cmd.back () != 'e' ? "ed " : "d ") << pv.string (); } return 0; } + + // pkg_command_vars + // + string pkg_command_vars:: + string () const + { + std::string r (pkg->string ()); + + if (!config_main) + r += " [" + config_orig.representation () + ']'; + + return r; + } } |