From bd02eaa1298271ecf8365aa869e93fdcb04fdeb1 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 2 Sep 2021 08:42:53 +0200 Subject: Add progress to configure/disfigure in pkg-build/drop if result is disabled For projects with a large number of dependencies (e.g., Boost) these can take a while. --- bpkg/common.cli | 4 +- bpkg/diagnostics.hxx | 5 ++ bpkg/pkg-build.cxx | 138 +++++++++++++++++++++++++++++++++++++++++++-------- bpkg/pkg-drop.cxx | 67 +++++++++++++++++++++---- 4 files changed, 182 insertions(+), 32 deletions(-) diff --git a/bpkg/common.cli b/bpkg/common.cli index 49a7788..46c4784 100644 --- a/bpkg/common.cli +++ b/bpkg/common.cli @@ -96,7 +96,9 @@ namespace bpkg bool --no-result { "Don't print informational messages about the outcome of performing - a command." + a command or some of its parts. Note that if this option is specified, + then for certain long-running command parts progress is displayed + instead, unless suppressed with \cb{--no-progress}." } // When it comes to external programs (such as curl, git, etc), if stderr diff --git a/bpkg/diagnostics.hxx b/bpkg/diagnostics.hxx index 04ede36..72fc9ae 100644 --- a/bpkg/diagnostics.hxx +++ b/bpkg/diagnostics.hxx @@ -109,6 +109,11 @@ namespace bpkg template inline void l5 (const F& f) {if (verb >= 5) f ();} template inline void l6 (const F& f) {if (verb >= 6) f ();} + // Progress reporting. + // + using butl::diag_progress; + using butl::diag_progress_lock; + // Diagnostic facility, base infrastructure. // using butl::diag_stream; diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index a76e4e2..66c9c36 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -6194,18 +6194,42 @@ namespace bpkg l4 ([&]{trace << "simulate: " << (simulate ? "yes" : "no");}); bool r (false); - uint16_t verbose (!simulate ? verb : 0); + uint16_t verb (!simulate ? bpkg::verb : 0); + + bool result (verb && !o.no_result ()); + bool progress (!result && verb == 1 && !o.no_progress () && stderr_term); + + size_t prog_i, prog_n, prog_percent; // disfigure // - for (build_package& p: build_pkgs) + // Note: similar code in pkg-drop. + // + auto disfigure_pred = [] (const build_package& p) { // We are only interested in configured packages that are either being // up/down-graded, need reconfiguration (e.g., dependents), or dropped. // + if (*p.action != build_package::drop && !p.reconfigure ()) + return false; + + return true; + }; + + if (progress) + { + prog_i = 0; + prog_n = static_cast (count_if (build_pkgs.begin (), + build_pkgs.end (), + disfigure_pred)); + prog_percent = 100; + } + + for (build_package& p: build_pkgs) + { assert (p.action); - if (*p.action != build_package::drop && !p.reconfigure ()) + if (!disfigure_pred (p)) continue; database& pdb (p.db); @@ -6255,10 +6279,30 @@ namespace bpkg assert (sp->state == package_state::unpacked || sp->state == package_state::transient); - if (verbose && !o.no_result ()) - text << (sp->state == package_state::transient - ? "purged " - : "disfigured ") << *sp << pdb; + + if (result || progress) + { + const char* what (sp->state == package_state::transient + ? "purged" + : "disfigured"); + if (result) + text << what << ' ' << *sp << pdb; + else if (progress) + { + size_t p ((++prog_i * 100) / prog_n); + + if (prog_percent != p) + { + prog_percent = p; + + diag_progress_lock pl; + diag_progress = ' '; + diag_progress += to_string (p); + diag_progress += "% of packages "; + diag_progress += what; + } + } + } // Selected system package is now gone from the database. Before we drop // the object we need to make sure the hold state is preserved in the @@ -6276,6 +6320,14 @@ namespace bpkg } } + // Clear the progress if shown. + // + if (progress) + { + diag_progress_lock pl; + diag_progress.clear (); + } + // purge, fetch/unpack|checkout // pkg_checkout_cache checkout_cache (o); @@ -6308,7 +6360,7 @@ namespace bpkg r = true; - if (verbose && !o.no_result ()) + if (result) text << "purged " << *sp << pdb; sp = nullptr; @@ -6339,7 +6391,7 @@ namespace bpkg r = true; - if (verbose && !o.no_result ()) + if (result) text << "purged " << *sp << pdb; if (!p.hold_package) @@ -6471,7 +6523,7 @@ namespace bpkg assert (sp->state == package_state::fetched || sp->state == package_state::unpacked); - if (verbose && !o.no_result ()) + if (result) { const repository_location& rl (sp->repository_fragment); @@ -6520,7 +6572,7 @@ namespace bpkg // sp = pkg_unpack (o, pdb, t, ap->id.name, simulate); - if (verbose && !o.no_result ()) + if (result) text << "unpacked " << *sp << pdb; } else @@ -6537,7 +6589,7 @@ namespace bpkg false, // Don't purge; commits the transaction. simulate); - if (verbose && !o.no_result ()) + if (result) text << "using " << *sp << pdb << " (external)"; } @@ -6553,16 +6605,41 @@ namespace bpkg // configure // + auto configure_pred = [] (const build_package& p) + { + // Skip package drops. + // + if (*p.action == build_package::drop) + return false; + + // We configure everything that isn't already configured. + // + if (p.selected != nullptr && + p.selected->state == package_state::configured) + return false; + + return true; + }; + + if (progress) + { + prog_i = 0; + prog_n = static_cast (count_if (build_pkgs.begin (), + build_pkgs.end (), + configure_pred)); + prog_percent = 100; + } + for (build_package& p: reverse_iterate (build_pkgs)) { assert (p.action); + if (!configure_pred (p)) + continue; + shared_ptr& sp (p.selected); const shared_ptr& ap (p.available); - if (*p.action == build_package::drop) // Skip package drops. - continue; - // Configure the package. // // At this stage the package is either selected, in which case it's a @@ -6571,11 +6648,6 @@ namespace bpkg // assert (sp != nullptr || p.system); - // We configure everything that isn't already configured. - // - if (sp != nullptr && sp->state == package_state::configured) - continue; - database& pdb (p.db); transaction t (pdb, !simulate /* start */); @@ -6633,8 +6705,30 @@ namespace bpkg assert (sp->state == package_state::configured); - if (verbose && !o.no_result ()) + if (result) text << "configured " << *sp << pdb; + else if (progress) + { + size_t p ((++prog_i * 100) / prog_n); + + if (prog_percent != p) + { + prog_percent = p; + + diag_progress_lock pl; + diag_progress = ' '; + diag_progress += to_string (p); + diag_progress += "% of packages configured"; + } + } + } + + // Clear the progress if shown. + // + if (progress) + { + diag_progress_lock pl; + diag_progress.clear (); } // Update the hold state. @@ -6677,7 +6771,7 @@ namespace bpkg r = true; - if (verbose > 1) + if (verb > 1) { if (hp) text << "holding package " << sp->name << pdb; diff --git a/bpkg/pkg-drop.cxx b/bpkg/pkg-drop.cxx index dfae66f..014ddb9 100644 --- a/bpkg/pkg-drop.cxx +++ b/bpkg/pkg-drop.cxx @@ -370,25 +370,47 @@ namespace bpkg !(o.yes () || !need_prompt || yn_prompt ("continue? [Y/n]", 'y'))) return 1; + bool result (verb && !o.no_result ()); + bool progress (!result && verb == 1 && !o.no_progress () && stderr_term); + + size_t prog_i, prog_n, prog_percent; + // All that's left to do is first disfigure configured packages and // then purge all of them. We do both left to right (i.e., from more // dependent to less dependent). For disfigure this order is required. // For purge, it will be the order closest to the one specified by the // user. // - for (const drop_package& dp: pkgs) + // Note: similar code in pkg-build. + // + auto disfigure_pred = [drop_prq] (const drop_package& dp) { // Skip prerequisites if we weren't instructed to drop them. // if (dp.reason == drop_reason::prerequisite && !drop_prq) - continue; + return false; - const shared_ptr& p (dp.package); + if (dp.package->state != package_state::configured) + return false; - if (p->state != package_state::configured) + return true; + }; + + if (progress) + { + prog_i = 0; + prog_n = static_cast (count_if (pkgs.begin (), pkgs.end (), + disfigure_pred)); + prog_percent = 100; + } + + for (const drop_package& dp: pkgs) + { + if (!disfigure_pred (dp)) continue; database& db (dp.db); + const shared_ptr& p (dp.package); // Each package is disfigured in its own transaction, so that we always // leave the configuration in a valid state. @@ -402,10 +424,37 @@ namespace bpkg assert (p->state == package_state::unpacked || p->state == package_state::transient); - if (verb && !o.no_result ()) - text << (p->state == package_state::transient - ? "purged " - : "disfigured ") << p->name << db; + if (result || progress) + { + const char* what (p->state == package_state::transient + ? "purged" + : "disfigured"); + if (result) + text << what << ' ' << p->name << db; + else if (progress) + { + size_t p ((++prog_i * 100) / prog_n); + + if (prog_percent != p) + { + prog_percent = p; + + diag_progress_lock pl; + diag_progress = ' '; + diag_progress += to_string (p); + diag_progress += "% of packages "; + diag_progress += what; + } + } + } + } + + // Clear the progress if shown. + // + if (progress) + { + diag_progress_lock pl; + diag_progress.clear (); } if (o.disfigure_only ()) @@ -436,7 +485,7 @@ namespace bpkg // pkg_purge (db, t, p, false /* simulate */); - if (verb && !o.no_result ()) + if (result) text << "purged " << p->name << db; } -- cgit v1.1