From 3a6c4ab1b6fc79a6a543088553cdd6bc8cb0a1dd Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 21 May 2018 21:10:09 +0300 Subject: Adapt to inventing package_name type --- bpkg/manifest-utility.cxx | 26 +++--- bpkg/manifest-utility.hxx | 15 +-- bpkg/odb.sh | 1 + bpkg/package.cxx | 8 +- bpkg/package.hxx | 26 ++++-- bpkg/package.ixx | 2 +- bpkg/package.xml | 16 ++-- bpkg/pkg-build.cxx | 126 +++++++++++++------------- bpkg/pkg-checkout.cxx | 26 ++++-- bpkg/pkg-checkout.hxx | 8 +- bpkg/pkg-command.cxx | 5 +- bpkg/pkg-configure.cxx | 20 ++-- bpkg/pkg-configure.hxx | 10 +- bpkg/pkg-disfigure.cxx | 4 +- bpkg/pkg-drop.cxx | 22 +++-- bpkg/pkg-fetch.cxx | 28 ++++-- bpkg/pkg-fetch.hxx | 11 ++- bpkg/pkg-purge.cxx | 4 +- bpkg/pkg-status.cxx | 6 +- bpkg/pkg-unpack.cxx | 33 +++++-- bpkg/pkg-unpack.hxx | 13 ++- bpkg/pkg-verify.cxx | 2 +- bpkg/rep-create.cxx | 5 +- bpkg/satisfaction.cxx | 6 +- bpkg/satisfaction.hxx | 6 +- bpkg/system-repository.cxx | 2 +- bpkg/system-repository.hxx | 9 +- bpkg/value-traits.hxx | 54 +++++++++++ tests/common/satisfy/libBar-2.0.0.tar.gz | Bin 0 -> 352 bytes tests/common/satisfy/t6/libBar-2.0.0.tar.gz | 1 + tests/common/satisfy/t6/repositories.manifest | 1 + tests/pkg-build.test | 42 +++++++++ tests/pkg-build/t6 | 1 + tests/pkg-drop.test | 4 +- 34 files changed, 369 insertions(+), 174 deletions(-) create mode 100644 bpkg/value-traits.hxx create mode 100644 tests/common/satisfy/libBar-2.0.0.tar.gz create mode 120000 tests/common/satisfy/t6/libBar-2.0.0.tar.gz create mode 120000 tests/common/satisfy/t6/repositories.manifest create mode 120000 tests/pkg-build/t6 diff --git a/bpkg/manifest-utility.cxx b/bpkg/manifest-utility.cxx index defa675..fcda389 100644 --- a/bpkg/manifest-utility.cxx +++ b/bpkg/manifest-utility.cxx @@ -35,32 +35,34 @@ namespace bpkg return package_scheme::none; } - string - parse_package_name (const char* s) + package_name + parse_package_name (const char* s, bool allow_version) { using traits = string::traits_type; + if (!allow_version) + try + { + return package_name (s); + } + catch (const invalid_argument& e) + { + fail << "invalid package name '" << s << "': " << e; + } + size_t n (traits::length (s)); if (const char* p = traits::find (s, n, '/')) n = static_cast (p - s); - string nm (s, n); - - // The package name may be a part of some compound argument. So while the - // invalid package name would likely result in the operation failure, the - // validating can ease the troubleshooting. - // try { - validate_package_name (nm); + return package_name (string (s, n)); } catch (const invalid_argument& e) { - fail << "invalid package name in '" << s << "': " << e; + fail << "invalid package name in '" << s << "': " << e << endf; } - - return nm; } version diff --git a/bpkg/manifest-utility.hxx b/bpkg/manifest-utility.hxx index c22746b..984786d 100644 --- a/bpkg/manifest-utility.hxx +++ b/bpkg/manifest-utility.hxx @@ -6,6 +6,7 @@ #define BPKG_MANIFEST_UTILITY_HXX #include +#include #include #include @@ -31,16 +32,16 @@ namespace bpkg package_scheme parse_package_scheme (const char*&); - // Extract and validate the package name and version components from - // [/]. + // Extract the package name and version components from [/]. + // Diagnose invalid components and throw failed. // - string - parse_package_name (const char*); + package_name + parse_package_name (const char*, bool allow_version = true); - inline string - parse_package_name (const string& s) + inline package_name + parse_package_name (const string& s, bool allow_version = true) { - return parse_package_name (s.c_str ()); + return parse_package_name (s.c_str (), allow_version); } // Return empty version if none is specified. diff --git a/bpkg/odb.sh b/bpkg/odb.sh index f0f9915..0149930 100755 --- a/bpkg/odb.sh +++ b/bpkg/odb.sh @@ -14,5 +14,6 @@ $odb $lib -I.. -I../../libbpkg -I../../libbutl \ -d sqlite --std c++14 --generate-query \ --odb-epilogue '#include ' \ --hxx-prologue '#include ' \ + --hxx-prologue '#include ' \ --include-with-brackets --include-prefix bpkg --guard-prefix BPKG \ --sqlite-override-null package.hxx diff --git a/bpkg/package.cxx b/bpkg/package.cxx index 788935e..dea16f2 100644 --- a/bpkg/package.cxx +++ b/bpkg/package.cxx @@ -249,15 +249,17 @@ namespace bpkg } string - package_string (const string& n, const version& v, bool system) + package_string (const package_name& n, const version& v, bool system) { + assert (!n.empty ()); + string vs (v.empty () ? string () : v == wildcard_version ? "/*" : '/' + v.string ()); - return system ? "sys:" + n + vs : n + vs; + return system ? "sys:" + n.string () + vs : n.string () + vs; } // selected_package @@ -273,7 +275,7 @@ namespace bpkg const dir_path& c, transaction& t, const dir_path& d, - const string& n, + const package_name& n, const version& v, bool check_external) { diff --git a/bpkg/package.hxx b/bpkg/package.hxx index d4db971..67ff6dd 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -16,6 +16,8 @@ #include +#include + #include #include // transaction #include @@ -408,16 +410,20 @@ namespace bpkg // extern const version wildcard_version; + // package_name + // + #pragma db value(package_name) type("TEXT") options("COLLATE NOCASE") + // available_package // #pragma db value struct available_package_id { - string name; + package_name name; canonical_version version; available_package_id () = default; - available_package_id (string, const bpkg::version&); + available_package_id (package_name, const bpkg::version&); }; bool @@ -474,7 +480,7 @@ namespace bpkg // constructor is only used to create transient/fake available packages // based on the system selected packages. // - available_package (string n, version_type sysv) + available_package (package_name n, version_type sysv) : id (move (n), wildcard_version), version (wildcard_version), system_version_ (sysv) {} @@ -659,7 +665,9 @@ namespace bpkg // is omitted for the empty one. // string - package_string (const string& name, const version&, bool system = false); + package_string (const package_name& name, + const version&, + bool system = false); // A map of "effective" prerequisites (i.e., pointers to other selected // packages) to optional dependency constraint. Note that because it is a @@ -678,7 +686,7 @@ namespace bpkg public: using version_type = bpkg::version; - std::string name; // Object id. + package_name name; // Object id. version_type version; package_state state; package_substate substate; @@ -802,8 +810,8 @@ namespace bpkg // #pragma db member(name) id - #pragma db member(prerequisites) id_column("package") \ - key_column("prerequisite") value_column("") key_not_null + #pragma db member(prerequisites) id_column("package") \ + key_column("prerequisite") key_not_null value_column("") private: friend class odb::access; @@ -853,7 +861,7 @@ namespace bpkg const dir_path& configuration, transaction&, const dir_path&, - const string& name, + const package_name&, const version&, bool check_external); @@ -968,7 +976,7 @@ namespace bpkg struct package_dependent { #pragma db column("pp.package") - string name; + package_name name; #pragma db column("pp.") optional constraint; diff --git a/bpkg/package.ixx b/bpkg/package.ixx index 17cbd95..9762ce8 100644 --- a/bpkg/package.ixx +++ b/bpkg/package.ixx @@ -7,7 +7,7 @@ namespace bpkg // available_package_id // inline available_package_id:: - available_package_id (string n, const bpkg::version& v) + available_package_id (package_name n, const bpkg::version& v) : name (move (n)), version {v.epoch, v.canonical_upstream, diff --git a/bpkg/package.xml b/bpkg/package.xml index fe297e7..2b7ac59 100644 --- a/bpkg/package.xml +++ b/bpkg/package.xml @@ -80,7 +80,7 @@ - + @@ -99,7 +99,7 @@
- + @@ -139,7 +139,7 @@
- + @@ -178,7 +178,7 @@
- + @@ -186,7 +186,7 @@ - + @@ -229,7 +229,7 @@
- + @@ -254,8 +254,8 @@
- - + + diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index e78244b..a4cbe7f 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -52,7 +52,7 @@ namespace bpkg // odb::result query_available (database& db, - const string& name, + const package_name& name, const optional& c) { using query = query; @@ -135,7 +135,7 @@ namespace bpkg // static pair, shared_ptr> find_available (database& db, - const string& name, + const package_name& name, const shared_ptr& rf, const optional& c, bool prereq = true) @@ -264,7 +264,7 @@ namespace bpkg // shared_ptr repository_fragment; - const string& + const package_name& name () const { return selected != nullptr ? selected->name : available->id.name; @@ -276,10 +276,10 @@ namespace bpkg optional hold_package; optional hold_version; - // Constraint value plus, normally, the dependent package name that - // placed this constraint but can also be some other name for the - // initial selection (e.g., package version specified by the user - // on the command line). + // Constraint value plus, normally, the dependent package name that placed + // this constraint but can also be some other name for the initial + // selection (e.g., package version specified by the user on the command + // line). This why we use the string type, rather than package_name. // struct constraint_type { @@ -306,12 +306,12 @@ namespace bpkg // Set of package names that caused this package to be built or adjusted. // Empty name signifies user selection. // - set required_by; + set required_by; bool user_selection () const { - return required_by.find ("") != required_by.end (); + return required_by.find (package_name ()) != required_by.end (); } // Adjustment flags. @@ -396,7 +396,9 @@ namespace bpkg if (p.keep_out) keep_out = p.keep_out; - required_by.insert (""); // Propagate the user-selection tag. + // Propagate the user-selection tag. + // + required_by.insert (package_name ()); } // Required-by package names have different semantics for different @@ -454,7 +456,7 @@ namespace bpkg // may already exists. // void - enter (string name, build_package pkg) + enter (package_name name, build_package pkg) { assert (!pkg.action); @@ -547,9 +549,9 @@ namespace bpkg // if (auto c1 = test (p2, p1)) { - const string& n (i->first); - const string& d1 (c1->dependent); - const string& d2 (c2->dependent); + const package_name& n (i->first); + const string& d1 (c1->dependent); + const string& d2 (c2->dependent); fail << "unable to satisfy constraints on package " << n << info << d1 << " depends on (" << n << " " << c1->value @@ -603,7 +605,9 @@ namespace bpkg // l4 ([&]{trace << "add " << pkg.available_name_version ();}); - string n (pkg.available->id.name); // Note: copy; see emplace() below. + // Note: copy; see emplace() below. + // + package_name n (pkg.available->id.name); i = map_.emplace (move (n), data_type {end (), move (pkg)}).first; } @@ -655,7 +659,7 @@ namespace bpkg const shared_ptr& ap (pkg.available); const shared_ptr& af (pkg.repository_fragment); - const string& name (ap->id.name); + const package_name& name (ap->id.name); for (const dependency_alternatives& da: ap->dependencies) { @@ -666,7 +670,7 @@ namespace bpkg fail << "multiple dependency alternatives not yet supported"; const dependency& dp (da.front ()); - const string& dn (dp.name); + const package_name& dn (dp.name); if (da.buildtime) { @@ -948,7 +952,7 @@ namespace bpkg // completeness. // if (dp.constraint) - bp.constraints.emplace_back (name, *dp.constraint); + bp.constraints.emplace_back (name.string (), *dp.constraint); // Now collect this prerequisite. If it was actually collected // (i.e., it wasn't already there) and we are forcing an upgrade @@ -1013,7 +1017,7 @@ namespace bpkg void collect_drop (shared_ptr sp) { - const string& nm (sp->name); + const package_name& nm (sp->name); build_package p { build_package::drop, @@ -1086,7 +1090,7 @@ namespace bpkg collect_build_prerequisites (const common_options& o, const dir_path& cd, database& db, - const string& name, + const package_name& name, postponed_packages& postponed) { auto mi (map_.find (name)); @@ -1121,7 +1125,7 @@ namespace bpkg // package to be considered as "early" as possible. // iterator - order (const string& name, bool reorder = true) + order (const package_name& name, bool reorder = true) { // Every package that we order should have already been collected. // @@ -1209,7 +1213,7 @@ namespace bpkg { for (const auto& p: sp->prerequisites) { - const string& name (p.first.object_id ()); + const package_name& name (p.first.object_id ()); // The prerequisites may not necessarily be in the map. // @@ -1234,7 +1238,7 @@ namespace bpkg { assert (!da.conditional && da.size () == 1); // @@ TODO const dependency& d (da.front ()); - const string& dn (d.name); + const package_name& dn (d.name); // Skip special names. // @@ -1252,7 +1256,7 @@ namespace bpkg { for (const auto& p: sp->prerequisites) { - const string& name (p.first.object_id ()); + const package_name& name (p.first.object_id ()); // The prerequisites may not necessarily be in the map. // @@ -1317,7 +1321,7 @@ namespace bpkg build_package& p (*pos); const shared_ptr& sp (p.selected); - const string& n (sp->name); + const package_name& n (sp->name); // See if we are up/downgrading this package. In particular, the // available package could be NULL meaning we are just adjusting. @@ -1330,7 +1334,7 @@ namespace bpkg for (auto& pd: db.query (query::name == n)) { - string& dn (pd.name); + package_name& dn (pd.name); auto i (map_.find (dn)); // First make sure the up/downgraded package still satisfies this @@ -1378,8 +1382,8 @@ namespace bpkg string rb; if (!p.user_selection ()) { - for (const string& n: p.required_by) - rb += ' ' + n; + for (const package_name& n: p.required_by) + rb += ' ' + n.string (); } if (!rb.empty ()) @@ -1394,7 +1398,7 @@ namespace bpkg // Add this contraint to the list for completeness. // - p.constraints.emplace_back (dn, c); + p.constraints.emplace_back (dn.string (), c); } auto adjustment = [&dn, &n, &db] () -> build_package @@ -1505,7 +1509,7 @@ namespace bpkg build_package package; }; - map map_; + map map_; }; // Return a patch version constraint for the selected package if it has a @@ -1519,8 +1523,8 @@ namespace bpkg static optional patch_constraint (const shared_ptr& sp, bool quiet = false) { - const string& nm (sp->name); - const version& sv (sp->version); + const package_name& nm (sp->name); + const version& sv (sp->version); // Note that we don't pass allow_stub flag so the system wildcard version // will (naturally) not be patched. @@ -1558,7 +1562,7 @@ namespace bpkg // struct dependency_package { - string name; + package_name name; bpkg::version version; // Empty if unspecified. shared_ptr selected; // NULL if not present. bool system; @@ -1614,7 +1618,7 @@ namespace bpkg assert (sp != nullptr && !sp->hold_package); - const string& nm (sp->name); + const package_name& nm (sp->name); // Query the dependents and bail out if the dependency is unused. // @@ -1712,8 +1716,8 @@ namespace bpkg { tracer trace ("evaluate_dependency"); - const string& nm (sp->name); - const version& sv (sp->version); + const package_name& nm (sp->name); + const version& sv (sp->version); auto no_change = [] () { @@ -1969,9 +1973,9 @@ namespace bpkg // struct recursive_package { - string name; - bool upgrade; // true -- upgrade, false -- patch. - bool recursive; // true -- recursive, false -- immediate. + package_name name; + bool upgrade; // true -- upgrade, false -- patch. + bool recursive; // true -- recursive, false -- immediate. }; using recursive_packages = vector; @@ -1981,7 +1985,7 @@ namespace bpkg // static optional upgrade_dependencies (database& db, - const string& nm, + const package_name& nm, const recursive_packages& recs, bool recursion = false) { @@ -2405,7 +2409,7 @@ namespace bpkg struct pkg_arg { package_scheme scheme; - string name; + package_name name; bpkg::version version; string value; pkg_options options; @@ -2414,7 +2418,7 @@ namespace bpkg // Create the parsed package argument. // auto arg_package = [] (package_scheme sc, - string nm, + package_name nm, version v, pkg_options o) -> pkg_arg { @@ -2447,7 +2451,7 @@ namespace bpkg auto arg_raw = [] (string v, pkg_options o) -> pkg_arg { return pkg_arg { - package_scheme::none, string (), version (), move (v), move (o)}; + package_scheme::none, package_name (), version (), move (v), move (o)}; }; auto arg_parsed = [] (const pkg_arg& a) {return !a.name.empty ();}; @@ -2497,8 +2501,8 @@ namespace bpkg if (h != package_scheme::none) // Add parsed. { - string n (parse_package_name (s)); - version v (parse_package_version (s)); + package_name n (parse_package_name (s)); + version v (parse_package_version (s)); pkg_args.push_back ( arg_package (h, move (n), move (v), move (ps.options))); @@ -2526,7 +2530,7 @@ namespace bpkg { // Collect the latest package versions. // - map pvs; + map pvs; for (const repository::fragment_type& rf: r->fragments) { @@ -2542,7 +2546,7 @@ namespace bpkg if (p->stub ()) // Skip stubs. continue; - const string& nm (p->id.name); + const package_name& nm (p->id.name); if (ps.options.patch ()) { @@ -2617,8 +2621,8 @@ namespace bpkg const char* s (pkg.c_str ()); package_scheme sc (parse_package_scheme (s)); - string n (parse_package_name (s)); - version v (parse_package_version (s)); + package_name n (parse_package_name (s)); + version v (parse_package_version (s)); // Check if the package is present in the repository and its // complements, recursively. If the version is not specified then @@ -2726,7 +2730,7 @@ namespace bpkg // Check if the package is a duplicate. Return true if it is but // harmless. // - map package_map; + map package_map; auto check_dup = [&package_map, &arg_string, arg_parsed] ( const pkg_arg& pa) -> bool @@ -2930,8 +2934,8 @@ namespace bpkg // Make sure that we can parse both package name and version, // prior to saving them into the package arg. // - string n (parse_package_name (package)); - version v (parse_package_version (package)); + package_name n (parse_package_name (package)); + version v (parse_package_version (package)); pa = arg_package (package_scheme::none, move (n), @@ -3211,7 +3215,7 @@ namespace bpkg {}, // Constraints. arg_sys (pa), keep_out, - {""}, // Required by (command line). + {package_name ()}, // Required by (command line). 0}; // Adjustments. l4 ([&]{trace << "stashing held package " @@ -3249,7 +3253,7 @@ namespace bpkg if (sp->system ()) continue; - const string& name (sp->name); + const package_name& name (sp->name); optional pc; @@ -3298,7 +3302,7 @@ namespace bpkg {}, // Constraints. false, // System package. keep_out, - {""}, // Required by (command line). + {package_name ()}, // Required by (command line). 0}; // Adjustments. l4 ([&]{trace << "stashing held package " @@ -3374,7 +3378,7 @@ namespace bpkg { struct dep { - string name; // Empty if up/down-grade. + package_name name; // Empty if up/down-grade. // Both are NULL if drop. // @@ -3420,7 +3424,7 @@ namespace bpkg {}, // Constraints. p.system, p.keep_out, - {""}, // Required by (command line). + {package_name ()}, // Required by (command line). 0}; // Adjustments. if (!p.version.empty ()) @@ -3491,7 +3495,7 @@ namespace bpkg {}, // Constraints. d.system, keep_out, - {""}, // Required by (command line). + {package_name ()}, // Required by (command line). 0}; // Adjustments. pkgs.collect_build (o, c, db, p, &postponed /* recursively */); @@ -3842,7 +3846,7 @@ namespace bpkg act += "/unhold"; } - act += ' ' + sp->name; + act += ' ' + sp->name.string (); } else { @@ -3892,8 +3896,8 @@ namespace bpkg string rb; if (!p.user_selection ()) { - for (const string& n: p.required_by) - rb += ' ' + n; + for (const package_name& n: p.required_by) + rb += ' ' + n.string (); // If not user-selected, then there should be another (implicit) // reason for the action. diff --git a/bpkg/pkg-checkout.cxx b/bpkg/pkg-checkout.cxx index 21af094..a7421b5 100644 --- a/bpkg/pkg-checkout.cxx +++ b/bpkg/pkg-checkout.cxx @@ -60,7 +60,7 @@ namespace bpkg pkg_checkout (const common_options& o, const dir_path& c, transaction& t, - string n, + package_name n, version v, bool replace, bool simulate) @@ -150,7 +150,7 @@ namespace bpkg auto_rmdir rmd; optional mc; - dir_path d (c / dir_path (n + '-' + v.string ())); + dir_path d (c / dir_path (n.string () + '-' + v.string ())); if (!simulate) { @@ -160,7 +160,7 @@ namespace bpkg // The temporary out of source directory that is required for the dist // meta-operation. // - auto_rmdir rmo (temp_dir / dir_path (n)); + auto_rmdir rmo (temp_dir / dir_path (n.string ())); const dir_path& od (rmo.path); if (exists (od)) @@ -213,6 +213,20 @@ namespace bpkg // pkg_purge_fs (c, t, p, simulate); + // Note that if the package name spelling changed then we need to update + // it, to make sure that the subsequent commands don't fail and the + // diagnostics is not confusing. Hover, we cannot update the object id, + // so have to erase it and persist afterwards. + // + if (p->name.string () != n.string ()) + { + db.erase (p); + p = nullptr; + } + } + + if (p != nullptr) + { p->version = move (v); p->state = package_state::unpacked; p->repository_fragment = rl; @@ -269,9 +283,9 @@ namespace bpkg fail << "package name/version argument expected" << info << "run 'bpkg help pkg-checkout' for more information"; - const char* arg (args.next ()); - string n (parse_package_name (arg)); - version v (parse_package_version (arg)); + const char* arg (args.next ()); + package_name n (parse_package_name (arg)); + version v (parse_package_version (arg)); if (v.empty ()) fail << "package version expected" << diff --git a/bpkg/pkg-checkout.hxx b/bpkg/pkg-checkout.hxx index d95cc77..30b96ee 100644 --- a/bpkg/pkg-checkout.hxx +++ b/bpkg/pkg-checkout.hxx @@ -5,7 +5,8 @@ #ifndef BPKG_PKG_CHECKOUT_HXX #define BPKG_PKG_CHECKOUT_HXX -#include // version +#include // version +#include #include #include // transaction, selected_package @@ -19,13 +20,14 @@ namespace bpkg pkg_checkout (const pkg_checkout_options&, cli::scanner& args); // Check out the package from a version control-based repository and commit - // the transaction. + // the transaction. Can return a new selected package object, replacing the + // existing one. // shared_ptr pkg_checkout (const common_options&, const dir_path& configuration, transaction&, - string name, + package_name, version, bool replace, bool simulate); diff --git a/bpkg/pkg-command.cxx b/bpkg/pkg-command.cxx index 6deb1d4..52e47c0 100644 --- a/bpkg/pkg-command.cxx +++ b/bpkg/pkg-command.cxx @@ -10,6 +10,7 @@ #include #include #include +#include using namespace std; using namespace butl; @@ -237,7 +238,9 @@ namespace bpkg { while (args.more ()) { - string n (args.next ()); + package_name n (parse_package_name (args.next (), + false /* allow_version */)); + shared_ptr p (db.find (n)); if (p == nullptr) diff --git a/bpkg/pkg-configure.cxx b/bpkg/pkg-configure.cxx index 056b85c..6db60d4 100644 --- a/bpkg/pkg-configure.cxx +++ b/bpkg/pkg-configure.cxx @@ -23,7 +23,7 @@ namespace bpkg pkg_configure_prerequisites (const common_options& o, transaction& t, const dependencies& deps, - const string& package) + const package_name& package) { package_prerequisites r; @@ -36,7 +36,7 @@ namespace bpkg bool satisfied (false); for (const dependency& d: da) { - const string& n (d.name); + const package_name& n (d.name); if (da.buildtime) { @@ -127,9 +127,10 @@ namespace bpkg // Calculate package's out_root. // - dir_path out_root (p->external () - ? c / dir_path (p->name) - : c / dir_path (p->name + "-" + p->version.string ())); + dir_path out_root ( + p->external () + ? c / dir_path (p->name.string ()) + : c / dir_path (p->name.string () + "-" + p->version.string ())); l4 ([&]{trace << "src_root: " << src_root << ", " << "out_root: " << out_root;}); @@ -193,7 +194,9 @@ namespace bpkg } shared_ptr - pkg_configure_system (const string& n, const version& v, transaction& t) + pkg_configure_system (const package_name& n, + const version& v, + transaction& t) { tracer trace ("pkg_configure_system"); @@ -271,7 +274,7 @@ namespace bpkg // Configure system package. // version v (parse_package_version (package)); - n = parse_package_name (package); + package_name n (parse_package_name (package)); p = db.find (n); @@ -292,7 +295,8 @@ namespace bpkg { // Configure unpacked package. // - p = db.find (n); + p = db.find ( + parse_package_name (n, false /* allow_version */)); if (p == nullptr) fail << "package " << n << " does not exist in configuration " << c; diff --git a/bpkg/pkg-configure.hxx b/bpkg/pkg-configure.hxx index f82c699..2aeb8bb 100644 --- a/bpkg/pkg-configure.hxx +++ b/bpkg/pkg-configure.hxx @@ -5,11 +5,15 @@ #ifndef BPKG_PKG_CONFIGURE_HXX #define BPKG_PKG_CONFIGURE_HXX +#include // version +#include + #include #include // transaction, selected_package #include -#include +#include // package_prerequisites, + // dependencies. #include namespace bpkg @@ -31,7 +35,7 @@ namespace bpkg // Configure a system package and commit the transaction. // shared_ptr - pkg_configure_system (const string& name, const version&, transaction&); + pkg_configure_system (const package_name&, const version&, transaction&); // Return package prerequisites given its dependencies. Fail if some of the // prerequisites are not configured or don't satisfy the package's @@ -42,7 +46,7 @@ namespace bpkg pkg_configure_prerequisites (const common_options&, transaction&, const dependencies&, - const string& package); + const package_name&); } #endif // BPKG_PKG_CONFIGURE_HXX diff --git a/bpkg/pkg-disfigure.cxx b/bpkg/pkg-disfigure.cxx index 44a3006..bcd14f1 100644 --- a/bpkg/pkg-disfigure.cxx +++ b/bpkg/pkg-disfigure.cxx @@ -8,6 +8,7 @@ #include #include #include +#include using namespace std; using namespace butl; @@ -204,7 +205,8 @@ namespace bpkg fail << "package name argument expected" << info << "run 'bpkg help pkg-disfigure' for more information"; - string n (args.next ()); + package_name n (parse_package_name (args.next (), + false /* allow_version */)); database db (open (c, trace)); transaction t (db); diff --git a/bpkg/pkg-drop.cxx b/bpkg/pkg-drop.cxx index 8b22347..33ccb20 100644 --- a/bpkg/pkg-drop.cxx +++ b/bpkg/pkg-drop.cxx @@ -42,8 +42,8 @@ namespace bpkg // struct dependent_name { - string name; - string prq_name; // Prerequisite package name. + package_name name; + package_name prq_name; // Prerequisite package name. }; using dependent_names = vector; @@ -72,7 +72,7 @@ namespace bpkg bool collect (shared_ptr p, drop_reason r = drop_reason::user) { - string n (p->name); // Because of move(p) below. + package_name n (p->name); // Because of move(p) below. return map_.emplace (move (n), data_type {end (), {move (p), r}}).second; } @@ -107,7 +107,7 @@ namespace bpkg for (auto& pd: db.query (query::name == p->name)) { - const string& dn (pd.name); + const package_name& dn (pd.name); if (map_.find (dn) == map_.end ()) { @@ -172,7 +172,7 @@ namespace bpkg // returning its positions. // iterator - order (const string& name) + order (const package_name& name) { // Every package that we order should have already been collected. // @@ -215,7 +215,7 @@ namespace bpkg { for (const auto& pair: p->prerequisites) { - const string& pn (pair.first.object_id ()); + const package_name& pn (pair.first.object_id ()); // The prerequisites may not necessarily be in the map (e.g., // a held package that we prunned). @@ -285,7 +285,7 @@ namespace bpkg drop_package package; }; - map map_; + map map_; }; // Drop ordered list of packages. @@ -464,10 +464,12 @@ namespace bpkg // The first step is to load and collect all the packages specified // by the user. // - strings names; + vector names; while (args.more ()) { - string n (args.next ()); + package_name n (parse_package_name (args.next (), + false /* allow_version */)); + l4 ([&]{trace << "package " << n;}); shared_ptr p (db.find (n)); @@ -538,7 +540,7 @@ namespace bpkg // the user selection, it will be inserted before the first package // on which it depends. // - for (const string& n: names) + for (const package_name& n: names) pkgs.order (n); for (const dependent_name& dn: dnames) diff --git a/bpkg/pkg-fetch.cxx b/bpkg/pkg-fetch.cxx index e157bd9..0ce6d9e 100644 --- a/bpkg/pkg-fetch.cxx +++ b/bpkg/pkg-fetch.cxx @@ -22,10 +22,12 @@ using namespace butl; namespace bpkg { + // Can return a new selected package object, replacing the existing one. + // static shared_ptr pkg_fetch (dir_path c, transaction& t, - string n, + package_name n, version v, path a, repository_location rl, @@ -56,6 +58,20 @@ namespace bpkg // pkg_purge_fs (c, t, p, simulate); + // Note that if the package name spelling changed then we need to update + // it, to make sure that the subsequent commands don't fail and the + // diagnostics is not confusing. However, we cannot update the object + // id, so have to erase it and persist afterwards. + // + if (p->name.string () != n.string ()) + { + db.erase (p); + p = nullptr; + } + } + + if (p != nullptr) + { p->version = move (v); p->state = package_state::fetched; p->repository_fragment = move (rl); @@ -100,7 +116,7 @@ namespace bpkg static void pkg_fetch_check (const dir_path& c, transaction& t, - const string& n, + const package_name& n, bool replace) { tracer trace ("pkg_fetch_check"); @@ -170,7 +186,7 @@ namespace bpkg pkg_fetch (const common_options& co, const dir_path& c, transaction& t, - string n, + package_name n, version v, bool replace, bool simulate) @@ -299,9 +315,9 @@ namespace bpkg fail << "package name/version argument expected" << info << "run 'bpkg help pkg-fetch' for more information"; - const char* arg (args.next ()); - string n (parse_package_name (arg)); - version v (parse_package_version (arg)); + const char* arg (args.next ()); + package_name n (parse_package_name (arg)); + version v (parse_package_version (arg)); if (v.empty ()) fail << "package version expected" << diff --git a/bpkg/pkg-fetch.hxx b/bpkg/pkg-fetch.hxx index 54df466..bdb7f77 100644 --- a/bpkg/pkg-fetch.hxx +++ b/bpkg/pkg-fetch.hxx @@ -5,7 +5,8 @@ #ifndef BPKG_PKG_FETCH_HXX #define BPKG_PKG_FETCH_HXX -#include // version +#include // version +#include #include #include // transaction, selected_package @@ -18,7 +19,8 @@ namespace bpkg int pkg_fetch (const pkg_fetch_options&, cli::scanner& args); - // Fetch the package as an archive file and commit the transaction. + // Fetch the package as an archive file and commit the transaction. Can + // return a new selected package object, replacing the existing one. // shared_ptr pkg_fetch (const common_options&, @@ -30,13 +32,14 @@ namespace bpkg bool simulate); // Fetch the package from an archive-based repository and commit the - // transaction. + // transaction. Can return a new selected package object, replacing the + // existing one. // shared_ptr pkg_fetch (const common_options&, const dir_path& configuration, transaction&, - string name, + package_name, version, bool replace, bool simulate); diff --git a/bpkg/pkg-purge.cxx b/bpkg/pkg-purge.cxx index 2db4249..c4e89c3 100644 --- a/bpkg/pkg-purge.cxx +++ b/bpkg/pkg-purge.cxx @@ -8,6 +8,7 @@ #include #include #include +#include using namespace std; using namespace butl; @@ -117,7 +118,8 @@ namespace bpkg fail << "package name argument expected" << info << "run 'bpkg help pkg-purge' for more information"; - string n (args.next ()); + package_name n (parse_package_name (args.next (), + false /* allow_version */)); database db (open (c, trace)); transaction t (db); diff --git a/bpkg/pkg-status.cxx b/bpkg/pkg-status.cxx index c5f74d9..8ca2ac7 100644 --- a/bpkg/pkg-status.cxx +++ b/bpkg/pkg-status.cxx @@ -19,7 +19,7 @@ namespace bpkg { struct package { - string name; + package_name name; bpkg::version version; // Empty if unspecified. shared_ptr selected; // NULL if none selected. optional constraint; // Version constraint, if any. @@ -129,7 +129,9 @@ namespace bpkg cout << '!'; } - cout << p.name; + // If the package name is selected, then print its exact spelling. + // + cout << (s != nullptr ? s->name : p.name); if (o.constraint () && p.constraint) cout << ' ' << *p.constraint; diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx index 89a737b..85cd93f 100644 --- a/bpkg/pkg-unpack.cxx +++ b/bpkg/pkg-unpack.cxx @@ -33,7 +33,7 @@ namespace bpkg static void pkg_unpack_check (const dir_path& c, transaction& t, - const string& n, + const package_name& n, bool replace) { tracer trace ("pkg_update_check"); @@ -61,13 +61,14 @@ namespace bpkg } } - // Select the external package in this configuration. + // Select the external package in this configuration. Can return a new + // selected package object, replacing the existing one. // static shared_ptr pkg_unpack (const common_options& o, dir_path c, transaction& t, - string n, + package_name n, version v, dir_path d, repository_location rl, @@ -104,6 +105,20 @@ namespace bpkg // pkg_purge_fs (c, t, p, simulate); + // Note that if the package name spelling changed then we need to update + // it, to make sure that the subsequent commands don't fail and the + // diagnostics is not confusing. Hover, we cannot update the object id, + // so have to erase it and persist afterwards. + // + if (p->name.string () != n.string ()) + { + db.erase (p); + p = nullptr; + } + } + + if (p != nullptr) + { p->version = move (v); p->state = package_state::unpacked; p->repository_fragment = move (rl); @@ -190,7 +205,7 @@ namespace bpkg pkg_unpack (const common_options& o, const dir_path& c, transaction& t, - string n, + package_name n, version v, bool replace, bool simulate) @@ -254,7 +269,7 @@ namespace bpkg pkg_unpack (const common_options& co, const dir_path& c, transaction& t, - const string& name, + const package_name& name, bool simulate) { tracer trace ("pkg_unpack"); @@ -280,7 +295,7 @@ namespace bpkg // Also, since we must have verified the archive during fetch, // here we can just assume what the resulting directory will be. // - dir_path d (c / dir_path (p->name + '-' + p->version.string ())); + dir_path d (c / dir_path (p->name.string () + '-' + p->version.string ())); if (exists (d)) fail << "package directory " << d << " already exists"; @@ -462,9 +477,9 @@ namespace bpkg fail << "package name argument expected" << info << "run 'bpkg help pkg-unpack' for more information"; - const char* arg (args.next ()); - string n (parse_package_name (arg)); - version v (parse_package_version (arg)); + const char* arg (args.next ()); + package_name n (parse_package_name (arg)); + version v (parse_package_version (arg)); external = !v.empty (); diff --git a/bpkg/pkg-unpack.hxx b/bpkg/pkg-unpack.hxx index 79dfe1c..cab335f 100644 --- a/bpkg/pkg-unpack.hxx +++ b/bpkg/pkg-unpack.hxx @@ -5,7 +5,8 @@ #ifndef BPKG_PKG_UNPACK_HXX #define BPKG_PKG_UNPACK_HXX -#include // version +#include // version +#include #include #include // transaction, selected_package @@ -18,7 +19,8 @@ namespace bpkg int pkg_unpack (const pkg_unpack_options&, cli::scanner& args); - // Unpack the package as a source directory and commit the transaction. + // Unpack the package as a source directory and commit the transaction. Can + // return a new selected package object, replacing the existing one. // shared_ptr pkg_unpack (const common_options&, @@ -35,17 +37,18 @@ namespace bpkg pkg_unpack (const common_options&, const dir_path& configuration, transaction&, - const string& name, + const package_name&, bool simulate); // Unpack the package as a source directory from a directory-based - // repository and commit the transaction. + // repository and commit the transaction. Can return a new selected package + // object, replacing the existing one. // shared_ptr pkg_unpack (const common_options&, const dir_path& configuration, transaction&, - string name, + package_name, version, bool replace, bool simulate); diff --git a/bpkg/pkg-verify.cxx b/bpkg/pkg-verify.cxx index bad13d3..2711394 100644 --- a/bpkg/pkg-verify.cxx +++ b/bpkg/pkg-verify.cxx @@ -47,7 +47,7 @@ namespace bpkg { // Verify package archive/directory is -. // - dir_path ed (m.name + "-" + m.version.string ()); + dir_path ed (m.name.string () + "-" + m.version.string ()); if (pd != ed) { diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx index d052223..ad63267 100644 --- a/bpkg/rep-create.cxx +++ b/bpkg/rep-create.cxx @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -28,7 +29,7 @@ namespace bpkg { struct package_key { - string name; + package_name name; bpkg::version version; // There shouldn't be multiple revisions of the same package @@ -111,7 +112,7 @@ namespace bpkg // m.location = a.leaf (root); - dir_path pd (m.name + "-" + m.version.string ()); + dir_path pd (m.name.string () + "-" + m.version.string ()); // Expand the description-file manifest value. // diff --git a/bpkg/satisfaction.cxx b/bpkg/satisfaction.cxx index a41b79a..e620d3b 100644 --- a/bpkg/satisfaction.cxx +++ b/bpkg/satisfaction.cxx @@ -100,7 +100,7 @@ namespace bpkg void satisfy_build2 (const common_options& o, - const string& pkg, + const package_name& pkg, const dependency& d) { assert (d.name == "build2"); @@ -157,7 +157,9 @@ namespace bpkg static version bpkg_version; void - satisfy_bpkg (const common_options&, const string& pkg, const dependency& d) + satisfy_bpkg (const common_options&, + const package_name& pkg, + const dependency& d) { assert (d.name == "bpkg"); diff --git a/bpkg/satisfaction.hxx b/bpkg/satisfaction.hxx index 85733c7..c79d1fb 100644 --- a/bpkg/satisfaction.hxx +++ b/bpkg/satisfaction.hxx @@ -41,10 +41,12 @@ namespace bpkg // Special build-time dependencies. // void - satisfy_build2 (const common_options&, const string& pkg, const dependency&); + satisfy_build2 (const common_options&, + const package_name&, + const dependency&); void - satisfy_bpkg (const common_options&, const string& pkg, const dependency&); + satisfy_bpkg (const common_options&, const package_name&, const dependency&); } #endif // BPKG_SATISFACTION_HXX diff --git a/bpkg/system-repository.cxx b/bpkg/system-repository.cxx index 6735bce..3ea02a6 100644 --- a/bpkg/system-repository.cxx +++ b/bpkg/system-repository.cxx @@ -9,7 +9,7 @@ namespace bpkg system_repository_type system_repository; const version& system_repository_type:: - insert (const string& name, const version& v, bool authoritative) + insert (const package_name& name, const version& v, bool authoritative) { auto p (map_.emplace (name, system_package {v, authoritative})); diff --git a/bpkg/system-repository.hxx b/bpkg/system-repository.hxx index eeddf39..ba42b0e 100644 --- a/bpkg/system-repository.hxx +++ b/bpkg/system-repository.hxx @@ -7,7 +7,8 @@ #include -#include +#include // version +#include #include #include @@ -36,17 +37,17 @@ namespace bpkg { public: const version& - insert (const string& name, const version&, bool authoritative); + insert (const package_name& name, const version&, bool authoritative); const system_package* - find (const string& name) + find (const package_name& name) { auto i (map_.find (name)); return i != map_.end () ? &i->second : nullptr; } private: - std::map map_; + std::map map_; }; extern system_repository_type system_repository; diff --git a/bpkg/value-traits.hxx b/bpkg/value-traits.hxx new file mode 100644 index 0000000..b55cfb5 --- /dev/null +++ b/bpkg/value-traits.hxx @@ -0,0 +1,54 @@ +// file : bpkg/value-traits.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BPKG_VALUE_TRAITS_HXX +#define BPKG_VALUE_TRAITS_HXX + +#include +#include // size_t +#include // move() + +#include + +#include + +namespace odb +{ + namespace sqlite + { + template <> + class value_traits: + value_traits + { + public: + using value_type = bpkg::package_name; + using query_type = bpkg::package_name; + using image_type = details::buffer; + + using base_type = value_traits; + + static void + set_value (value_type& v, + const details::buffer& b, + std::size_t n, + bool is_null) + { + std::string s; + base_type::set_value (s, b, n, is_null); + v = !s.empty () ? value_type (std::move (s)) : value_type (); + } + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + const value_type& v) + { + base_type::set_image (b, n, is_null, v.string ()); + } + }; + }; +} + +#endif // BPKG_WRAPPER_TRAITS_HXX diff --git a/tests/common/satisfy/libBar-2.0.0.tar.gz b/tests/common/satisfy/libBar-2.0.0.tar.gz new file mode 100644 index 0000000..9a11ec9 Binary files /dev/null and b/tests/common/satisfy/libBar-2.0.0.tar.gz differ diff --git a/tests/common/satisfy/t6/libBar-2.0.0.tar.gz b/tests/common/satisfy/t6/libBar-2.0.0.tar.gz new file mode 120000 index 0000000..8a99698 --- /dev/null +++ b/tests/common/satisfy/t6/libBar-2.0.0.tar.gz @@ -0,0 +1 @@ +../libBar-2.0.0.tar.gz \ No newline at end of file diff --git a/tests/common/satisfy/t6/repositories.manifest b/tests/common/satisfy/t6/repositories.manifest new file mode 120000 index 0000000..0d4767a --- /dev/null +++ b/tests/common/satisfy/t6/repositories.manifest @@ -0,0 +1 @@ +../repositories.manifest \ No newline at end of file diff --git a/tests/pkg-build.test b/tests/pkg-build.test index 88d069a..7a6a83d 100644 --- a/tests/pkg-build.test +++ b/tests/pkg-build.test @@ -96,6 +96,10 @@ # | |-- libbar-1.2.0.tar.gz # | `-- repositories.manifest # | +# |-- t6 +# | |-- libBar-2.0.0.tar.gz +# | `-- repositories.manifest +# | # |-- libhello-1.0.0 # | |-- build # | | |-- bootstrap.build @@ -125,6 +129,7 @@ cp -r $src/t4c $out/t4c && $rep_create $out/t4c &$out/t4c/packages.manifest cp -r $src/t4d $out/t4d && $rep_create $out/t4d &$out/t4d/packages.manifest cp -r $src/t5 $out/t5 && $rep_create $out/t5 &$out/t5/packages.manifest + cp -r $src/t6 $out/t6 && $rep_create $out/t6 &$out/t6/packages.manifest # Create git repositories. # @@ -3329,6 +3334,43 @@ rep_fetch += -d cfg --auth all --trust-yes 2>! } } +: ignore-case +: +{ + test.arguments += --yes --auth all --trust-yes + + $clone_cfg; + + $* "libbar@$rep/t5" 2>>~%EOE%; + added pkg:build2.org/pkg-build/t5 + fetching pkg:build2.org/pkg-build/t5 + %.* + %.*fetched libbar/1.2.0% + unpacked libbar/1.2.0 + configured libbar/1.2.0 + %info: .+dir\{libbar-1.2.0.\} is up to date% + updated libbar/1.2.0 + EOE + + $* "libbar@$rep/t6" 2>>~%EOE%; + added pkg:build2.org/pkg-build/t6 + fetching pkg:build2.org/pkg-build/t6 + disfigured libbar/1.2.0 + %.* + %.*fetched libBar/2.0.0% + unpacked libBar/2.0.0 + configured libBar/2.0.0 + %info: .+dir\{libBar-2.0.0.\} is up to date% + updated libBar/2.0.0 + EOE + + $pkg_status libbar >'!libBar configured !2.0.0'; + + test -d cfg/libBar-2.0.0; + + $pkg_drop libbar +} + : git-rep : if ($git_supported != true) diff --git a/tests/pkg-build/t6 b/tests/pkg-build/t6 new file mode 120000 index 0000000..1174dda --- /dev/null +++ b/tests/pkg-build/t6 @@ -0,0 +1 @@ +../common/satisfy/t6 \ No newline at end of file diff --git a/tests/pkg-drop.test b/tests/pkg-drop.test index c035837..f0ff50f 100644 --- a/tests/pkg-drop.test +++ b/tests/pkg-drop.test @@ -53,11 +53,11 @@ $* libfoo 2>>/EOE != 0 error: package libfoo does not exist in configuration cfg/ EOE -: unknown-package-ver +: invalid-name : $clone_cfg; $* libfoo/1.0.0 2>>~%EOE% != 0 - %error: package libfoo/1.0.0 does not exist in configuration cfg[/\\]% + %error: invalid package name 'libfoo/1.0.0': illegal character% EOE : dependencies-or-dependents -- cgit v1.1