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