diff options
-rw-r--r-- | bdep/build.txx | 14 | ||||
-rw-r--r-- | bdep/ci.cli | 4 | ||||
-rw-r--r-- | bdep/ci.cxx | 15 | ||||
-rw-r--r-- | bdep/clean.cli | 4 | ||||
-rw-r--r-- | bdep/deinit.cli | 4 | ||||
-rw-r--r-- | bdep/deinit.cxx | 11 | ||||
-rw-r--r-- | bdep/project.cxx | 78 | ||||
-rw-r--r-- | bdep/project.hxx | 33 | ||||
-rw-r--r-- | bdep/projects-configs.cli | 9 | ||||
-rw-r--r-- | bdep/publish.cli | 4 | ||||
-rw-r--r-- | bdep/publish.cxx | 16 | ||||
-rw-r--r-- | bdep/status.cli | 8 | ||||
-rw-r--r-- | bdep/status.cxx | 142 | ||||
-rw-r--r-- | bdep/sync.cli | 9 | ||||
-rw-r--r-- | bdep/sync.cxx | 153 | ||||
-rw-r--r-- | bdep/test.cli | 4 | ||||
-rw-r--r-- | bdep/update.cli | 4 | ||||
-rw-r--r-- | tests/ci.testscript | 39 | ||||
-rw-r--r-- | tests/publish.testscript | 58 | ||||
-rw-r--r-- | tests/status.testscript | 179 | ||||
-rw-r--r-- | tests/sync.testscript | 61 | ||||
-rw-r--r-- | tests/update.testscript | 36 |
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 +} |