aboutsummaryrefslogtreecommitdiff
path: root/bpkg/package-query.hxx
blob: de389c1b677797a43a16a564951d57a037eccb7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
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