aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2021-07-09 20:55:15 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2021-07-20 17:08:09 +0300
commit07ab59a93f9447d5489743e8d7e19b6adb5ebbf1 (patch)
treeaa202b26e7ac2b3b6477855e250ab0464301fd2d
parent8da242097fcaec5f3676f8d2296b639879825ddd (diff)
Add support for configuration type and bdep-config-link sub-command
-rw-r--r--bdep/build.txx78
-rw-r--r--bdep/ci.cli14
-rw-r--r--bdep/ci.cxx92
-rw-r--r--bdep/clean.cli6
-rw-r--r--bdep/config.cli49
-rw-r--r--bdep/config.cxx230
-rw-r--r--bdep/config.hxx7
-rw-r--r--bdep/database.cxx18
-rw-r--r--bdep/deinit.cli4
-rw-r--r--bdep/deinit.cxx93
-rw-r--r--bdep/fetch.cli4
-rw-r--r--bdep/fetch.cxx2
-rw-r--r--bdep/init.cli9
-rw-r--r--bdep/init.cxx169
-rw-r--r--bdep/init.hxx2
-rw-r--r--bdep/new.cxx12
-rw-r--r--bdep/project.cli8
-rw-r--r--bdep/project.cxx43
-rw-r--r--bdep/project.hxx24
-rw-r--r--bdep/project.xml6
-rw-r--r--bdep/projects-configs.cli11
-rw-r--r--bdep/publish.cli4
-rw-r--r--bdep/publish.cxx99
-rw-r--r--bdep/status.cli4
-rw-r--r--bdep/status.cxx102
-rw-r--r--bdep/sync.cli4
-rw-r--r--bdep/sync.cxx35
-rw-r--r--bdep/test.cli6
-rw-r--r--bdep/update.cli6
-rw-r--r--tests/ci.testscript26
-rw-r--r--tests/config.testscript85
-rw-r--r--tests/init.testscript18
-rw-r--r--tests/new.testscript4
-rw-r--r--tests/publish.testscript44
-rw-r--r--tests/update.testscript43
35 files changed, 980 insertions, 381 deletions
diff --git a/bdep/build.txx b/bdep/build.txx
index 0090be5..7d17088 100644
--- a/bdep/build.txx
+++ b/bdep/build.txx
@@ -44,56 +44,72 @@ namespace bdep
const dir_path& prj (pp.project);
- // Load the configurations without keeping the database open longer
- // than necessary.
+ // Load the configurations without keeping the database open longer than
+ // necessary.
//
configurations cfgs;
{
database db (open (prj, trace));
transaction t (db.begin ());
- cfgs = find_configurations (o, prj, t);
+ pair<configurations, bool> cs (find_configurations (o, prj, t));
t.commit ();
- }
- // If specified, verify packages are present in each configuration.
- //
- if (!pp.packages.empty ())
- verify_project_packages (pp, cfgs);
+ // If specified, verify packages are present in at least one
+ // configuration.
+ //
+ if (!pp.packages.empty ())
+ verify_project_packages (pp, cs);
+
+ cfgs = move (cs.first);
+ }
// If no packages were explicitly specified, then we build all that have
- // been initialized in each configuration.
+ // been initialized in each configuration. Otherwise, we build only
+ // specified packages initialized in the (specified) configurations.
//
- cstrings pkgs;
+ const package_locations& pkgs (pp.packages);
- bool all (pp.packages.empty ());
- if (!all)
- {
- for (const package_location& p: pp.packages)
- pkgs.push_back (p.name.string ().c_str ());
- }
+ bool all (pkgs.empty ());
- // Build in each configuration skipping empty ones.
+ // Build in each configuration, skipping those where no packages needs to
+ // be built.
//
bool first (true);
for (const shared_ptr<configuration>& c: cfgs)
{
- if (c->packages.empty ())
- {
- if (verb)
- info << "skipping empty configuration " << *c;
+ // Collect packages to build.
+ //
+ cstrings ps;
- continue;
+ for (const package_state& s: c->packages)
+ {
+ if (all ||
+ find_if (pkgs.begin (),
+ pkgs.end (),
+ [&s] (const package_location& p)
+ {
+ return p.name == s.name;
+ }) != pkgs.end ())
+ ps.push_back (s.name.string ().c_str ());
}
- // Collect packages.
- //
- if (all)
+ if (ps.empty ())
{
- pkgs.clear ();
+ if (verb)
+ {
+ diag_record dr (info);
+
+ dr << "skipping configuration " << *c;
- for (const package_state& p: c->packages)
- pkgs.push_back (p.name.string ().c_str ());
+ if (c->packages.empty ())
+ dr << info << "configuration is empty";
+ else
+ dr << info << "none of specified packages initialized in this "
+ << "configuration";
+ }
+
+ continue;
}
// If we are printing multiple configurations, separate them with a
@@ -107,12 +123,12 @@ namespace bdep
first = false;
}
- // Pre-sync the configuration to avoid triggering the build system
- // hook (see sync for details).
+ // Pre-sync the configuration to avoid triggering the build system hook
+ // (see sync for details).
//
cmd_sync (o, prj, c, strings () /* pkg_args */, true /* implicit */);
- build (o, c, pkgs, cfg_vars);
+ build (o, c, ps, cfg_vars);
}
return 0;
diff --git a/bdep/ci.cli b/bdep/ci.cli
index 08d65cc..5f955ea 100644
--- a/bdep/ci.cli
+++ b/bdep/ci.cli
@@ -20,9 +20,9 @@ namespace bdep
\c{\b{bdep ci} [<options>] [<cfg-spec>] [<pkg-spec>]}
- \c{<pkg-spec> = (\b{--directory}|\b{-d} <pkg-dir>)... | <prj-spec>\n
- <prj-spec> = \b{--directory}|\b{-d} <prj-dir>\n
- <cfg-spec> = \b{@}<cfg-name> | \b{--config}|\b{-c} <cfg-dir>}
+ \c{<cfg-spec> = (\b{@}<cfg-name> | \b{--config}|\b{-c} <cfg-dir>)... | \b{--all}|\b{-a}\n
+ <pkg-spec> = (\b{--directory}|\b{-d} <pkg-dir>)... | <prj-spec>\n
+ <prj-spec> = \b{--directory}|\b{-d} <prj-dir>}
\h|DESCRIPTION|
@@ -31,10 +31,10 @@ namespace bdep
If no project or package directory is specified, then the current working
directory is assumed. If no configuration is specified, then the default
- configuration is used. If the specified directory is a project directory,
- then all the packages initialized in the configuration are submitted. See
- \l{bdep-projects-configs(1)} for details on specifying projects and
- configurations.
+ configurations are used. If the specified directory is a project
+ directory, then all the packages initialized in the configurations are
+ submitted. See \l{bdep-projects-configs(1)} for details on specifying
+ projects and configurations.
A CI request consists of the specified packages and their versions as
well as the project's remote version control repository URL corresponding
diff --git a/bdep/ci.cxx b/bdep/ci.cxx
index 3b59a30..a4acd94 100644
--- a/bdep/ci.cxx
+++ b/bdep/ci.cxx
@@ -249,10 +249,10 @@ namespace bdep
// If we are submitting the entire project, then we have two choices: we
// can list all the packages in the project or we can only do so for
- // packages that were initialized in the (specified) configuration(s?).
+ // packages that were initialized in the specified configurations.
//
// Note that other than getting the list of packages, we would only need
- // the configuration to obtain their versions. Since we can only have one
+ // the configurations to obtain their versions. Since we can only have one
// version for each package this is not strictly necessary but is sure a
// good sanity check against local/remote mismatches. Also, it would be
// nice to print the versions we are submitting in the prompt.
@@ -262,10 +262,14 @@ namespace bdep
// has configurations for subsets of packages or some such. And in the
// future, who knows, we could have multi-project CI.
//
- // So, let's go with the configuration. Specifically, if packages were
+ // So, let's go with the configurations. Specifically, if packages were
// explicitly specified, we verify they are initialized. Otherwise, we use
- // the list of packages that are initialized in a configuration (single
- // for now).
+ // the list of packages that are initialized in configurations. In both
+ // cases we also verify that for each package only one configuration, it
+ // is initialized in, is specified (while we currently don't need this
+ // restriction, this may change in the future if we decide to support
+ // archive-based CI or some such).
+ //
//
// Note also that no pre-sync is needed since we are only getting versions
// (via the info meta-operation).
@@ -277,51 +281,87 @@ namespace bdep
const dir_path& prj (pp.project);
- shared_ptr<configuration> cfg;
+ configurations cfgs;
{
// Don't keep the database open longer than necessary.
//
database db (open (prj, trace));
transaction t (db.begin ());
- configurations cfgs (find_configurations (o, prj, t));
+ cfgs = find_configurations (o, prj, t).first;
t.commit ();
-
- if (cfgs.size () > 1)
- fail << "multiple configurations specified for ci";
-
- // If specified, verify packages are present in the configuration.
- //
- if (!pp.packages.empty ())
- verify_project_packages (pp, cfgs);
-
- cfg = move (cfgs[0]);
}
- // Collect package names and their versions.
+ // Collect package names, versions, and configurations used.
//
struct package
{
- package_name name;
- standard_version version;
+ package_name name;
+ standard_version version;
+ shared_ptr<configuration> config;
};
vector<package> pkgs;
- auto add_package = [&o, &cfg, &pkgs] (package_name n)
+ // Add a package to the list, suppressing duplicates and verifying that it
+ // is initialized in only one configuration.
+ //
+ auto add_package = [&o, &pkgs] (package_name n,
+ shared_ptr<configuration> c)
{
- standard_version v (package_version (o, cfg->path, n));
- pkgs.push_back (package {move (n), move (v)});
+ auto i (find_if (pkgs.begin (),
+ pkgs.end (),
+ [&n] (const package& p) {return p.name == n;}));
+
+ if (i != pkgs.end ())
+ {
+ if (i->config == c)
+ return;
+
+ fail << "package " << n << " is initialized in multiple specified "
+ << "configurations" <<
+ info << *i->config <<
+ info << *c;
+ }
+
+ standard_version v (package_version (o, c->path, n));
+ pkgs.push_back (package {move (n), move (v), move (c)});
};
if (pp.packages.empty ())
{
- for (const package_state& p: cfg->packages)
- add_package (p.name);
+ for (const shared_ptr<configuration>& c: cfgs)
+ {
+ for (const package_state& p: c->packages)
+ add_package (p.name, c);
+ }
}
else
{
for (package_location& p: pp.packages)
- add_package (p.name);
+ {
+ bool init (false);
+
+ for (const shared_ptr<configuration>& c: cfgs)
+ {
+ if (find_if (c->packages.begin (),
+ c->packages.end (),
+ [&p] (const package_state& s)
+ {
+ return p.name == s.name;
+ }) != c->packages.end ())
+ {
+ // Add the package, but continue the loop to detect a potential
+ // configuration ambiguity.
+ //
+ add_package (p.name, c);
+ init = true;
+ }
+ }
+
+ if (!init)
+ fail << "package " << p.name << " is not initialized in any "
+ << "configuration";
+ }
}
// Extract the interactive mode configuration and breakpoint from the
diff --git a/bdep/clean.cli b/bdep/clean.cli
index 141d20a..6a2e140 100644
--- a/bdep/clean.cli
+++ b/bdep/clean.cli
@@ -41,9 +41,9 @@ namespace bdep
If no project or package directory is specified, then the current working
directory is assumed. If no configuration is specified, then the default
- configuration is assumed. See \l{bdep-projects-configs(1)} for details on
- specifying projects and configurations. Optional \c{\i{cfg-var}...} are
- the additional configuration variables to pass to the build system.
+ configurations are assumed. See \l{bdep-projects-configs(1)} for details
+ on specifying projects and configurations. Optional \c{\i{cfg-var}...}
+ are the additional configuration variables to pass to the build system.
"
}
diff --git a/bdep/config.cli b/bdep/config.cli
index 6d26432..a1cdba2 100644
--- a/bdep/config.cli
+++ b/bdep/config.cli
@@ -19,6 +19,7 @@ namespace bdep
\c{\b{bdep config add} \ \ \ [<options>] [<prj-spec>] [\b{@}<cfg-name>] <cfg-dir>\n
\b{bdep config create} [<options>] [<prj-spec>] [\b{@}<cfg-name>] <cfg-dir> [<cfg-args>]\n
+ \b{bdep config link} \ \ [<options>] [<prj-spec>] <cfg-spec> <cfg-spec>\n
\b{bdep config list} \ \ [<options>] [<prj-spec>] [<cfg-spec>...]\n
\b{bdep config move} \ \ [<options>] [<prj-spec>] <cfg-spec> <cfg-dir>\n
\b{bdep config rename} [<options>] [<prj-spec>] <cfg-spec> <cfg-name>\n
@@ -77,23 +78,31 @@ namespace bdep
$ bdep config create -- @gcc cc config.cxx=g++ # ../hello-gcc
\
+ A configuration also has a type that is specified with the
+ \cb{--config-type} option. If the type is not specified explicitly,
+ then \cb{target} is assumed. See \l{bpkg-cfg-create(1)} for
+ background on configuration types.
+
Unless the \cb{--no-default} option is specified, the first added or
- created build configuration is designated as the default. Several
- \cb{bdep} commands use such a configuration by default if no
- configuration was specified explicitly (see
+ created build configuration of each type is designated as the
+ default. Several \cb{bdep} commands use such a configuration by
+ default if no configuration was specified explicitly (see
\l{bdep-projects-configs(1)} for details). To make a subsequently
- added configuration the default use the \cb{--default} option.
-
- The default build configuration is also designated as forwarded
- unless the \cb{--no-forward} option is specified or another
- configuration is already designated as forwarded. When a project is
- initialized in a forwarded build configuration, its source directory
- is configured to forward to this configuration (see \l{b(1)} for
- details on forwarded configurations). To designate a non-default
- configuration as forwarded use the \cb{--forward} option. Note also
- that it is possible to have multiple forwarded configurations,
- however, any given package within a project can only be initialized
- in one such configuration.
+ added configuration the default use the \cb{--default} option. Note
+ also that in case of multiple default configurations any given
+ package within a project can only be initialized in one such
+ configuration.
+
+ The default build configuration of each type is also designated as
+ forwarded unless the \cb{--no-forward} option is specified or another
+ configuration of this type is already designated as forwarded. When a
+ project is initialized in a forwarded build configuration, its source
+ directory is configured to forward to this configuration (see
+ \l{b(1)} for details on forwarded configurations). To designate a
+ non-default configuration as forwarded use the \cb{--forward}
+ option. Note also that it is possible to have multiple forwarded
+ configurations, however, any given package within a project can only
+ be initialized in one such configuration.
Unless the \cb{--no-auto-sync} option is specified, an added or
created build configuration will be automatically synchronized on
@@ -102,6 +111,12 @@ namespace bdep
configuration, then they must have a consistent auto-synchronization
setting.|
+ \li|\cb{link}
+
+ The \cb{link} subcommand links one build configuration with another
+ by executing the \l{bpkg-cfg-link(1)} command. See
+ \l{bpkg-cfg-create(1)} for background on linked configurations.|
+
\li|\cb{list}
The \cb{list} subcommand prints the list of build configurations
@@ -145,10 +160,11 @@ namespace bdep
(\c{\b{--}[\b{no-}]\b{forward}}), and auto-synchronization
(\c{\b{--}[\b{no-}]\b{auto-sync}}) flags. Note that changing any of
these flags requires an explicit \l{bdep-sync(1)} command to take
- effect. ||"
+ effect.||"
bool add;
bool create;
+ bool link;
bool list;
bool move;
bool rename;
@@ -164,7 +180,6 @@ namespace bdep
"\h|CONFIG OPTIONS|"
};
-
"
\h|DEFAULT OPTIONS FILES|
diff --git a/bdep/config.cxx b/bdep/config.cxx
index 8d33155..f06bb98 100644
--- a/bdep/config.cxx
+++ b/bdep/config.cxx
@@ -22,7 +22,7 @@ namespace bdep
if (c->name)
o << '@' << *c->name << ' ';
- o << c->path << ' ' << *c->id;
+ o << c->path << ' ' << *c->id << ' ' << c->type;
if (flags)
{
@@ -54,14 +54,15 @@ namespace bdep
if (o.existing () && o.wipe ())
fail << "both --existing|-e and --wipe specified";
- return (o.default_ () ? "--default" :
- o.no_default () ? "--no-default" :
- o.forward () ? "--forward" :
- o.no_forward () ? "--no-forward" :
- o.auto_sync () ? "--auto-sync" :
- o.no_auto_sync () ? "--no-auto-sync" :
- o.existing () ? "--existing|-e" :
- o.wipe () ? "--wipe" : nullptr);
+ return (o.config_type_specified () ? "--config-type" :
+ o.default_ () ? "--default" :
+ o.no_default () ? "--no-default" :
+ o.forward () ? "--forward" :
+ o.no_forward () ? "--no-forward" :
+ o.auto_sync () ? "--auto-sync" :
+ o.no_auto_sync () ? "--no-auto-sync" :
+ o.existing () ? "--existing|-e" :
+ o.wipe () ? "--wipe" : nullptr);
}
void
@@ -137,12 +138,14 @@ namespace bdep
}
shared_ptr<configuration>
- cmd_config_add (const configuration_add_options& ao,
+ cmd_config_add (const common_options& co,
+ const configuration_add_options& ao,
const dir_path& prj,
const package_locations& pkgs,
database& db,
dir_path path,
optional<string> name,
+ optional<string> type,
optional<uint64_t> id,
const char* what)
{
@@ -161,8 +164,53 @@ namespace bdep
verify_configuration_path (path, prj, pkgs);
- optional<dir_path> rel_path;
- try {rel_path = path.relative (prj);} catch (const invalid_path&) {}
+ // Use bpkg-cfg-info to query the configuration type, unless specified
+ // explicitly.
+ //
+ if (!type)
+ {
+ fdpipe pipe (open_pipe ()); // Text mode seems appropriate.
+
+ process pr (start_bpkg (3,
+ co,
+ pipe /* stdout */,
+ 2 /* stderr */,
+ "cfg-info",
+ "-d", path));
+
+ // Shouldn't throw, unless something is severely damaged.
+ //
+ pipe.out.close ();
+
+ bool io (false);
+ try
+ {
+ ifdstream is (move (pipe.in), fdstream_mode::skip, ifdstream::badbit);
+
+ for (string l; !eof (getline (is, l)); )
+ {
+ if (l.compare (0, 6, "type: ") == 0)
+ {
+ type = string (l, 6);
+ break;
+ }
+ }
+
+ is.close (); // Detect errors.
+
+ if (!type || type->empty ())
+ fail << "invalid bpkg-cfg-info output: no configuration type";
+ }
+ catch (const io_error&)
+ {
+ // Presumably the child process failed and issued diagnostics so let
+ // finish_bpkg() try to deal with that first.
+ //
+ io = true;
+ }
+
+ finish_bpkg (co, pr, io);
+ }
transaction t (db.begin ());
@@ -172,36 +220,43 @@ namespace bdep
{
using query = bdep::query<configuration>;
- // By default the first added configuration is the default.
+ // By default the first added for its type configuration is the default.
//
if (ao.default_ () || ao.no_default ())
def = ao.default_ () && !ao.no_default ();
if (!def)
- def = (db.query_value<count> () == 0);
+ def = (db.query_value<count> (query::type == *type) == 0);
else if (*def)
{
- if (auto p = db.query_one<configuration> (query::default_))
- fail << "configuration " << *p << " is already the default" <<
+ if (auto p = db.query_one<configuration> (query::default_ &&
+ query::type == *type))
+ fail << "configuration " << *p << " of type " << *type
+ << " is already the default" <<
info << "use 'bdep config set --no-default' to clear";
}
// By default the default configuration is forwarded unless another is
- // already forwarded.
+ // already forwarded for its configuration type.
//
if (ao.forward () || ao.no_forward ())
- fwd = ao.forward () && !ao.no_forward ();
+ fwd = ao.forward () && !ao.no_forward ();
+ // Note: there can be multiple forwarded configurations for a type.
+ //
if (!fwd)
- fwd = *def && db.query_one<configuration> (query::forward) == nullptr;
+ fwd = *def &&
+ db.query_value<count> (query::forward &&
+ query::type == *type) == 0;
}
shared_ptr<configuration> r (
new configuration {
id,
name,
+ move (*type),
path,
- move (rel_path),
+ path.try_relative (prj),
*def,
*fwd,
!ao.no_auto_sync (),
@@ -258,6 +313,7 @@ namespace bdep
dir_path path,
const strings& args,
optional<string> name,
+ string type,
optional<uint64_t> id)
{
// Similar logic to *_add().
@@ -274,16 +330,22 @@ namespace bdep
co,
"create",
"-d", path,
+ (name
+ ? strings ({"--name", *name})
+ : strings ()),
+ "--type", type,
(ao.existing () ? "--existing" : nullptr),
(ao.wipe () ? "--wipe" : nullptr),
args);
- return cmd_config_add (ao,
+ return cmd_config_add (co,
+ ao,
prj,
package_locations {}, // Already verified.
db,
move (path),
move (name),
+ move (type),
id,
ao.existing () ? "initialized" : "created");
}
@@ -324,11 +386,13 @@ namespace bdep
database db (open (prj, trace));
cmd_config_add (o,
+ o,
prj,
load_packages (prj, true /* allow_empty */),
db,
move (path),
move (name),
+ nullopt, /* type */
move (id));
return 0;
}
@@ -382,11 +446,61 @@ namespace bdep
move (path),
cfg_args,
move (name),
+ o.config_type (),
move (id));
return 0;
}
static int
+ cmd_config_link (const cmd_config_options& o, cli::scanner&)
+ {
+ tracer trace ("config_link");
+
+ // Load project configurations.
+ //
+ configurations cfgs;
+ {
+ dir_path prj (find_project (o));
+ database db (open (prj, trace));
+
+ transaction t (db.begin ());
+
+ cfgs = find_configurations (o,
+ prj,
+ t,
+ false /* fallback_default */,
+ true /* validate */).first;
+
+ t.commit ();
+ }
+
+ if (cfgs.size () != 2)
+ fail << "two configurations must be specified for config link";
+
+ const dir_path& cd (cfgs[0]->path);
+ const dir_path& ld (cfgs[1]->path);
+
+ // Call bpkg to link the configurations.
+ //
+ // If possible, rebase the linked configuration directory path relative to
+ // the other configuration path.
+ //
+ run_bpkg (2,
+ o,
+ "cfg-link",
+ ld.try_relative (cd) ? "--relative" : nullptr,
+ "-d", cd,
+ ld);
+
+ if (verb)
+ text << "linked configuration " << *cfgs[0] << " (" << cfgs[0]->type
+ << ") with configuration " << *cfgs[1] << " (" << cfgs[1]->type
+ << ")";
+
+ return 0;
+ }
+
+ static int
cmd_config_list (const cmd_config_options& o, cli::scanner&)
{
tracer trace ("config_list");
@@ -405,7 +519,7 @@ namespace bdep
prj,
t,
false /* fallback_default */,
- false /* validate */);
+ false /* validate */).first;
}
else
{
@@ -425,7 +539,6 @@ namespace bdep
t.commit ();
-
for (const shared_ptr<configuration>& c: cfgs)
{
//@@ TODO: use tabular layout facility when ready.
@@ -467,7 +580,7 @@ namespace bdep
fail << "invalid configuration directory '" << a << "'";
}
- try {rel_path = path.relative (prj);} catch (const invalid_path&) {}
+ rel_path = path.try_relative (prj);
}
database db (open (prj, trace));
@@ -480,7 +593,7 @@ namespace bdep
prj,
t,
false /* fallback_default */,
- false /* validate */));
+ false /* validate */).first);
if (cfgs.size () > 1)
fail << "multiple configurations specified for config move";
@@ -500,6 +613,10 @@ namespace bdep
// Save the old path for diagnostics.
//
+ // @@ We should probably also adjust explicit and implicit links in the
+ // respective bpkg configurations, if/when bpkg provides the required
+ // API.
+ //
c->path.swap (path);
c->relative_path = move (rel_path);
@@ -567,7 +684,7 @@ namespace bdep
prj,
t,
false /* fallback_default */,
- false /* validate */));
+ false /* validate */).first);
if (cfgs.size () > 1)
fail << "multiple configurations specified for config rename";
@@ -625,7 +742,7 @@ namespace bdep
prj,
t,
false /* fallback_default */,
- false /* validate */));
+ false /* validate */).first);
for (const shared_ptr<configuration>& c: cfgs)
{
@@ -683,19 +800,46 @@ namespace bdep
prj,
t,
false /* fallback_default */,
- false /* validate */));
+ false /* validate */).first);
for (const shared_ptr<configuration>& c: cfgs)
{
using query = bdep::query<configuration>;
+ // Verify that there is no other default or forwarded configuration with
+ // the same package as us.
+ //
+ auto verify = [&c, &db] (const query& q, const char* what)
+ {
+ for (const shared_ptr<configuration>& o:
+ pointer_result (db.query<configuration> (q)))
+ {
+ auto i (find_first_of (
+ o->packages.begin (), o->packages.end (),
+ c->packages.begin (), c->packages.end (),
+ [] (const package_state& x, const package_state& y)
+ {
+ return x.name == y.name;
+ }));
+
+ if (i != o->packages.end ())
+ fail << "configuration " << *o << " is also " << what << " and "
+ << "also has package " << i->name << " initialized" <<
+ info << "while updating configuration " << *c;
+ }
+ };
+
if (d)
{
if (*d && !c->default_)
{
- if (auto p = db.query_one<configuration> (query::default_))
- fail << "configuration " << *p << " is already the default" <<
+ if (auto p = db.query_one<configuration> (query::default_ &&
+ query::type == c->type))
+ fail << "configuration " << *p << " of type " << p->type
+ << " is already the default" <<
info << "while updating configuration " << *c;
+
+ verify (query::default_, "default");
}
c->default_ = *d;
@@ -704,27 +848,7 @@ namespace bdep
if (f)
{
if (*f && !c->forward)
- {
- // Make sure there are no other forwarded configurations with the
- // same package as us.
- //
- for (const shared_ptr<configuration>& o:
- pointer_result (db.query<configuration> (query::forward)))
- {
- auto i (find_first_of (
- o->packages.begin (), o->packages.end (),
- c->packages.begin (), c->packages.end (),
- [] (const package_state& x, const package_state& y)
- {
- return x.name == y.name;
- }));
-
- if (i != o->packages.end ())
- fail << "configuration " << *o << " is also forwarded and "
- << "also has package " << i->name << " initialized" <<
- info << "while updating configuration " << *c;
- }
- }
+ verify (query::forward, "forwarded");
c->forward = *f;
}
@@ -768,6 +892,9 @@ namespace bdep
if (!c.add () && !c.create () && !c.set ())
fail << n << " not valid for this subcommand";
+ if (o.config_type_specified () && !c.create ())
+ fail << "--config-type is not valid for this subcommand";
+
if (o.existing () && !c.create ())
fail << "--existing|-e is not valid for this subcommand";
@@ -787,6 +914,7 @@ namespace bdep
//
if (c.add ()) return cmd_config_add (o, scan);
if (c.create ()) return cmd_config_create (o, scan);
+ if (c.link ()) return cmd_config_link (o, scan);
if (c.list ()) return cmd_config_list (o, scan);
if (c.move ()) return cmd_config_move (o, scan);
if (c.rename ()) return cmd_config_rename (o, scan);
diff --git a/bdep/config.hxx b/bdep/config.hxx
index 049f030..111ce15 100644
--- a/bdep/config.hxx
+++ b/bdep/config.hxx
@@ -12,13 +12,17 @@
namespace bdep
{
+ // If type is nullopt, then query the bpkg configuration type.
+ //
shared_ptr<configuration>
- cmd_config_add (const configuration_add_options&,
+ cmd_config_add (const common_options&,
+ const configuration_add_options&,
const dir_path& prj,
const package_locations&,
database&,
dir_path path,
optional<string> name,
+ optional<string> type,
optional<uint64_t> id = nullopt,
const char* what = "added");
@@ -31,6 +35,7 @@ namespace bdep
dir_path path,
const strings& args,
optional<string> name,
+ string type,
optional<uint64_t> id = nullopt);
int
diff --git a/bdep/database.cxx b/bdep/database.cxx
index 5e0aea5..064f9ed 100644
--- a/bdep/database.cxx
+++ b/bdep/database.cxx
@@ -8,6 +8,8 @@
#include <bdep/diagnostics.hxx>
+#include <bdep/project.hxx>
+#include <bdep/project-odb.hxx>
#include <bdep/database-views.hxx>
#include <bdep/database-views-odb.hxx>
@@ -18,6 +20,22 @@ namespace bdep
using namespace odb::sqlite;
using odb::schema_catalog;
+ // Register the data migration functions.
+ //
+ template <odb::schema_version v>
+ using migration_entry = odb::data_migration_entry<v, DB_SCHEMA_VERSION_BASE>;
+
+ static const migration_entry<2>
+ migrate_v2 ([] (odb::database& db)
+ {
+ for (const shared_ptr<configuration>& c:
+ pointer_result (db.query<configuration> ()))
+ {
+ c->type = "target";
+ db.update (c);
+ }
+ });
+
database
open (const dir_path& d, tracer& tr, bool create)
{
diff --git a/bdep/deinit.cli b/bdep/deinit.cli
index 6aad32c..e78cdbe 100644
--- a/bdep/deinit.cli
+++ b/bdep/deinit.cli
@@ -32,8 +32,8 @@ namespace bdep
If no project directory is specified, then the current working directory
is assumed. If no configuration is specified, then the default
- configuration is assumed. See \l{bdep-projects-configs(1)} for details on
- specifying projects and configurations.
+ configurations are assumed. See \l{bdep-projects-configs(1)} for details
+ on specifying projects and configurations.
"
}
diff --git a/bdep/deinit.cxx b/bdep/deinit.cxx
index 598efd5..0018aaf 100644
--- a/bdep/deinit.cxx
+++ b/bdep/deinit.cxx
@@ -113,32 +113,33 @@ namespace bdep
configurations cfgs;
{
transaction t (db.begin ());
- cfgs = find_configurations (o,
- prj,
- t,
- true /* fallback_default */,
- !force /* validate */);
+ pair<configurations, bool> cs (
+ find_configurations (o,
+ prj,
+ t,
+ true /* fallback_default */,
+ !force /* validate */));
t.commit ();
- }
- // If specified, verify packages are present in each configuration.
- //
- if (!pp.packages.empty ())
- verify_project_packages (pp, cfgs);
+ // If specified, verify packages are present in at least one
+ // configuration.
+ //
+ if (!pp.packages.empty ())
+ verify_project_packages (pp, cs);
+
+ cfgs = move (cs.first);
+ }
// If no packages were explicitly specified, then we deinitalize all that
- // have been initialized in each configuration.
+ // have been initialized in each configuration. Otherwise, we deinitalize
+ // only specified packages initialized in the (specified) configurations.
//
- strings pkgs;
+ const package_locations& pkgs (pp.packages);
- bool all (pp.packages.empty ());
- if (!all)
- {
- for (const package_location& p: pp.packages)
- pkgs.push_back (p.name.string ());
- }
+ bool all (pkgs.empty ());
- // Deinitialize in each configuration skipping empty ones.
+ // Deinitialize in each configuration, skipping those where no packages
+ // needs to be deinitialized.
//
// We do each configuration in a separate transaction so that our state
// reflects the bpkg configuration as closely as possible.
@@ -146,10 +147,36 @@ namespace bdep
bool first (true);
for (const shared_ptr<configuration>& c: cfgs)
{
- if (c->packages.empty ())
+ // Collect packages to deinitialize.
+ //
+ strings ps;
+
+ for (const package_state& s: c->packages)
+ {
+ if (all ||
+ find_if (pkgs.begin (),
+ pkgs.end (),
+ [&s] (const package_location& p)
+ {
+ return p.name == s.name;
+ }) != pkgs.end ())
+ ps.push_back (s.name.string ());
+ }
+
+ if (ps.empty ())
{
if (verb)
- info << "skipping empty configuration " << *c;
+ {
+ diag_record dr (info);
+
+ dr << "skipping configuration " << *c;
+
+ if (c->packages.empty ())
+ dr << info << "configuration is empty";
+ else
+ dr << info << "none of specified packages initialized in this "
+ << "configuration";
+ }
continue;
}
@@ -167,41 +194,33 @@ namespace bdep
transaction t (db.begin ());
- // Collect packages to drop and remove them from the configuration.
+ // Remove collected packages from the configuration.
//
- if (all)
- {
- pkgs.clear ();
-
- for (const package_state& p: c->packages)
- pkgs.push_back (p.name.string ());
- }
-
c->packages.erase (
remove_if (c->packages.begin (),
c->packages.end (),
- [&pkgs] (const package_state& p)
+ [&ps] (const package_state& p)
{
- return find_if (pkgs.begin (),
- pkgs.end (),
+ return find_if (ps.begin (),
+ ps.end (),
[&p] (const string& n)
{
return p.name == n;
- }) != pkgs.end ();
+ }) != ps.end ();
}),
c->packages.end ());
// If we are deinitializing multiple packages, print their names.
//
- if (verb && pkgs.size () > 1)
+ if (verb && ps.size () > 1)
{
- for (const string& n: pkgs)
+ for (const string& n: ps)
text << "deinitializing package " << n;
}
// The same story as in init with regard to the state update order.
//
- cmd_deinit (o, prj, c, pkgs);
+ cmd_deinit (o, prj, c, ps);
db.update (c);
t.commit ();
diff --git a/bdep/fetch.cli b/bdep/fetch.cli
index 4349bdd..bfd9c53 100644
--- a/bdep/fetch.cli
+++ b/bdep/fetch.cli
@@ -29,8 +29,8 @@ namespace bdep
If no project or package directory is specified, then the current working
directory is assumed. If no configuration is specified, then the default
- configuration is assumed. See \l{bdep-projects-configs(1)} for details on
- specifying projects and configurations.
+ configurations are assumed. See \l{bdep-projects-configs(1)} for details
+ on specifying projects and configurations.
If the \cb{--full|-F} option is specified, then instead \cb{fetch}
performs a full re-fetch of all the repositories added to the
diff --git a/bdep/fetch.cxx b/bdep/fetch.cxx
index 93a727f..96bfd4b 100644
--- a/bdep/fetch.cxx
+++ b/bdep/fetch.cxx
@@ -40,7 +40,7 @@ namespace bdep
database db (open (prj, trace));
transaction t (db.begin ());
- cfgs = find_configurations (o, prj, t);
+ cfgs = find_configurations (o, prj, t).first;
t.commit ();
}
diff --git a/bdep/init.cli b/bdep/init.cli
index c8616c3..658c81e 100644
--- a/bdep/init.cli
+++ b/bdep/init.cli
@@ -42,10 +42,11 @@ namespace bdep
If no project directory is specified, then the current working directory
is assumed. If no configuration is specified, then the default
- configuration is assumed. See \l{bdep-projects-configs(1)} for details on
- specifying projects and configurations. Optional <pkg-args> are the
- additional dependency packages and/or configuration variables to pass
- to the underlying \l{bpkg-pkg-build(1)} command.
+ configuration is assumed (failing if multiple default configurations are
+ present). See \l{bdep-projects-configs(1)} for details on specifying
+ projects and configurations. Optional <pkg-args> are the additional
+ dependency packages and/or configuration variables to pass to the
+ underlying \l{bpkg-pkg-build(1)} command.
The second form (\cb{--empty} is specified) initializes an empty project
database that can later be used to first add build configurations
diff --git a/bdep/init.cxx b/bdep/init.cxx
index a3f0859..2dbc1bb 100644
--- a/bdep/init.cxx
+++ b/bdep/init.cxx
@@ -53,7 +53,7 @@ namespace bdep
const dir_path& cfg,
const strings& args,
bool ca,
- bool cc)
+ optional<string> cc)
{
const char* m (!ca ? "--config-create" :
!cc ? "--config-add" : nullptr);
@@ -66,8 +66,25 @@ namespace bdep
cmd_config_validate_add (o, m, nm, id);
return ca
- ? cmd_config_add ( ao, prj, ps, db, cfg, move (nm), move (id))
- : cmd_config_create (o, ao, prj, ps, db, cfg, args, move (nm), move (id));
+ ? cmd_config_add (o,
+ ao,
+ prj,
+ ps,
+ db,
+ cfg,
+ move (nm),
+ nullopt /* type */,
+ move (id))
+ : cmd_config_create (o,
+ ao,
+ prj,
+ ps,
+ db,
+ cfg,
+ args,
+ move (nm),
+ move (*cc),
+ move (id));
}
void
@@ -79,6 +96,91 @@ namespace bdep
const strings& pkg_args,
bool sync)
{
+ // Return true if a package is initialized in the specified configuration.
+ //
+ auto initialized = [] (const package_location& p,
+ const shared_ptr<configuration>& c)
+ {
+ return find_if (c->packages.begin (),
+ c->packages.end (),
+ [&p] (const package_state& s)
+ {
+ return p.name == s.name;
+ }) != c->packages.end ();
+ };
+
+ // Verify that as a result of this operation, none of the packages will be
+ // initialized in multiple default or forwarded configurations and fail if
+ // that's not the case.
+ //
+ // Note that we perform verification in a separate loop to make sure that
+ // no actual bpkg commands are executed and no database changes are
+ // committed by the time of potential failure.
+ //
+ {
+ transaction t (db.begin ());
+
+ // For the sake of simplicity, add packages to the configuration
+ // objects, updating their state in the database (so that the changes
+ // are seen by the queries) and rollback the transaction in the
+ // end. Note that by doing so, we can end up modifying passed
+ // configuration objects and then failing, which is probably ok.
+ //
+ for (const shared_ptr<configuration>& c: cfgs)
+ {
+ for (const package_location& p: pkgs)
+ {
+ // Skip the package if it is already initialized in this
+ // configuration.
+ //
+ if (initialized (p, c))
+ continue;
+
+ // Verify that there is no other default or forwarded configuration
+ // that also has this package.
+ //
+ using query = bdep::query<configuration>;
+
+ auto verify = [&c, &p, &db, &initialized] (const query& q,
+ const char* what)
+ {
+ for (const shared_ptr<configuration>& o:
+ pointer_result (db.query<configuration> (q)))
+ {
+ if (initialized (p, o))
+ {
+ // Differ, since the package is not initialized in `c` (see
+ // above).
+ //
+ assert (o->id != c->id);
+
+ fail << what << " configuration " << *o << " also has package "
+ << p.name << " initialized" <<
+ info << "while initializing in " << what << " configuration "
+ << *c <<
+ info << "specify packages and configurations explicitly";
+ }
+ }
+ };
+
+ if (c->default_)
+ verify (query::default_, "default");
+
+ if (c->forward)
+ verify (query::forward, "forwarded");
+
+ c->packages.push_back (package_state {p.name});
+ }
+
+ db.update (c);
+ }
+
+ t.rollback ();
+ }
+
+ // Now, execute the actual bpkg commands and update configurations for
+ // real.
+ //
// We do each configuration in a separate transaction so that our state
// reflects the bpkg configuration as closely as possible.
//
@@ -108,14 +210,15 @@ namespace bdep
transaction t (db.begin ());
+ // Reload the configuration object that could have been changed during
+ // verification. This is required for skipping the already initialized
+ // packages.
+ //
+ db.reload (*c);
+
for (const package_location& p: pkgs)
{
- if (find_if (c->packages.begin (),
- c->packages.end (),
- [&p] (const package_state& s)
- {
- return p.name == s.name;
- }) != c->packages.end ())
+ if (initialized (p, c))
{
if (verb)
info << "package " << p.name << " is already initialized";
@@ -123,38 +226,11 @@ namespace bdep
continue;
}
- // If this configuration is forwarded, verify there is no other
- // forwarded configuration that also has this package.
- //
- if (c->forward)
- {
- using query = bdep::query<configuration>;
-
- for (const shared_ptr<configuration>& o:
- pointer_result (db.query<configuration> (query::forward)))
- {
- if (o == c)
- continue;
-
- if (find_if (o->packages.begin (),
- o->packages.end (),
- [&p] (const package_state& s)
- {
- return p.name == s.name;
- }) != o->packages.end ())
- {
- fail << "forwarded configuration " << *o << " also has package "
- << p.name << " initialized" <<
- info << "while initializing in forwarded configuration " << *c;
- }
- }
- }
-
// If we are initializing multiple packages or there will be no sync,
// print their names.
//
if (verb && (pkgs.size () > 1 || !sync))
- text << "initializing package " << p.name;;
+ text << "initializing package " << p.name;
c->packages.push_back (package_state {p.name});
}
@@ -190,7 +266,12 @@ namespace bdep
tracer trace ("init");
bool ca (o.config_add_specified ());
- bool cc (o.config_create_specified ());
+
+ // Type of configuration being created, if --config-create is specified.
+ //
+ optional<string> cc (o.config_create_specified ()
+ ? o.config_type ()
+ : optional<string> ());
if (o.empty ())
{
@@ -204,6 +285,9 @@ namespace bdep
if (!ca && !cc)
fail << n << " specified without --config-(add|create)";
+ if (o.config_type_specified () && !cc)
+ fail << "--config-type specified without --config-create";
+
if (o.existing () && !cc)
fail << "--existing|-e specified without --config-create";
@@ -243,11 +327,6 @@ namespace bdep
configurations cfgs;
{
- // Make sure everyone refers to the same objects across all the
- // transactions.
- //
- session s;
-
// --config-add/create
//
if (ca || cc)
@@ -272,7 +351,7 @@ namespace bdep
ca ? o.config_add () : o.config_create (),
cfg_args,
ca,
- cc));
+ move (cc)));
}
else
{
@@ -280,7 +359,7 @@ namespace bdep
// wants us to use.
//
transaction t (db.begin ());
- cfgs = find_configurations (o, prj, t);
+ cfgs = find_configurations (o, prj, t).first;
t.commit ();
}
}
diff --git a/bdep/init.hxx b/bdep/init.hxx
index 6a2afd2..fff5f84 100644
--- a/bdep/init.hxx
+++ b/bdep/init.hxx
@@ -23,7 +23,7 @@ namespace bdep
const dir_path& cfg,
const strings& cfg_args,
bool config_add_specified,
- bool config_create_specified);
+ optional<string> config_create_type);
// Initialize each package in each configuration skipping those that are
// already initialized. Then synchronize each configuration unless sync
diff --git a/bdep/new.cxx b/bdep/new.cxx
index b512497..5998630 100644
--- a/bdep/new.cxx
+++ b/bdep/new.cxx
@@ -242,7 +242,12 @@ cmd_new (cmd_new_options&& o, cli::group_scanner& args)
// Validate options.
//
bool ca (o.config_add_specified ());
- bool cc (o.config_create_specified ());
+
+ // Type of configuration being created, if --config-create is specified.
+ //
+ optional<string> cc (o.config_create_specified ()
+ ? o.config_type ()
+ : optional<string> ());
if (o.subdirectory ())
fail << "--subdirectory was renamed to --source";
@@ -271,6 +276,9 @@ cmd_new (cmd_new_options&& o, cli::group_scanner& args)
if (!ca && !cc)
fail << n << " specified without --config-(add|create)";
+ if (o.config_type_specified () && !cc)
+ fail << "--config-type specified without --config-create";
+
if (o.existing () && !cc)
fail << "--existing|-e specified without --config-create";
@@ -3159,7 +3167,7 @@ cmd_new (cmd_new_options&& o, cli::group_scanner& args)
ca ? o.config_add () : o.config_create (),
cfg_args,
ca,
- cc)};
+ move (cc))};
cmd_init (o, prj, db, cfgs, pkgs, strings () /* pkg_args */);
}
diff --git a/bdep/project.cli b/bdep/project.cli
index 1b6c7aa..17ef72e 100644
--- a/bdep/project.cli
+++ b/bdep/project.cli
@@ -11,6 +11,14 @@ namespace bdep
//
class configuration_add_options
{
+ string --config-type = "target"
+ {
+ "<type>",
+ "The type of the configuration being created. By default, configuration
+ of type \cb{target} is created. See \l{bpkg-cfg-create(1)} for
+ background on configuration types."
+ }
+
bool --default
{
"Make the added or created configuration the default."
diff --git a/bdep/project.cxx b/bdep/project.cxx
index 7190045..ace8e3b 100644
--- a/bdep/project.cxx
+++ b/bdep/project.cxx
@@ -16,7 +16,7 @@ using namespace butl;
namespace bdep
{
- configurations
+ pair<configurations, bool>
find_configurations (const project_options& po,
const dir_path& prj,
transaction& t,
@@ -24,6 +24,7 @@ namespace bdep
bool validate)
{
configurations r;
+ bool fallback (false);
// Weed out duplicates.
//
@@ -99,12 +100,16 @@ namespace bdep
{
if (fallback_default)
{
- if (auto c = db.query_one<configuration> (query::default_))
+ for (shared_ptr<configuration> c:
+ pointer_result (db.query<configuration> (query::default_)))
add (move (c));
- else
+
+ if (r.empty ())
fail << "no default configuration in project " << prj <<
info << "use (@<cfg-name> | --config|-c <cfg-dir> | --all|-a) to "
- << "specify configuration explicitly";
+ << "specify configuration explicitly";
+
+ fallback = true;
}
else
fail << "no configurations specified";
@@ -123,7 +128,7 @@ namespace bdep
}
}
- return r;
+ return make_pair (move (r), fallback);
}
project_package
@@ -400,23 +405,39 @@ namespace bdep
void
verify_project_packages (const project_packages& pp,
- const configurations& cfgs)
+ const pair<configurations, bool>& cfgs)
{
- for (const shared_ptr<configuration>& c: cfgs)
+ for (const package_location& p: pp.packages)
{
- for (const package_location& p: pp.packages)
+ bool init (false);
+
+ for (const shared_ptr<configuration>& c: cfgs.first)
{
if (find_if (c->packages.begin (),
c->packages.end (),
[&p] (const package_state& s)
{
return p.name == s.name;
- }) == c->packages.end ())
+ }) != c->packages.end ())
{
- fail << "package " << p.name << " is not initialized "
- << "in configuration " << *c;
+ init = true;
+ break;
}
}
+
+ if (!init)
+ {
+ diag_record dr (fail);
+
+ dr << "package " << p.name << " is not initialized in ";
+
+ if (cfgs.second)
+ dr << "any default configuration(s)";
+ else if (cfgs.first.size () == 1)
+ dr << "configuration " << *cfgs.first.front ();
+ else
+ dr << "any specified configurations";
+ }
}
}
diff --git a/bdep/project.hxx b/bdep/project.hxx
index 86b833f..5c6be87 100644
--- a/bdep/project.hxx
+++ b/bdep/project.hxx
@@ -15,7 +15,11 @@
#include <bdep/project-options.hxx>
-#pragma db model version(1, 1, closed)
+// Used by the data migration entries.
+//
+#define DB_SCHEMA_VERSION_BASE 1
+
+#pragma db model version(DB_SCHEMA_VERSION_BASE, 2, closed)
// Prevent assert() macro expansion in get/set expressions. This should appear
// after all #include directives since the assert() macro is redefined in each
@@ -85,6 +89,7 @@ namespace bdep
//
optional_uint64_t id;
optional_string name;
+ string type;
dir_path path;
optional_dir_path relative_path;
@@ -122,6 +127,7 @@ namespace bdep
//
configuration (optional_uint64_t i,
optional_string n,
+ string t,
dir_path p,
optional_dir_path rp,
bool d,
@@ -130,6 +136,7 @@ namespace bdep
vector<package_state> ps)
: id (i),
name (move (n)),
+ type (move (t)),
path (move (p)),
relative_path (move (rp)),
default_ (d),
@@ -166,12 +173,15 @@ namespace bdep
// Given the project directory, database, and options resolve all the
// mentioned configurations or, unless fallback_default is false, find the
- // default configuration if none were mentioned. Unless validate is false,
+ // default configurations if none were mentioned. Unless validate is false,
// also validate that the configuration directories still exist.
//
+ // Besides configurations, also return an indication if they are retrieved
+ // as a fallback to default configurations (true if that's the case).
+ //
using configurations = vector<shared_ptr<configuration>>;
- configurations
+ pair<configurations, bool>
find_configurations (const project_options&,
const dir_path& prj,
transaction&,
@@ -255,10 +265,14 @@ namespace bdep
return find_project_packages (o, true /* ignore_packages */).project;
}
- // Verify all the packages are present in all the configurations.
+ // Verify that each package is present in at least one configuration.
+ //
+ // Note that the default configurations fallback indication (see above) is
+ // only used for diagnostics.
//
void
- verify_project_packages (const project_packages&, const configurations&);
+ verify_project_packages (const project_packages&,
+ const pair<configurations, bool>&);
// Determine the version of a package in the specified package (first
// version) or configuration (second version) directory.
diff --git a/bdep/project.xml b/bdep/project.xml
index e69af8b..805d741 100644
--- a/bdep/project.xml
+++ b/bdep/project.xml
@@ -1,4 +1,10 @@
<changelog xmlns="http://www.codesynthesis.com/xmlns/odb/changelog" database="sqlite" version="1">
+ <changeset version="2">
+ <alter-table name="configuration">
+ <add-column name="type" type="TEXT" null="true"/>
+ </alter-table>
+ </changeset>
+
<model version="1">
<table name="configuration" kind="object">
<column name="id" type="INTEGER" null="true"/>
diff --git a/bdep/projects-configs.cli b/bdep/projects-configs.cli
index 72b9736..a5c5808 100644
--- a/bdep/projects-configs.cli
+++ b/bdep/projects-configs.cli
@@ -58,11 +58,12 @@ include <bdep/common-options.hxx>;
\cb{packages.manifest}).
A project managed by \cb{bdep} has one or more associated build
- configurations (see \l{bdep-config(1)} for details). One of these
- configurations can be designated as the default and used if no configuration
- is specified explicitly. So, for example, running \cb{status} without any
- arguments in the project directory will show the status of all the project
- packages initialized in the default configuration.
+ configurations (see \l{bdep-config(1)} for details). Some of these
+ configurations, one per the configuration type, can be designated as default
+ and used if no configuration is specified explicitly. So, for example,
+ running \cb{status} without any arguments in the project directory will show
+ the status of all the project packages initialized in the default
+ configurations.
An associated build configuration can be assigned a name in which case we
can specify it using the \c{\b{@}\i{cfg-name}} notation. For example:
diff --git a/bdep/publish.cli b/bdep/publish.cli
index d8ecb82..42504ac 100644
--- a/bdep/publish.cli
+++ b/bdep/publish.cli
@@ -23,7 +23,7 @@ namespace bdep
\c{<pkg-spec> = (\b{--directory}|\b{-d} <pkg-dir>)... | <prj-spec>\n
<prj-spec> = \b{--directory}|\b{-d} <prj-dir>\n
- <cfg-spec> = \b{@}<cfg-name> | \b{--config}|\b{-c} <cfg-dir> | \b{--forward}}
+ <cfg-spec> = (\b{@}<cfg-name> | \b{--config}|\b{-c} <cfg-dir>)... | \b{--all}|\b{-a} | \b{--forward}}
\h|DESCRIPTION|
@@ -32,7 +32,7 @@ namespace bdep
If no project or package directory is specified, then the current working
directory is assumed. If no configuration is specified, then the default
- configuration is used to prepare the package distributions. If the
+ configurations are used to prepare the package distributions. If the
specified directory is a project directory, then all the packages in the
project are published. See \l{bdep-projects-configs(1)} for details on
specifying projects and configurations.
diff --git a/bdep/publish.cxx b/bdep/publish.cxx
index d39cbcc..75c38d8 100644
--- a/bdep/publish.cxx
+++ b/bdep/publish.cxx
@@ -48,16 +48,18 @@ namespace bdep
info << "use --control to specify explicitly" << endf;
}
- // If cfg is empty, then use each package's (forwarded) source directory.
+ // Distribute packages in the specified (per-package) directories.
//
static int
cmd_publish (const cmd_publish_options& o,
const dir_path& prj,
- const dir_path& cfg,
- package_locations&& pkg_locs)
+ package_locations&& pkg_locs,
+ dir_paths&& dist_dirs)
{
using bpkg::package_manifest;
+ assert (pkg_locs.size () == dist_dirs.size ()); // Parallel vectors.
+
const url& repo (o.repository ());
// Control repository URL.
@@ -125,7 +127,7 @@ namespace bdep
struct package
{
package_name name;
- dir_path path;
+ dir_path dist_dir;
standard_version version;
package_name project;
string section; // alpha|beta|stable (or --section)
@@ -158,14 +160,14 @@ namespace bdep
info << "use --force=uncommitted to publish anyway";
}
- for (package_location& pl: pkg_locs)
+ for (size_t i (0); i != pkg_locs.size (); ++i)
{
- package_name n (move (pl.name));
- package_name p (pl.project ? move (*pl.project) : n);
+ package_location& pl (pkg_locs[i]);
- standard_version v (cfg.empty ()
- ? package_version (o, prj / pl.path)
- : package_version (o, cfg, n));
+ package_name n (move (pl.name));
+ package_name p (pl.project ? move (*pl.project) : n);
+ dir_path d (move (dist_dirs[i]));
+ standard_version v (package_version (o, d));
// Should we allow publishing snapshots and, if so, to which section?
// For example, is it correct to consider a "between betas" snapshot a
@@ -204,7 +206,7 @@ namespace bdep
v.beta () ? "beta" : "stable");
pkgs.push_back (package {move (n),
- move (pl.path),
+ move (d),
move (v),
move (p),
move (s),
@@ -269,13 +271,10 @@ namespace bdep
// build2's version module by default does not allow distribution of
// uncommitted projects.
//
- dir_path d (cfg.empty ()
- ? prj / p.path
- : dir_path (cfg) /= p.name.string ());
run_b (
o,
"dist:",
- "'" + d.representation () + "'",
+ "'" + p.dist_dir.representation () + "'",
"config.dist.root='" + dr.representation () + "'",
"config.dist.archives=tar.gz",
"config.dist.checksums=sha256",
@@ -858,16 +857,17 @@ namespace bdep
const dir_path& prj (pp.project);
- // Unless we are using the forwarded configurations, we need a single
- // configuration to prepare package distributions.
+ // Collect directories to distribute the packages in. In the forward mode
+ // the packages are distributed in the package's (forwarded) source
+ // directories and in their configuration directories otherwise.
//
- dir_path cfg_dir;
+ dir_paths dist_dirs;
if (o.forward ())
{
// Note: in this case we don't even open the database.
//
- dir_paths cfgs;
+ dir_paths cfgs; // Configuration directories to sync.
for (const package_location& pl: pp.packages)
{
@@ -883,6 +883,8 @@ namespace bdep
//
(pi.out_root /= pi.amalgamation).normalize ();
+ dist_dirs.push_back (move (d));
+
if (find (cfgs.begin (), cfgs.end (), pi.out_root) == cfgs.end ())
cfgs.push_back (move (pi.out_root));
}
@@ -895,31 +897,66 @@ namespace bdep
}
else
{
- shared_ptr<configuration> cfg;
+ configurations cfgs;
{
// Don't keep the database open longer than necessary.
//
database db (open (prj, trace));
transaction t (db.begin ());
- configurations cfgs (find_configurations (o, prj, t));
+ cfgs = find_configurations (o, prj, t).first;
t.commit ();
+ }
- if (cfgs.size () > 1)
- fail << "multiple configurations specified for publish";
+ // Configurations to sync.
+ //
+ // We could probably unify syncing configuration directories with the
+ // forward mode, however configuration name-based progress indication
+ // feels preferable for the common case.
+ //
+ configurations scs;
- // Verify packages are present in the configuration.
- //
- verify_project_packages (pp, cfgs);
+ // Besides collecting the package directories and configurations to
+ // sync, also verify that for each package being published only one
+ // configuration, it is initialized in, is specified.
+ //
+ for (const package_location& p: pp.packages)
+ {
+ shared_ptr<configuration> pc;
- cfg = move (cfgs[0]);
- }
+ for (const shared_ptr<configuration>& c: cfgs)
+ {
+ if (find_if (c->packages.begin (),
+ c->packages.end (),
+ [&p] (const package_state& s)
+ {
+ return p.name == s.name;
+ }) != c->packages.end ())
+ {
+ if (pc != nullptr)
+ fail << "package " << p.name << " is initialized in multiple "
+ << "specified configurations" <<
+ info << *pc <<
+ info << *c;
+
+ pc = c;
+ }
+ }
+
+ if (pc == nullptr)
+ fail << "package " << p.name << " is not initialized in any "
+ << "configuration";
- cmd_sync (o, prj, cfg, strings () /* pkg_args */, true /* implicit */);
+ dist_dirs.push_back (dir_path (pc->path) /= p.name.string ());
+
+ if (find (scs.begin (), scs.end (), pc) == scs.end ())
+ scs.push_back (move (pc));
+ }
- cfg_dir = cfg->path;
+ for (const shared_ptr<configuration>& c: scs)
+ cmd_sync (o, prj, c, strings () /* pkg_args */, true /* implicit */);
}
- return cmd_publish (o, prj, cfg_dir, move (pp.packages));
+ return cmd_publish (o, prj, move (pp.packages), move (dist_dirs));
}
}
diff --git a/bdep/status.cli b/bdep/status.cli
index 39688cb..38e70e0 100644
--- a/bdep/status.cli
+++ b/bdep/status.cli
@@ -32,8 +32,8 @@ namespace bdep
If no project or package directory is specified, then the current working
directory is assumed. If no configuration is specified, then the default
- configuration is assumed. See \l{bdep-projects-configs(1)} for details on
- specifying projects and configurations.
+ configurations are assumed. See \l{bdep-projects-configs(1)} for details
+ on specifying projects and configurations.
If no <dep-spec> arguments are specified, then \cb{status} prints the
status of the project's packages. Otherwise, the status of the specified
diff --git a/bdep/status.cxx b/bdep/status.cxx
index 2e60b29..fc07698 100644
--- a/bdep/status.cxx
+++ b/bdep/status.cxx
@@ -50,34 +50,6 @@ namespace bdep
pkgs);
}
- static void
- cmd_status (const cmd_status_options& o,
- const dir_path& prj,
- const shared_ptr<configuration>& 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.
- //
- strings pkgs;
-
- if (ps.empty ())
- {
- for (const package_state& p: c->packages)
- pkgs.push_back (p.name.string ());
- }
- else
- {
- for (const package_location& p: ps)
- pkgs.push_back (p.name.string ());
- }
-
- cmd_status (o, prj, c->path, pkgs, fetch);
- }
-
int
cmd_status (const cmd_status_options& o, cli::scanner& args)
{
@@ -103,16 +75,23 @@ namespace bdep
database db (open (prj, trace));
- transaction t (db.begin ());
- configurations cfgs (find_configurations (o, prj, t));
- t.commit ();
+ configurations cfgs;
+ {
+ transaction t (db.begin ());
+ pair<configurations, bool> cs (find_configurations (o, prj, t));
+ t.commit ();
- // If specified, verify packages are present in each configuration.
- //
- if (!pp.packages.empty ())
- verify_project_packages (pp, cfgs);
+ // If specified, verify packages are present in at least one
+ // configuration.
+ //
+ if (!pp.packages.empty ())
+ verify_project_packages (pp, cs);
+
+ cfgs = move (cs.first);
+ }
- // Print status in each configuration skipping empty ones.
+ // Print status in each configuration, skipping those where no package
+ // statuses needs to be printed.
//
bool first (true);
for (const shared_ptr<configuration>& c: cfgs)
@@ -120,11 +99,50 @@ namespace bdep
if (c->packages.empty ())
{
if (verb)
- info << "skipping empty configuration " << *c;
+ info << "skipping configuration " << *c <<
+ info << "configuration is empty";
continue;
}
+ // Collect the packages to print, unless the dependency packages are
+ // specified.
+ //
+ // If no packages were explicitly specified, then we print the status
+ // for all that have been initialized in the configuration. Otherwise,
+ // only for specified packages initialized in the (specified)
+ // configurations.
+ //
+ strings pkgs;
+
+ if (dep_pkgs.empty ())
+ {
+ const package_locations& ps (pp.packages);
+ bool all (ps.empty ());
+
+ for (const package_state& s: c->packages)
+ {
+ if (all ||
+ find_if (ps.begin (),
+ ps.end (),
+ [&s] (const package_location& p)
+ {
+ return p.name == s.name;
+ }) != ps.end ())
+ pkgs.push_back (s.name.string ());
+ }
+
+ if (pkgs.empty ())
+ {
+ if (verb)
+ info << "skipping configuration " << *c <<
+ info << "none of specified packages initialized in this "
+ << "configuration";
+
+ continue;
+ }
+ }
+
// If we are printing multiple configurations, separate them with a
// blank line and print the configuration name/directory.
//
@@ -141,10 +159,12 @@ namespace bdep
if (fetch)
cmd_fetch (o, prj, c, o.fetch_full ());
- if (dep_pkgs.empty ())
- cmd_status (o, prj, c, pp.packages, !fetch);
- else
- cmd_status (o, prj, c->path, dep_pkgs, !fetch);
+ // Status for either packages or their dependencies must be printed, but
+ // not for both.
+ //
+ assert (pkgs.empty () == !dep_pkgs.empty ());
+
+ cmd_status (o, prj, c->path, !pkgs.empty () ? pkgs : dep_pkgs, !fetch);
}
return 0;
diff --git a/bdep/sync.cli b/bdep/sync.cli
index 8f806b6..07c46a2 100644
--- a/bdep/sync.cli
+++ b/bdep/sync.cli
@@ -41,8 +41,8 @@ namespace bdep
If no project or package directory is specified, then the current working
directory is assumed. If no configuration is specified, then the default
- configuration is assumed. See \l{bdep-projects-configs(1)} for details on
- specifying projects and configurations. Optional <pkg-args> are the
+ configurations are assumed. See \l{bdep-projects-configs(1)} for details
+ on specifying projects and configurations. Optional <pkg-args> are the
additional dependency packages and/or configuration variables to pass to
the underlying \l{bpkg-pkg-build(1)} command.
diff --git a/bdep/sync.cxx b/bdep/sync.cxx
index d47cd6c..0d5132f 100644
--- a/bdep/sync.cxx
+++ b/bdep/sync.cxx
@@ -188,7 +188,7 @@ namespace bdep
// 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.
+ // upgrading specific dependency packages. Otherwise -- project packages.
//
static void
cmd_sync (const common_options& co,
@@ -743,12 +743,14 @@ namespace bdep
if (o.directory_specified () || !o.implicit ())
{
// We could be running from a package directory (or the user specified
- // one 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 is false).
+ // one with -d) that has not been init'ed in this configuration. This,
+ // however, doesn't really matter since the specified packages are only
+ // used to determine which configuration package dependencies needs to
+ // be ugraded (see cmd_sync() for details).
+ //
+ // 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
+ // is false).
//
project_packages pp (
find_project_packages (o,
@@ -761,21 +763,24 @@ namespace bdep
// Load project configurations.
//
+ pair<configurations, bool> cs;
{
database db (open (pp.project, trace));
transaction t (db.begin ());
- cfgs = find_configurations (o, pp.project, t);
+ cs = find_configurations (o, pp.project, t);
t.commit ();
}
- // If specified, verify packages are present in each configuration.
+ // If specified, verify packages are present in at least one
+ // configuration.
//
if (!pp.packages.empty ())
- verify_project_packages (pp, cfgs);
+ verify_project_packages (pp, cs);
prj = move (pp.project);
prj_pkgs = move (pp.packages);
+ cfgs = move (cs.first);
}
else
{
@@ -838,7 +843,8 @@ namespace bdep
if (c != nullptr && c->packages.empty ())
{
if (verb)
- info << "skipping empty configuration " << *c;
+ info << "skipping configuration " << *c <<
+ info << "configuration is empty";
continue;
}
@@ -857,6 +863,11 @@ namespace bdep
if (!dep_pkgs.empty ())
{
+ // We ignore the project packages if the dependencies are specified
+ // explicitly (see the above find_project_packages() call).
+ //
+ assert (prj_pkgs.empty ());
+
// The third form: upgrade of the specified dependencies.
//
// Only prompt if upgrading their dependencies.
@@ -873,7 +884,7 @@ namespace bdep
!o.patch (), // Upgrade by default unless patch requested.
(o.recursive () ? optional<bool> (true) :
o.immediate () ? optional<bool> (false) : nullopt),
- prj_pkgs,
+ package_locations () /* prj_pkgs */,
dep_pkgs);
}
else if (o.upgrade () || o.patch ())
diff --git a/bdep/test.cli b/bdep/test.cli
index 18c9b04..a283b1b 100644
--- a/bdep/test.cli
+++ b/bdep/test.cli
@@ -41,9 +41,9 @@ namespace bdep
If no project or package directory is specified, then the current working
directory is assumed. If no configuration is specified, then the default
- configuration is assumed. See \l{bdep-projects-configs(1)} for details on
- specifying projects and configurations. Optional \c{\i{cfg-var}...} are
- the additional configuration variables to pass to the build system.
+ configurations are assumed. See \l{bdep-projects-configs(1)} for details
+ on specifying projects and configurations. Optional \c{\i{cfg-var}...}
+ are the additional configuration variables to pass to the build system.
"
}
diff --git a/bdep/update.cli b/bdep/update.cli
index 4a66298..fc3df84 100644
--- a/bdep/update.cli
+++ b/bdep/update.cli
@@ -41,9 +41,9 @@ namespace bdep
If no project or package directory is specified, then the current working
directory is assumed. If no configuration is specified, then the default
- configuration is assumed. See \l{bdep-projects-configs(1)} for details on
- specifying projects and configurations. Optional \c{\i{cfg-var}...} are
- the additional configuration variables to pass to the build system.
+ configurations are assumed. See \l{bdep-projects-configs(1)} for details
+ on specifying projects and configurations. Optional \c{\i{cfg-var}...}
+ are the additional configuration variables to pass to the build system.
"
}
diff --git a/tests/ci.testscript b/tests/ci.testscript
index d0407b5..bc3174f 100644
--- a/tests/ci.testscript
+++ b/tests/ci.testscript
@@ -102,7 +102,11 @@ windows = ($cxx.target.class == 'windows')
$init -C @cfg1 &prj-cfg1/***;
$init -C @cfg2 &prj-cfg2/***;
- $* --all 2>'error: multiple configurations specified for ci' != 0
+ $* --all 2>>EOE != 0
+ error: package prj is initialized in multiple specified configurations
+ info: @cfg1
+ info: @cfg2
+ EOE
}
: no-commits
@@ -393,6 +397,26 @@ windows = ($cxx.target.class == 'windows')
EOE
}
+ : diff-configs
+ :
+ {
+ $clone_prj;
+ $init -C @cfg1 -d prj/libprj &prj-cfg1/***;
+
+ # While at it, test that we fail for uninitialized package.
+ #
+ $* -d prj/prj 2>>EOE != 0;
+ error: package prj is not initialized in any configuration
+ EOE
+
+ $init -C @cfg2 --config-type host -d prj/prj &prj-cfg2/***;
+
+ $* 2>>~%EOE%
+ %CI request is queued.*%
+ %reference: .+%
+ EOE
+ }
+
: single
:
{
diff --git a/tests/config.testscript b/tests/config.testscript
index db02947..cb8ed7e 100644
--- a/tests/config.testscript
+++ b/tests/config.testscript
@@ -22,10 +22,10 @@ deinit += -d prj
$clone_root_prj;
$* create @cfg cfg-dir $config_cxx 2>>/"EOE" &cfg-dir/***;
- created configuration @cfg $~/cfg-dir/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/cfg-dir/ 1 target default,forwarded,auto-synchronized
EOE
- $status 2>'error: package prj is not initialized in configuration @cfg' != 0;
+ $status 2>'error: package prj is not initialized in any default configuration(s)' != 0;
$init @cfg 2>>/~"%EOE%";
initializing in project $~/prj/
@@ -36,7 +36,7 @@ deinit += -d prj
$status >'prj configured 0.1.0-a.0.19700101000000';
$* list @cfg >>/"EOO";
- @cfg $~/cfg-dir/ 1 default,forwarded,auto-synchronized
+ @cfg $~/cfg-dir/ 1 target default,forwarded,auto-synchronized
EOO
$update @cfg 2>>~%EOE%;
@@ -56,7 +56,7 @@ deinit += -d prj
$clone_root_prj;
$* create -- @cfg $config_cxx 2>>/"EOE" &prj-cfg/***;
- created configuration @cfg $~/prj-cfg/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/prj-cfg/ 1 target default,forwarded,auto-synchronized
EOE
$init @cfg 2>>/~"%EOE%";
@@ -68,7 +68,7 @@ deinit += -d prj
$status >'prj configured 0.1.0-a.0.19700101000000';
$* list >>/"EOO";
- @cfg $~/prj-cfg/ 1 default,forwarded,auto-synchronized
+ @cfg $~/prj-cfg/ 1 target default,forwarded,auto-synchronized
EOO
$update @cfg 2>>~%EOE%;
@@ -88,7 +88,7 @@ deinit += -d prj
$clone_root_prj;
$* create cfg $config_cxx 2>>/"EOE" &cfg/***;
- created configuration $~/cfg/ 1 default,forwarded,auto-synchronized
+ created configuration $~/cfg/ 1 target default,forwarded,auto-synchronized
EOE
$init -c cfg 2>>/~"%EOE%";
@@ -100,7 +100,7 @@ deinit += -d prj
$status >'prj configured 0.1.0-a.0.19700101000000';
$* list >>/"EOO";
- $~/cfg/ 1 default,forwarded,auto-synchronized
+ $~/cfg/ 1 target default,forwarded,auto-synchronized
EOO
$update -c cfg 2>>~%EOE%;
@@ -114,6 +114,38 @@ deinit += -d prj
EOE
}
+ : type
+ :
+ {
+ $clone_root_prj;
+
+ $* create --config-type host -- @cfg $config_cxx 2>>/"EOE" &prj-cfg/***;
+ created configuration @cfg $~/prj-cfg/ 1 host default,forwarded,auto-synchronized
+ EOE
+
+ $init @cfg 2>>/~"%EOE%";
+ initializing in project $~/prj/
+ synchronizing:
+ % new prj.+19700101000000%
+ EOE
+
+ $status >'prj configured 0.1.0-a.0.19700101000000';
+
+ $* list @cfg >>/"EOO";
+ @cfg $~/prj-cfg/ 1 host default,forwarded,auto-synchronized
+ EOO
+
+ $update @cfg 2>>~%EOE%;
+ %(mkdir|c\+\+|ld) .+%{3}
+ EOE
+
+ $deinit @cfg 2>>/"EOE"
+ deinitializing in project $~/prj/
+ synchronizing:
+ drop prj
+ EOE
+ }
+
: wipe
:
{
@@ -128,7 +160,7 @@ deinit += -d prj
EOE
$* create --wipe cfg $config_cxx 2>>/"EOE" &cfg/***
- created configuration $~/cfg/ 1 default,forwarded,auto-synchronized
+ created configuration $~/cfg/ 1 target default,forwarded,auto-synchronized
EOE
}
}
@@ -144,11 +176,11 @@ deinit += -d prj
$new -C prj-cfg2 tmp2 $config_cxx 2>! &prj-cfg2/*** &tmp2/***;
$* add @cfg1 prj-cfg1 2>>/"EOE";
- added configuration @cfg1 $~/prj-cfg1/ 1 default,forwarded,auto-synchronized
+ added configuration @cfg1 $~/prj-cfg1/ 1 target default,forwarded,auto-synchronized
EOE
$* add @cfg2 prj-cfg2 2>>/"EOE";
- added configuration @cfg2 $~/prj-cfg2/ 2 auto-synchronized
+ added configuration @cfg2 $~/prj-cfg2/ 2 target auto-synchronized
EOE
$init --all 2>>/~"%EOE%";
@@ -171,8 +203,8 @@ deinit += -d prj
EOO
$* list >>/"EOO";
- @cfg1 $~/prj-cfg1/ 1 default,forwarded,auto-synchronized
- @cfg2 $~/prj-cfg2/ 2 auto-synchronized
+ @cfg1 $~/prj-cfg1/ 1 target default,forwarded,auto-synchronized
+ @cfg2 $~/prj-cfg2/ 2 target auto-synchronized
EOO
$update --all 2>>~%EOE%;
@@ -201,7 +233,7 @@ deinit += -d prj
$clone_root_prj;
$* create -- @cfg $config_cxx &prj-cfg/*** 2>>/"EOE";
- created configuration @cfg $~/prj-cfg/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/prj-cfg/ 1 target default,forwarded,auto-synchronized
EOE
$init @cfg 2>>/~"%EOE%";
@@ -213,7 +245,7 @@ deinit += -d prj
mv prj-cfg prj-cfg2;
$* move @cfg prj-cfg2 2>>/"EOE";
- moved configuration @cfg $~/prj-cfg/ 1 to $~/prj-cfg2/
+ moved configuration @cfg $~/prj-cfg/ 1 target to $~/prj-cfg2/
info: explicit sync command is required for changes to take effect
EOE
@@ -234,7 +266,7 @@ deinit += -d prj
$clone_root_prj;
$* create -- @cfg $config_cxx 2>>/"EOE" &prj-cfg/***;
- created configuration @cfg $~/prj-cfg/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/prj-cfg/ 1 target default,forwarded,auto-synchronized
EOE
$init @cfg 2>>/~"%EOE%";
@@ -244,7 +276,7 @@ deinit += -d prj
EOE
$* rename @cfg cfg2 2>>/"EOE";
- renamed configuration @cfg $~/prj-cfg/ 1 to @cfg2
+ renamed configuration @cfg $~/prj-cfg/ 1 target to @cfg2
EOE
$update @cfg2 2>>~%EOE%;
@@ -283,7 +315,7 @@ deinit += -d prj
EOE
$* remove @cfg1 2>>/"EOE";
- removed configuration @cfg1 $~/prj-cfg1/ 1
+ removed configuration @cfg1 $~/prj-cfg1/ 1 target
EOE
$status --all >>EOO;
@@ -291,7 +323,7 @@ deinit += -d prj
EOO
$* list >>/"EOO";
- @cfg2 $~/prj-cfg2/ 2 auto-synchronized
+ @cfg2 $~/prj-cfg2/ 2 target auto-synchronized
EOO
$update 2>>/"EOE" != 0;
@@ -300,12 +332,12 @@ deinit += -d prj
EOE
$* set @cfg2 --default --forward --no-auto-sync 2>>/"EOE";
- updated configuration @cfg2 $~/prj-cfg2/ 2 default,forwarded
+ updated configuration @cfg2 $~/prj-cfg2/ 2 target default,forwarded
info: explicit sync command is required for changes to take effect
EOE
$* list >>/"EOO";
- @cfg2 $~/prj-cfg2/ 2 default,forwarded
+ @cfg2 $~/prj-cfg2/ 2 target default,forwarded
EOO
$update 2>>~%EOE%;
@@ -318,3 +350,16 @@ deinit += -d prj
drop prj
EOE
}
+
+: link
+:
+{
+ $clone_root_prj;
+
+ $* create -- @cfg1 $config_cxx 2>! &prj-cfg1/***;
+ $* create -- @cfg2 $config_cxx 2>! &prj-cfg2/***;
+
+ $* link @cfg1 @cfg2 2>>EOE
+ linked configuration @cfg1 (target) with configuration @cfg2 (target)
+ EOE
+}
diff --git a/tests/init.testscript b/tests/init.testscript
index ba67b56..5192145 100644
--- a/tests/init.testscript
+++ b/tests/init.testscript
@@ -27,7 +27,7 @@ deinit += -d prj
$* -C @cfg $config_cxx 'config.cc.poptions=-DTEST' -- '?sys:libprj/*' 2>>/~"%EOE%" &prj-cfg/***;
initializing in project $~/prj/
- created configuration @cfg $~/prj-cfg/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/prj-cfg/ 1 target default,forwarded,auto-synchronized
synchronizing:
% configure sys:libprj.*%
% new prj.+19700101000000%
@@ -67,7 +67,7 @@ deinit += -d prj
$* -C @cfg -- $config_cxx 'config.cc.poptions=-DTEST' -- '?sys:libprj/*' 2>>/~"%EOE%" &prj-cfg/***;
initializing in project $~/prj/
- created configuration @cfg $~/prj-cfg/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/prj-cfg/ 1 target default,forwarded,auto-synchronized
synchronizing:
% configure sys:libprj.*%
% new prj.+19700101000000%
@@ -99,7 +99,7 @@ deinit += -d prj
$* -C @cfg -- -- '?sys:libprj/*' 2>>/~"%EOE%" &prj-cfg/***;
initializing in project $~/prj/
- created configuration @cfg $~/prj-cfg/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/prj-cfg/ 1 target default,forwarded,auto-synchronized
synchronizing:
% configure sys:libprj.*%
% new prj.+19700101000000%
@@ -125,20 +125,20 @@ deinit += -d prj
# Pre-create configurations.
#
- $new -C prj-cfg1 tmp $config_cxx 2>! &prj-cfg1/*** &tmp/***;
- $init -C prj-cfg2 -d tmp $config_cxx 2>! &prj-cfg2/***;
+ $new -C prj-cfg1 --no-default tmp $config_cxx 2>! &prj-cfg1/*** &tmp/***;
+ $init -C prj-cfg2 --config-type host -d tmp $config_cxx 2>! &prj-cfg2/***;
$* -A @cfg1 '?sys:libprj/*' 2>>/~"%EOE%";
initializing in project $~/prj/
- added configuration @cfg1 $~/prj-cfg1/ 1 default,forwarded,auto-synchronized
+ added configuration @cfg1 $~/prj-cfg1/ 1 target default,forwarded,auto-synchronized
synchronizing:
% configure sys:libprj.*%
% new prj.+19700101000000%
EOE
- $* -A prj-cfg2 @cfg2 '?sys:libprj/*' 2>>/~"%EOE%";
+ $* -A prj-cfg2 --no-default @cfg2 '?sys:libprj/*' 2>>/~"%EOE%";
initializing in project $~/prj/
- added configuration @cfg2 $~/prj-cfg2/ 2 auto-synchronized
+ added configuration @cfg2 $~/prj-cfg2/ 2 host auto-synchronized
synchronizing:
% configure sys:libprj.*%
% new prj.+19700101000000%
@@ -188,7 +188,7 @@ deinit += -d prj
$* -C @cfg $config_cxx 2>>/~"%EOE%" &prj-cfg/***;
initializing in project $~/prj/
- created configuration @cfg $~/prj-cfg/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/prj-cfg/ 1 target default,forwarded,auto-synchronized
synchronizing:
% new prj.+19700101000000%
EOE
diff --git a/tests/new.testscript b/tests/new.testscript
index 4d98feb..727f338 100644
--- a/tests/new.testscript
+++ b/tests/new.testscript
@@ -1836,7 +1836,7 @@ subdir=hello,no-subdir-source \
{
$* -C prj-config @cfg prj cc $config_cxx 2>>/~"%EOE%" &prj/*** &prj-config/***;
created new executable project prj in $~/prj/
- created configuration @cfg $~/prj-config/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/prj-config/ 1 target default,forwarded,auto-synchronized
synchronizing:
% new prj.+19700101000000%
EOE
@@ -1858,7 +1858,7 @@ subdir=hello,no-subdir-source \
{
$* -C -@cfg prj cc $config_cxx 2>>/~"%EOE%" &prj/*** &prj-cfg/***;
created new executable project prj in $~/prj/
- created configuration @cfg $~/prj-cfg/ 1 default,forwarded,auto-synchronized
+ created configuration @cfg $~/prj-cfg/ 1 target default,forwarded,auto-synchronized
synchronizing:
% new prj.+19700101000000%
EOE
diff --git a/tests/publish.testscript b/tests/publish.testscript
index 8f5ec85..07c3632 100644
--- a/tests/publish.testscript
+++ b/tests/publish.testscript
@@ -33,7 +33,7 @@ g = git -C prj >! 2>!
# duplicate submissions. We will use unique version for each test,
# incrementing the patch version for 1.0.X.
#
-# Next version to use: 1.0.20
+# Next version to use: 1.0.22
#
# Normally we disable the progress indication that complicates stderr output
@@ -104,7 +104,11 @@ g = git -C prj >! 2>!
$init -C @cfg1 &prj-cfg1/***;
$init -C @cfg2 &prj-cfg2/***;
- $* --all 2>'error: multiple configurations specified for publish' != 0
+ $* --all 2>>EOE != 0
+ error: package prj is initialized in multiple specified configurations
+ info: @cfg1
+ info: @cfg2
+ EOE
}
: snapshot
@@ -152,6 +156,42 @@ g = git -C prj >! 2>!
EOE
}
+ : diff-configs
+ :
+ {
+ $clone_prj;
+ sed -i -e 's/^(version:) .*$/\1 1.0.20/' prj/libprj/manifest;
+ sed -i -e 's/^(version:) .*$/\1 1.0.20/' prj/prj/manifest;
+
+ $init -C @cfg1 -d prj/libprj &prj-cfg1/***;
+ $init -C @cfg2 --config-type host -d prj/prj &prj-cfg2/***;
+
+ $* 2>>~%EOE%
+ %package submission is queued(: \.*libprj/1.0.20)?%d
+ %reference: .{12}%
+ %package submission is queued(: \.*prj/1.0.20)?%d
+ %reference: .{12}%
+ EOE
+ }
+
+ : diff-configs-forward
+ :
+ {
+ $clone_prj;
+ sed -i -e 's/^(version:) .*$/\1 1.0.21/' prj/libprj/manifest;
+ sed -i -e 's/^(version:) .*$/\1 1.0.21/' prj/prj/manifest;
+
+ $init -C @cfg1 --no-default --forward -d prj/libprj &prj-cfg1/***;
+ $init -C @cfg2 --config-type host --no-default --forward -d prj/prj &prj-cfg2/***;
+
+ $* --forward 2>>~%EOE%
+ %package submission is queued(: \.*libprj/1.0.21)?%d
+ %reference: .{12}%
+ %package submission is queued(: \.*prj/1.0.21)?%d
+ %reference: .{12}%
+ EOE
+ }
+
: single
:
{
diff --git a/tests/update.testscript b/tests/update.testscript
index 7e03238..3823b9d 100644
--- a/tests/update.testscript
+++ b/tests/update.testscript
@@ -88,3 +88,46 @@ deinit += -d prj
drop pkg2
EOE
}
+
+: multi-default-cfg
+:
+{
+ $new -t empty prj &prj/***;
+
+ $new --package pkg1 -d prj;
+ $new --package pkg2 -d prj;
+
+ $init -C @cfg1 -d prj/pkg1 &prj-cfg1/***;
+ $init -C @cfg2 -d prj/pkg2 --config-type host &prj-cfg2/***;
+
+ # Update.
+ #
+ $* -d prj 2>>~%EOE%;
+ in configuration @cfg1:
+ %(mkdir|c\+\+|ld) .+pkg1.+%{3}
+
+ in configuration @cfg2:
+ %(mkdir|c\+\+|ld) .+pkg2.+%{3}
+ EOE
+
+ # Clean.
+ #
+ $clean -d prj 2>>~%EOE%;
+ in configuration @cfg1:
+ %rm .+pkg1.+%{3}
+
+ in configuration @cfg2:
+ %rm .+pkg2.+%{3}
+ EOE
+
+ $deinit 2>>/"EOE"
+ deinitializing in project $~/prj/
+ in configuration @cfg1:
+ synchronizing:
+ drop pkg1
+
+ in configuration @cfg2:
+ synchronizing:
+ drop pkg2
+ EOE
+}