diff options
-rw-r--r-- | bpkg/auth.cxx | 137 | ||||
-rw-r--r-- | bpkg/buildfile | 11 | ||||
-rwxr-xr-x | bpkg/odb.sh | 11 | ||||
-rw-r--r-- | bpkg/pkg-build-collect.cxx | 124 | ||||
-rw-r--r-- | bpkg/rep-fetch.cxx | 4 | ||||
-rw-r--r-- | bpkg/rep-mask.cxx | 11 | ||||
-rw-r--r-- | bpkg/rep-remove.cxx | 55 | ||||
-rw-r--r-- | bpkg/rep-remove.hxx | 7 | ||||
-rw-r--r-- | bpkg/version.hxx.in | 8 | ||||
-rw-r--r-- | manifest | 3 | ||||
-rw-r--r-- | repositories.manifest | 12 |
11 files changed, 225 insertions, 158 deletions
diff --git a/bpkg/auth.cxx b/bpkg/auth.cxx index 663054d..191da0a 100644 --- a/bpkg/auth.cxx +++ b/bpkg/auth.cxx @@ -23,15 +23,15 @@ using namespace butl; namespace bpkg { - static const string openssl_version ("version"); - static const string openssl_pkeyutl ("pkeyutl"); - static const string openssl_rsautl ("rsautl"); - static const string openssl_x509 ("x509"); - - const char* openssl_commands[5] = {openssl_version.c_str (), - openssl_pkeyutl.c_str (), - openssl_rsautl.c_str (), - openssl_x509.c_str (), + static const string openssl_version_cmd ("version"); + static const string openssl_pkeyutl_cmd ("pkeyutl"); + static const string openssl_rsautl_cmd ("rsautl"); + static const string openssl_x509_cmd ("x509"); + + const char* openssl_commands[5] = {openssl_version_cmd.c_str (), + openssl_pkeyutl_cmd.c_str (), + openssl_rsautl_cmd.c_str (), + openssl_x509_cmd.c_str (), nullptr}; // Print process command line. @@ -43,9 +43,42 @@ namespace bpkg print_process (args, n); } + // Query the openssl information and return the openssl version. Cache the + // version on the first function call. Fail on the underlying process and IO + // error. Return the 0.0.0 version if unable to parse the openssl stdout. + // + static optional<semantic_version> openssl_ver; + + static const semantic_version& + openssl_version (const common_options& co) + { + const path& openssl_path (co.openssl ()[openssl_version_cmd]); + + if (!openssl_ver) + try + { + optional<openssl_info> oi ( + openssl::info (print_command, 2, openssl_path)); + + openssl_ver = (oi && oi->name == "OpenSSL" + ? move (oi->version) + : semantic_version ()); + } + catch (const process_error& e) + { + fail << "unable to execute " << openssl_path << ": " << e << endf; + } + catch (const io_error& e) + { + fail << "unable to read '" << openssl_path << "' output: " << e + << endf; + } + + return *openssl_ver; + } + // Return true if the openssl version is greater or equal to 3.0.0 and so - // pkeyutl needs to be used instead of rsautl. Cache the result on the first - // function call. + // pkeyutl needs to be used instead of rsautl. // // Note that openssl 3.0.0 deprecates rsautl in favor of pkeyutl. // @@ -54,37 +87,28 @@ namespace bpkg // (see the 'pkeyutl -verifyrecover error "input data too long to be a // hash"' issue report for details). // - static optional<bool> use_pkeyutl; - - static bool + static inline bool use_openssl_pkeyutl (const common_options& co) { - if (!use_pkeyutl) - { - const path& openssl_path (co.openssl ()[openssl_version]); - - try - { - optional<openssl_info> oi ( - openssl::info (print_command, 2, openssl_path)); - - use_pkeyutl = oi && - oi->name == "OpenSSL" && - oi->version >= semantic_version {3, 0, 0}; - } - catch (const process_error& e) - { - fail << "unable to execute " << openssl_path << ": " << e << endf; - } - catch (const io_error& e) - { - fail << "unable to read '" << openssl_path << "' output: " << e - << endf; - } - } + return openssl_version (co) >= semantic_version {3, 0, 0}; + } - return *use_pkeyutl; + // Return true if some openssl commands (openssl x509 -fingerprint, etc) may + // issue the 'Reading certificate from stdin since no -in or -new option is + // given' warning. This is the case for the openssl version in the [3.2.0 + // 3.3.0) range (see GH issue #353 for details). + // + // Note that there is no easy way to suppress this warning on Windows and + // thus we don't define this function there. + // +#ifndef _WIN32 + static inline bool + openssl_warn_stdin (const common_options& co) + { + const semantic_version& v (openssl_version (co)); + return v >= semantic_version {3, 2, 0} && v < semantic_version {3, 3, 0}; } +#endif // Find the repository location prefix that ends with the version component. // We consider all repositories under this location to be related. @@ -190,15 +214,25 @@ namespace bpkg dr << ": " << *e; }; - const path& openssl_path (co.openssl ()[openssl_x509]); - const strings& openssl_opts (co.openssl_option ()[openssl_x509]); + const path& openssl_path (co.openssl ()[openssl_x509_cmd]); + const strings& openssl_opts (co.openssl_option ()[openssl_x509_cmd]); try { openssl os (print_command, fdstream_mode::text, fdstream_mode::text, 2, - openssl_path, openssl_x509, - openssl_opts, "-sha256", "-noout", "-fingerprint"); + openssl_path, openssl_x509_cmd, + openssl_opts, + "-sha256", + "-noout", + "-fingerprint" +#ifndef _WIN32 + , + (openssl_warn_stdin (co) + ? cstrings ({"-in", "/dev/stdin"}) + : cstrings ()) +#endif + ); os.out << pem; os.out.close (); @@ -288,8 +322,8 @@ namespace bpkg dr << ": " << *e; }; - const path& openssl_path (co.openssl ()[openssl_x509]); - const strings& openssl_opts (co.openssl_option ()[openssl_x509]); + const path& openssl_path (co.openssl ()[openssl_x509_cmd]); + const strings& openssl_opts (co.openssl_option ()[openssl_x509_cmd]); try { @@ -315,7 +349,7 @@ namespace bpkg openssl os ( print_command, fdstream_mode::text, fdstream_mode::text, 2, - openssl_path, openssl_x509, + openssl_path, openssl_x509_cmd, openssl_opts, "-noout", "-subject", "-dates", "-email", // Previously we have used "RFC2253,sep_multiline" format to display @@ -347,6 +381,13 @@ namespace bpkg // sep_multiline - display field per line. // "-nameopt", "utf8,esc_ctrl,dump_nostr,dump_der,sname,sep_multiline" + +#ifndef _WIN32 + , + (openssl_warn_stdin (co) + ? cstrings ({"-in", "/dev/stdin"}) + : cstrings ()) +#endif ); // We unset failbit to provide the detailed error description (which @@ -877,7 +918,7 @@ namespace bpkg }; bool ku (use_openssl_pkeyutl (co)); - const string& cmd (ku ? openssl_pkeyutl : openssl_rsautl); + const string& cmd (ku ? openssl_pkeyutl_cmd : openssl_rsautl_cmd); const path& openssl_path (co.openssl ()[cmd]); const strings& openssl_opts (co.openssl_option ()[cmd]); @@ -973,8 +1014,8 @@ namespace bpkg }; const string& cmd (use_openssl_pkeyutl (co) - ? openssl_pkeyutl - : openssl_rsautl); + ? openssl_pkeyutl_cmd + : openssl_rsautl_cmd); const path& openssl_path (co.openssl ()[cmd]); const strings& openssl_opts (co.openssl_option ()[cmd]); diff --git a/bpkg/buildfile b/bpkg/buildfile index 0ba60dc..8836712 100644 --- a/bpkg/buildfile +++ b/bpkg/buildfile @@ -15,15 +15,12 @@ import libs = build2%lib{build2} for m: bash bin c cc cli cxx in version import libs += build2%lib{build2-$m} +# @@ TMP we require libsqlite3 to be interface dependency of libbut-odb only +# for the database migrations to schema versions 13 and 14. +# import libs += libbpkg%lib{bpkg} import libs += libbutl%lib{butl} -import libs += libodb%lib{odb} -import libs += libodb-sqlite%lib{odb-sqlite} - -# @@ TMP Only required for the database migrations to schema versions 13 and -# 14. -# -import libs += libsqlite3%lib{sqlite3} +import libs += libbutl%lib{butl-odb} options_topics = \ bpkg-options \ diff --git a/bpkg/odb.sh b/bpkg/odb.sh index 75c6d2d..1387773 100755 --- a/bpkg/odb.sh +++ b/bpkg/odb.sh @@ -16,8 +16,9 @@ if test -d ../.bdep; then sed -r -ne 's#^(@[^ ]+ )?([^ ]+)/ .*default.*$#\2#p')" fi - inc+=("-I$(echo "$cfg"/libodb-[1-9]*/)") - inc+=("-I$(echo "$cfg"/libodb-sqlite-[1-9]*/)") + # Note: there is nothing generated in libbutl-odb. + # + inc+=("-I../../libbutl/libbutl-odb") inc+=("-I$cfg/libbutl") inc+=("-I../../libbutl") @@ -30,11 +31,7 @@ sed -r -ne 's#^(@[^ ]+ )?([^ ]+)/ .*default.*$#\2#p')" else - inc+=("-I$HOME/work/odb/builds/default/libodb-sqlite-default") - inc+=("-I$HOME/work/odb/libodb-sqlite") - - inc+=("-I$HOME/work/odb/builds/default/libodb-default") - inc+=("-I$HOME/work/odb/libodb") + inc+=("-I../../libbutl/libbutl-odb") inc+=(-I.. -I../../libbpkg -I../../libbutl) diff --git a/bpkg/pkg-build-collect.cxx b/bpkg/pkg-build-collect.cxx index 6f1195c..436d629 100644 --- a/bpkg/pkg-build-collect.cxx +++ b/bpkg/pkg-build-collect.cxx @@ -1490,78 +1490,87 @@ namespace bpkg // applied. Ignore the replacement if its version doesn't satisfy the // dependency constraints specified by the caller. Also ignore if this is // a drop and the required-by package names of the specified build package - // object have the "required by dependents" semantics + // object have the "required by dependents" semantics. // auto vi (replaced_vers.find (pk)); + const version* replacement_version (nullptr); - if (vi != replaced_vers.end () && !vi->second.replaced) + if (vi != replaced_vers.end ()) { - l5 ([&]{trace << "apply version replacement for " - << pkg.available_name_version_db ();}); - replaced_version& v (vi->second); if (v.available != nullptr) + replacement_version = (v.system + ? v.available->system_version (pk.db) + : &v.available->version); + + if (!vi->second.replaced) { - const version& rv (v.system - ? *v.available->system_version (pk.db) - : v.available->version); + l5 ([&]{trace << "apply version replacement for " + << pkg.available_name_version_db ();}); - bool replace (true); - for (const constraint_type& c: pkg.constraints) + if (v.available != nullptr) { - if (!satisfies (rv, c.value)) + assert (replacement_version != nullptr); + + const version& rv (*replacement_version); + + bool replace (true); + for (const constraint_type& c: pkg.constraints) { - replace = false; + if (!satisfies (rv, c.value)) + { + replace = false; - l5 ([&]{trace << "replacement to " << rv << " is denied since " - << c.dependent << " depends on (" << pk.name << ' ' - << c.value << ')';}); + l5 ([&]{trace << "replacement to " << rv << " is denied since " + << c.dependent << " depends on (" << pk.name << ' ' + << c.value << ')';}); + } } - } - if (replace) - { - v.replaced = true; + if (replace) + { + v.replaced = true; - pkg.available = v.available; - pkg.repository_fragment = v.repository_fragment; - pkg.system = v.system; + pkg.available = v.available; + pkg.repository_fragment = v.repository_fragment; + pkg.system = v.system; - l5 ([&]{trace << "replacement: " - << pkg.available_name_version_db ();}); + l5 ([&]{trace << "replacement: " + << pkg.available_name_version_db ();}); + } } - } - else - { - if (!pkg.required_by_dependents) + else { - v.replaced = true; + if (!pkg.required_by_dependents) + { + v.replaced = true; - l5 ([&]{trace << "replacement: drop";}); + l5 ([&]{trace << "replacement: drop";}); - // We shouldn't be replacing a package build with the drop if someone - // depends on this package. - // - assert (pkg.selected != nullptr); + // We shouldn't be replacing a package build with the drop if someone + // depends on this package. + // + assert (pkg.selected != nullptr); - collect_drop (options, pkg.db, pkg.selected, replaced_vers); - return nullptr; - } - else - { - assert (!pkg.required_by.empty ()); + collect_drop (options, pkg.db, pkg.selected, replaced_vers); + return nullptr; + } + else + { + assert (!pkg.required_by.empty ()); - l5 ([&] - { - diag_record dr (trace); - dr << "replacement to drop is denied since " << pk - << " is required by "; - for (auto b (pkg.required_by.begin ()), i (b); - i != pkg.required_by.end (); - ++i) - dr << (i != b ? ", " : "") << *i; - }); + l5 ([&] + { + diag_record dr (trace); + dr << "replacement to drop is denied since " << pk + << " is required by "; + for (auto b (pkg.required_by.begin ()), i (b); + i != pkg.required_by.end (); + ++i) + dr << (i != b ? ", " : "") << *i; + }); + } } } } @@ -1629,19 +1638,28 @@ namespace bpkg build_package* p2 (&pkg); // Pick with the following preference order: user selection over - // implicit one, source package over a system one, newer version over - // an older one. So get the preferred into p1 and the other into p2. + // implicit one, source package over a system one, replacement version + // over a non-replacement one, newer version over an older one. So get + // the preferred into p1 and the other into p2. // { + const version& v1 (p1->available_version ()); + const version& v2 (p2->available_version ()); + int us (p1->user_selection () - p2->user_selection ()); int sf (p1->system - p2->system); + int rv (replacement_version != nullptr + ? (v1 == *replacement_version) - (v2 == *replacement_version) + : 0); if (us < 0 || (us == 0 && sf > 0) || (us == 0 && sf == 0 && - p2->available_version () > p1->available_version ())) + (rv < 0 || (rv == 0 && v2 > v1)))) + { swap (p1, p2); + } } // If the versions differ, pick the satisfactory one and if both are diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index d02a064..fe25b86 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -1552,6 +1552,10 @@ namespace bpkg } } +#ifndef NDEBUG + rep_remove_verify (db, t); +#endif + // Make sure that the external packages are available from a single // directory-based repository. // diff --git a/bpkg/rep-mask.cxx b/bpkg/rep-mask.cxx index d7f9c6a..e670005 100644 --- a/bpkg/rep-mask.cxx +++ b/bpkg/rep-mask.cxx @@ -6,6 +6,7 @@ #include <bpkg/package.hxx> #include <bpkg/package-odb.hxx> #include <bpkg/database.hxx> +#include <bpkg/rep-remove.hxx> // rep_remove_verify() #include <bpkg/diagnostics.hxx> #include <bpkg/package-query.hxx> // repo_configs #include <bpkg/manifest-utility.hxx> // repository_name() @@ -273,6 +274,16 @@ namespace bpkg for (database& db: repo_configs) { + // While at it, verify that the repository information has stayed + // consistent after the potential repository removals. + // + // Note that rep_remove() doesn't remove the available packages in the + // mask mode and thus we don't verify them. + // +#ifndef NDEBUG + rep_remove_verify (db, t, false /* verify_packages */); +#endif + // Add the repository location canonical name to the database-specific // unmasked repositories or repository fragments lists. Note that // repository location is used only for tracing. diff --git a/bpkg/rep-remove.cxx b/bpkg/rep-remove.cxx index ad10f56..22702a5 100644 --- a/bpkg/rep-remove.cxx +++ b/bpkg/rep-remove.cxx @@ -178,12 +178,6 @@ namespace bpkg for (const repository::fragment_type& fr: r->fragments) rep_remove_fragment (db, t, fr.fragment.load (), mask); - // If there are no repositories stayed in the database then no repository - // fragments should stay either. - // - if (db.query_value<repository_count> () == 0) - assert (db.query_value<repository_fragment_count> () == 0); - // Unless in the mask repositories mode, cleanup the repository state if // present and there are no more repositories referring this state. // @@ -272,20 +266,6 @@ namespace bpkg // db.erase (rf); - // If there are no repository fragments stayed in the database then no - // repositories nor packages should stay either. - // - // Note that a repository is removed prior to the removal of fragments it - // contains (see rep_remove()). Also note that the packages contained in a - // repository fragment are removed, if this is the only containing - // fragment, prior to the fragment removal (see above). - // - if (db.query_value<repository_fragment_count> () == 0) - { - assert (db.query_value<repository_count> () == 0); - assert (mask || db.query_value<available_package_count> () == 0); - } - // Remove dangling complements and prerequisites. // // Prior to removing a prerequisite/complement we need to make sure it @@ -521,6 +501,10 @@ namespace bpkg text << "removed " << r.object_id (); } +#ifndef NDEBUG + rep_remove_verify (db, t); +#endif + // If the --all option is specified then no user-added repositories should // remain. // @@ -538,4 +522,35 @@ namespace bpkg return 0; } + + void + rep_remove_verify (database& db, transaction&, bool verify_packages) + { + size_t rn (db.query_value<repository_count> ()); + size_t fn (db.query_value<repository_fragment_count> ()); + + // If there are no repositories stayed in the database then no repository + // fragments should stay either. + // + assert (rn != 0 || fn == 0); + + // If there are no repository fragments stayed in the database then no + // repositories with fragments nor packages should stay either. + // + // Note that repositories may not have any fragments if they are not + // fetched yet or due to the refname exclusions in the repository URL + // fragments (see repository-types(1) for details). + // + if (fn == 0) + { + // If there are some repositories have stayed, then make sure that none + // of them have any fragments. + // + assert (rn == 0 || + db.query_value<fragment_repository_count> ("repository!=''") == 0); + + if (verify_packages) + assert (db.query_value<available_package_count> () == 0); + } + } } diff --git a/bpkg/rep-remove.hxx b/bpkg/rep-remove.hxx index 0fc82e8..94a38c6 100644 --- a/bpkg/rep-remove.hxx +++ b/bpkg/rep-remove.hxx @@ -57,6 +57,13 @@ namespace bpkg rep_remove_package_locations (database&, transaction&, const string& fragment_name); + + // Verify that after all the repository/fragment removals the repository + // information is consistent in the database (if no repositories stayed then + // no fragments stayed either, etc). + // + void + rep_remove_verify (database&, transaction&, bool verify_packages = true); } #endif // BPKG_REP_REMOVE_HXX diff --git a/bpkg/version.hxx.in b/bpkg/version.hxx.in index 22da973..603a5f7 100644 --- a/bpkg/version.hxx.in +++ b/bpkg/version.hxx.in @@ -43,14 +43,6 @@ $libbutl.check(LIBBUTL_VERSION, LIBBUTL_SNAPSHOT)$ $libbpkg.check(LIBBPKG_VERSION, LIBBPKG_SNAPSHOT)$ -#include <odb/version.hxx> - -$libodb.check(LIBODB_VERSION, LIBODB_SNAPSHOT)$ - -#include <odb/sqlite/version.hxx> - -$libodb_sqlite.check(LIBODB_SQLITE_VERSION, LIBODB_SQLITE_SNAPSHOT)$ - // User agent. // #if defined(_WIN32) @@ -18,9 +18,6 @@ depends: * build2 >= 0.16.0- depends: * bpkg >= 0.16.0- # @@ DEP Should probably become conditional dependency. #requires: ? cli ; Only required if changing .cli files. -depends: libodb [2.5.0-b.26.1 2.5.0-b.27) -depends: libodb-sqlite [2.5.0-b.26.1 2.5.0-b.27) -depends: libsqlite3 ^3.21.0 ; ATTACH in transaction depends: libbutl [0.17.0-a.0.1 0.17.0-a.1) depends: libbpkg [0.17.0-a.0.1 0.17.0-a.1) depends: build2 [0.17.0-a.0.1 0.17.0-a.1) diff --git a/repositories.manifest b/repositories.manifest index 29cb1cf..5adbbe4 100644 --- a/repositories.manifest +++ b/repositories.manifest @@ -12,15 +12,3 @@ location: ../libbutl.git##HEAD : role: prerequisite location: ../libbpkg.git##HEAD - -: -role: prerequisite -location: https://git.build2.org/packaging/sqlite/sqlite.git##HEAD - -: -role: prerequisite -location: https://git.codesynthesis.com/odb/libodb.git##HEAD - -: -role: prerequisite -location: https://git.codesynthesis.com/odb/libodb-sqlite.git##HEAD |