aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-09-02 08:42:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-09-02 08:42:53 +0200
commitbd02eaa1298271ecf8365aa869e93fdcb04fdeb1 (patch)
treeaed95a08521920e99ffced3c3e67799ad2009f43
parentdfef71dd6cd5f63a03abb172e6e553bd92b670bb (diff)
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.
-rw-r--r--bpkg/common.cli4
-rw-r--r--bpkg/diagnostics.hxx5
-rw-r--r--bpkg/pkg-build.cxx138
-rw-r--r--bpkg/pkg-drop.cxx67
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 <typename F> inline void l5 (const F& f) {if (verb >= 5) f ();}
template <typename F> 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<size_t> (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<size_t> (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<selected_package>& sp (p.selected);
const shared_ptr<available_package>& 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<selected_package>& 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<size_t> (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<selected_package>& 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;
}