diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2023-02-09 15:46:32 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2023-02-21 04:46:55 +0200 |
commit | 5e004f94984476ddda74f90e8adaacd3c0871062 (patch) | |
tree | 5c5e4df4a4be02917d118d4cbd547ade87ff569b | |
parent | eaebfcff492cf7f707b44a3d28620e786116faf1 (diff) |
Initial work on pkg-bindist command and Debian implementation
-rw-r--r-- | bpkg/bpkg.cli | 5 | ||||
-rw-r--r-- | bpkg/bpkg.cxx | 2 | ||||
-rw-r--r-- | bpkg/buildfile | 2 | ||||
-rw-r--r-- | bpkg/pkg-bindist.cli | 123 | ||||
-rw-r--r-- | bpkg/pkg-bindist.cxx | 338 | ||||
-rw-r--r-- | bpkg/pkg-bindist.hxx | 27 | ||||
-rw-r--r-- | bpkg/system-package-manager-debian.cxx | 172 | ||||
-rw-r--r-- | bpkg/system-package-manager-debian.hxx | 6 | ||||
-rw-r--r-- | bpkg/system-package-manager-fedora.hxx | 2 | ||||
-rw-r--r-- | bpkg/system-package-manager.cxx | 8 | ||||
-rw-r--r-- | bpkg/system-package-manager.hxx | 10 | ||||
-rwxr-xr-x | doc/cli.sh | 8 |
12 files changed, 653 insertions, 50 deletions
diff --git a/bpkg/bpkg.cli b/bpkg/bpkg.cli index 17ac927..6edea97 100644 --- a/bpkg/bpkg.cli +++ b/bpkg/bpkg.cli @@ -257,6 +257,11 @@ namespace bpkg "\l{bpkg-pkg-clean(1)} \- clean package" } + bool pkg-bindist|bindist + { + "\l{bpkg-pkg-bindist(1)} \- generate binary distribution package" + } + bool pkg-verify { "\l{bpkg-pkg-verify(1)} \- verify package archive" diff --git a/bpkg/bpkg.cxx b/bpkg/bpkg.cxx index 28ba75f..21cbefc 100644 --- a/bpkg/bpkg.cxx +++ b/bpkg/bpkg.cxx @@ -49,6 +49,7 @@ #include <bpkg/cfg-link.hxx> #include <bpkg/cfg-unlink.hxx> +#include <bpkg/pkg-bindist.hxx> #include <bpkg/pkg-build.hxx> #include <bpkg/pkg-checkout.hxx> #include <bpkg/pkg-clean.hxx> @@ -767,6 +768,7 @@ try // These commands need the '--' separator to be kept in args. // + PKG_COMMAND (bindist, true, true); PKG_COMMAND (build, true, false); PKG_COMMAND (clean, true, true); PKG_COMMAND (configure, true, true); diff --git a/bpkg/buildfile b/bpkg/buildfile index ca78218..1531b9a 100644 --- a/bpkg/buildfile +++ b/bpkg/buildfile @@ -34,6 +34,7 @@ cfg-unlink-options \ common-options \ configuration-options \ help-options \ +pkg-bindist-options \ pkg-build-options \ pkg-checkout-options \ pkg-clean-options \ @@ -148,6 +149,7 @@ if $cli.configured # pkg-* command. # + cli.cxx{pkg-bindist-options}: cli{pkg-bindist} cli.cxx{pkg-build-options}: cli{pkg-build} cli.cxx{pkg-checkout-options}: cli{pkg-checkout} cli.cxx{pkg-clean-options}: cli{pkg-clean} diff --git a/bpkg/pkg-bindist.cli b/bpkg/pkg-bindist.cli new file mode 100644 index 0000000..5686ed6 --- /dev/null +++ b/bpkg/pkg-bindist.cli @@ -0,0 +1,123 @@ +// file : bpkg/pkg-bindist.cli +// license : MIT; see accompanying LICENSE file + +include <bpkg/configuration.cli>; + +"\section=1" +"\name=bpkg-pkg-bindist" +"\summary=generate binary distribution package" + +namespace bpkg +{ + { + "<options> <vars> <out-dir> <pkg>", + + "\h|SYNOPSIS| + + \c{\b{bpkg pkg-bindist}|\b{bindist} [<options>] [<vars>] <out-dir> <pkg> [<pkg>...]} + + \h|DESCRIPTION| + + The \cb{pkg-bindist} command generates a binary distribution package for + the specified package. If additional packages are specified, then they + are bundled in the same distribution package. All the specified packages + must have been previously configured with \l{bpkg-pkg-build(1)} or + \l{bpkg-pkg-configure(1)}. The intermediate files and the resulting + binary package are created in the <out-dir> directory. + + Underneath, this command roughly performs the following steps: First it + installs the specified packages similar to the \l{bpkg-pkg-install(1)} + command except that it may override the installation locations (via the + \cb{config.install.*} variables) to match the distribution's layout. Then + it generates any necessary distribution package metadata files based on + the information from the package \cb{manifest} files. Finally, it invokes + the distribution-specified command to produce the binary package. Unless + overrident with the \cb{--architecture} and \cb{--distribution} options, + the binary package is generated for the host architecture using the + host's standard system package manager. Additional command line variables + (<vars>, normally \cb{config.*}) can be passed to the build system during + the installation step. + + The specified packages may have dependencies and the default behavior is + to not bundle them but rather to specify them as dependencies in the + corresponding distribution package metadata, if applicable. This default + behavior can be overridden with the \cb{--recursive} option (see the + option description for the available modes). Note, however, that + dependencies that are satisfied by system packages are always specified + as dependencies in the distribution package metadata. + " + } + + // @@ Have section for each package manager with options? + + class pkg_bindist_options: configuration_options + { + "\h|PKG-BINDIST OPTIONS|" + + string --distribution + { + "<name>", + "Alternative system/distribution package manager to generate the binary + package for. The valid <name> values are \cb{debian} (Debian and + alike, such as Ubuntu, etc) and \cb{fedora} (Fedora and alike, + such as RHEL, CentOS, etc). Note that some package managers may + only be supported when running on certain host operating systems." + } + + string --architecture + { + "<name>", + "Alternative architecture to generate the binary package for. The + valid <name> values are system/distribution package manager-specific. + If unspecified, the host architecture is used." + } + + string --recursive + { + "<mode>", + "Bundle dependencies of the specified packages. The <mode> value can be + either \cb{auto}, in which case only the required files from each + dependency package are bundled, or \cb{full}, in which case all the + files are bundled. Specifically, in the \cb{auto} mode any required + files, for example, shared libraries, are pulled implicitly by the + \cb{install} build system operation, for example, as part of + installing an executable from one of the specified packages. In + contrast, in the \cb{full} mode, each dependency package is + installed explicitly and completely, as if they were specified + as additional package on the command line. See also the \cb{--private} + option." + } + + bool --private + { + "Enable the private installation subdirectory functionality using the + binary package name as the private subdirectory. This is primarily + useful when bundling dependencies, such as shared libraries, of an + executable that is being installed into a shared location, such as + \cb{/usr/}. See the \cb{config.install.private} configuration variable + documentation in the build system manual for details. This option + only makes sense together with \cb{--recursive}." + } + }; + + " + \h|DEFAULT OPTIONS FILES| + + See \l{bpkg-default-options-files(1)} for an overview of the default + options files. For the \cb{pkg-bindist} command the search start + directory is the configuration directory. The following options files are + searched for in each directory and, if found, loaded in the order listed: + + \ + bpkg.options + bpkg-pkg-bindist.options + \ + + The following \cb{pkg-bindist} command options cannot be specified in the + default options files: + + \ + --directory|-d + \ + " +} diff --git a/bpkg/pkg-bindist.cxx b/bpkg/pkg-bindist.cxx new file mode 100644 index 0000000..289f34b --- /dev/null +++ b/bpkg/pkg-bindist.cxx @@ -0,0 +1,338 @@ +// file : bpkg/pkg-bindist.cxx -*- C++ -*- +// license : MIT; see accompanying LICENSE file + +#include <bpkg/pkg-bindist.hxx> + +#include <bpkg/package.hxx> +#include <bpkg/package-odb.hxx> +#include <bpkg/package-query.hxx> +#include <bpkg/database.hxx> +#include <bpkg/diagnostics.hxx> +#include <bpkg/system-package-manager.hxx> + +using namespace std; +using namespace butl; + +namespace bpkg +{ + using packages = system_package_manager::packages; + using recursive_mode = system_package_manager::recursive_mode; + + // Find the available package(s) for the specified selected package. + // + // Specifically, for non-system packages we look for a single available + // package failing if it's an orphan. For system packages we look for all + // the available packages analogous to pkg-build. If none are found then + // we assume the --sys-no-stub option was used to configure this package + // and return an empty list. @@ What if it was configured with a specific + // bpkg version or `*`? + // + static available_packages + find_available_packages (const common_options& co, + database& db, + const shared_ptr<selected_package>& p) + { + assert (p->state == package_state::configured); + + available_packages r; + if (p->substate == package_substate::system) + { + r = find_available_all (repo_configs, p->name); + } + else + { + pair<shared_ptr<available_package>, + lazy_shared_ptr<repository_fragment>> ap ( + find_available_fragment (co, db, p)); + + if (ap.second.loaded () && ap.second == nullptr) + fail << "package " << p->name << " is orphaned"; + + r.push_back (move (ap)); + } + + return r; + } + + // Collect dependencies of the specified package, potentially recursively. + // System dependencies go to deps, non-system -- to pkgs, which could be the + // same as deps or NULL, depending on the desired semantics (see the call + // site for details). Find available packages for deps. + // + static void + collect_dependencies (const common_options& co, + packages* pkgs, + packages& deps, + const selected_package& p, + bool recursive) + { + for (const auto& pr: p.prerequisites) + { + const lazy_shared_ptr<selected_package>& ld (pr.first); + + // We only consider dependencies from target configurations, similar + // to pkg-install. + // + database& db (ld.database ()); + if (db.type == host_config_type || db.type == build2_config_type) + continue; + + shared_ptr<selected_package> d (ld.load ()); + + // The selected package can only be configured if all its dependencies + // are configured. + // + assert (d->state == package_state::configured); + + bool sys (d->substate == package_substate::system); + packages* ps (sys ? &deps : pkgs); + + // Skip duplicates. + // + if (ps == nullptr || + find_if (ps->begin (), ps->end (), + [&d] (const pair<shared_ptr<selected_package>, + available_packages>& p) + { + return p.first == d; + }) == ps->end ()) + { + available_packages aps; + if (ps == &deps) // Note: covers the (pkgs == &deps) case. + aps = find_available_packages (co, db, d); + + const selected_package& p (*d); + + if (ps != nullptr) + ps->push_back (make_pair (move (d), move (aps))); + + if (recursive && !sys) + collect_dependencies (co, pkgs, deps, p, recursive); + } + } + } + + int + pkg_bindist (const pkg_bindist_options& o, cli::scanner& args) + { + tracer trace ("pkg_bindist"); + + dir_path c (o.directory ()); + l4 ([&]{trace << "configuration: " << c;}); + + // Verify options. + // + optional<recursive_mode> rec; + { + diag_record dr; + + if (o.recursive_specified ()) + { + const string& m (o.recursive ()); + + if (m == "auto") rec = recursive_mode::auto_; + else if (m == "full") rec = recursive_mode::full; + else + dr << fail << "unknown mode '" << m << "' specified with --recursive"; + } + else if (o.private_ ()) + dr << fail << "--private specified without --recursive"; + + if (!dr.empty ()) + dr << info << "run 'bpkg help pkg-bindist' for more information"; + } + + // Sort arguments into the output directory, package names, and + // configuration variables. + // + dir_path out; + vector<package_name> pns; + strings vars; + { + bool sep (false); // Seen `--`. + + while (args.more ()) + { + string a (args.next ()); + + // If we see the `--` separator, then we are done parsing variables + // (while they won't clash with package names, we may be given a + // directory path that contains `=`). + // + if (!sep && a == "--") + { + sep = true; + continue; + } + + if (a.find ('=') != string::npos) + vars.push_back (move (trim (a))); + else if (out.empty ()) + { + try + { + out = dir_path (move (a)); + } + catch (const invalid_path& e) + { + fail << "invalid output directory '" << e.path << "'"; + } + } + else + { + try + { + pns.push_back (package_name (move (a))); // Not moved on failure. + } + catch (const invalid_argument& e) + { + fail << "invalid package name '" << a << "': " << e; + } + } + } + + if (out.empty () || pns.empty ()) + fail << "output directory or package name argument expected" << + info << "run 'bpkg help pkg-bindist' for more information"; + } + + database db (c, trace, true /* pre_attach */); + + // Similar to pkg-install we disallow generating packages from the + // host/build2 configurations. + // + if (db.type == host_config_type || db.type == build2_config_type) + { + fail << "unable to generate distribution package from " << db.type + << " configuration" << + info << "use target configuration instead"; + } + + // Prepare for the find_available_*() calls. + // + repo_configs.push_back (db); + + transaction t (db); + + // We need to suppress duplicate dependencies for the recursive mode. + // + session ses; + + // Resolve package names to selected packages and verify they are all + // configured. While at it collect their available packages and + // dependencies. + // + packages pkgs, deps; + + for (const package_name& n: pns) + { + shared_ptr<selected_package> p (db.find<selected_package> (n)); + + if (p == nullptr) + fail << "package " << n << " does not exist in configuration " << c; + + if (p->state != package_state::configured) + fail << "package " << n << " is " << p->state << + info << "expected it to be configured"; + + if (p->substate == package_substate::system) + fail << "package " << n << " is configured as system"; + + // If this is the first package, load its available package for the + // mapping information. We don't need it for any additional packages. + // + available_packages aps; + if (pkgs.empty ()) + aps = find_available_packages (o, db, p); + + const selected_package& r (*p); + pkgs.push_back (make_pair (move (p), move (aps))); + + // If --recursive is not specified then we want all the immediate + // (system and non-) dependecies in deps. Otherwise, if the recursive + // mode is full, then we want all the transitive non-system dependecies + // in pkgs. In both recursive modes we also want all the transitive + // system dependecies in deps. + // + // Note also that in the auto recursive mode it's possible that some of + // the system dependencies are not really needed. But there is no way + // for us to detect this and it's better to over- than under-specify. + // + collect_dependencies (o, + (rec + ? *rec == recursive_mode::full ? &pkgs : nullptr + : &deps), + deps, + r, + rec.has_value ()); + } + + t.commit (); + + // Note that we shouldn't need to install anything or use sudo. + // + unique_ptr<system_package_manager> spm ( + make_production_system_package_manager (o, + host_triplet, + o.distribution (), + o.architecture ())); + if (spm == nullptr) + { + fail << "no standard distribution package manager for this host " + << "or it is not yet supported" << + info << "consider specifying alternative distribution package " + << "manager with --distribution"; + } + + // @@ TODO: pass/handle --private. + + // Note that we certain move the arguments to allow the implementation to + // rearrange things if/as convenient. + // + spm->generate (move (pkgs), + move (deps), + move (vars), + out, + rec); + + + // @@ TODO: need to save name/version (or change the output, maybe + // to something returned by spm? + // +#if 0 + if (verb && !o.no_result ()) + { + const selected_package& p (*pkgs.front ().first); + + text << "generated " << spm->os_release.name_id << " package for " + << p.name << '/' << p.version; + } +#endif + + return 0; + } + + pkg_bindist_options + merge_options (const default_options<pkg_bindist_options>& defs, + const pkg_bindist_options& cmd) + { + // NOTE: remember to update the documentation if changing anything here. + + return merge_default_options ( + defs, + cmd, + [] (const default_options_entry<pkg_bindist_options>& e, + const pkg_bindist_options&) + { + const pkg_bindist_options& o (e.options); + + auto forbid = [&e] (const char* opt, bool specified) + { + if (specified) + fail (e.file) << opt << " in default options file"; + }; + + forbid ("--directory|-d", o.directory_specified ()); + }); + } +} diff --git a/bpkg/pkg-bindist.hxx b/bpkg/pkg-bindist.hxx new file mode 100644 index 0000000..3a756f8 --- /dev/null +++ b/bpkg/pkg-bindist.hxx @@ -0,0 +1,27 @@ +// file : bpkg/pkg-bindist.hxx -*- C++ -*- +// license : MIT; see accompanying LICENSE file + +#ifndef BPKG_PKG_BINDIST_HXX +#define BPKG_PKG_BINDIST_HXX + +#include <bpkg/types.hxx> +#include <bpkg/utility.hxx> + +#include <bpkg/pkg-command.hxx> +#include <bpkg/pkg-bindist-options.hxx> + +namespace bpkg +{ + // Note that for now it doesn't seem we need to bother with package- + // specific configuration variables so it's scanner instead of + // group_scanner. + // + int + pkg_bindist (const pkg_bindist_options&, cli::scanner&); + + pkg_bindist_options + merge_options (const default_options<pkg_bindist_options>&, + const pkg_bindist_options&); +} + +#endif // BPKG_PKG_BINDIST_HXX diff --git a/bpkg/system-package-manager-debian.cxx b/bpkg/system-package-manager-debian.cxx index b541541..d3e63b6 100644 --- a/bpkg/system-package-manager-debian.cxx +++ b/bpkg/system-package-manager-debian.cxx @@ -894,14 +894,6 @@ namespace bpkg optional<const system_package_status*> system_package_manager_debian:: pkg_status (const package_name& pn, const available_packages* aps) { - // For now we ignore -doc and -dbg package components (but we may want to - // have options controlling this later). Note also that we assume -common - // is pulled automatically by the main package so we ignore it as well - // (see equivalent logic in parse_name_value()). - // - bool need_doc (false); - bool need_dbg (false); - // First check the cache. // { @@ -914,6 +906,25 @@ namespace bpkg return nullopt; } + optional<package_status> r (status (pn, *aps)); + + // Cache. + // + auto i (status_cache_.emplace (pn, move (r)).first); + return i->second ? &*i->second : nullptr; + } + + optional<package_status> system_package_manager_debian:: + status (const package_name& pn, const available_packages& aps) + { + // For now we ignore -doc and -dbg package components (but we may want to + // have options controlling this later). Note also that we assume -common + // is pulled automatically by the main package so we ignore it as well + // (see equivalent logic in parse_name_value()). + // + bool need_doc (false); + bool need_dbg (false); + vector<package_status> candidates; // Translate our package name to the Debian package names. @@ -927,8 +938,8 @@ namespace bpkg }); strings ns; - if (!aps->empty ()) - ns = system_package_names (*aps, + if (!aps.empty ()) + ns = system_package_names (aps, os_release.name_id, os_release.version_id, os_release.like_ids); @@ -1269,9 +1280,9 @@ namespace bpkg string sv (r->system_version, 0, r->system_version.rfind ('-')); optional<version> v; - if (!aps->empty ()) + if (!aps.empty ()) v = downstream_package_version (sv, - *aps, + aps, os_release.name_id, os_release.version_id, os_release.like_ids); @@ -1304,10 +1315,7 @@ namespace bpkg r->version = move (*v); } - // Cache. - // - auto i (status_cache_.emplace (pn, move (r)).first); - return i->second ? &*i->second : nullptr; + return r; } void system_package_manager_debian:: @@ -1455,8 +1463,8 @@ namespace bpkg // create the package completely manually without using any of the Debian // tools and while some implementations (for example, cargo-deb) do it this // way, we are not going to go this route because it does not scale well to - // more complex packages which may require additional functionality, such as - // managing systemd files, and which is covered by the Debian tools (for an + // more complex packages which may require additional functionality (such as + // managing systemd files) and which is covered by the Debian tools (for an // example of where this leads, see the partial debhelper re-implementation // in cargo-deb). Another issues with this approach is that it's not // amenable to customizations, at least not in a way familiar to Debian @@ -1464,24 +1472,24 @@ namespace bpkg // // At the lowest level of the Debian tools for creating packages sits the // dpkg-deb --build|-b command (also accessible as dpkg --build|-b). Given a - // directory with all the binary contents (including the package metadata, - // such as the control file, in the debian/ subdirectory) this command will - // pack everything up into a .deb file. While an improvement over the fully - // manual packaging, this approach has essentially the same drawbacks. In - // particular, this command generates a single package which means we will - // have to manually sort out things into -dev, -doc, etc. + // directory with all the binary package contents (including the package + // metadata, such as the control file, in the debian/ subdirectory) this + // command will pack everything up into a .deb file. While an improvement + // over the fully manual packaging, this approach has essentially the same + // drawbacks. In particular, this command generates a single package which + // means we will have to manually sort out things into -dev, -doc, etc. // // Next up the stack is dpkg-buildpackage. This tool expects the package to - // follow the Debian way, that is, to provide the debian/rules makefile with - // a number of required targets which it then invokes to build, install, and - // pack a package from source (and somewhere in this process it calls - // dpkg-deb --build). The dpkg-buildpackage(1) man page has an overview of - // all the steps that this command performs and it is the recommended, - // lower-level, way to build packages on Debian. + // follow the Debian way of packaging, that is, to provide the debian/rules + // makefile with a number of required targets which it then invokes to + // build, install, and pack a package from source (and sometime during this + // process it calls dpkg-deb --build). The dpkg-buildpackage(1) man page has + // an overview of all the steps that this command performs and it is the + // recommended, lower-level, way to build packages on Debian. // // At the top of the stack sits debuild which calls dpkg-buildpackage, then - // lintian and finally design (though signing can also be performed by - // dpkg-buildpackage). + // lintian, and finally design (though signing can also be performed by + // dpkg-buildpackage itself). // // Based on this our plan is to use dpkg-buildpackage which brings us to the // Debian way of packaging with debian/rules at its core. As it turns out, @@ -1498,7 +1506,7 @@ namespace bpkg // While debhelper tools definitely simplify debian/rules, there is often // still a lot of boilerplate code. So second-level helpers are often used, // with the dominant option being the dh(1) command sequencer (there is also - // CDBS but it appears to be mostly obsolete). + // CDBS but it appears to be fading into obsolescence). // // Based on that our options appear to be classic debhelper and dh. Looking // at the statistics, it's clear that the majority of packages (including @@ -1508,16 +1516,104 @@ namespace bpkg // So, to sum up, the plan is to produce debian/rules that uses the dh // command sequencer and then invoke dpkg-buildpackage to produce the binary // package from that. While this approach is normally used to build things - // from source, it feels like we should be able to pretend that we are by, - // for example, overriding the install target to invoke the build system to - // install all the packages directly from their bpkg locations. + // from source, it feels like we should be able to pretend that we are. + // Specifially, we can override the install target to invoke the build + // system and install all the packages directly from their bpkg locations. // void system_package_manager_debian:: - generate (packages&&, - packages&&, + generate (packages&& pkgs, + packages&& deps, strings&&, const dir_path&, optional<recursive_mode>) { + // @@ What are we doing with extras, in both deps and the package being + // generated? + + // Map non-system bpkg package to system package name(s) and version. + // + auto map_package = [this] (const selected_package& sp, + const available_packages& aps) -> package_status + { + // We should only have one available package corresponding to the + // selected package. + // + assert (sp.substate != package_substate::system && aps.size () == 1); + + strings ns (system_package_names (aps, + os_release.name_id, + os_release.version_id, + os_release.like_ids)); + package_status r; + if (ns.empty ()) + { + // Automatically translate our package name similar to the consumption + // case above. Except here we don't attempt to deduce main from -dev, + // naturally. + // + const string& pn (sp.name.string ()); + + // The best we can do in trying to detect whether this is a library is + // to check for the lib prefix. Libraries without the lib prefix and + // non-libraries with the lib prefix (both of which we do not + // recomment) will have to provide a manual mapping. + // + if (pn.compare (0, 3, "lib") == 0 && pn.size () > 3) + { + r = package_status (pn, pn + "-dev"); + } + else + r = package_status (pn); + } + else + { + // Even though we only pass one available package, we may still end up + // with multiple mappings. In this case we take the first per the + // documentation. + // + r = parse_name_value (sp.name, + ns.front (), + false /* need_doc */, + false /* need_dbg */); + } + + return r; + }; + + // As a first step, figure out the system names and version of the package + // we are generating and all the dependencies, diagnosing anything fishy. + // + // Note that there should be no duplicate dependencies and we can sidestep + // the status cache. + // + const selected_package& sp (*pkgs.front ().first); + const available_packages& aps (pkgs.front ().second); + package_status s (map_package (sp, aps)); + + vector<package_status> sdeps; + sdeps.reserve (deps.size ()); + for (const pair<shared_ptr<selected_package>, available_packages>& p: deps) + { + const selected_package& sp (*p.first); + const available_packages& aps (p.second); + + package_status s; + if (sp.substate == package_substate::system) + { + optional<package_status> os (status (sp.name, aps)); + + if (!os) + fail << "bad boy"; + + // @@ We should confirm configured version matches mapped back. + // Can be `*`! + + s = move (*os); + } + else + s = map_package (sp, aps); + + sdeps.push_back (move (s)); + } } } diff --git a/bpkg/system-package-manager-debian.hxx b/bpkg/system-package-manager-debian.hxx index 0186b76..1e53e38 100644 --- a/bpkg/system-package-manager-debian.hxx +++ b/bpkg/system-package-manager-debian.hxx @@ -233,7 +233,11 @@ namespace bpkg const simulation* simulate_ = nullptr; - protected: + private: + optional<system_package_status_debian> + status (const package_name&, const available_packages&); + + private: bool fetched_ = false; // True if already fetched metadata. bool installed_ = false; // True if already installed. diff --git a/bpkg/system-package-manager-fedora.hxx b/bpkg/system-package-manager-fedora.hxx index 6c72b81..7692822 100644 --- a/bpkg/system-package-manager-fedora.hxx +++ b/bpkg/system-package-manager-fedora.hxx @@ -327,7 +327,7 @@ namespace bpkg const simulation* simulate_ = nullptr; - protected: + private: bool fetched_ = false; // True if already fetched metadata. bool installed_ = false; // True if already installed. diff --git a/bpkg/system-package-manager.cxx b/bpkg/system-package-manager.cxx index 2ec7a60..f25c0e0 100644 --- a/bpkg/system-package-manager.cxx +++ b/bpkg/system-package-manager.cxx @@ -13,6 +13,8 @@ #include <bpkg/database.hxx> #include <bpkg/diagnostics.hxx> +#include <bpkg/pkg-bindist-options.hxx> + #include <bpkg/system-package-manager-debian.hxx> #include <bpkg/system-package-manager-fedora.hxx> @@ -122,15 +124,15 @@ namespace bpkg } unique_ptr<system_package_manager> - make_production_system_package_manager (const common_options& co, + make_production_system_package_manager (const pkg_bindist_options& o, const target_triplet& host, const string& name, const string& arch) { // Note: similar to make_production_system_package_manager() above. - optional<bool> progress (co.progress () ? true : - co.no_progress () ? false : + optional<bool> progress (o.progress () ? true : + o.no_progress () ? false : optional<bool> ()); unique_ptr<system_package_manager> r; diff --git a/bpkg/system-package-manager.hxx b/bpkg/system-package-manager.hxx index 941c981..81adeee 100644 --- a/bpkg/system-package-manager.hxx +++ b/bpkg/system-package-manager.hxx @@ -155,9 +155,11 @@ namespace bpkg virtual void pkg_install (const vector<package_name>&) = 0; - // Generate a binary distribution package. + // Generate a binary distribution package. @@ TODO: doc more // - // @@ TODO: doc + // The available packages are loaded for the first package in pkgs and for + // all the packages in deps. For non-system packages there is always a + // single available package that corresponds to the selected package. // // See the pkg-bindist(1) man page and the pkg_bindist() function // implementation for background and details. @@ -321,8 +323,10 @@ namespace bpkg bool yes, const string& sudo); + class pkg_bindist_options; + unique_ptr<system_package_manager> - make_production_system_package_manager (const common_options&, + make_production_system_package_manager (const pkg_bindist_options&, const target_triplet&, const string& name, const string& arch); @@ -81,10 +81,10 @@ compile "pkg-build" $o --class-doc bpkg::pkg_build_pkg_options=exclude-base # NOTE: remember to update a similar list in buildfile and bpkg.cli as well as # the help topics sections in bpkg/buildfile and help.cxx. # -pages="cfg-create cfg-info cfg-link cfg-unlink help pkg-clean pkg-configure \ -pkg-disfigure pkg-drop pkg-fetch pkg-checkout pkg-install pkg-purge \ -pkg-status pkg-test pkg-uninstall pkg-unpack pkg-update pkg-verify rep-add \ -rep-remove rep-list rep-create rep-fetch rep-info repository-signing \ +pages="cfg-create cfg-info cfg-link cfg-unlink help pkg-bindist pkg-clean \ +pkg-configure pkg-disfigure pkg-drop pkg-fetch pkg-checkout pkg-install \ +pkg-purge pkg-status pkg-test pkg-uninstall pkg-unpack pkg-update pkg-verify \ +rep-add rep-remove rep-list rep-create rep-fetch rep-info repository-signing \ repository-types argument-grouping default-options-files" for p in $pages; do |