aboutsummaryrefslogtreecommitdiff
path: root/bpkg/package-query.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'bpkg/package-query.hxx')
-rw-r--r--bpkg/package-query.hxx281
1 files changed, 281 insertions, 0 deletions
diff --git a/bpkg/package-query.hxx b/bpkg/package-query.hxx
new file mode 100644
index 0000000..de389c1
--- /dev/null
+++ b/bpkg/package-query.hxx
@@ -0,0 +1,281 @@
+// file : bpkg/package-query.hxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BPKG_PACKAGE_QUERY_HXX
+#define BPKG_PACKAGE_QUERY_HXX
+
+#include <odb/core.hxx>
+
+#include <bpkg/types.hxx>
+#include <bpkg/utility.hxx>
+
+#include <bpkg/package.hxx>
+#include <bpkg/database.hxx>
+
+#include <bpkg/common-options.hxx>
+
+namespace bpkg
+{
+ // Query the available packages that optionally satisfy the specified
+ // version constraint and return them in the version descending order, by
+ // default. Note that a stub satisfies any constraint.
+ //
+ // By default if the revision is not explicitly specified for the version
+ // constraint, 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 have to spell the revision
+ // explicitly. Similarly, when we have 'depends: libfoo == 1', then it would
+ // be strange if 1+1 did not satisfy this constraint. The same for libfoo <=
+ // 1 -- 1+1 should satisfy.
+ //
+ // Note that by default we compare ignoring the iteration, as it can not be
+ // specified in the manifest/command line. This way the latest iteration
+ // will always be picked up.
+ //
+ // Pass true as the revision argument to query the exact available package
+ // version, also comparing the version revision and iteration.
+ //
+ odb::result<available_package>
+ query_available (database&,
+ const package_name&,
+ const optional<version_constraint>&,
+ bool order = true,
+ bool revision = false);
+
+ // Only return packages that are in the specified repository fragments, their
+ // complements or prerequisites (if prereq is true), recursively. While you
+ // could maybe come up with a (barely comprehensible) view/query to achieve
+ // this, doing it on the "client side" is definitely more straightforward.
+ //
+ vector<shared_ptr<available_package>>
+ filter (const shared_ptr<repository_fragment>&,
+ odb::result<available_package>&&,
+ bool prereq = true);
+
+ pair<shared_ptr<available_package>, shared_ptr<repository_fragment>>
+ filter_one (const shared_ptr<repository_fragment>&,
+ odb::result<available_package>&&,
+ bool prereq = true);
+
+ shared_ptr<repository_fragment>
+ filter (const shared_ptr<repository_fragment>&,
+ const shared_ptr<available_package>&,
+ bool prereq = true);
+
+ vector<pair<shared_ptr<available_package>, shared_ptr<repository_fragment>>>
+ filter (const vector<shared_ptr<repository_fragment>>&,
+ odb::result<available_package>&&,
+ bool prereq = true);
+
+ pair<shared_ptr<available_package>, shared_ptr<repository_fragment>>
+ filter_one (const vector<shared_ptr<repository_fragment>>&,
+ odb::result<available_package>&&,
+ bool prereq = true);
+
+ // Try to find packages that optionally satisfy the specified version
+ // constraint in multiple databases, suppressing duplicates. Return the list
+ // of packages and repository fragments in which each was found in the
+ // package version descending order or empty list if none were found. Note
+ // that a stub satisfies any constraint.
+ //
+ // Note that we return (loaded) lazy_shared_ptr in order to also convey
+ // the database to which it belongs.
+ //
+ available_packages
+ find_available (const linked_databases&,
+ const package_name&,
+ const optional<version_constraint>&);
+
+ // As above but only look for packages from the specified list of repository
+ // fragments, their prerequisite repositories, and their complements,
+ // recursively (note: recursivity applies to complements, not prerequisites).
+ //
+ using config_repo_fragments =
+ database_map<vector<shared_ptr<repository_fragment>>>;
+
+ available_packages
+ find_available (const package_name&,
+ const optional<version_constraint>&,
+ const config_repo_fragments&,
+ bool prereq = true);
+
+ // As above but only look for packages from a single repository fragment,
+ // its prerequisite repositories, and its complements, recursively (note:
+ // recursivity applies to complements, not prerequisites). Doesn't provide
+ // the repository fragments the packages come from.
+ //
+ // It is assumed that the repository fragment lazy pointer contains the
+ // database information.
+ //
+ vector<shared_ptr<available_package>>
+ find_available (const package_name&,
+ const optional<version_constraint>&,
+ const lazy_shared_ptr<repository_fragment>&,
+ bool prereq = true);
+
+ // As above but only look for a single package from the specified repository
+ // fragment, its prerequisite repositories, and their complements,
+ // recursively (note: recursivity applies to complements, not
+ // prerequisites). Return the package and the repository fragment in which
+ // it was found or NULL for both if not found.
+ //
+ // It is assumed that the repository fragment lazy pointer contains the
+ // database information.
+ //
+ pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>
+ find_available_one (const package_name&,
+ const optional<version_constraint>&,
+ const lazy_shared_ptr<repository_fragment>&,
+ bool prereq = true,
+ bool revision = false);
+
+ // As above but look for a single package from a list of repository
+ // fragments.
+ //
+ pair<shared_ptr<available_package>, shared_ptr<repository_fragment>>
+ find_available_one (database&,
+ const package_name&,
+ const optional<version_constraint>&,
+ const vector<shared_ptr<repository_fragment>>&,
+ bool prereq = true,
+ bool revision = false);
+
+ // As above but look for a single package in multiple databases from their
+ // respective root repository fragments.
+ //
+ pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>
+ find_available_one (const linked_databases&,
+ const package_name&,
+ const optional<version_constraint>&,
+ bool prereq = true,
+ bool revision = false);
+
+ // Try to find an available package corresponding to the specified selected
+ // package and, if not found, return a transient one. The search is
+ // performed in the ultimate dependent configurations of the selected
+ // package (see dependent_repo_configs() for details).
+ //
+ // NOTE: repo_configs needs to be filled prior to the function call.
+ //
+ shared_ptr<available_package>
+ find_available (const common_options&,
+ database&,
+ const shared_ptr<selected_package>&);
+
+ // As above but also pair the available package with the repository fragment
+ // the available package comes from. Note that the package locations list is
+ // left empty and that the returned repository fragment could be NULL if the
+ // package is an orphan.
+ //
+ // NOTE: repo_configs needs to be filled prior to the function call.
+ //
+ pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>
+ find_available_fragment (const common_options&,
+ database&,
+ const shared_ptr<selected_package>&);
+
+ // Try to find packages in multiple databases, traversing the explicitly and
+ // implicitly linked databases recursively and suppressing duplicates and,
+ // optionally, older package revisions. Return the list of packages and
+ // repository fragments in which each was found in the package version
+ // descending order or empty list if none were found.
+ //
+ // Note that we return (loaded) lazy_shared_ptr in order to also convey
+ // the database to which it belongs.
+ //
+ available_packages
+ find_available_all (const linked_databases&,
+ const package_name&,
+ bool suppress_older_revisions = true);
+
+ // Create a transient (or fake, if you prefer) available_package object
+ // corresponding to the specified selected object. Note that the package
+ // locations list is left empty and that the returned repository fragment
+ // could be NULL if the package is an orphan.
+ //
+ // Note that the repository fragment is searched in the ultimate dependent
+ // configurations of the selected package (see dependent_repo_configs() for
+ // details).
+ //
+ // Also note that in our model we assume that make_available_fragment() is
+ // only called if there is no real available_package. This makes sure that
+ // if the package moves (e.g., from testing to stable), then we will be
+ // using stable to resolve its dependencies.
+ //
+ // NOTE: repo_configs needs to be filled prior to the function call.
+ //
+ pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>
+ make_available_fragment (const common_options&,
+ database&,
+ const shared_ptr<selected_package>&);
+
+ // Try to find an available stub package in the imaginary system repository.
+ // Such a repository contains stubs corresponding to the system packages
+ // specified by the user on the command line with version information
+ // (sys:libfoo/1.0, ?sys:libfoo/* but not ?sys:libfoo; the idea is that a
+ // real stub won't add any extra information to such a specification so we
+ // shouldn't insist on its presence). Semantically this imaginary repository
+ // complements all real repositories.
+ //
+ extern vector<shared_ptr<available_package>> imaginary_stubs;
+
+ shared_ptr<available_package>
+ find_imaginary_stub (const package_name&);
+
+ // Try to find an available package in the existing packages registry. Such
+ // a registry is configuration-specific and contains package versions
+ // specified by the user on the command line as archives or directories for
+ // specific configurations (see pkg-build for details on such packages).
+ //
+ // Note that semantically such a registry can be considered as an imaginary
+ // repository which complements all the real repositories fetched in the
+ // respective configuration. Also note that normally this repository is used
+ // first (by calling this function) when trying to resolve a dependency
+ // package, prior to searching in the real repositories.
+ //
+ extern vector<pair<reference_wrapper<database>,
+ shared_ptr<available_package>>> existing_packages;
+
+ pair<shared_ptr<available_package>, lazy_shared_ptr<repository_fragment>>
+ find_existing (database&,
+ const package_name&,
+ const optional<version_constraint>&);
+
+ inline pair<shared_ptr<available_package>,
+ lazy_shared_ptr<repository_fragment>>
+ find_existing (const package_name& n,
+ const optional<version_constraint>& c,
+ const lazy_shared_ptr<repository_fragment>& rf)
+ {
+ return find_existing (rf.database (), n, c);
+ }
+
+ // Configurations to use as the repository information sources.
+ //
+ // The list normally contains the current configurations and configurations
+ // of the specified on the command line build-to-hold packages (ultimate
+ // dependents).
+ //
+ // For ultimate dependents we use configurations in which they are being
+ // built as a source of the repository information. For dependency packages
+ // we use configurations of their ultimate dependents.
+ //
+ extern linked_databases repo_configs;
+
+ // Return the ultimate dependent configurations for packages in this
+ // configuration.
+ //
+ // Specifically, this is an intersection of all the dependent configurations
+ // for the specified configuration (see database::dependent_configs() for
+ // details) and configurations which contain repository information
+ // (repo_configs).
+ //
+ linked_databases
+ dependent_repo_configs (database&);
+}
+
+#endif // BPKG_PACKAGE_QUERY_HXX