From 4f6abb0576e810b37d56ad3cafc67fac84682ec2 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 15 Mar 2018 15:24:48 +0200 Subject: Implement status command --- bdep/bdep.cli | 5 ++ bdep/bdep.cxx | 2 + bdep/buildfile | 3 +- bdep/config.cli | 6 +-- bdep/fetch.cli | 4 +- bdep/init.cli | 6 +-- bdep/project.cli | 14 +++--- bdep/project.cxx | 22 +++++++++ bdep/project.hxx | 5 ++ bdep/status.cli | 70 ++++++++++++++++++++++++++ bdep/status.cxx | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ bdep/status.hxx | 19 +++++++ bdep/sync.cli | 4 +- bdep/sync.cxx | 18 +------ doc/cli.sh | 3 +- 15 files changed, 293 insertions(+), 35 deletions(-) create mode 100644 bdep/status.cli create mode 100644 bdep/status.cxx create mode 100644 bdep/status.hxx diff --git a/bdep/bdep.cli b/bdep/bdep.cli index ac70b62..69c7ffc 100644 --- a/bdep/bdep.cli +++ b/bdep/bdep.cli @@ -79,6 +79,11 @@ namespace bdep "\l{bdep-fetch(1)} \- fetch list of available project dependencies" } + bool status + { + "\l{bdep-status(1)} \- print status of project and/or its dependencies" + } + bool config { "\l{bdep-config(1)} \- manage project's build configurations" diff --git a/bdep/bdep.cxx b/bdep/bdep.cxx index c51285e..05fcc47 100644 --- a/bdep/bdep.cxx +++ b/bdep/bdep.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include using namespace std; @@ -270,6 +271,7 @@ try COMMAND_IMPL (init, init, "init"); COMMAND_IMPL (sync, sync, "sync"); COMMAND_IMPL (fetch, fetch, "fetch"); + COMMAND_IMPL (status, status, "status"); COMMAND_IMPL (config, config, "config"); assert (false); diff --git a/bdep/buildfile b/bdep/buildfile index 3bda74b..75f5320 100644 --- a/bdep/buildfile +++ b/bdep/buildfile @@ -23,6 +23,7 @@ new-options \ init-options \ sync-options \ fetch-options \ +status-options \ config-options exe{bdep}: {hxx ixx txx cxx}{** -{$options_topics} -*-odb -version} \ @@ -58,9 +59,9 @@ if $cli.configured cli.cxx{init-options}: cli{init} cli.cxx{sync-options}: cli{sync} cli.cxx{fetch-options}: cli{fetch} + cli.cxx{status-options}: cli{status} cli.cxx{config-options}: cli{config} - # Option length must be the same to get commands/topics/options aligned. # cli.options += -I $src_root --include-with-brackets --include-prefix bdep \ diff --git a/bdep/config.cli b/bdep/config.cli index 434dfc2..5b414b3 100644 --- a/bdep/config.cli +++ b/bdep/config.cli @@ -22,9 +22,9 @@ namespace bdep \b{bdep config create} [] [] [\b{@}] []\n \b{bdep config remove} [] [] } - \c{ = \b{--directory}|\b{-d} \n - = ( | )...\n - = (\b{@} | \b{--config}|\b{-c} )... | \b{--all}|\b{-a}} + \c{ = ( | )...\n + = (\b{@} | \b{--config}|\b{-c} )... | \b{--all}|\b{-a}\n + = \b{--directory}|\b{-d} } \h|DESCRIPTION| diff --git a/bdep/fetch.cli b/bdep/fetch.cli index f5e17d3..60e20f4 100644 --- a/bdep/fetch.cli +++ b/bdep/fetch.cli @@ -19,8 +19,8 @@ namespace bdep \c{\b{bdep fetch} [] [\b{--full}|\b{-F}] [] []} - \c{ = \b{--directory}|\b{-d} \n - = (\b{@} | \b{--config}|\b{-c} )... | \b{--all}|\b{-a}} + \c{ = (\b{@} | \b{--config}|\b{-c} )... | \b{--all}|\b{-a}\n + = \b{--directory}|\b{-d} } \h|DESCRIPTION| diff --git a/bdep/init.cli b/bdep/init.cli index 617a5cc..8629bfe 100644 --- a/bdep/init.cli +++ b/bdep/init.cli @@ -26,10 +26,10 @@ namespace bdep \b{bdep init} [] [] \b{--config-create|-C} [\b{@}]\n \ \ \ \ \ \ \ \ \ \ []} - \c{ = \b{--directory}|\b{-d} \n - = (\b{--directory}|\b{-d} )... | \n + \c{ = ( | )...\n = (\b{@} | \b{--config}|\b{-c} )... | \b{--all}|\b{-a}\n - = ( | )...\n + = (\b{--directory}|\b{-d} )... | \n + = \b{--directory}|\b{-d} \n = ( | )...} \h|DESCRIPTION| diff --git a/bdep/project.cli b/bdep/project.cli index c3f2e29..15faea8 100644 --- a/bdep/project.cli +++ b/bdep/project.cli @@ -31,13 +31,6 @@ namespace bdep // class project_options: configuration_name_options { - dir_paths --directory|-d - { - "", - "Assume project/package is in the specified directory rather than in the - current working directory." - } - bool --all|-a { "Use all build configurations." @@ -48,5 +41,12 @@ namespace bdep "", "Specify the build configuration as a directory." } + + dir_paths --directory|-d + { + "", + "Assume project/package is in the specified directory rather than in the + current working directory." + } }; } diff --git a/bdep/project.cxx b/bdep/project.cxx index e09371e..64f82ca 100644 --- a/bdep/project.cxx +++ b/bdep/project.cxx @@ -326,4 +326,26 @@ namespace bdep return r; } + + void + verify_project_packages (const project_packages& pp, + const configurations& cfgs) + { + for (const shared_ptr& c: cfgs) + { + for (const package_location& p: pp.packages) + { + if (find_if (c->packages.begin (), + c->packages.end (), + [&p] (const package_state& s) + { + return p.name == s.name; + }) == c->packages.end ()) + { + fail << "package " << p.name << " is not initialized " + << "in configuration " << *c; + } + } + } + } } diff --git a/bdep/project.hxx b/bdep/project.hxx index 16716ef..cf96c0b 100644 --- a/bdep/project.hxx +++ b/bdep/project.hxx @@ -170,6 +170,11 @@ namespace bdep find_project_packages (const project_options&, bool ignore_packages = false, bool load_packages = true); + + // Verify all the packages are present in all the configurations. + // + void + verify_project_packages (const project_packages&, const configurations&); } #endif // BDEP_PROJECT_HXX diff --git a/bdep/status.cli b/bdep/status.cli new file mode 100644 index 0000000..a8d1e49 --- /dev/null +++ b/bdep/status.cli @@ -0,0 +1,70 @@ +// file : bdep/status.cli +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +include ; + +"\section=1" +"\name=bdep-status" +"\summary=print status of project and/or its dependencies" + +namespace bdep +{ + { + " + + + + ", + + "\h|SYNOPSIS| + + \c{\b{bdep status} [] [] [] [...]} + + \c{ = [\b{/}]\n + = (\b{@} | \b{--config}|\b{-c} )... | \b{--all}|\b{-a}\n + = (\b{--directory}|\b{-d} )... | \n + = \b{--directory}|\b{-d} } + + \h|DESCRIPTION| + + The \cb{status} command prints the status of the project and/or its + dependencies in build configurations. If no arguments are + specified, then \cb{status} prints the status of the project's packages. + Otherwise, the status of the specified dependency packages is printed. + Additionally, the status of immediate or all dependencies of the above + packages can be printed by specifying the \c{\b{--immediate}|\b{-i}} or + \c{\b{--recursive}|\b{-r}} options, respectively. Note that the status is + written to \cb{STDOUT}, not \cb{STDERR}. + + The status of each package is printed on a separate line. The semantics + of and the format of the status line are described in + \l{bpkg-pkg-status(1)}. + " + } + + class cmd_status_options: project_options + { + "\h|STATUS OPTIONS|" + + bool --immediate|-i + { + "Also print the status of immediate dependencies." + } + + bool --recursive|-r + { + "Also print the status of all dependencies, recursively." + } + + bool --fetch|-f + { + "Perform the \cb{fetch} command prior to printing the status." + } + + bool --fetch-full|-F + { + "Perform the \cb{fetch --full} command prior to printing the status." + } + }; +} diff --git a/bdep/status.cxx b/bdep/status.cxx new file mode 100644 index 0000000..ade5381 --- /dev/null +++ b/bdep/status.cxx @@ -0,0 +1,147 @@ +// file : bdep/status.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include +#include +#include + +#include + +using namespace std; + +namespace bdep +{ + static void + cmd_status (const cmd_status_options& o, + const dir_path& prj, + const dir_path& cfg, + const cstrings& pkgs, + bool fetch) + { + // Shallow fetch the project to make sure we show latest iterations and + // pick up any new repositories. + // + // We do it in a separate command for the same reason as in sync. + // + if (fetch) + run_bpkg (o, + "fetch", + "-d", cfg, + "--shallow", + "dir:" + prj.string ()); + + run_bpkg (o, + "status", + "-d", cfg, + (o.immediate () ? "--immediate" : + o.recursive () ? "--recursive" : + nullptr), + pkgs); + } + + static void + cmd_status (const cmd_status_options& o, + const dir_path& prj, + const shared_ptr& c, + const package_locations& ps, + bool fetch) + { + assert (!c->packages.empty ()); + + // If no packages were explicitly specified, then we print the status for + // all that have been initialized in the configuration. + // + cstrings pkgs; + + if (ps.empty ()) + { + for (const package_state& p: c->packages) + pkgs.push_back (p.name.c_str ()); + } + else + { + for (const package_location& p: ps) + pkgs.push_back (p.name.c_str ()); + } + + cmd_status (o, prj, c->path, pkgs, fetch); + } + + int + cmd_status (const cmd_status_options& o, cli::scanner& args) + { + tracer trace ("status"); + + if (o.immediate () && o.recursive ()) + fail << "both --immediate|-i and --recursive|-r specified"; + + // We have two pretty different modes: project status and dependency + // status (have arguments). + // + cstrings pkgs; + for (; args.more (); pkgs.push_back (args.next ())) ; + + // For the project status the same story as in sync. + // + project_packages pp ( + find_project_packages (o, + !pkgs.empty () /* ignore_packages */, + false /* load_packages */)); + + const dir_path& prj (pp.project); + + database db (open (prj, trace)); + + transaction t (db.begin ()); + configurations cfgs (find_configurations (prj, t, o)); + t.commit (); + + // If specified, verify packages are present in each configuration. + // + if (!pp.packages.empty ()) + verify_project_packages (pp, cfgs); + + // Print status in each configuration skipping empty ones. + // + bool first (true); + for (const shared_ptr& c: cfgs) + { + if (c->packages.empty ()) + { + if (verb) + info << "skipping empty configuration " << *c; + + continue; + } + + // If we are printing multiple configurations, separate them with a + // blank line and print the configuration name/directory. + // + if (verb && cfgs.size () > 1) + { + text << (first ? "" : "\n") + << "status in configuration " << *c; + + first = false; + } + + bool fetch (o.fetch () || o.fetch_full ()); + + if (fetch) + cmd_fetch (o, prj, c, o.fetch_full ()); + + // Don't re-fetch if we just fetched. + // + if (pkgs.empty ()) + cmd_status (o, prj, c, pp.packages, !fetch); + else + cmd_status (o, prj, c->path, pkgs, !fetch); + } + + return 0; + } +} diff --git a/bdep/status.hxx b/bdep/status.hxx new file mode 100644 index 0000000..2ff45c8 --- /dev/null +++ b/bdep/status.hxx @@ -0,0 +1,19 @@ +// file : bdep/status.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BDEP_STATUS_HXX +#define BDEP_STATUS_HXX + +#include +#include + +#include + +namespace bdep +{ + int + cmd_status (const cmd_status_options&, cli::scanner& args); +} + +#endif // BDEP_STATUS_HXX diff --git a/bdep/sync.cli b/bdep/sync.cli index 9d2f4ca..e6c5d37 100644 --- a/bdep/sync.cli +++ b/bdep/sync.cli @@ -20,9 +20,9 @@ namespace bdep \c{\b{bdep sync} [] [] []} - \c{ = \b{--directory}|\b{-d} \n + \c{ = (\b{@} | \b{--config}|\b{-c} )... | \b{--all}|\b{-a}\n = (\b{--directory}|\b{-d} )... | \n - = (\b{@} | \b{--config}|\b{-c} )... | \b{--all}|\b{-a}} + = \b{--directory}|\b{-d} } \h|DESCRIPTION| diff --git a/bdep/sync.cxx b/bdep/sync.cxx index dff6489..6f95080 100644 --- a/bdep/sync.cxx +++ b/bdep/sync.cxx @@ -90,22 +90,8 @@ namespace bdep // If specified, verify packages are present in each configuration. // - for (const shared_ptr& c: cfgs) - { - for (const package_location& p: pp.packages) - { - if (find_if (c->packages.begin (), - c->packages.end (), - [&p] (const package_state& s) - { - return p.name == s.name; - }) == c->packages.end ()) - { - fail << "package " << p.name << " is not initialized " - << "in configuration " << *c; - } - } - } + if (!pp.packages.empty ()) + verify_project_packages (pp, cfgs); // Synchronize each configuration skipping empty ones. // diff --git a/doc/cli.sh b/doc/cli.sh index a10c1d2..af6638d 100755 --- a/doc/cli.sh +++ b/doc/cli.sh @@ -39,6 +39,7 @@ function compile () cli -I .. -v project="bdep" -v version="$version" -v date="$date" \ --include-base-last "${o[@]}" --generate-html --html-prologue-file \ man-prologue.xhtml --html-epilogue-file man-epilogue.xhtml --html-suffix .xhtml \ +--link-regex '%bpkg([-.].+)%../../bpkg/doc/bpkg$1%' \ --link-regex '%bdep(#.+)?%build2-project-manager-manual.xhtml$1%' \ ../bdep/$n.cli @@ -56,7 +57,7 @@ o="--suppress-undocumented --output-prefix bdep- --class-doc bdep::common_option compile "common" $o --output-suffix "-options" --class-doc bdep::common_options=long compile "bdep" $o --output-prefix "" --class-doc bdep::commands=short --class-doc bdep::topics=short -pages="config help init sync new fetch" +pages="new help init sync fetch status config" for p in $pages; do compile $p $o -- cgit v1.1