diff options
Diffstat (limited to 'bpkg/pkg-disfigure.cxx')
-rw-r--r-- | bpkg/pkg-disfigure.cxx | 166 |
1 files changed, 98 insertions, 68 deletions
diff --git a/bpkg/pkg-disfigure.cxx b/bpkg/pkg-disfigure.cxx index 9347bbc..2239314 100644 --- a/bpkg/pkg-disfigure.cxx +++ b/bpkg/pkg-disfigure.cxx @@ -15,11 +15,12 @@ using namespace butl; namespace bpkg { void - pkg_disfigure (const dir_path& c, - const common_options& o, + pkg_disfigure (const common_options& o, + database& db, transaction& t, const shared_ptr<selected_package>& p, bool clean, + bool disfigure, bool simulate) { assert (p->state == package_state::configured || @@ -29,28 +30,30 @@ namespace bpkg l4 ([&]{trace << *p;}); - database& db (t.database ()); tracer_guard tg (db, trace); // Check that we have no dependents. // if (p->state == package_state::configured) { - using query = query<package_dependent>; - - auto r (db.query<package_dependent> (query::name == p->name)); - - if (!r.empty ()) + diag_record dr; + for (database& ddb: db.dependent_configs ()) { - diag_record dr; - dr << fail << "package " << p->name << " still has dependents:"; + auto r (query_dependents (ddb, p->name, db)); - for (const package_dependent& pd: r) + if (!r.empty ()) { - dr << info << "package " << pd.name; + if (dr.empty ()) + dr << fail << "package " << p->name << db << " still has " + << "dependents:"; + + for (const package_dependent& pd: r) + { + dr << info << "package " << pd.name << ddb; - if (pd.constraint) - dr << " on " << p->name << " " << *pd.constraint; + if (pd.constraint) + dr << " on " << p->name << " " << *pd.constraint; + } } } } @@ -69,14 +72,19 @@ namespace bpkg // Since we are no longer configured, clear the prerequisites list. // p->prerequisites.clear (); + p->dependency_alternatives.clear (); + + // Mark the section as loaded, so dependency alternatives are updated. + // + p->dependency_alternatives_section.load (); assert (p->src_root); // Must be set since unpacked. assert (p->out_root); // Must be set since configured. if (!simulate) { - dir_path src_root (p->effective_src_root (c)); - dir_path out_root (p->effective_out_root (c)); + dir_path src_root (p->effective_src_root (db.config_orig)); + dir_path out_root (p->effective_out_root (db.config_orig)); l4 ([&]{trace << "src_root: " << src_root << ", " << "out_root: " << out_root;}); @@ -92,9 +100,13 @@ namespace bpkg if (p->state == package_state::configured) { if (clean) - bspec = "clean('" + rep + "') "; + bspec = "clean('" + rep + "')"; - bspec += "disfigure('" + rep + "')"; + if (disfigure) + { + bspec += (bspec.empty () ? "" : " "); + bspec += "disfigure('" + rep + "')"; + } } else { @@ -105,69 +117,77 @@ namespace bpkg if (src_root == out_root) bspec = "disfigure('" + rep + "')"; else - bspec = "disfigure('" + src_root.representation () + "'@'" + - rep + "')"; - } + bspec = "disfigure('" + src_root.representation () + "'@'" + rep + + "')"; - l4 ([&]{trace << "buildspec: " << bspec;}); + disfigure = true; // Make sure the flag matches the behavior. + } - // Disfigure. + // Clean and/or disfigure. // + if (!bspec.empty () && exists (out_root)) try { - if (exists (out_root)) + l4 ([&]{trace << "buildspec: " << bspec;}); + + // Note that for external packages out_root is only the output + // directory. It is also possible that the buildfiles in the source + // directory have changed in a way that they don't clean everything. + // So in this case we just remove the output directory manually rather + // then running 'b clean disfigure'. + // + // It may also happen that we cannot disfigure the external package' + // output directory (the source directory have moved, etc.). If that's + // the case, then we fallback to the output directory removal. + // + if (p->external ()) { - // Note that for external packages this is just the output - // directory. It is also possible that the buildfiles in the source - // directory have changed in a way that they don't clean everything. - // So in this case we just remove the output directory manually - // rather then running 'b clean disfigure'. + // clean disfigure // - // It may also happen that we can not disfigure the external - // package' output directory (the source directory have moved, etc.). - // If that's the case, then we fallback to the output directory - // removal. + // true true -- wipe the directory + // true false -- try to clean, ignore if failed + // false true -- try to disfigure, fallback to wipe if failed + // false false -- never get here (bspec is empty) // - if (p->external ()) + + if (!clean || !disfigure) { - if (!clean) + auto_fd dev_null (open_null ()); + + // Redirect stderr to /dev/null. Note that we don't expect + // anything to be written to stdout. + // + process pr (start_b (o, + 1 /* stdout */, + dev_null /* stderr */, + verb_b::quiet, + bspec)); + + // If the disfigure meta-operation failed then we report the + // abnormal termination and fallback to the output directory + // removal otherwise. + // + if (!pr.wait ()) { - auto_fd dev_null (open_null ()); - - // Redirect stderr to /dev/null. Note that we don't expect - // anything to be written to stdout. - // - process pr (start_b (o, - 1 /* stdout */, dev_null /* stderr */, - verb_b::quiet, - bspec)); - - // If the disfigure meta-operation failed then we report the - // abnormal termination and fallback to the output directory - // removal otherwise. - // - if (!pr.wait ()) - { - const process_exit& e (*pr.exit); - - if (!e.normal ()) - fail << "process " << name_b (o) << " " << e; - - clean = true; - } - } + const process_exit& e (*pr.exit); + + if (!e.normal ()) + fail << "process " << name_b (o) << " " << e; - if (clean) - rm_r (out_root); + clean = true; + } } - else - run_b (o, verb_b::quiet, bspec); + + if (clean && disfigure) + rm_r (out_root); } + else + run_b (o, verb_b::quiet, bspec); // Make sure the out directory is gone unless it is the same as src, - // or we didn't clean it. + // or we didn't clean or disfigure it. // - if (out_root != src_root && clean && exists (out_root)) + if (out_root != src_root && clean && disfigure && exists (out_root)) fail << "package output directory " << out_root << " still exists"; } catch (const failed&) @@ -179,10 +199,16 @@ namespace bpkg db.update (p); t.commit (); - info << "package " << p->name << " is now broken; " + info << "package " << p->name << db << " is now broken; " << "use 'pkg-purge' to remove"; throw; } + + if (disfigure) + { + p->config_variables.clear (); + p->config_checksum.clear (); + } } p->out_root = nullopt; @@ -207,7 +233,7 @@ namespace bpkg package_name n (parse_package_name (args.next (), false /* allow_version */)); - database db (open (c, trace)); + database db (c, trace, true /* pre_attach */); transaction t (db); shared_ptr<selected_package> p (db.find<selected_package> (n)); @@ -221,7 +247,11 @@ namespace bpkg // Commits the transaction. // - pkg_disfigure (c, o, t, p, !o.keep_out (), false /* simulate */); + pkg_disfigure (o, db, t, + p, + !o.keep_out () /* clean */, + !o.keep_config () /* disfigure */, + false /* simulate */); assert (p->state == package_state::unpacked || p->state == package_state::transient); |