]> cygwin.com Git - cygwin-apps/setup.git/blob - package_version.cc
2002-11-25 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / package_version.cc
1 /*
2 * Copyright (c) 2001, Robert Collins.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Robert Collins <rbtcollins@hotmail.com>
13 *
14 */
15
16 /* this is the parent class for all package operations.
17 */
18
19 #if 0
20 static const char *cvsid =
21 "\n%%% $Id$\n";
22 #endif
23
24 #include "package_version.h"
25 #include "package_db.h"
26 #include "package_meta.h"
27 #include "state.h"
28 #include "resource.h"
29 #include <algorithm>
30
31 using namespace std;
32
33 /* a default class to avoid special casing empty packageversions */
34
35 /* TODO place into the class header */
36 class _defaultversion : public _packageversion
37 {
38 public:
39 _defaultversion()
40 {
41 // never try to free me!
42 ++references;
43 }
44 String const Name(){return String();}
45 String const Vendor_version() {return String();}
46 String const Package_version() {return String();}
47 String const Canonical_version() {return String();}
48 void setCanonicalVersion (String const &) {}
49 package_status_t Status (){return package_notinstalled;}
50 package_type_t Type () {return package_binary;}
51 String const getfirstfile () {return String();}
52 String const getnextfile () {return String();}
53 String const SDesc () {return String();}
54 void set_sdesc (String const &) {}
55 String const LDesc () {return String();}
56 void set_ldesc (String const &) {}
57 void uninstall (){}
58 };
59 static _defaultversion defaultversion;
60
61 /* the wrapper class */
62 packageversion::packageversion() : data (&defaultversion)
63 {
64 ++data->references;
65 }
66
67 /* Create from an actual package */
68 packageversion::packageversion (_packageversion *pkg)
69 {
70 if (pkg)
71 data = pkg;
72 else
73 data = &defaultversion;
74 ++data->references;
75 }
76
77 packageversion::packageversion (packageversion const &existing) :
78 data(existing.data)
79 {
80 ++data->references;
81 }
82
83 packageversion::~packageversion()
84 {
85 if (--data->references == 0)
86 delete data;
87 }
88
89 packageversion &
90 packageversion::operator= (packageversion const &rhs)
91 {
92 ++rhs.data->references;
93 if (--data->references == 0)
94 delete data;
95 data = rhs.data;
96 return *this;
97 }
98
99 bool
100 packageversion::operator ! () const
101 {
102 return !data->Name().size();
103 }
104
105 packageversion::operator bool () const
106 {
107 return data->Name().size();
108 }
109
110 bool
111 packageversion::operator == (packageversion const &rhs) const
112 {
113 if (this == &rhs || data == rhs.data)
114 return true;
115 else
116 return data->Name () == rhs.data->Name() && data->Canonical_version () == rhs.data->Canonical_version();
117 }
118
119 bool
120 packageversion::operator != (packageversion const &rhs) const
121 {
122 return ! (*this == rhs);
123 }
124
125 bool
126 packageversion::operator < (packageversion const &rhs) const
127 {
128 int t = data->Name ().casecompare (rhs.data->Name());
129 if (t < 0)
130 return true;
131 else if (t > 0)
132 return false;
133 else if (data->Canonical_version().casecompare (rhs.data->Canonical_version()) < 0)
134 return true;
135 return false;
136 }
137
138 String const
139 packageversion::Name () const
140 {
141 return data->Name ();
142 }
143
144 String const
145 packageversion::Canonical_version() const
146 {
147 return data->Canonical_version();
148 }
149
150 void
151 packageversion::setCanonicalVersion (String const &ver)
152 {
153 data->setCanonicalVersion (ver);
154 }
155
156 String const
157 packageversion::getfirstfile ()
158 {
159 return data->getfirstfile ();
160 }
161
162 String const
163 packageversion::getnextfile ()
164 {
165 return data->getnextfile ();
166 }
167
168 String const
169 packageversion::SDesc () const
170 {
171 return data->SDesc ();
172 }
173
174 void
175 packageversion::set_sdesc (String const &sdesc)
176 {
177 data->set_sdesc (sdesc);
178 }
179
180 String const
181 packageversion::LDesc () const
182 {
183 return data->LDesc ();
184 }
185
186 void
187 packageversion::set_ldesc (String const &ldesc)
188 {
189 data->set_ldesc (ldesc);
190 }
191
192 packageversion
193 packageversion::sourcePackage()
194 {
195 return data->sourcePackage();
196 }
197
198 PackageSpecification &
199 packageversion::sourcePackageSpecification ()
200 {
201 return data->sourcePackageSpecification ();
202 }
203
204 void
205 packageversion::setSourcePackageSpecification (PackageSpecification const &spec)
206 {
207 data->setSourcePackageSpecification(spec);
208 }
209
210 vector <vector <PackageSpecification *> *> *
211 packageversion::depends()
212 {
213 return &data->depends;
214 }
215
216 vector <vector <PackageSpecification *> *> *
217 packageversion::predepends()
218 {
219 return &data->predepends;
220 }
221
222 vector <vector <PackageSpecification *> *> *
223 packageversion::recommends()
224 {
225 return &data->recommends;
226 }
227
228 vector <vector <PackageSpecification *> *> *
229 packageversion::suggests()
230 {
231 return &data->suggests;
232 }
233
234 vector <vector <PackageSpecification *> *> *
235 packageversion::replaces()
236 {
237 return &data->replaces;
238 }
239
240 vector <vector <PackageSpecification *> *> *
241 packageversion::conflicts()
242 {
243 return &data->conflicts;
244 }
245
246 vector <vector <PackageSpecification *> *> *
247 packageversion::provides()
248 {
249 return &data->provides;
250 }
251
252 vector <vector <PackageSpecification *> *> *
253 packageversion::binaries()
254 {
255 return &data->binaries;
256 }
257
258 bool
259 packageversion::picked () const
260 {
261 return data->picked;
262 }
263
264 void
265 packageversion::pick (bool aBool)
266 {
267 data->picked = aBool;
268 }
269
270 bool
271 packageversion::changeRequested () const
272 {
273 return data->changeRequested ();
274 }
275
276 void
277 packageversion::uninstall ()
278 {
279 data->uninstall ();
280 }
281
282 packagesource *
283 packageversion::source ()
284 {
285 if (!data->sources.size())
286 data->sources.push_back (packagesource());
287 return &data->sources[0];
288 }
289
290 vector<packagesource> *
291 packageversion::sources ()
292 {
293 return &data->sources;
294 }
295
296 bool
297 packageversion::accessible() const
298 {
299 return data->accessible();
300 }
301
302 static bool
303 checkForInstalled (PackageSpecification *spec)
304 {
305 packagedb db;
306 packagemeta *required = db.findBinary (*spec);
307 if (!required)
308 return false;
309 if (spec->satisfies (required->installed)
310 && required->desired == required->installed )
311 /* done, found a satisfactory installed version that will remain
312 installed */
313 return true;
314 return false;
315 }
316
317 static bool
318 checkForUpgradeable (PackageSpecification *spec)
319 {
320 packagedb db;
321 packagemeta *required = db.findBinary (*spec);
322 if (!required || !required->installed)
323 return false;
324 for (set <packageversion>::iterator i = required->versions.begin();
325 i != required->versions.end(); ++i)
326 if (spec->satisfies (*i))
327 return true;
328 return false;
329 }
330
331 static bool
332 checkForSatisfiable (PackageSpecification *spec)
333 {
334 packagedb db;
335 packagemeta *required = db.findBinary (*spec);
336 if (!required)
337 return false;
338 for (set <packageversion>::iterator i = required->versions.begin();
339 i != required->versions.end(); ++i)
340 if (spec->satisfies (*i))
341 return true;
342 return false;
343 }
344
345 /* Convenience class for now */
346 class DependencyProcessor {
347 public:
348 DependencyProcessor (trusts const &aTrust, int aDepth=0) : deftrust (aTrust), depth (aDepth) {}
349 trusts const deftrust;
350 size_t depth;
351 };
352
353 static int
354 select (DependencyProcessor &processor, packagemeta *required, packageversion const &aVersion)
355 {
356 /* preserve source */
357 bool sourceticked = required->desired.sourcePackage().picked();
358 /* install this version */
359 required->desired = aVersion;
360 required->desired.pick (required->installed != required->desired);
361 required->desired.sourcePackage().pick (sourceticked);
362 /* does this requirement have requirements? */
363 return required->set_requirements (processor.deftrust, processor.depth + 1);
364 }
365
366 static int
367 processOneDependency(trusts deftrust, size_t depth, PackageSpecification *spec)
368 {
369 /* TODO: add this to a set of packages to be offered to meet the
370 requirement. For now, simply set the install to the first
371 satisfactory version. The user can step through the list if
372 desired */
373 packagedb db;
374 packagemeta *required = db.findBinary (*spec);
375 DependencyProcessor processor (deftrust, depth);
376
377 packageversion trusted = required->trustp(deftrust);
378 if (spec->satisfies (trusted))
379 select (processor,required,trusted);
380
381 set <packageversion>::iterator v;
382 for (v = required->versions.begin();
383 v != required->versions.end() && !spec->satisfies (*v); ++v);
384
385 if (v == required->versions.end())
386 /* assert ?! */
387 return 0;
388
389 return select (processor, required, *v);
390 }
391
392 int
393 packageversion::set_requirements (trusts deftrust, size_t depth)
394 {
395 int changed = 0;
396 vector <vector <PackageSpecification *> *>::iterator dp = depends ()->begin();
397 /* cheap test for too much recursion */
398 if (depth > 5)
399 return changed;
400 /* walk through each and clause */
401 while (dp != depends ()->end())
402 {
403 /* three step:
404 1) is a satisfactory or clause installed?
405 2) is an unsatisfactory version of an or clause which has
406 a satisfactory version available installed?
407 3) is a satisfactory package available?
408 */
409 /* check each or clause for an installed match */
410 vector <PackageSpecification *>::iterator i =
411 find_if ((*dp)->begin(), (*dp)->end(), checkForInstalled);
412 if (i != (*dp)->end())
413 {
414 /* we found an installed ok package */
415 /* next and clause */
416 ++dp;
417 continue;
418 }
419 /* check each or clause for an upgradeable version */
420 i = find_if ((*dp)->begin(), (*dp)->end(), checkForUpgradeable);
421 if (i != (*dp)->end())
422 {
423 /* we found a package that can be up/downgraded to meet the
424 requirement. (*i is the packagespec that can be satisfied.)
425 */
426 ++dp;
427 changed += processOneDependency (deftrust, depth, *i) + 1;
428 continue;
429 }
430 /* check each or clause for an installable version */
431 i = find_if ((*dp)->begin(), (*dp)->end(), checkForSatisfiable);
432 if (i != (*dp)->end())
433 {
434 /* we found a package that can be installed to meet the requirement */
435 ++dp;
436 changed += processOneDependency (deftrust, depth, *i) + 1;
437 continue;
438 }
439 ++dp;
440 }
441 return changed;
442 }
443
444 /* the parent data class */
445
446 _packageversion::_packageversion ():picked (false), references (0)
447 {
448 }
449
450 _packageversion::~_packageversion ()
451 {
452 }
453
454 PackageSpecification &
455 _packageversion::sourcePackageSpecification ()
456 {
457 return _sourcePackage;
458 }
459
460 void
461 _packageversion::setSourcePackageSpecification (PackageSpecification const &spec)
462 {
463 _sourcePackage = spec;
464 }
465
466 packageversion
467 _packageversion::sourcePackage ()
468 {
469 if (!sourceVersion)
470 {
471 packagedb db;
472 packagemeta * pkg;
473 pkg = db.findSource (_sourcePackage);
474 /* no valid source meta available, just return the default
475 (blank) package version
476 */
477 if (!pkg)
478 return sourceVersion;
479 set<packageversion>::iterator i=pkg->versions.begin();
480 while (i != pkg->versions.end())
481 {
482 packageversion const & ver = * i;
483 if (_sourcePackage.satisfies (ver))
484 sourceVersion = ver;
485 ++i;
486 }
487 }
488 return sourceVersion;
489 }
490
491 bool
492 _packageversion::accessible() const
493 {
494 bool cached = true;
495 for (vector<packagesource>::const_iterator i = sources.begin();
496 i!=sources.end(); ++i)
497 if (!i->Cached ())
498 cached = false;
499 if (cached)
500 return true;
501 if (::source == IDC_SOURCE_CWD)
502 return false;
503 unsigned int retrievable = 0;
504 for (vector<packagesource>::const_iterator i = sources.begin();
505 i!=sources.end(); ++i)
506 if (i->sites.size() || i->Cached ())
507 retrievable += 1;
508 return retrievable == sources.size();
509 }
510
511 bool
512 _packageversion::changeRequested ()
513 {
514 return (picked || sourcePackage().picked());
515 }
This page took 0.056124 seconds and 5 git commands to generate.