aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-03-28 14:06:10 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-03-28 14:06:10 +0200
commit9defb02d42361b28d5ec345b5f65a8f2790fb2aa (patch)
tree3b6bc4afca18847e640a0dc59e000cddbfcda352
parent213f50f8dbc13f541780bad8506413aa54839fda (diff)
Handle sync's upgrade forms
-rw-r--r--bdep/status.cxx26
-rw-r--r--bdep/sync.cxx171
2 files changed, 154 insertions, 43 deletions
diff --git a/bdep/status.cxx b/bdep/status.cxx
index 814e21b..beb8e4f 100644
--- a/bdep/status.cxx
+++ b/bdep/status.cxx
@@ -19,7 +19,7 @@ namespace bdep
cmd_status (const cmd_status_options& o,
const dir_path& prj,
const dir_path& cfg,
- const cstrings& pkgs,
+ const strings& pkgs,
bool fetch)
{
// Shallow fetch the project to make sure we show latest iterations and
@@ -61,17 +61,17 @@ namespace bdep
// If no packages were explicitly specified, then we print the status for
// all that have been initialized in the configuration.
//
- cstrings pkgs;
+ strings pkgs;
if (ps.empty ())
{
for (const package_state& p: c->packages)
- pkgs.push_back (p.name.c_str ());
+ pkgs.push_back (p.name);
}
else
{
for (const package_location& p: ps)
- pkgs.push_back (p.name.c_str ());
+ pkgs.push_back (p.name);
}
cmd_status (o, prj, c->path, pkgs, fetch);
@@ -85,18 +85,18 @@ namespace bdep
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).
+ // We have two pretty different modes: project package status and
+ // dependency package status (have arguments).
//
- cstrings pkgs;
- for (; args.more (); pkgs.push_back (args.next ())) ;
+ strings dep_pkgs;
+ for (; args.more (); dep_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 */));
+ !dep_pkgs.empty () /* ignore_packages */,
+ false /* load_packages */));
const dir_path& prj (pp.project);
@@ -140,12 +140,10 @@ namespace bdep
if (fetch)
cmd_fetch (o, prj, c, o.fetch_full ());
- // Don't re-fetch if we just fetched.
- //
- if (pkgs.empty ())
+ if (dep_pkgs.empty ())
cmd_status (o, prj, c, pp.packages, !fetch);
else
- cmd_status (o, prj, c->path, pkgs, !fetch);
+ cmd_status (o, prj, c->path, dep_pkgs, !fetch);
}
return 0;
diff --git a/bdep/sync.cxx b/bdep/sync.cxx
index 3d2ee9c..526ac4a 100644
--- a/bdep/sync.cxx
+++ b/bdep/sync.cxx
@@ -13,14 +13,24 @@ using namespace std;
namespace bdep
{
- void
+ // Sync with optional upgrade.
+ //
+ // If upgrade is not nullopt, then: If there are dep_pkgs, then we are
+ // upgrading specific dependency packages. Othewise -- project packages.
+ //
+ static void
cmd_sync (const common_options& co,
const dir_path& prj,
const shared_ptr<configuration>& c,
bool fetch,
- bool yes)
+ bool yes,
+ optional<bool> upgrade, // true - upgrade, false - patch
+ optional<bool> recursive, // true - recursive, false - immediate
+ const package_locations& prj_pkgs,
+ const strings& dep_pkgs)
{
assert (!c->packages.empty ());
+ assert (prj_pkgs.empty () || dep_pkgs.empty ()); // Can't have both.
// Do a separate fetch instead of letting pkg-build do it. This way we get
// better control of the diagnostics (no "fetching ..." for the project
@@ -31,7 +41,7 @@ namespace bdep
// "I want this dependency upgraded to the latest version available from
// this repository").
//
- // We also use the repository name rather than then location as a sanity
+ // We also use the repository name rather than the location as a sanity
// check (the repository must have been added as part of init).
//
if (fetch)
@@ -41,43 +51,106 @@ namespace bdep
"--shallow",
"dir:" + prj.string ());
- // Prepare the pkg-spec.
+ // Prepare the package list.
//
- string spec;
+ strings args;
+
for (const package_state& p: c->packages)
{
- if (!spec.empty ())
- spec += ',';
+ if (upgrade)
+ {
+ // We synchronize all the init'ed packages but only upgrade the
+ // specified.
+ //
+ if (find_if (prj_pkgs.begin (),
+ prj_pkgs.end (),
+ [&p] (const package_location& pl)
+ {
+ return pl.name == p.name;
+ }) != prj_pkgs.end ())
+ {
+ // The project package itself must always be upgraded to the latest
+ // version/iteration. So we have to translate our option to their
+ // dependency-only --{upgrade,patch}-{recursive,immediate}.
+ //
+ args.push_back ("{");
+ args.push_back (
+ *upgrade
+ ? *recursive ? "--upgrade-recursive" : "--upgrade-immediate"
+ : *recursive ? "--patch-recursive" : "--patch-immediate");
+ args.push_back ("}+");
+ }
+ }
- spec += p.name;
+ // We need to add the explicit location qualification (@<rep-loc>) since
+ // there is no guarantee a higher version isn't available from another
+ // repository.
+ //
+ args.push_back (p.name + '@' + prj.string ());
}
- spec += '@';
- spec += prj.string ();
+ if (upgrade)
+ {
+ for (const string& p: dep_pkgs)
+ {
+ // Unless this is the default "non-recursive upgrade" we need to add a
+ // group.
+ //
+ if (recursive || !*upgrade)
+ {
+ args.push_back ("{");
+ args.push_back (*upgrade ? "-u" : "-p");
+ if (recursive) args.push_back (*recursive ? "-r" : "-i");
+ args.push_back ("}+");
+ }
+
+ // Make sure it is treated as a dependency.
+ //
+ args.push_back ('?' + p);
+ }
+ }
- // It feels right to drop unused dependencies without any confirmation.
- //
// @@ TODO: right now it is silent. Can we print a plan without the
// prompts? Probably also a good idea even if from build system
// hook... Issue: drop dependents has no "drop " prefix. Also indented
- // stuff out of nowhere will look odd.
+ // stuff out of nowhere will look odd. -- Need custom prompt.
//
run_bpkg (co,
"build",
"-d", c->path,
"--no-fetch",
"--configure-only",
- "--drop-prerequisite",
"--keep-out",
(yes ? "--yes" : nullptr),
- spec);
+ args);
+ }
+
+ void
+ cmd_sync (const common_options& co,
+ const dir_path& prj,
+ const shared_ptr<configuration>& c,
+ bool fetch,
+ bool yes)
+ {
+ cmd_sync (co,
+ prj,
+ c,
+ fetch,
+ yes,
+ nullopt /* upgrade */,
+ nullopt /* recursive */,
+ package_locations () /* prj_pkgs */,
+ strings () /* dep_pkgs */);
}
int
- cmd_sync (const cmd_sync_options& o, cli::scanner&)
+ cmd_sync (const cmd_sync_options& o, cli::scanner& args)
{
tracer trace ("sync");
+ if (o.upgrade () && o.patch ())
+ fail << "both --upgrade|-u and --patch|-p specified";
+
// The --immediate or --recursive option can only be specified with
// an explicit --upgrade or --patch.
//
@@ -88,19 +161,26 @@ namespace bdep
fail << n << " requires explicit --upgrade|-u or --patch|-p";
}
+ // We have two pretty different upgrade modes: project package upgrade and
+ // dependency package upgrade (have arguments).
+ //
+ strings dep_pkgs;
+ for (; args.more (); dep_pkgs.push_back (args.next ())) ;
+
// We could be running from a package directory (or the user specified one
- // with -d) that has not been init'ed in this configuration. We want to
- // diagnose that since such a package will not be present in the bpkg
- // configuration. But if we are running from the project, then we don't
- // want to treat all the available packages as specified by the user (thus
- // load_packages=false).
+ // with -d) that has not been init'ed in this configuration. Unless we are
+ // upgrading specific dependencies, we want to diagnose that since such a
+ // package will not be present in the bpkg configuration. But if we are
+ // running from the project, then we don't want to treat all the available
+ // packages as specified by the user (thus load_packages=false).
//
project_packages pp (
find_project_packages (o,
- false /* ignore_packages */,
- false /* load_packages */));
+ !dep_pkgs.empty () /* ignore_packages */,
+ false /* load_packages */));
const dir_path& prj (pp.project);
+ const package_locations& prj_pkgs (pp.packages);
database db (open (prj, trace));
@@ -110,7 +190,7 @@ namespace bdep
// If specified, verify packages are present in each configuration.
//
- if (!pp.packages.empty ())
+ if (!prj_pkgs.empty ())
verify_project_packages (pp, cfgs);
// Synchronize each configuration skipping empty ones.
@@ -142,11 +222,44 @@ namespace bdep
if (fetch)
cmd_fetch (o, prj, c, o.fetch_full ());
- // Don't re-fetch if we just fetched.
- //
- cmd_sync (o, prj, c, !fetch);
-
- //@@ TODO: sync upgrade (see status for structure ideas). Pass o.yes().
+ if (!dep_pkgs.empty ())
+ {
+ // The third form: upgrade of the specified dependencies.
+ //
+ // Only prompt if upgrading their dependencies.
+ //
+ cmd_sync (o,
+ prj,
+ c,
+ !fetch,
+ o.recursive () || o.immediate () ? o.yes () : true,
+ !o.patch (), // Upgrade by default unless patch requested.
+ (o.recursive () ? optional<bool> (true) :
+ o.immediate () ? optional<bool> (false) : nullopt),
+ prj_pkgs,
+ dep_pkgs);
+ }
+ else if (o.upgrade () || o.patch ())
+ {
+ // The second form: upgrade of project packages' dependencies
+ // (immediate by default, recursive if requested).
+ //
+ cmd_sync (o,
+ prj,
+ c,
+ !fetch,
+ o.yes (),
+ o.upgrade (),
+ o.recursive (),
+ prj_pkgs,
+ dep_pkgs);
+ }
+ else
+ {
+ // The first form: sync of project packages.
+ //
+ cmd_sync (o, prj, c, !fetch, true /* yes */);
+ }
}
return 0;