diff options
Diffstat (limited to 'bpkg/pkg-unpack.cxx')
-rw-r--r-- | bpkg/pkg-unpack.cxx | 204 |
1 files changed, 140 insertions, 64 deletions
diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx index 9685f3e..22ff02f 100644 --- a/bpkg/pkg-unpack.cxx +++ b/bpkg/pkg-unpack.cxx @@ -10,6 +10,7 @@ #include <bpkg/package-odb.hxx> #include <bpkg/database.hxx> #include <bpkg/checksum.hxx> +#include <bpkg/rep-mask.hxx> #include <bpkg/diagnostics.hxx> #include <bpkg/manifest-utility.hxx> @@ -24,14 +25,13 @@ namespace bpkg // diagnose all the illegal cases. // static void - pkg_unpack_check (const dir_path& c, - transaction& t, + pkg_unpack_check (database& db, + transaction&, const package_name& n, bool replace) { tracer trace ("pkg_update_check"); - database& db (t.database ()); tracer_guard tg (db, trace); if (shared_ptr<selected_package> p = db.find<selected_package> (n)) @@ -42,6 +42,7 @@ namespace bpkg if (!replace || !s) { diag_record dr (fail); + const dir_path& c (db.config_orig); dr << "package " << n << " already exists in configuration " << c << info << "version: " << p->version_string () @@ -58,37 +59,26 @@ namespace bpkg // package object which may replace the existing one. // static shared_ptr<selected_package> - pkg_unpack (const common_options& o, - dir_path c, + pkg_unpack (database& db, transaction& t, - package_name n, - version v, - dir_path d, - repository_location rl, + package_name&& n, + version&& v, + dir_path&& d, + repository_location&& rl, + shared_ptr<selected_package>&& p, + optional<string>&& mc, + optional<string>&& bc, bool purge, bool simulate) { - tracer trace ("pkg_unpack"); - - database& db (t.database ()); - tracer_guard tg (db, trace); - - optional<string> mc; - - if (!simulate) - mc = sha256 (o, d / manifest_file); - - // Make the package and configuration paths absolute and normalized. - // If the package is inside the configuration, use the relative path. - // This way we can move the configuration around. + // Make the package path absolute and normalized. If the package is inside + // the configuration, use the relative path. This way we can move the + // configuration around. // - normalize (c, "configuration"); normalize (d, "package"); - if (d.sub (c)) - d = d.leaf (c); - - shared_ptr<selected_package> p (db.find<selected_package> (n)); + if (d.sub (db.config)) + d = d.leaf (db.config); if (p != nullptr) { @@ -96,7 +86,7 @@ namespace bpkg // replacing. Once this is done, there is no going back. If things // go badly, we can't simply abort the transaction. // - pkg_purge_fs (c, t, p, simulate); + pkg_purge_fs (db, 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 @@ -118,6 +108,7 @@ namespace bpkg p->src_root = move (d); p->purge_src = purge; p->manifest_checksum = move (mc); + p->buildfiles_checksum = move (bc); db.update (p); } @@ -136,6 +127,7 @@ namespace bpkg move (d), purge, move (mc), + move (bc), nullopt, // No output directory yet. {}}); // No prerequisites captured yet. @@ -145,12 +137,68 @@ namespace bpkg assert (p->external ()); t.commit (); - return p; + return move (p); + } + + template <typename T> + static shared_ptr<selected_package> + pkg_unpack (const common_options& o, + database& db, + transaction& t, + package_name n, + version v, + const vector<T>& deps, + const package_info* pi, + dir_path d, + repository_location rl, + bool purge, + bool simulate) + { + tracer trace ("pkg_unpack"); + + tracer_guard tg (db, trace); + + shared_ptr<selected_package> p (db.find<selected_package> (n)); + + optional<string> mc; + optional<string> bc; + + // Only calculate the manifest/subprojects and buildfiles checksums for + // external packages (see selected_package::external() for details). + // + if (!simulate && (rl.empty () || rl.directory_based ())) + { + mc = package_checksum (o, d, pi); + + // Calculate the buildfiles checksum if the package has any buildfile + // clauses in the dependencies. Always calculate it over the buildfiles + // since the package is external. + // + if ((p != nullptr && p->manifest_checksum == mc) + ? p->buildfiles_checksum.has_value () + : has_buildfile_clause (deps)) + bc = package_buildfiles_checksum (nullopt /* bootstrap_build */, + nullopt /* root_build */, + {} /* buildfiles */, + d); + } + + return pkg_unpack (db, + t, + move (n), + move (v), + move (d), + move (rl), + move (p), + move (mc), + move (bc), + purge, + simulate); } shared_ptr<selected_package> pkg_unpack (const common_options& o, - const dir_path& c, + database& db, transaction& t, const dir_path& d, bool replace, @@ -162,37 +210,59 @@ namespace bpkg if (!exists (d)) fail << "package directory " << d << " does not exist"; + // For better diagnostics, let's obtain the package info after + // pkg_verify() verifies that this is a package directory. + // + package_version_info pvi; + // Verify the directory is a package and get its manifest. // package_manifest m ( - pkg_verify (d, + pkg_verify (o, + d, true /* ignore_unknown */, - [&o, &d] (version& v) + false /* ignore_toolchain */, + false /* load_buildfiles */, + [&o, &d, &pvi] (version& v) { - if (optional<version> pv = package_version (o, d)) - v = move (*pv); + // Note that we also query subprojects since the package + // information will be used for the subsequent + // package_iteration() call. + // + pvi = package_version (o, d, b_info_flags::subprojects); + + if (pvi.version) + v = move (*pvi.version); })); l4 ([&]{trace << d << ": " << m.name << " " << m.version;}); // Check/diagnose an already existing package. // - pkg_unpack_check (c, t, m.name, replace); + pkg_unpack_check (db, t, m.name, replace); // Fix-up the package version. // - if (optional<version> v = package_iteration ( - o, c, t, d, m.name, m.version, true /* check_external */)) + if (optional<version> v = package_iteration (o, + db, + t, + d, + m.name, + m.version, + &pvi.info, + true /* check_external */)) m.version = move (*v); // Use the special root repository fragment as the repository fragment of // this package. // return pkg_unpack (o, - c, + db, t, move (m.name), move (m.version), + m.dependencies, + &pvi.info, d, repository_location (), purge, @@ -201,7 +271,8 @@ namespace bpkg shared_ptr<selected_package> pkg_unpack (const common_options& o, - const dir_path& c, + database& pdb, + database& rdb, transaction& t, package_name n, version v, @@ -210,20 +281,19 @@ namespace bpkg { tracer trace ("pkg_unpack"); - database& db (t.database ()); - tracer_guard tg (db, trace); + tracer_guard tg (pdb, trace); // NOTE: sets tracer for the whole cluster. // Check/diagnose an already existing package. // - pkg_unpack_check (c, t, n, replace); + pkg_unpack_check (pdb, t, n, replace); - check_any_available (c, t); + check_any_available (rdb, t); - // Note that here we compare including the revision (see pkg-fetch() + // Note that here we compare including the revision (see pkg_fetch() // implementation for more details). // shared_ptr<available_package> ap ( - db.find<available_package> (available_package_id (n, v))); + rdb.find<available_package> (available_package_id (n, v))); if (ap == nullptr) fail << "package " << n << " " << v << " is not available"; @@ -235,7 +305,8 @@ namespace bpkg for (const package_location& l: ap->locations) { - if (l.repository_fragment.load ()->location.directory_based ()) + if (!rep_masked_fragment (l.repository_fragment) && + l.repository_fragment.load ()->location.directory_based ()) { pl = &l; break; @@ -253,35 +324,37 @@ namespace bpkg const repository_location& rl (pl->repository_fragment->location); return pkg_unpack (o, - c, + pdb, t, move (n), move (v), + ap->dependencies, + nullptr /* package_info */, path_cast<dir_path> (rl.path () / pl->location), rl, - false /* purge */, + false /* purge */, simulate); } shared_ptr<selected_package> pkg_unpack (const common_options& co, - const dir_path& c, + database& db, transaction& t, const package_name& name, bool simulate) { tracer trace ("pkg_unpack"); - database& db (t.database ()); tracer_guard tg (db, trace); + const dir_path& c (db.config_orig); shared_ptr<selected_package> p (db.find<selected_package> (name)); if (p == nullptr) fail << "package " << name << " does not exist in configuration " << c; if (p->state != package_state::fetched) - fail << "package " << name << " is " << p->state << + fail << "package " << name << db << " is " << p->state << info << "expected it to be fetched"; l4 ([&]{trace << *p;}); @@ -293,20 +366,22 @@ 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.string () + '-' + p->version.string ())); + const package_name& n (p->name); + const version& v (p->version); - if (exists (d)) - fail << "package directory " << d << " already exists"; + dir_path d (c / dir_path (n.string () + '-' + v.string ())); auto_rmdir arm; - optional<string> mc; if (!simulate) { + if (exists (d)) + fail << "package directory " << d << " already exists"; + // If the archive path is not absolute, then it must be relative // to the configuration. // - path a (p->archive->absolute () ? *p->archive : c / *p->archive); + path a (p->effective_archive (c)); l4 ([&]{trace << "archive: " << a;}); @@ -329,15 +404,11 @@ namespace bpkg { fail << "unable to extract " << a << " to " << c << ": " << e; } - - mc = sha256 (co, d / manifest_file); } p->src_root = d.leaf (); // For now assuming to be in configuration. p->purge_src = true; - p->manifest_checksum = move (mc); - p->state = package_state::unpacked; db.update (p); @@ -356,7 +427,7 @@ namespace bpkg const dir_path& c (o.directory ()); l4 ([&]{trace << "configuration: " << c;}); - database db (open (c, trace)); + database db (c, trace, true /* pre_attach */); transaction t (db); shared_ptr<selected_package> p; @@ -371,7 +442,7 @@ namespace bpkg info << "run 'bpkg help pkg-unpack' for more information"; p = pkg_unpack (o, - c, + db, t, dir_path (args.next ()), o.replace (), @@ -400,9 +471,14 @@ namespace bpkg // "unpack" it from the directory-based repository. // p = v.empty () - ? pkg_unpack (o, c, t, n, false /* simulate */) + ? pkg_unpack (o, + db /* pdb */, + t, + n, + false /* simulate */) : pkg_unpack (o, - c, + db /* pdb */, + db /* rdb */, t, move (n), move (v), |