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