aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bdep/build.txx14
-rw-r--r--bdep/ci.cli4
-rw-r--r--bdep/ci.cxx15
-rw-r--r--bdep/clean.cli4
-rw-r--r--bdep/deinit.cli4
-rw-r--r--bdep/deinit.cxx11
-rw-r--r--bdep/project.cxx78
-rw-r--r--bdep/project.hxx33
-rw-r--r--bdep/projects-configs.cli9
-rw-r--r--bdep/publish.cli4
-rw-r--r--bdep/publish.cxx16
-rw-r--r--bdep/status.cli8
-rw-r--r--bdep/status.cxx142
-rw-r--r--bdep/sync.cli9
-rw-r--r--bdep/sync.cxx153
-rw-r--r--bdep/test.cli4
-rw-r--r--bdep/update.cli4
-rw-r--r--tests/ci.testscript39
-rw-r--r--tests/publish.testscript58
-rw-r--r--tests/status.testscript179
-rw-r--r--tests/sync.testscript61
-rw-r--r--tests/update.testscript36
22 files changed, 798 insertions, 87 deletions
diff --git a/bdep/build.txx b/bdep/build.txx
index a9b237c..3c5fd7c 100644
--- a/bdep/build.txx
+++ b/bdep/build.txx
@@ -22,17 +22,18 @@ namespace bdep
{
tracer trace ("build");
- // Save cfg-vars with some sanity checking.
+ // Save cfg-vars and the package names.
//
strings cfg_vars;
+ strings ps;
while (args.more ())
{
const char* a (args.next ());
- if (strchr (a , '=') == nullptr)
- fail << "'" << a << "' does not look like a variable assignment";
-
- cfg_vars.push_back (trim (a));
+ if (strchr (a , '=') != nullptr)
+ cfg_vars.push_back (trim (a));
+ else
+ ps.emplace_back (a);
}
// The same ignore/load story as in sync.
@@ -44,6 +45,9 @@ namespace bdep
const dir_path& prj (pp.project);
+ if (!ps.empty ())
+ pp.append (find_project_packages (prj, ps).first.packages);
+
// Load the configurations without keeping the database open longer than
// necessary.
//
diff --git a/bdep/ci.cli b/bdep/ci.cli
index 99b7834..7707935 100644
--- a/bdep/ci.cli
+++ b/bdep/ci.cli
@@ -13,7 +13,7 @@ namespace bdep
{
"<options>
<prj-spec> <prj-dir>
- <pkg-spec> <pkg-dir>
+ <pkg-spec> <pkg> <pkg-dir>
<cfg-spec> <cfg-name> <cfg-dir>",
"\h|SYNOPSIS|
@@ -21,7 +21,7 @@ namespace bdep
\c{\b{bdep ci} [<options>] [<cfg-spec>] [<pkg-spec>]}
\c{<cfg-spec> = (\b{@}<cfg-name> | \b{--config}|\b{-c} <cfg-dir>)... | \b{--all}|\b{-a} | \b{--forward}\n
- <pkg-spec> = (\b{--directory}|\b{-d} <pkg-dir>)... | <prj-spec>\n
+ <pkg-spec> = (<pkg> | (\b{--directory}|\b{-d} <pkg-dir>))... | <prj-spec>\n
<prj-spec> = \b{--directory}|\b{-d} <prj-dir>}
\h|DESCRIPTION|
diff --git a/bdep/ci.cxx b/bdep/ci.cxx
index 0b26b35..f4c6412 100644
--- a/bdep/ci.cxx
+++ b/bdep/ci.cxx
@@ -176,7 +176,7 @@ namespace bdep
}
int
- cmd_ci (const cmd_ci_options& o, cli::scanner&)
+ cmd_ci (const cmd_ci_options& o, cli::scanner& args)
{
tracer trace ("ci");
@@ -189,6 +189,12 @@ namespace bdep
fail << n << " specified together with --forward";
}
+ // Save the package names.
+ //
+ strings ps;
+ while (args.more ())
+ ps.emplace_back (args.next ());
+
// Collect the packages manifest value overrides parsing the --override,
// etc options and verify that the resulting overrides list contains valid
// package manifest values and is semantically correct.
@@ -416,11 +422,14 @@ namespace bdep
//
project_packages pp (
find_project_packages (o,
- false /* ignore_packages */,
- o.forward () /* load_packages */));
+ false /* ignore_packages */,
+ o.forward () && ps.empty () /* load_packages */));
const dir_path& prj (pp.project);
+ if (!ps.empty ())
+ pp.append (find_project_packages (prj, ps).first.packages);
+
// Collect package names, versions, and configurations used (except for
// the forward mode).
//
diff --git a/bdep/clean.cli b/bdep/clean.cli
index 6a2e140..759bc15 100644
--- a/bdep/clean.cli
+++ b/bdep/clean.cli
@@ -12,7 +12,7 @@ namespace bdep
{
"<options>
<prj-spec> <prj-dir>
- <pkg-spec> <pkg-dir>
+ <pkg-spec> <pkg> <pkg-dir>
<cfg-spec> <cfg-name> <cfg-dir>
<cfg-var>",
@@ -21,7 +21,7 @@ namespace bdep
\c{\b{bdep clean} [<options>] [<pkg-spec>] [<cfg-spec>] [<cfg-var>...]}
\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
+ <pkg-spec> = (<pkg> | (\b{--directory}|\b{-d} <pkg-dir>))... | <prj-spec>\n
<prj-spec> = \b{--directory}|\b{-d} <prj-dir>}
\h|DESCRIPTION|
diff --git a/bdep/deinit.cli b/bdep/deinit.cli
index 3ec0e72..f0e2320 100644
--- a/bdep/deinit.cli
+++ b/bdep/deinit.cli
@@ -12,7 +12,7 @@ namespace bdep
{
"<options>
<prj-spec> <prj-dir>
- <pkg-spec> <pkg-dir>
+ <pkg-spec> <pkg> <pkg-dir>
<cfg-spec> <cfg-name> <cfg-dir>",
"\h|SYNOPSIS|
@@ -20,7 +20,7 @@ namespace bdep
\c{\b{bdep deinit} [<options>] [<pkg-spec>] [<cfg-spec>]}
\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
+ <pkg-spec> = (<pkg> | (\b{--directory}|\b{-d} <pkg-dir>))... | <prj-spec>\n
<prj-spec> = \b{--directory}|\b{-d} <prj-dir>}
\h|DESCRIPTION|
diff --git a/bdep/deinit.cxx b/bdep/deinit.cxx
index d36f39c..60bef1c 100644
--- a/bdep/deinit.cxx
+++ b/bdep/deinit.cxx
@@ -128,10 +128,16 @@ namespace bdep
}
int
- cmd_deinit (const cmd_deinit_options& o, cli::scanner&)
+ cmd_deinit (const cmd_deinit_options& o, cli::scanner& args)
{
tracer trace ("deinit");
+ // Save the package names.
+ //
+ strings ps;
+ while (args.more ())
+ ps.emplace_back (args.next ());
+
bool force (o.force ());
// The same ignore/load story as in sync.
@@ -143,6 +149,9 @@ namespace bdep
const dir_path& prj (pp.project);
+ if (!ps.empty ())
+ pp.append (find_project_packages (prj, ps).first.packages);
+
if (verb)
text << "deinitializing in project " << prj;
diff --git a/bdep/project.cxx b/bdep/project.cxx
index 7321cc4..743d6fe 100644
--- a/bdep/project.cxx
+++ b/bdep/project.cxx
@@ -447,6 +447,66 @@ namespace bdep
return r;
}
+ pair<project_packages, strings>
+ find_project_packages (dir_path prj,
+ const strings& pkgs,
+ bool ignore_nf,
+ bool allow_empty)
+ {
+ package_locations pls (load_package_locations (prj, allow_empty));
+
+ if (!pls.empty ())
+ load_package_names (prj, pls);
+
+ package_locations rpls;
+ strings rps;
+
+ for (const string& p: pkgs)
+ {
+ // Skip duplicates to be consistent with the other function overloads.
+ //
+ if (find_if (rpls.begin (), rpls.end (),
+ [&p] (const package_location& pl)
+ {
+ return pl.name == p;
+ }) != rpls.end ())
+ continue;
+
+ auto i (find_if (pls.begin (), pls.end (),
+ [&p] (const package_location& pl)
+ {
+ return pl.name == p;
+ }));
+
+ if (i != pls.end ())
+ {
+ rpls.push_back (move (*i));
+
+ // Keep name in the definite state, since it is referred during search.
+ //
+ i->name = package_name ();
+ }
+ else if (ignore_nf)
+ {
+ rps.push_back (p);
+ }
+ else
+ {
+ try
+ {
+ package_name n (p);
+ fail << "no package " << n << " in project " << prj;
+ }
+ catch (const invalid_argument& e)
+ {
+ fail << "package name '" << p << "' is invalid: " << e;
+ }
+ }
+ }
+
+ return make_pair (project_packages {move (prj), move (rpls)}, move (rps));
+ }
+
void
verify_project_packages (const project_packages& pp,
const pair<configurations, bool>& cfgs)
@@ -553,4 +613,22 @@ namespace bdep
fail << "package " << p << " does not use standard version" <<
info << "perhaps the package does not load the version module?";
}
+
+ // project_packages
+ //
+ void project_packages::
+ append (package_locations&& pls)
+ {
+ for (package_location& l: pls)
+ {
+ if (find_if (packages.begin (), packages.end (),
+ [&l] (const package_location& pl)
+ {
+ return pl.path == l.path;
+ }) == packages.end ())
+ {
+ packages.push_back (move (l));
+ }
+ }
+ }
}
diff --git a/bdep/project.hxx b/bdep/project.hxx
index c40fe61..0bb49c8 100644
--- a/bdep/project.hxx
+++ b/bdep/project.hxx
@@ -241,6 +241,11 @@ namespace bdep
{
dir_path project;
package_locations packages;
+
+ // Append package locations suppressing duplicates.
+ //
+ void
+ append (package_locations&&);
};
// Search project packages in the specified directories or the current
@@ -274,6 +279,34 @@ namespace bdep
return find_project_packages (o, true /* ignore_packages */).project;
}
+ // Search for the specified packages in the specified project
+ // directory. Fail if some packages are not found in the project, unless
+ // ignore_not_found is true in which case return them (`second` member).
+ //
+ pair<project_packages, strings>
+ find_project_packages (dir_path,
+ const strings&,
+ bool ignore_not_found = false,
+ bool allow_empty = false);
+
+ inline pair<project_packages, strings>
+ find_project_packages (const dir_paths& dirs,
+ const strings& pkgs,
+ bool ignore_nf = false,
+ bool ae = false)
+ {
+ return find_project_packages (find_project (dirs), pkgs, ignore_nf, ae);
+ }
+
+ inline pair<project_packages, strings>
+ find_project_packages (const project_options& po,
+ const strings& pkgs,
+ bool ignore_nf = false,
+ bool ae = false)
+ {
+ return find_project_packages (po.directory (), move (pkgs), ignore_nf, ae);
+ }
+
// Verify that each package is present in at least one configuration.
//
// Note that the default configurations fallback indication (see above) is
diff --git a/bdep/projects-configs.cli b/bdep/projects-configs.cli
index a5c5808..6c23689 100644
--- a/bdep/projects-configs.cli
+++ b/bdep/projects-configs.cli
@@ -10,7 +10,7 @@ include <bdep/common-options.hxx>;
{
"<command>
<prj-spec> <prj-dir>
- <pkg-spec> <pkg-dir>
+ <pkg-spec> <pkg> <pkg-dir>
<cfg-spec> <cfg-name> <cfg-dir>",
"
@@ -19,7 +19,7 @@ include <bdep/common-options.hxx>;
\c{\b{bdep} <command> [<pkg-spec>] [<cfg-spec>] ...}
\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
+ <pkg-spec> = (<pkg> | (\b{--directory}|\b{-d} <pkg-dir>))... | <prj-spec>\n
<prj-spec> = \b{--directory}|\b{-d} <prj-dir>}
\h|DESCRIPTION|
@@ -43,6 +43,11 @@ include <bdep/common-options.hxx>;
on a single project but potentially multiple packages belonging to said
project at a time.
+ A package can always be specified with the \c{\b{--directory}|\b{-d}} option
+ and normally with the package name argument, unless such an argument would
+ be ambiguous. Refer to the specific command documentation on the possibility
+ to specify a package as a name.
+
Some \cb{bdep} commands, such as \cb{fetch}, operate on the whole project.
If such a command is given a package directory (either as the working
directory or with \c{\b{--directory}|\b{-d}}), then it automatically
diff --git a/bdep/publish.cli b/bdep/publish.cli
index 85925ec..89a8e4d 100644
--- a/bdep/publish.cli
+++ b/bdep/publish.cli
@@ -14,14 +14,14 @@ namespace bdep
{
"<options>
<prj-spec> <prj-dir>
- <pkg-spec> <pkg-dir>
+ <pkg-spec> <pkg> <pkg-dir>
<cfg-spec> <cfg-name> <cfg-dir>",
"\h|SYNOPSIS|
\c{\b{bdep publish} [<options>] [<cfg-spec>] [<pkg-spec>]}
- \c{<pkg-spec> = (\b{--directory}|\b{-d} <pkg-dir>)... | <prj-spec>\n
+ \c{<pkg-spec> = (<pkg> | (\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{--all}|\b{-a} | \b{--forward}}
diff --git a/bdep/publish.cxx b/bdep/publish.cxx
index 3bdbf46..57a16cd 100644
--- a/bdep/publish.cxx
+++ b/bdep/publish.cxx
@@ -862,7 +862,7 @@ namespace bdep
}
int
- cmd_publish (const cmd_publish_options& o, cli::scanner&)
+ cmd_publish (const cmd_publish_options& o, cli::scanner& args)
{
tracer trace ("publish");
@@ -875,6 +875,12 @@ namespace bdep
fail << n << " specified together with --forward";
}
+ // Save the package names.
+ //
+ strings ps;
+ while (args.more ())
+ ps.emplace_back (args.next ());
+
// If we are publishing the entire project, then we have two choices: we
// can publish all the packages in the project or we can only do so for
// packages that were initialized in the configuration that we are going
@@ -885,10 +891,14 @@ namespace bdep
//
project_packages pp (
find_project_packages (o,
- false /* ignore_packages */,
- true /* load_packages */));
+ false /* ignore_packages */,
+ ps.empty () /* load_packages */));
const dir_path& prj (pp.project);
+
+ if (!ps.empty ())
+ pp.append (find_project_packages (prj, ps).first.packages);
+
package_locations& pkgs (pp.packages);
// If we are submitting multiple packages, verify they are from the same
diff --git a/bdep/status.cli b/bdep/status.cli
index 1360606..41d270a 100644
--- a/bdep/status.cli
+++ b/bdep/status.cli
@@ -12,7 +12,7 @@ namespace bdep
{
"<options>
<prj-spec> <prj-dir>
- <pkg-spec> <pkg-dir>
+ <pkg-spec> <pkg> <pkg-dir>
<cfg-spec> <cfg-name> <cfg-dir>
<dep-spec> <pkg> <ver>",
@@ -22,7 +22,7 @@ namespace bdep
\c{<dep-spec> = <pkg>[\b{/}<ver>]\n
<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
+ <pkg-spec> = (<pkg> | (\b{--directory}|\b{-d} <pkg-dir>))... | <prj-spec>\n
<prj-spec> = \b{--directory}|\b{-d} <prj-dir>}
\h|DESCRIPTION|
@@ -35,6 +35,10 @@ namespace bdep
configurations are assumed. See \l{bdep-projects-configs(1)} for details
on specifying projects and configurations.
+ Note that if the package specified on the command line belongs to the
+ project and is initialized in any of the specified configurations, then
+ it is the <pkg-spec>. Otherwise, it is the <dep-spec>.
+
If no <dep-spec> 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
diff --git a/bdep/status.cxx b/bdep/status.cxx
index c8b74b4..6ff9065 100644
--- a/bdep/status.cxx
+++ b/bdep/status.cxx
@@ -348,13 +348,102 @@ namespace bdep
if (o.immediate () && o.recursive ())
fail << "both --immediate|-i and --recursive|-r specified";
+ bool json (o.stdout_format () == stdout_format::json);
+
+ optional<pair<configurations, bool>> cs;
+
// We have two pretty different modes: project package status and
- // dependency package status (have arguments).
+ // dependency package status (<dep-specs> are specified).
+ //
+ // Sort arguments (if any) into dep-specs and pkg-specs as follows:
+ //
+ // - If the argument contains '/' (package version) or this package
+ // doesn't belong to this project or is not initialized, then we assume
+ // dep-spec.
+ //
+ // - Otherwise, we assume pkg-spec.
//
strings dep_pkgs;
- for (; args.more (); dep_pkgs.push_back (args.next ())) ;
+ package_locations pkgs;
+ {
+ strings ps;
+ while (args.more ())
+ {
+ const char* a (args.next ());
- bool json (o.stdout_format () == stdout_format::json);
+ if (strchr (a, '/') != nullptr)
+ dep_pkgs.push_back (a);
+ else
+ ps.push_back (a);
+ }
+
+ // Add packages which don't belong to the project or are not initialized
+ // to dep_pkgs and to pkgs otherwise.
+ //
+ if (!ps.empty ())
+ {
+ pair<project_packages, strings> pps (
+ find_project_packages (o,
+ ps,
+ true /* ignore_not_found */,
+ json /* allow_empty */));
+
+ // Assume the packages that don't belong to the project as dep-specs.
+ //
+ dep_pkgs.insert (dep_pkgs.end (),
+ make_move_iterator (pps.second.begin ()),
+ make_move_iterator (pps.second.end ()));
+
+ // Assume the initialized packages of the project as the pkg-specs and
+ // the dep-specs otherwise.
+ //
+ // Note that here we check if the packages are initialized in only the
+ // specified configurations.
+ //
+ project_packages& pp (pps.first);
+
+ if (!pp.packages.empty ())
+ {
+ database db (open (pp.project, trace));
+
+ transaction t (db.begin ());
+ cs = find_configurations (o,
+ pp.project,
+ t,
+ true /* fallback_default */,
+ true /* validate */,
+ json /* allow_none */);
+ t.commit ();
+
+ for (package_location& p: pp.packages)
+ {
+ bool init (false);
+
+ for (const shared_ptr<configuration>& c: cs->first)
+ {
+ if (find_if (c->packages.begin (),
+ c->packages.end (),
+ [&p] (const package_state& s)
+ {
+ return p.name == s.name;
+ }) != c->packages.end ())
+ {
+ init = true;
+ break;
+ }
+ }
+
+ if (init)
+ pkgs.push_back (move (p));
+ else
+ dep_pkgs.push_back (move (p.name).string ());
+ }
+
+ if (!pkgs.empty () && !dep_pkgs.empty ())
+ fail << "initialized packages specified with dependency packages";
+ }
+ }
+ }
// The same ignore/load story as in sync for the lines format.
//
@@ -365,40 +454,47 @@ namespace bdep
//
project_packages pp (
find_project_packages (o,
- !dep_pkgs.empty () /* ignore_packages */,
- json /* load_packages */,
- json /* allow_empty */));
+ !dep_pkgs.empty () /* ignore_packages */,
+ json && pkgs.empty () /* load_packages */,
+ json /* allow_empty */));
- const dir_path& prj (pp.project);
+ if (!pkgs.empty ())
+ pp.append (move (pkgs));
- database db (open (prj, trace));
+ const dir_path& prj (pp.project);
configurations cfgs;
{
- transaction t (db.begin ());
-
- // If --all|-a is specified and the project has no associated
- // configurations let's print an empty array of configurations for the
- // JSON format instead of failing (as we do for the lines format).
+ // Load project configurations, if not loaded yet.
//
- pair<configurations, bool> cs (
- find_configurations (o,
- prj,
- t,
- true /* fallback_default */,
- true /* validate */,
- json /* allow_none */));
+ if (!cs)
+ {
+ database db (open (prj, trace));
+
+ transaction t (db.begin ());
- t.commit ();
+ // If --all|-a is specified and the project has no associated
+ // configurations let's print an empty array of configurations for the
+ // JSON format instead of failing (as we do for the lines format).
+ //
+ cs = find_configurations (o,
+ prj,
+ t,
+ true /* fallback_default */,
+ true /* validate */,
+ json /* allow_none */);
+
+ t.commit ();
+ }
// If specified, verify packages are present in at least one
// configuration. But not for the JSON format where we also print
// statuses of uninitialized packages.
//
if (!pp.packages.empty () && !json)
- verify_project_packages (pp, cs);
+ verify_project_packages (pp, *cs);
- cfgs = move (cs.first);
+ cfgs = move (cs->first);
}
switch (o.stdout_format ())
diff --git a/bdep/sync.cli b/bdep/sync.cli
index 6e3082f..dcb2865 100644
--- a/bdep/sync.cli
+++ b/bdep/sync.cli
@@ -12,7 +12,7 @@ namespace bdep
{
"<options>
<prj-spec> <prj-dir>
- <pkg-spec> <pkg-dir>
+ <pkg-spec> <pkg> <pkg-dir>
<cfg-spec> <cfg-name> <cfg-dir>
<dep-spec> <pkg> <ver>
<pkg-args> <pkg> <cfg-var>",
@@ -27,7 +27,7 @@ namespace bdep
\c{<dep-spec> = <pkg>[\b{/}<ver>]\n
<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
+ <pkg-spec> = (<pkg> | (\b{--directory}|\b{-d} <pkg-dir>))... | <prj-spec>\n
<prj-spec> = \b{--directory}|\b{-d} <prj-dir>\n
<pkg-args> = (\b{?}<pkg> | <cfg-var>)...}
@@ -64,6 +64,11 @@ namespace bdep
respectively. Alternative to \cb{--upgrade} and \cb{--patch}, the desired
upgrade (or downgrade) version can be specified explicitly.
+ Note that if the package specified on the command line belongs to the
+ project and is initialized in any of the specified configurations, then
+ it is the <pkg-spec> in the first or second form of the command line.
+ Otherwise, it is the <dep-spec> in the third from of the command line.
+
Note also that \c{\b{--immediate}|\b{-i}} or \c{\b{--recursive}|\b{-r}}
can only be specified with an explicit \cb{--upgrade} or \cb{--patch}.
diff --git a/bdep/sync.cxx b/bdep/sync.cxx
index d92d86a..119a739 100644
--- a/bdep/sync.cxx
+++ b/bdep/sync.cxx
@@ -2488,22 +2488,6 @@ namespace bdep
fail << n << " requires explicit --upgrade|-u or --patch|-p";
}
- // Sort arguments (if any) into pkg-args and dep-spec: if the argument
- // starts with '?' (dependency flag) or contains '=' (config variable),
- // then we assume it is pkg-args.
- //
- // Note: scan_argument() passes through groups.
- //
- strings pkg_args;
- strings dep_pkgs;
- while (args.more ())
- {
- const char* r (args.peek ());
- scan_argument (
- (*r == '?' || strchr (r, '=') != nullptr) ? pkg_args : dep_pkgs,
- args);
- }
-
// --hook
//
if (o.hook_specified ())
@@ -2518,6 +2502,121 @@ namespace bdep
o.implicit (true); // Implies --implicit.
}
+ // Note: in the implicit mode we don't search the current working
+ // directory for a project.
+ //
+ bool implicit_no_orig (o.implicit () && !o.directory_specified ());
+
+ optional<pair<configurations, bool>> cs;
+
+ // Sort arguments (if any) into pkg-args, dep-specs, and pkg-specs as
+ // follows:
+ //
+ // - If the argument starts with '?' (dependency flag) or contains '='
+ // (config variable), then we assume it is pkg-arg.
+ //
+ // - Otherwise, if this is an implicit sync without an originating project
+ // or the argument contains '/' (package version) or has a group or this
+ // package doesn't belong to this project or is not initialized, then we
+ // assume dep-spec.
+ //
+ // - Otherwise, we assume pkg-spec.
+ //
+ // Note: scan_argument() passes through groups.
+ //
+ strings pkg_args;
+ strings dep_pkgs;
+ package_locations pkgs;
+ {
+ strings ps;
+ while (args.more ())
+ {
+ const char* r (args.peek ());
+
+ if (*r == '?' || strchr (r, '=') != nullptr)
+ {
+ scan_argument (pkg_args, args);
+ }
+ else
+ {
+ // If this is not an implicit sync without an originating project
+ // and the argument doesn't contain '/' (package version) nor has a
+ // group, then stash the package for a subsequent check if it is an
+ // initialized package of this project or not.
+ //
+ size_t n (dep_pkgs.size ());
+ scan_argument (dep_pkgs, args);
+
+ if (!implicit_no_orig &&
+ dep_pkgs.size () == n + 1 && // No group?
+ strchr (r, '/') == nullptr) // No version?
+ {
+ ps.push_back (move (dep_pkgs.back ()));
+ dep_pkgs.pop_back ();
+ }
+ }
+ }
+
+ // Move packages which don't belong to the project or are not
+ // initialized back to dep_pkgs.
+ //
+ if (!ps.empty ())
+ {
+ pair<project_packages, strings> pps (
+ find_project_packages (o, ps, true /* ignore_not_found */));
+
+ // Assume the packages that don't belong to the project as dep-specs.
+ //
+ dep_pkgs.insert (dep_pkgs.end (),
+ make_move_iterator (pps.second.begin ()),
+ make_move_iterator (pps.second.end ()));
+
+ // Assume the initialized packages of the project as the pkg-specs and
+ // the dep-specs otherwise.
+ //
+ // Note that here we check if the packages are initialized in only the
+ // specified configurations.
+ //
+ project_packages& pp (pps.first);
+
+ if (!pp.packages.empty ())
+ {
+ database db (open (pp.project, trace));
+
+ transaction t (db.begin ());
+ cs = find_configurations (o, pp.project, t);
+ t.commit ();
+
+ for (package_location& p: pp.packages)
+ {
+ bool init (false);
+
+ for (const shared_ptr<configuration>& c: cs->first)
+ {
+ if (find_if (c->packages.begin (),
+ c->packages.end (),
+ [&p] (const package_state& s)
+ {
+ return p.name == s.name;
+ }) != c->packages.end ())
+ {
+ init = true;
+ break;
+ }
+ }
+
+ if (init)
+ pkgs.push_back (move (p));
+ else
+ dep_pkgs.push_back (move (p.name).string ());
+ }
+
+ if (!pkgs.empty () && !dep_pkgs.empty ())
+ fail << "initialized packages specified with dependency packages";
+ }
+ }
+ }
+
// --implicit
//
if (o.implicit ())
@@ -2557,10 +2656,7 @@ namespace bdep
bool default_fallback (false);
- // In the implicit mode we don't search the current working directory
- // for a project.
- //
- if (o.directory_specified () || !o.implicit ())
+ if (!implicit_no_orig)
{
// We could be running from a package directory (or the user specified
// one with -d) that has not been init'ed in this configuration. This,
@@ -2577,13 +2673,16 @@ namespace bdep
!dep_pkgs.empty () /* ignore_packages */,
false /* load_packages */));
+ if (!pkgs.empty ())
+ pp.append (move (pkgs));
+
// Initialize tmp directory.
//
init_tmp (pp.project);
- // Load project configurations.
+ // Load project configurations, if not loaded yet.
//
- pair<configurations, bool> cs;
+ if (!cs)
{
database db (open (pp.project, trace));
@@ -2596,13 +2695,13 @@ namespace bdep
// configuration.
//
if (!pp.packages.empty ())
- verify_project_packages (pp, cs);
+ verify_project_packages (pp, *cs);
prj = move (pp.project);
prj_pkgs = move (pp.packages);
- cfgs.assign (make_move_iterator (cs.first.begin ()),
- make_move_iterator (cs.first.end ()));
- default_fallback = cs.second;
+ cfgs.assign (make_move_iterator (cs->first.begin ()),
+ make_move_iterator (cs->first.end ()));
+ default_fallback = cs->second;
}
else
{
@@ -2624,6 +2723,8 @@ namespace bdep
// noop loads the buildfiles. Maybe need something like bootstrap
// and load meta-operation?
//
+ // Note: this question also relates to bdep-status.
+ //
optional<string> open (getenv ("BPKG_OPEN_CONFIGS"));
for (const pair<dir_path, size_t>& c: o.config ())
diff --git a/bdep/test.cli b/bdep/test.cli
index a283b1b..35d099d 100644
--- a/bdep/test.cli
+++ b/bdep/test.cli
@@ -12,7 +12,7 @@ namespace bdep
{
"<options>
<prj-spec> <prj-dir>
- <pkg-spec> <pkg-dir>
+ <pkg-spec> <pkg> <pkg-dir>
<cfg-spec> <cfg-name> <cfg-dir>
<cfg-var>",
@@ -21,7 +21,7 @@ namespace bdep
\c{\b{bdep test} [<options>] [<pkg-spec>] [<cfg-spec>] [<cfg-var>...]}
\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
+ <pkg-spec> = (<pkg> | (\b{--directory}|\b{-d} <pkg-dir>))... | <prj-spec>\n
<prj-spec> = \b{--directory}|\b{-d} <prj-dir>}
\h|DESCRIPTION|
diff --git a/bdep/update.cli b/bdep/update.cli
index fc3df84..4c3f289 100644
--- a/bdep/update.cli
+++ b/bdep/update.cli
@@ -12,7 +12,7 @@ namespace bdep
{
"<options>
<prj-spec> <prj-dir>
- <pkg-spec> <pkg-dir>
+ <pkg-spec> <pkg> <pkg-dir>
<cfg-spec> <cfg-name> <cfg-dir>
<cfg-var>",
@@ -21,7 +21,7 @@ namespace bdep
\c{\b{bdep update} [<options>] [<pkg-spec>] [<cfg-spec>] [<cfg-var>...]}
\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
+ <pkg-spec> = (<pkg> | (\b{--directory}|\b{-d} <pkg-dir>))... | <prj-spec>\n
<prj-spec> = \b{--directory}|\b{-d} <prj-dir>}
\h|DESCRIPTION|
diff --git a/tests/ci.testscript b/tests/ci.testscript
index 7f3e538..bc22f36 100644
--- a/tests/ci.testscript
+++ b/tests/ci.testscript
@@ -910,10 +910,26 @@ windows = ($cxx.target.class == 'windows')
$build 'configure:' prj/@prj-cfg/,forward &prj/build/bootstrap/*** 2>!;
- $* --no-progress --forward 2>>~%EOE%
+ $* --no-progress --forward 2>>~%EOE%;
%CI request is queued.*%
%reference: .+%
EOE
+
+ # While at it, test specifying a package name on the command line.
+ #
+ # Suppress the --yes option.
+ #
+ test.arguments = $regex.apply($test.arguments, '^(--yes)$', '');
+
+ $* --no-progress --forward prj <'y' 2>>~"%EOE%"
+ submitting:
+ to: $server
+ % in: $repository#non-standard-version@.{40}%
+ package: prj
+ version: 12345
+ %continue\\?.+ CI request is queued.*%
+ %reference: .+%
+ EOE
}
}
@@ -954,6 +970,27 @@ windows = ($cxx.target.class == 'windows')
EOE
}
+ : pkg-by-name
+ :
+ {
+ $clone_prj;
+ $init -C @cfg &prj-cfg/***;
+
+ # Suppress the --yes option.
+ #
+ test.arguments = $regex.apply($test.arguments, '^(--yes)$', '');
+
+ $* libprj <'y' 2>>~"%EOE%"
+ submitting:
+ to: $server
+ % in: $repository#master@.{40}%
+ package: libprj
+ version: 1.0.1
+ %continue\\?.+ CI request is queued.*%
+ %reference: .+%
+ EOE
+ }
+
: diff-configs
:
{
diff --git a/tests/publish.testscript b/tests/publish.testscript
index 41b5eed..c34828a 100644
--- a/tests/publish.testscript
+++ b/tests/publish.testscript
@@ -33,7 +33,7 @@ g = [cmdline] 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.22
+# Next version to use: 1.0.25
#
# Normally we disable the progress indication that complicates stderr output
@@ -136,17 +136,39 @@ g = [cmdline] git -C prj >! 2>!
:
{
$new --no-init --no-amalgamation prj 2>- &prj/***;
- sed -i -e 's/^(version:) .*$/\1 12345/' prj/manifest;
+ sed -i -e 's/^(version:) .*$/\1 1.0.22/' prj/manifest;
sed -i \
- -e 's/^(amalgamation =.*)$/\1\nversion = 12345\ndist.package = $project-$version/' \
+ -e 's/^(amalgamation =.*)$/\1\nversion = 1.0.22\ndist.package = $project-$version/' \
-e 's/^using version$//' \
prj/build/bootstrap.build;
$build 'configure:' prj/@prj-cfg/,forward &prj/build/bootstrap/*** 2>!;
- $* --no-progress --forward --section alpha 2>>~%EOE%
- %package submission is queued(: .*prj/12345)?%
+ $* --no-progress --forward --section alpha 2>>~%EOE%;
+ %package submission is queued(: .*prj/1.0.22)?%
+ %reference: .{12}%
+ EOE
+
+ # While at it, test specifying a package name on the command line.
+ #
+ sed -i -e 's/^(version:) .*$/\1 1.0.23/' prj/manifest;
+ sed -i -e 's/^(version =) .*$/\1 1.0.23/' prj/build/bootstrap.build;
+
+ # Suppress the --yes option.
+ #
+ test.arguments = $regex.apply($test.arguments, '^(--yes)$', '');
+
+ $* --no-progress --forward --section alpha prj <'y' 2>>~"%EOE%"
+ publishing:
+ % to: $repository%
+ as: user <user@example.com>
+ package: prj
+ version: 1.0.23
+ project: prj
+ section: alpha
+ %.?
+ %continue\\?.+ package submission is queued.+%
%reference: .{12}%
EOE
}
@@ -178,6 +200,32 @@ g = [cmdline] git -C prj >! 2>!
EOE
}
+ : pkg-by-name
+ :
+ {
+ $clone_prj;
+ sed -i -e 's/^(version:) .*$/\1 1.0.24/' prj/libprj/manifest;
+ sed -i -e 's/^(version:) .*$/\1 1.0.24/' prj/prj/manifest;
+ $init -C @cfg &prj-cfg/***;
+
+ # Suppress the --yes option.
+ #
+ test.arguments = $regex.apply($test.arguments, '^(--yes)$', '');
+
+ $* libprj <'y' 2>>~"%EOE%"
+ publishing:
+ % to: $repository%
+ as: user <user@example.com>
+ package: libprj
+ version: 1.0.24
+ project: prj
+ section: stable
+ %.?
+ %continue\\?.+ package submission is queued.+%
+ %reference: .{12}%
+ EOE
+ }
+
: diff-configs
:
{
diff --git a/tests/status.testscript b/tests/status.testscript
index 10480ac..8c214c4 100644
--- a/tests/status.testscript
+++ b/tests/status.testscript
@@ -102,8 +102,8 @@ config += -d prj 2>!
]
EOO
- $* libbar 2>>EOE;
- info: no packages initialized in configuration @cfg, skipping
+ $* libbar 2>>/"EOE" != 0;
+ error: no packages in project $~/prj/
EOE
$* --stdout-format 'json' libbar >>~%EOO%
@@ -323,3 +323,178 @@ config += -d prj 2>!
drop libprj
EOE
}
+
+: pkg-by-name
+:
+{
+ $new -t empty prj &prj/***;
+
+ $new --package pkg1 -d prj;
+ $new --package pkg2 -d prj;
+
+ $init -C @cfg $config_cxx -d prj/pkg1 &prj-cfg/***;
+
+ $new -t lib libprj &libprj/***;
+
+ cat <<EOI >+prj/repositories.manifest;
+ :
+ role: prerequisite
+ location: ../libprj
+ type: dir
+ EOI
+
+ cat <<EOI >+prj/pkg1/manifest;
+ depends: libprj
+ EOI
+
+ $sync;
+
+ # Initialized package is specified.
+ #
+ $* -d prj/pkg1 >>EOO;
+ pkg1 configured 0.1.0-a.0.19700101000000#1
+ EOO
+
+ $* pkg1 --stdout-format 'json' >>~%EOO%;
+ [
+ {
+ "configuration": {
+ "id": 1,
+ % "path": ".+prj-cfg",%
+ "name": "cfg"
+ },
+ "packages": [
+ {
+ "name": "pkg1",
+ "status": "configured",
+ "version": "0.1.0-a.0.19700101000000#1",
+ "hold_package": true,
+ "hold_version": true
+ }
+ ]
+ }
+ ]
+ EOO
+
+ # Not initialized package is specified.
+ #
+ $* pkg2 >>EOO;
+ pkg2 available 0.1.0-a.0.19700101000000
+ EOO
+
+ $* pkg2 --stdout-format 'json' >>~%EOO%;
+ [
+ {
+ "configuration": {
+ "id": 1,
+ % "path": ".+prj-cfg",%
+ "name": "cfg"
+ },
+ "packages": [
+ {
+ "name": "pkg2",
+ "status": "available",
+ "available_versions": [
+ {
+ "version": "0.1.0-a.0.19700101000000"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ EOO
+
+ # Dependency package is specified.
+ #
+ $* libprj >>EOO;
+ libprj configured 0.1.0-a.0.19700101000000
+ EOO
+
+ $* libprj --stdout-format 'json' >>~%EOO%;
+ [
+ {
+ "configuration": {
+ "id": 1,
+ % "path": ".+prj-cfg",%
+ "name": "cfg"
+ },
+ "packages": [
+ {
+ "name": "libprj",
+ "status": "configured",
+ "version": "0.1.0-a.0.19700101000000"
+ }
+ ]
+ }
+ ]
+ EOO
+
+ # Unknown dependency package is specified.
+ #
+ $* libprj1 >>EOO;
+ libprj1 unknown
+ EOO
+
+ $* libprj1 --stdout-format 'json' >>~%EOO%;
+ [
+ {
+ "configuration": {
+ "id": 1,
+ % "path": ".+prj-cfg",%
+ "name": "cfg"
+ },
+ "packages": [
+ {
+ "name": "libprj1",
+ "status": "unknown"
+ }
+ ]
+ }
+ ]
+ EOO
+
+ # No packages are specified.
+ #
+ $* >>EOO;
+ pkg1 configured 0.1.0-a.0.19700101000000#1
+ EOO
+
+ $* --stdout-format 'json' >>~%EOO%;
+ [
+ {
+ "configuration": {
+ "id": 1,
+ % "path": ".+prj-cfg",%
+ "name": "cfg"
+ },
+ "packages": [
+ {
+ "name": "pkg1",
+ "status": "configured",
+ "version": "0.1.0-a.0.19700101000000#1",
+ "hold_package": true,
+ "hold_version": true
+ },
+ {
+ "name": "pkg2",
+ "status": "uninitialized"
+ }
+ ]
+ }
+ ]
+ EOO
+
+ # Both initialized and dependency packages are specified.
+ #
+ $* libprj pkg1 -d prj 2>>EOE != 0;
+ error: initialized packages specified with dependency packages
+ EOE
+
+ $deinit 2>>/"EOE"
+ deinitializing in project $~/prj/
+ synchronizing:
+ drop pkg1
+ drop libprj
+ EOE
+}
diff --git a/tests/sync.testscript b/tests/sync.testscript
index 0bdfb16..43124ca 100644
--- a/tests/sync.testscript
+++ b/tests/sync.testscript
@@ -205,6 +205,67 @@ deinit += -d prj
EOE
}
+: pkg-by-name
+:
+{
+ $new -t empty prj &prj/***;
+
+ $new --package pkg1 -d prj;
+ $new --package pkg2 -d prj;
+
+ init += -d prj;
+
+ $init -C @cfg $config_cxx &prj-cfg/***;
+
+ $new -t lib libprj &libprj/***;
+
+ cat <<EOI >+prj/repositories.manifest;
+ :
+ role: prerequisite
+ location: ../libprj
+ type: dir
+ EOI
+
+ cat <<EOI >+prj/pkg1/manifest;
+ depends: libprj
+ EOI
+
+ cat <<EOI >+prj/pkg2/manifest;
+ tags: c++
+ EOI
+
+ $* pkg1 -d prj/pkg2 ?libprj 2>>~%EOE%;
+ %.+
+ synchronizing:
+ new libprj/0.1.0-a.0.19700101000000 (required by pkg1)
+ upgrade pkg1/0.1.0-a.0.19700101000000#1
+ upgrade pkg2/0.1.0-a.0.19700101000000#1
+ EOE
+
+ sed -i -e 's/^(version:).+$/\1 1.0.0/' libprj/manifest;
+
+ $* libprj -f -d prj 2>>~%EOE%;
+ %.+
+ synchronizing:
+ upgrade libprj/1.0.0
+ reconfigure pkg1/0.1.0-a.0.19700101000000#1
+ EOE
+
+ $* libprj pkg1 -d prj 2>>EOE != 0;
+ error: initialized packages specified with dependency packages
+ EOE
+
+ $deinit 2>>/"EOE"
+ deinitializing in project $~/prj/
+ deinitializing package pkg1
+ deinitializing package pkg2
+ synchronizing:
+ drop pkg1
+ drop libprj
+ drop pkg2
+ EOE
+}
+
: config-vars
:
{
diff --git a/tests/update.testscript b/tests/update.testscript
index 528a12b..1f1b408 100644
--- a/tests/update.testscript
+++ b/tests/update.testscript
@@ -135,3 +135,39 @@ deinit += -d prj
drop pkg1
EOE
}
+
+: pkg-by-name
+:
+{
+ $new -t empty prj &prj/***;
+
+ $new --package pkg1 -d prj;
+ $new --package pkg2 -d prj;
+
+ $init -C @cfg &prj-cfg/***;
+
+ $* pkg3 -d prj/ 2>>/"EOE" != 0;
+ error: no package pkg3 in project $~/prj/
+ EOE
+
+ $* pkg1 -d prj/pkg2 2>>~%EOE%;
+ %(mkdir|c\+\+|ld|ln) .+%{8}
+ EOE
+
+ $* pkg1 -d prj/ 2>>~%EOE%;
+ %info: .+pkg1.+ is up to date%
+ EOE
+
+ $deinit pkg3 -d prj 2>>/"EOE" != 0;
+ error: no package pkg3 in project $~/prj/
+ EOE
+
+ $deinit pkg1 -d prj/pkg2 2>>/"EOE"
+ deinitializing in project $~/prj/
+ deinitializing package pkg1
+ deinitializing package pkg2
+ synchronizing:
+ drop pkg1
+ drop pkg2
+ EOE
+}