From cbd3cd125b574deaf1ad3c7001c5b6c9c40198ed Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 22 Dec 2018 22:42:13 +0300 Subject: Add support for $ in package manifest dependency constraint --- bpkg/package.hxx | 2 + bpkg/pkg-build.cxx | 32 +++++++---- bpkg/pkg-checkout.cxx | 2 +- bpkg/pkg-configure.cxx | 4 +- bpkg/pkg-configure.hxx | 3 + bpkg/pkg-fetch.cxx | 4 +- bpkg/pkg-unpack.cxx | 2 +- bpkg/pkg-verify.cli | 2 +- bpkg/pkg-verify.cxx | 13 +++-- bpkg/pkg-verify.hxx | 10 ++-- bpkg/rep-create.cxx | 2 +- bpkg/satisfaction.cxx | 4 +- bpkg/satisfaction.hxx | 3 + doc/manual.cli | 95 ++++++++++++++++++++++++++++++- tests/common/git/state0/libbar.tar | Bin 71680 -> 81920 bytes tests/common/git/state0/libfoo.tar | Bin 317440 -> 327680 bytes tests/common/git/state0/libfox.tar | Bin 133120 -> 143360 bytes tests/common/git/state0/style-basic.tar | Bin 71680 -> 71680 bytes tests/common/git/state0/style.tar | Bin 133120 -> 143360 bytes tests/common/git/state1/libbaz.tar | Bin 61440 -> 61440 bytes tests/common/git/state1/libfoo.tar | Bin 389120 -> 409600 bytes tests/common/git/state1/libfox.tar | Bin 133120 -> 143360 bytes tests/common/git/state1/style-basic.tar | Bin 71680 -> 71680 bytes tests/common/git/state1/style.tar | Bin 133120 -> 143360 bytes tests/common/satisfy/libbar-0.0.1.tar.gz | Bin 367 -> 370 bytes tests/common/satisfy/libbar-1.1.0.tar.gz | Bin 360 -> 368 bytes tests/pkg-verify.testscript | 16 ++++++ tests/pkg-verify/foo-2.tar.gz | Bin 413 -> 437 bytes tests/rep-create.testscript | 40 ++++++++++++- tests/rep-create/stable/bar-1.tar.gz | Bin 0 -> 269 bytes tests/rep-info.testscript | 25 ++++++++ 31 files changed, 224 insertions(+), 35 deletions(-) create mode 100644 tests/rep-create/stable/bar-1.tar.gz diff --git a/bpkg/package.hxx b/bpkg/package.hxx index e508bc0..8172a19 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -477,6 +477,8 @@ namespace bpkg mutable optional system_version_; public: + // Note: dependency constraints must be complete. + // available_package (package_manifest&& m) : id (move (m.name), m.version), version (move (m.version)), diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index 7002b0f..e24e9f0 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -65,6 +65,8 @@ namespace bpkg // if (c) { + assert (c->complete ()); + // If the revision is not explicitly specified, then compare ignoring the // revision. The idea is that when the user runs 'bpkg build libfoo/1' // and there is 1+1 available, it should just work. The user shouldn't @@ -189,9 +191,9 @@ namespace bpkg sp->state == package_state::fetched ? pkg_verify (options, a->absolute () ? *a : c / *a, - false /* expand_values */, - true /* ignore_unknown */) - : pkg_verify (sp->effective_src_root (c), true)); + true /* ignore_unknown */, + false /* expand_values */) + : pkg_verify (sp->effective_src_root (c), true /* ignore_unknown */)); // Copy the possibly fixed up version from the selected package. // @@ -1558,7 +1560,8 @@ namespace bpkg // Note that we don't pass allow_stub flag so the system wildcard version // will (naturally) not be patched. // - optional v (parse_standard_version (sv.string ())); + string vs (sv.string ()); + optional v (parse_standard_version (vs)); if (!v) { @@ -1571,7 +1574,7 @@ namespace bpkg try { - return dependency_constraint ("~" + sv.string ()); + return dependency_constraint ("~" + vs); } // Note that the only possible reason for invalid_argument exception to // be thrown is that minor version reached the 999 limit (see @@ -2923,11 +2926,13 @@ namespace bpkg info << "'" << package << "' does not appear to be a valid " << "package archive: "; - package_manifest m (pkg_verify (o, - a, - false /* expand_values */, - true /* ignore_unknown */, - diag)); + package_manifest m ( + pkg_verify (o, + a, + true /* ignore_unknown */, + false /* expand_values */, + true /* complete_depends */, + diag)); // This is a package archive. // @@ -2988,7 +2993,8 @@ namespace bpkg info << "'" << package << "' does not appear to be a valid " << "package directory: "; - package_manifest m (pkg_verify (d, true, diag)); + package_manifest m ( + pkg_verify (d, true /* ignore_unknown */, diag)); // This is a package directory. // @@ -4535,7 +4541,9 @@ namespace bpkg // assert (sp->state == package_state::unpacked); - package_manifest m (pkg_verify (sp->effective_src_root (c), true)); + package_manifest m ( + pkg_verify (sp->effective_src_root (c), true /* ignore_unknown */)); + pkg_configure (c, o, t, sp, m.dependencies, p.config_vars, simulate); } diff --git a/bpkg/pkg-checkout.cxx b/bpkg/pkg-checkout.cxx index a7421b5..67aa165 100644 --- a/bpkg/pkg-checkout.cxx +++ b/bpkg/pkg-checkout.cxx @@ -145,7 +145,7 @@ namespace bpkg // Verify the package prerequisites are all configured since the dist // meta-operation generally requires all imports to be resolvable. // - package_manifest m (pkg_verify (sd, true)); + package_manifest m (pkg_verify (sd, true /* ignore_unknown */)); pkg_configure_prerequisites (o, t, m.dependencies, m.name); auto_rmdir rmd; diff --git a/bpkg/pkg-configure.cxx b/bpkg/pkg-configure.cxx index d63b010..75c371e 100644 --- a/bpkg/pkg-configure.cxx +++ b/bpkg/pkg-configure.cxx @@ -316,7 +316,9 @@ namespace bpkg l4 ([&]{trace << *p;}); - package_manifest m (pkg_verify (p->effective_src_root (c), true)); + package_manifest m ( + pkg_verify (p->effective_src_root (c), true /* ignore_unknown */)); + pkg_configure (c, o, t, p, m.dependencies, vars, false /* simulate */); } diff --git a/bpkg/pkg-configure.hxx b/bpkg/pkg-configure.hxx index 2aeb8bb..c540c72 100644 --- a/bpkg/pkg-configure.hxx +++ b/bpkg/pkg-configure.hxx @@ -21,6 +21,9 @@ namespace bpkg int pkg_configure (const pkg_configure_options&, cli::scanner& args); + // Note: all of the following functions expect the package dependency + // constraints to be complete. + // Configure the package, update its state, and commit the transaction. // void diff --git a/bpkg/pkg-fetch.cxx b/bpkg/pkg-fetch.cxx index 261bc86..9212678 100644 --- a/bpkg/pkg-fetch.cxx +++ b/bpkg/pkg-fetch.cxx @@ -164,8 +164,8 @@ namespace bpkg // package_manifest m (pkg_verify (co, a, - false /* expand_values */, - true /* ignore_unknown */)); + true /* ignore_unknown */, + false /* expand_values */)); l4 ([&]{trace << m.name << " " << m.version;}); diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx index 85cd93f..65ad42d 100644 --- a/bpkg/pkg-unpack.cxx +++ b/bpkg/pkg-unpack.cxx @@ -171,7 +171,7 @@ namespace bpkg // Verify the directory is a package and get its manifest. // - package_manifest m (pkg_verify (d, true)); + package_manifest m (pkg_verify (d, true /* ignore_unknown */)); l4 ([&]{trace << d << ": " << m.name << " " << m.version;}); // Check/diagnose an already existing package. diff --git a/bpkg/pkg-verify.cli b/bpkg/pkg-verify.cli index a22c224..d31e461 100644 --- a/bpkg/pkg-verify.cli +++ b/bpkg/pkg-verify.cli @@ -56,7 +56,7 @@ namespace bpkg human-readable form, dump the package manifest to \cb{stdout}. If the \cb{--deep} option is specified, then in the resulting manifest the \cb{*-file} values are replaced with the contents of the referenced - files." + files and the package dependency constraints are completed." } }; } diff --git a/bpkg/pkg-verify.cxx b/bpkg/pkg-verify.cxx index d14f606..3dc2a53 100644 --- a/bpkg/pkg-verify.cxx +++ b/bpkg/pkg-verify.cxx @@ -22,8 +22,9 @@ namespace bpkg package_manifest pkg_verify (const common_options& co, const path& af, - bool ev, bool iu, + bool ev, + bool cd, bool diag) try { @@ -47,7 +48,7 @@ namespace bpkg { ifdstream is (move (pr.second.in_ofd), fdstream_mode::skip); manifest_parser mp (is, mf.string ()); - package_manifest m (mp, iu); + package_manifest m (mp, iu, cd); is.close (); if (wait ()) @@ -216,8 +217,12 @@ namespace bpkg // try { - package_manifest m ( - pkg_verify (o, a, o.deep (), o.ignore_unknown (), !o.silent ())); + package_manifest m (pkg_verify (o, + a, + o.ignore_unknown (), + o.deep () /* expand_values */, + o.deep () /* complete_depends */, + !o.silent ())); if (o.manifest ()) { diff --git a/bpkg/pkg-verify.hxx b/bpkg/pkg-verify.hxx index a772a8f..73d3c17 100644 --- a/bpkg/pkg-verify.hxx +++ b/bpkg/pkg-verify.hxx @@ -19,15 +19,17 @@ namespace bpkg // Verify archive is a valid package and return its manifest. If requested, // expand the file-referencing manifest values (description, changes, etc), - // setting them to the contents of files they refer to. Throw failed if - // invalid or if something goes wrong. If diag is false, then don't issue - // diagnostics about the reason why the package is invalid. + // setting them to the contents of files they refer to as well as complete + // the dependency constraints. Throw failed if invalid or if something goes + // wrong. If diag is false, then don't issue diagnostics about the reason + // why the package is invalid. // package_manifest pkg_verify (const common_options&, const path& archive, - bool expand_values, bool ignore_unknown, + bool expand_values, + bool complete_depends = true, bool diag = true); // Similar to the above but verifies that a source directory is a valid diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx index 16f6496..55ba0f8 100644 --- a/bpkg/rep-create.cxx +++ b/bpkg/rep-create.cxx @@ -100,7 +100,7 @@ namespace bpkg path a (d / p); package_manifest m ( - pkg_verify (o, a, true /* expand_values */, o.ignore_unknown ())); + pkg_verify (o, a, o.ignore_unknown (), true /* expand_values */)); // Calculate its checksum. // diff --git a/bpkg/satisfaction.cxx b/bpkg/satisfaction.cxx index e620d3b..801fe5f 100644 --- a/bpkg/satisfaction.cxx +++ b/bpkg/satisfaction.cxx @@ -17,7 +17,7 @@ namespace bpkg bool satisfies (const version& v, const dependency_constraint& c) { - assert (!c.empty ()); + assert (!c.empty () && c.complete ()); if (v == wildcard_version) return true; @@ -45,7 +45,7 @@ namespace bpkg bool satisfies (const dependency_constraint& l, const dependency_constraint& r) { - assert (!l.empty () && !r.empty ()); + assert (!l.empty () && l.complete () && !r.empty () && r.complete ()); // Note: the revision ignoring logic is still unclear/unimplemented. It // seems it will be specific to each case below. diff --git a/bpkg/satisfaction.hxx b/bpkg/satisfaction.hxx index c79d1fb..c49eb33 100644 --- a/bpkg/satisfaction.hxx +++ b/bpkg/satisfaction.hxx @@ -13,6 +13,9 @@ namespace bpkg { + // Note: all of the following functions expect the package dependency + // constraints to be complete. + // Return true if version satisfies the constraint. // bool diff --git a/doc/manual.cli b/doc/manual.cli index 4314771..c7fcebf 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -937,6 +937,94 @@ operators. While it is possible that the original manifest specified equality or shortucts as full ranges, it is acceptable to display/serialize them as simpler operators.| +Instead of a specific version, the constraint can be specified in terms of the +dependent package's version (that is, its \l{#manifest-package-version +\c{version}} value) using the special \c{$} value. A \c{depends} value that +contains \c{$} is called incomplete. This mechanism is primarily useful when +developing related packages that should track each other's versions exactly or +closely. For example: + +\ +name: sqlite3 +version: 3.18.2 +depends: libsqlite3 == $ +\ + +In comparison operators and ranges the \c{$} value is replaced with the +dependent version ignoring the revision. For shortcut operators, the dependent +version must be a standard version and the following additional processing is +applied depending on whether the version is a release, final pre-release, or a +snapshot pre-release. + +\ol| + +\li|For a release we set the min version patch to zero. For \c{^} we also set +the minor version to zero, unless the major version is zero (reduces to +\c{~}). The max version is set according to the standard shortcut logic. For +example, \c{~$} is completed as follows: + +\ +1.2.0 -> [1.2.0 1.3.0-) +1.2.1 -> [1.2.0 1.3.0-) +1.2.2 -> [1.2.0 1.3.0-) +\ + +And \c{^$} is completed as follows: + +\ +1.0.0 -> [1.0.0 2.0.0-) +1.1.1 -> [1.0.0 2.0.0-) +\ + +| + +\li|For a final pre-release the key observation is that if the patch +component for \c{~} or minor and patch components for \c{^} are not zero, then +that means there has been a compatible release and we treat this case the same +as release, ignoring the pre-release part. If, however, it/they are zero, then +that means there may yet be no final release and we have to start from the +first alpha. For example, for the \c{~$} case: + +\ +1.2.0-a.1 -> [1.2.0-a.1 1.3.0-) +1.2.0-b.2 -> [1.2.0-a.1 1.3.0-) +1.2.1-a.1 -> [1.2.0 1.3.0-) +1.2.2-b.2 -> [1.2.0 1.3.0-) +\ + +And for the \c{^$} case: + +\ +1.0.0-a.1 -> [1.0.0-a.1 2.0.0-) +1.0.0-b.2 -> [1.0.0-a.1 2.0.0-) +1.0.1-a.1 -> [1.0.0 2.0.0-) +1.1.0-b.2 -> [1.0.0 2.0.0-) +\ + +| + +\li|For a snapshot pre-release we distinguish two cases: a patch snapshot +(the patch component is not zero) and a major/minor snapshot (the patch +component is zero). For the patch snapshot case we assume that it is (most +likely) developed independently of the dependency and we treat it the same as +the final pre-release case. For example, if the dependent version is +\c{1.2.1-a.0.nnn}, the dependency could be \c{1.2.0} or \c{1.2.2} (or +somewhere in-between). + +For the major/minor snapshot we assume that all the packages are developed in +the lockstep and have the same \c{X.Y.0} version. In this case we make the +range start from the earliest possible version in this \"snapshot series\" and +end before the final pre-release. For example (in this case \c{~} and \c{^} +are treated the same): + +\ +1.2.0-a.0.nnn -> [1.2.0-a.0.1 1.2.0-a.1) +2.0.0-b.2.nnn -> [2.0.0-b.2.1 2.0.0-b.3) +\ + +|| + + \h2#manifest-package-requires|\c{requires}| \ @@ -1142,9 +1230,10 @@ sha256sum: \ After the list manifest comes a (potentially empty) sequence of package -manifests. These manifests shall not contain any \c{*-file} values (such -values should be converted to their inline versions) but must contain the -following additional (to package manifest) values: +manifests. These manifests shall not contain any \c{*-file} or incomplete +\l{#manifest-package-depends \c{depends}} values (such values should be +converted to their inline versions or completed, respectively) but must +contain the following additional (to package manifest) values: \ location: diff --git a/tests/common/git/state0/libbar.tar b/tests/common/git/state0/libbar.tar index 791d8f2..2e1a3ad 100644 Binary files a/tests/common/git/state0/libbar.tar and b/tests/common/git/state0/libbar.tar differ diff --git a/tests/common/git/state0/libfoo.tar b/tests/common/git/state0/libfoo.tar index e6bb1c2..6a0cc8a 100644 Binary files a/tests/common/git/state0/libfoo.tar and b/tests/common/git/state0/libfoo.tar differ diff --git a/tests/common/git/state0/libfox.tar b/tests/common/git/state0/libfox.tar index 31dda5a..a73f460 100644 Binary files a/tests/common/git/state0/libfox.tar and b/tests/common/git/state0/libfox.tar differ diff --git a/tests/common/git/state0/style-basic.tar b/tests/common/git/state0/style-basic.tar index 098e0ff..36d0dcd 100644 Binary files a/tests/common/git/state0/style-basic.tar and b/tests/common/git/state0/style-basic.tar differ diff --git a/tests/common/git/state0/style.tar b/tests/common/git/state0/style.tar index 5ad84da..7b48a9d 100644 Binary files a/tests/common/git/state0/style.tar and b/tests/common/git/state0/style.tar differ diff --git a/tests/common/git/state1/libbaz.tar b/tests/common/git/state1/libbaz.tar index cd2d215..1b35ec4 100644 Binary files a/tests/common/git/state1/libbaz.tar and b/tests/common/git/state1/libbaz.tar differ diff --git a/tests/common/git/state1/libfoo.tar b/tests/common/git/state1/libfoo.tar index 57befb1..ab694f7 100644 Binary files a/tests/common/git/state1/libfoo.tar and b/tests/common/git/state1/libfoo.tar differ diff --git a/tests/common/git/state1/libfox.tar b/tests/common/git/state1/libfox.tar index 648811f..a6ef40e 100644 Binary files a/tests/common/git/state1/libfox.tar and b/tests/common/git/state1/libfox.tar differ diff --git a/tests/common/git/state1/style-basic.tar b/tests/common/git/state1/style-basic.tar index ab302de..7b7a6c5 100644 Binary files a/tests/common/git/state1/style-basic.tar and b/tests/common/git/state1/style-basic.tar differ diff --git a/tests/common/git/state1/style.tar b/tests/common/git/state1/style.tar index 7772b98..e6243f4 100644 Binary files a/tests/common/git/state1/style.tar and b/tests/common/git/state1/style.tar differ diff --git a/tests/common/satisfy/libbar-0.0.1.tar.gz b/tests/common/satisfy/libbar-0.0.1.tar.gz index 97ad543..a88d874 100644 Binary files a/tests/common/satisfy/libbar-0.0.1.tar.gz and b/tests/common/satisfy/libbar-0.0.1.tar.gz differ diff --git a/tests/common/satisfy/libbar-1.1.0.tar.gz b/tests/common/satisfy/libbar-1.1.0.tar.gz index 881292e..16a8b47 100644 Binary files a/tests/common/satisfy/libbar-1.1.0.tar.gz and b/tests/common/satisfy/libbar-1.1.0.tar.gz differ diff --git a/tests/pkg-verify.testscript b/tests/pkg-verify.testscript index 6f12c51..c384eb6 100644 --- a/tests/pkg-verify.testscript +++ b/tests/pkg-verify.testscript @@ -90,4 +90,20 @@ $* --deep --ignore-unknown --manifest $src/foo-2.tar.gz >>EOO \ url: http://www.example.org/foo email: foo-users@example.org + depends: bar == 2 + EOO + +: incomplete-dependency +: +$* --ignore-unknown --manifest $src/foo-2.tar.gz >>EOO + : 1 + name: foo + version: 2 + summary: The "Foo" utility + license: MIT + description-file: README + changes-file: NEWS + url: http://www.example.org/foo + email: foo-users@example.org + depends: bar == $ EOO diff --git a/tests/pkg-verify/foo-2.tar.gz b/tests/pkg-verify/foo-2.tar.gz index eb72635..5f5739d 100644 Binary files a/tests/pkg-verify/foo-2.tar.gz and b/tests/pkg-verify/foo-2.tar.gz differ diff --git a/tests/rep-create.testscript b/tests/rep-create.testscript index 053902d..502a58b 100644 --- a/tests/rep-create.testscript +++ b/tests/rep-create.testscript @@ -28,12 +28,23 @@ $clone_rep; $* 1/stable/ 2>>/~%EOE% &1/stable/packages.manifest; + added bar 1 added foo 1 - %1 package\(s\) in .+/stable/% + %2 package\(s\) in .+/stable/% EOE $rep_info -p --manifest 1/stable/ >>EOO : 1 + name: bar + version: 1 + summary: The "Bar" utility + license: MIT + url: http://www.example.org/bar + email: bar-users@example.org + depends: foo == 1 + location: bar-1.tar.gz + sha256sum: 514a99f5fadb94f946f8abff59caa9c3cc442cd4f30d4383a1cf6d26ca058036 + : name: foo version: 1 summary: The "Foo" utility @@ -51,15 +62,26 @@ $clone_rep; $* --key $key 1/stable/ 2>>/~%EOE% &1/stable/packages.manifest; + added bar 1 added foo 1 warning: --key option ignored info: repository manifest contains no certificate info: run 'bpkg help rep-create' for more information - %1 package\(s\) in .+/stable/% + %2 package\(s\) in .+/stable/% EOE $rep_info -p --manifest 1/stable/ >>EOO : 1 + name: bar + version: 1 + summary: The "Bar" utility + license: MIT + url: http://www.example.org/bar + email: bar-users@example.org + depends: foo == 1 + location: bar-1.tar.gz + sha256sum: 514a99f5fadb94f946f8abff59caa9c3cc442cd4f30d4383a1cf6d26ca058036 + : name: foo version: 1 summary: The "Foo" utility @@ -96,13 +118,24 @@ $* --key $key 1/stable/ 2>>/~%EOE% &1/stable/packages.manifest \ &1/stable/signature.manifest; + added bar 1 added foo 1 - %1 package\(s\) in .+/stable/% + %2 package\(s\) in .+/stable/% EOE $rep_info --cert-fingerprint -p --manifest 1/stable/ >>~"%EOO%" $cert_fp : 1 + name: bar + version: 1 + summary: The "Bar" utility + license: MIT + url: http://www.example.org/bar + email: bar-users@example.org + depends: foo == 1 + location: bar-1.tar.gz + sha256sum: 514a99f5fadb94f946f8abff59caa9c3cc442cd4f30d4383a1cf6d26ca058036 + : name: foo version: 1 summary: The "Foo" utility @@ -118,6 +151,7 @@ : $clone_rep; $* 1/stable/ 2>>EOE &1/stable/packages.manifest != 0 + added bar 1 added foo 1 error: --key option required info: repository manifest contains a certificate diff --git a/tests/rep-create/stable/bar-1.tar.gz b/tests/rep-create/stable/bar-1.tar.gz new file mode 100644 index 0000000..66c79a2 Binary files /dev/null and b/tests/rep-create/stable/bar-1.tar.gz differ diff --git a/tests/rep-info.testscript b/tests/rep-info.testscript index 3ccbeb6..55a29da 100644 --- a/tests/rep-info.testscript +++ b/tests/rep-info.testscript @@ -251,4 +251,29 @@ else : 1 email: user@example.com EOO + + : complete-dependency + : + $* -p --manifest "$rep/libbar.git#master" >>~%EOO%d + : 1 + name: libbar + version: 1.0.0 + summary: libbar + license: MIT + url: http://example.org/libbar + email: pkg@example.org + depends: style-basic >= 1.0.0 + location: libbar + %fragment: \.+% + : + name: libmbar + version: 1.0.0 + summary: libmbar + license: MIT + url: http://example.org/libmbar + email: pkg@example.org + depends: style-basic >= 1.0.0 + location: libmbar + %fragment: \.+% + EOO } -- cgit v1.1