From 7cbea6d908fddc48357a88d6edf30451c7d2b487 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 21 Oct 2021 17:17:09 +0200 Subject: Add --progress common option --- bpkg/bpkg.cxx | 41 +++++++++++++++++++++++++++++++--- bpkg/buildfile | 6 ++++- bpkg/common.cli | 24 +++++++++++++------- bpkg/fetch-git.cxx | 10 ++++----- bpkg/fetch.cxx | 61 ++++++++++++++++++++++++++++++++++++++++----------- bpkg/pkg-build.cxx | 4 +++- bpkg/pkg-checkout.cxx | 8 +++---- bpkg/pkg-drop.cxx | 4 +++- bpkg/utility.txx | 7 ++++++ 9 files changed, 129 insertions(+), 36 deletions(-) diff --git a/bpkg/bpkg.cxx b/bpkg/bpkg.cxx index 92f4bb9..a4946fe 100644 --- a/bpkg/bpkg.cxx +++ b/bpkg/bpkg.cxx @@ -283,7 +283,7 @@ init (const common_options& co, if (o.default_options_specified ()) extra = o.default_options (); - o = merge_options ( + default_options dos ( load_default_options ( nullopt /* sys_dir */, path::home_directory (), @@ -301,8 +301,43 @@ init (const common_options& co, }, "--options-file", args_pos, - 1024), - o); + 1024)); + + // Verify common options. + // + // Also merge the --progress/--no-progress options, overriding a less + // specific flag with a more specific. + // + optional progress; + auto merge_progress = [&progress] + (const O& o, + const default_options_entry* e = nullptr) + { + if (o.progress () && o.no_progress ()) + { + diag_record dr; + (e != nullptr ? dr << fail (e->file) : dr << fail) + << "both --progress and --no-progress specified"; + } + + if (o.progress ()) + progress = true; + else if (o.no_progress ()) + progress = false; + }; + + for (const default_options_entry& e: dos) + merge_progress (e.options, &e); + + merge_progress (o); + + o = merge_options (dos, o); + + if (progress) + { + o.progress (*progress); + o.no_progress (!*progress); + } } catch (const invalid_argument& e) { diff --git a/bpkg/buildfile b/bpkg/buildfile index 3ae522d..1173977 100644 --- a/bpkg/buildfile +++ b/bpkg/buildfile @@ -183,7 +183,11 @@ if $cli.configured --page-usage 'bpkg::print_$name$_' --ansi-color --include-base-last \ --option-length 24 - cli.cxx{common-options}: cli.options += --short-usage --long-usage # Both. + # Both --*-usage options. + # + cli.cxx{common-options}: cli.options += --short-usage --long-usage \ +--generate-modifier + cli.cxx{bpkg-options}: cli.options += --short-usage --suppress-undocumented cli.options += --long-usage # All other pages -- long usage. diff --git a/bpkg/common.cli b/bpkg/common.cli index 46c4784..5f67357 100644 --- a/bpkg/common.cli +++ b/bpkg/common.cli @@ -103,15 +103,23 @@ namespace bpkg // When it comes to external programs (such as curl, git, etc), if stderr // is not a terminal, the logic is actually tri-state: With --no-progress - // we suppress any progress. With --progress (which we may add in the - // future), we request full progress. Finally, without any --*progress - // options we let the external program decide what to do: it may do - // something intelligent (like curl) and produce non-terminal-friendly - // progress (such as status lines printed periodically) or it may disable - // progress all together (like git). Of course, it may also do no - // detection and dump non-terminal-unfriendly progress in which case we - // should probably do the detection ourselves and suppress it. + // we suppress any progress. With --progress we request full progress. + // Finally, without any --*progress options we let the external program + // decide what to do: it may do something intelligent (like curl) and + // produce non-terminal-friendly progress (such as status lines printed + // periodically) or it may disable progress all together (like git). Of + // course, it may also do no detection and dump non-terminal-unfriendly + // progress in which case we should probably do the detection ourselves + // and suppress it. // + bool --progress + { + "Display progress indicators for long-lasting operations, such as + network transfers, building, etc. If printing to a terminal the + progress is displayed by default for low verbosity levels. Use + \cb{--no-progress} to suppress." + } + bool --no-progress { "Suppress progress indicators for long-lasting operations, such as diff --git a/bpkg/fetch-git.cxx b/bpkg/fetch-git.cxx index 5c63ea2..ea6dee0 100644 --- a/bpkg/fetch-git.cxx +++ b/bpkg/fetch-git.cxx @@ -873,7 +873,7 @@ namespace bpkg if (i != repository_refs.end ()) return i->second; - if (verb && !co.no_progress ()) + if ((verb && !co.no_progress ()) || co.progress ()) text << "querying " << url; refs rs; @@ -1504,7 +1504,7 @@ namespace bpkg if (progress) { - if (verb == 1 && stderr_term) + if ((verb == 1 && stderr_term) || co.progress ()) v.push_back ("--progress"); } else @@ -1556,7 +1556,7 @@ namespace bpkg // Print progress. // - if (verb && !co.no_progress ()) + if ((verb && !co.no_progress ()) || co.progress ()) { // Note that the clone command prints the following line prior to the // progress lines: @@ -1883,7 +1883,7 @@ namespace bpkg if (u && *u == "none") { - if (verb >= 2 && !co.no_progress ()) + if ((verb >= 2 && !co.no_progress ()) || co.progress ()) text << "skipping submodule '" << psd << "'"; // Note that the submodule can be enabled for some other snapshot we @@ -1993,7 +1993,7 @@ namespace bpkg // Let's make the message match the git-submodule script output (again, // except for capitalization). // - if (verb && !co.no_progress ()) + if ((verb && !co.no_progress ()) || co.progress ()) text << "submodule path '" << psd << "': checked out '" << sm.commit << "'"; diff --git a/bpkg/fetch.cxx b/bpkg/fetch.cxx index 9db4920..00461e9 100644 --- a/bpkg/fetch.cxx +++ b/bpkg/fetch.cxx @@ -87,6 +87,7 @@ namespace bpkg static process start_wget (const path& prog, const optional& timeout, + bool progress, bool no_progress, const strings& ops, const string& url, @@ -106,12 +107,21 @@ namespace bpkg "-U", ua.c_str () }; + // Wget 1.16 introduced the --show-progress option which in the quiet mode + // shows a nice and tidy progress bar (if only it also showed errors, then + // it would have been perfect). + // + bool has_show_progress (wget_major > 1 || + (wget_major == 1 && wget_minor >= 16)); + // Map verbosity level. If we are running quiet or at level 1 // and the output is stdout, then run wget quiet. If at level // 1 and the output is a file, then show the progress bar. At // level 2 and 3 run it at the default level (so we will print // the command line and it will display the progress, error // messages, etc). Higher than that -- run it with debug output. + // Always show the progress bar if requested explicitly, even in + // the quiet mode. // // In the wget world quiet means don't print anything, not even // error messages. There is also the -nv mode (aka "non-verbose") @@ -122,16 +132,29 @@ namespace bpkg // if (verb < (fo ? 1 : 2)) { - args.push_back ("-q"); - no_progress = false; // Already suppressed with -q. + bool quiet (true); + + if (progress) + { + // If --show-progress options is supported, then pass both + // --show-progress and -q, otherwise pass none of them and run + // verbose. + // + if (has_show_progress) + args.push_back ("--show-progress"); + else + quiet = false; + } + + if (quiet) + { + args.push_back ("-q"); + no_progress = false; // Already suppressed with -q. + } } else if (fo && verb == 1) { - // Wget 1.16 introduced the --show-progress option which in the - // quiet mode shows a nice and tidy progress bar (if only it also - // showed errors, then it would have been perfect). - // - if (wget_major > 1 || (wget_major == 1 && wget_minor >= 16)) + if (has_show_progress) { args.push_back ("-q"); @@ -255,6 +278,7 @@ namespace bpkg static process start_curl (const path& prog, const optional& timeout, + bool progress, bool no_progress, const strings& ops, const string& url, @@ -286,12 +310,16 @@ namespace bpkg // 1 and the output is a file, then show the progress bar. At // level 2 and 3 run it at the default level (so we will print // the command line and it will display its elaborate progress). - // Higher than that -- run it verbose. + // Higher than that -- run it verbose. Always show the progress + // bar if requested explicitly, even in the quiet mode. // if (verb < (fo ? 1 : 2)) { - suppress_progress (); - no_progress = false; // Already suppressed. + if (!progress) + { + suppress_progress (); + no_progress = false; // Already suppressed. + } } else if (fo && verb == 1) { @@ -413,6 +441,7 @@ namespace bpkg static process start_fetch (const path& prog, const optional& timeout, + bool progress, bool no_progress, const strings& ops, const string& url, @@ -437,7 +466,8 @@ namespace bpkg // Map verbosity level. If we are running quiet then run fetch quiet. // If we are at level 1 and we are fetching into a file or we are at // level 2 or 3, then run it at the default level (so it will display - // the progress). Higher than that -- run it verbose. + // the progress). Higher than that -- run it verbose. Always show the + // progress bar if requested explicitly, even in the quiet mode. // // Note that the only way to suppress progress for the fetch program is to // run it quiet (-q). However, it prints nothing but the progress by @@ -448,8 +478,11 @@ namespace bpkg // if (verb < (fo ? 1 : 2)) { - args.push_back ("-q"); - no_progress = false; // Already suppressed with -q. + if (!progress) + { + args.push_back ("-q"); + no_progress = false; // Already suppressed with -q. + } } else if (verb > 3) { @@ -616,6 +649,7 @@ namespace bpkg process (*f) (const path&, const optional&, bool, + bool, const strings&, const string&, const path&, @@ -700,6 +734,7 @@ namespace bpkg return f (path_, timeout, + o.progress (), o.no_progress (), o.fetch_option (), !http_url.empty () ? http_url : src, diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index 5db599f..c0374ac 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -6721,7 +6721,9 @@ namespace bpkg uint16_t verb (!simulate ? bpkg::verb : 0); bool result (verb && !o.no_result ()); - bool progress (!result && verb == 1 && !o.no_progress () && stderr_term); + bool progress (!result && + ((verb == 1 && !o.no_progress () && stderr_term) || + o.progress ())); size_t prog_i, prog_n, prog_percent; diff --git a/bpkg/pkg-checkout.cxx b/bpkg/pkg-checkout.cxx index 49fc89f..61561e2 100644 --- a/bpkg/pkg-checkout.cxx +++ b/bpkg/pkg-checkout.cxx @@ -44,7 +44,7 @@ namespace bpkg // Print the progress indicator to attribute the possible fetching // progress. // - if (verb && !o.no_progress ()) + if ((verb && !o.no_progress ()) || o.progress ()) text << "checking out " << package_string (ap->id.name, ap->version) << db; @@ -297,10 +297,10 @@ namespace bpkg // of our dependencies. // - // At verbosity level 1 we want our (nicer) progress header but the - // build system's actual progress. + // If the verbosity level is less than 2, then we want our (nicer) + // progress header but the build system's actual progress. // - if (verb == 1 && !o.no_progress ()) + if ((verb == 1 && !o.no_progress ()) || (verb == 0 && o.progress ())) text << "distributing " << n << '/' << v << pdb; run_b (o, diff --git a/bpkg/pkg-drop.cxx b/bpkg/pkg-drop.cxx index 2e9969c..08168d4 100644 --- a/bpkg/pkg-drop.cxx +++ b/bpkg/pkg-drop.cxx @@ -371,7 +371,9 @@ namespace bpkg return 1; bool result (verb && !o.no_result ()); - bool progress (!result && verb == 1 && !o.no_progress () && stderr_term); + bool progress (!result && + ((verb == 1 && !o.no_progress () && stderr_term) || + o.progress ())); size_t prog_i, prog_n, prog_percent; diff --git a/bpkg/utility.txx b/bpkg/utility.txx index b2c2a3c..47619c6 100644 --- a/bpkg/utility.txx +++ b/bpkg/utility.txx @@ -33,6 +33,7 @@ namespace bpkg // as us. // string vl; + bool progress (co.progress ()); bool no_progress (co.no_progress ()); if (verb == 0) @@ -49,7 +50,10 @@ namespace bpkg if (!no_progress) { if (v == verb_b::progress && stderr_term) + { ops.push_back ("--progress"); + progress = false; // The option is already added. + } } else no_progress = false; // Already suppressed with -q. @@ -64,6 +68,9 @@ namespace bpkg ops.push_back (vl.c_str ()); } + if (progress) + ops.push_back ("--progress"); + if (no_progress) ops.push_back ("--no-progress"); -- cgit v1.1