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