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