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