aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-01-17 10:51:29 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-01-17 10:51:29 +0200
commit7a572b703b7207bb9bc7b2d8d3443152aac42d19 (patch)
treea0a18b1083d3017c067ad2669299380cf1eb4f82
parent6f41ca43cd46658dad840fb51d5fb59431ceac67 (diff)
Continue sketching system package manager interface
-rw-r--r--bpkg/host-os-release.hxx6
-rw-r--r--bpkg/pkg-build.cxx3
-rw-r--r--bpkg/system-package-manager-debian.cxx28
-rw-r--r--bpkg/system-package-manager-debian.hxx35
-rw-r--r--bpkg/system-package-manager.cxx4
-rw-r--r--bpkg/system-package-manager.hxx80
6 files changed, 145 insertions, 11 deletions
diff --git a/bpkg/host-os-release.hxx b/bpkg/host-os-release.hxx
index c2d6672..3f85cb2 100644
--- a/bpkg/host-os-release.hxx
+++ b/bpkg/host-os-release.hxx
@@ -47,8 +47,10 @@ namespace bpkg
string variant; // VARIANT
};
- // Return the release information for the specified host or nullopt if
- // the specific host is unknown/unsupported.
+ // Return the release information for the specified host or nullopt if the
+ // specific host is unknown/unsupported. Note that "host" here implies that
+ // we may be examining files, environment variables, etc., of the machine we
+ // are running on.
//
optional<os_release>
host_os_release (const target_triplet& host);
diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx
index 61bd1da..f452d50 100644
--- a/bpkg/pkg-build.cxx
+++ b/bpkg/pkg-build.cxx
@@ -1762,6 +1762,9 @@ namespace bpkg
// no_db_system_repository or some such, which add_system_package()
// can use if db == NULL.
//
+ // @@ Actually, I think this should just be assert() since the only
+ // source of authoritative information is system package manager
+ // and it caches its results.
}
return vc;
diff --git a/bpkg/system-package-manager-debian.cxx b/bpkg/system-package-manager-debian.cxx
new file mode 100644
index 0000000..1e43206
--- /dev/null
+++ b/bpkg/system-package-manager-debian.cxx
@@ -0,0 +1,28 @@
+// file : bpkg/system-package-manager-debian.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#include <bpkg/system-package-manager-debian.hxx>
+
+#include <bpkg/diagnostics.hxx>
+
+namespace bpkg
+{
+ // Do we use apt or apt-get? From apt(8):
+ //
+ // "The apt(8) commandline is designed as an end-user tool and it may change
+ // behavior between versions. [...]
+ //
+ // All features of apt(8) are available in dedicated APT tools like
+ // apt-get(8) and apt-cache(8) as well. [...] So you should prefer using
+ // these commands (potentially with some additional options enabled) in
+ // your scripts as they keep backward compatibility as much as possible."
+
+ // @@ We actually need to fetch if some are not installed to get their
+ // versions. We can do it as part of the call, no? Keep track if
+ // already fetched.
+
+ // @@ We may map multiple our packages to the same system package
+ // (e.g., openssl-devel) so probably should track the status of
+ // individual system packages. What if we "installed any version"
+ // first and then need to install specific?
+}
diff --git a/bpkg/system-package-manager-debian.hxx b/bpkg/system-package-manager-debian.hxx
new file mode 100644
index 0000000..5b1f764
--- /dev/null
+++ b/bpkg/system-package-manager-debian.hxx
@@ -0,0 +1,35 @@
+// file : bpkg/system-package-manager-debian.hxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BPKG_SYSTEM_PACKAGE_MANAGER_DEBIAN_HXX
+#define BPKG_SYSTEM_PACKAGE_MANAGER_DEBIAN_HXX
+
+#include <bpkg/types.hxx>
+#include <bpkg/utility.hxx>
+
+#include <bpkg/system-package-manager.hxx>
+
+namespace bpkg
+{
+ // The system package manager implementation for Debian and alike (Ubuntu,
+ // etc) using the APT frontend.
+ //
+ class system_package_manager_debian: public system_package_manager
+ {
+ public:
+ virtual optional<const package_status*>
+ pkg_status (const package_name&,
+ const available_packages*,
+ bool install,
+ bool fetch) override;
+
+ public:
+ explicit
+ system_package_manager_debian (os_release&& osr)
+ : system_package_manager (move (osr)) {}
+
+ protected:
+ };
+}
+
+#endif // BPKG_SYSTEM_PACKAGE_MANAGER_DEBIAN_HXX
diff --git a/bpkg/system-package-manager.cxx b/bpkg/system-package-manager.cxx
index e5503f6..3d5bda7 100644
--- a/bpkg/system-package-manager.cxx
+++ b/bpkg/system-package-manager.cxx
@@ -10,6 +10,8 @@
#include <bpkg/database.hxx>
#include <bpkg/diagnostics.hxx>
+#include <bpkg/system-package-manager-debian.hxx>
+
using namespace std;
using namespace butl;
@@ -41,6 +43,8 @@ namespace bpkg
{
// @@ TODO: verify name if specified.
+ // @@ TMP
+ //
//r.reset (new system_package_manager_debian (move (*osr)));
}
}
diff --git a/bpkg/system-package-manager.hxx b/bpkg/system-package-manager.hxx
index 131c670..fb90e2c 100644
--- a/bpkg/system-package-manager.hxx
+++ b/bpkg/system-package-manager.hxx
@@ -23,23 +23,85 @@ namespace bpkg
public:
struct package_status
{
+ // Downstream (as in, bpkg package) version.
+ //
bpkg::version version;
- // The system package can be either "available already installed"
- // or "available not yet installed".
- //
- // If the package is partially installed (for example, libfoo but not
- // libfoo-dev is installed), then installed should be false (and perhaps
- // only a single available version should be returned).
+ // The system package can be either "available already installed",
+ // "available partially installed" (for example, libfoo but not
+ // libfoo-dev is installed) or "available not yet installed".
//
- bool installed;
+ enum {installed, partially_installed, not_installed} status;
+ // System (as in, distribution package) name and version.
+ //
+ // @@ But these could be multiple. Do we really need this?
+ /*
string system_name;
string system_version;
+ */
};
- // @@ We actually need to fetch is some are not installed to get their
- // versions. We can do it as part of the call, no?
+ // Query the system package status.
+ //
+ // This function has two modes: cache-only (available_packages is NULL)
+ // and full (available_packages is not NULL). In the cache-only mode this
+ // function returns the status of this package if it has already been
+ // queried and nullopt otherwise. This allows the caller to only collect
+ // all the available packages (for the name/version mapping information)
+ // if really necessary.
+ //
+ // The returned value can be NULL, which indicates that no such package is
+ // available from the system package manager. Note that NULL is returned
+ // if no fully installed package is available from the system and install
+ // is false.
+ //
+ // If fetch is false, then do not re-fetch the system package repository
+ // metadata (that is, available packages/versions) before querying for
+ // the available version of the not yet installed or partially installed
+ // packages.
+ //
+ // Note that currently the result is a single available version. While
+ // some package managers may support installing multiple versions in
+ // parallel, this is unlikely to be suppored for the packages we are
+ // interested in due to the underlying limitations.
+ //
+ // Specifically, the packages that we are primarily interested in are
+ // libraries with headers and executables (tools). While most package
+ // managers (e.g., Debian, Fedora) are able to install multiple libraries
+ // in parallel, they normally can only install a single set of headers,
+ // static libraries, pkg-config files, etc., (e.g., -dev/-devel package)
+ // at a time due to them being installed into the same location (e.g.,
+ // /usr/include). The same holds for executables, which are installed into
+ // the same location (e.g., /usr/bin).
+ //
+ // @@ But it's still plausible to have multiple available versions but
+ // only being able to install one at a time?
+ //
+ // It is possible that a certain library has made arrangements for
+ // multiple of its versions to co-exist. For example, hypothetically, our
+ // libssl package could be mapped to both libssl1.1 libssl1.1-dev and
+ // libssl3 libssl3-dev which could be installed at the same time (note
+ // that it is not the case in reality; there is only libssl-dev). However,
+ // in this case, we should probably also have two packages with separate
+ // names (e.g., libssl and libssl3) that can also co-exist. An example of
+ // this would be libQt5Core and libQt6Core. (Note that strictly speaking
+ // there could be different degrees of co-existence: for the system
+ // package manager it is sufficient for different versions not to clobber
+ // each other's files while for us we may also need the ability to use
+ // different versions in the base build).
+ //
+ // Note also that the above reasoning is quite C/C++-centric and it's
+ // possible that multiple versions of libraries (or equivalent) for other
+ // languages (e.g., Rust) can always co-exist. In this case we may need to
+ // revise this decision to only return a single version (and pick the best
+ // suitable version as part of the constraint resolution).
+ //
+ virtual optional<const package_status*>
+ pkg_status (const package_name&,
+ const available_packages*,
+ bool install,
+ bool fetch) = 0;
public:
virtual