]> cygwin.com Git - cygwin-apps/setup.git/blame - package_version.cc
2003-03-16 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / package_version.cc
CommitLineData
7939f6d1
RC
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
20static const char *cvsid =
21 "\n%%% $Id$\n";
22#endif
bb849dbd
RC
23
24#include "package_version.h"
3c196821
RC
25#include "package_db.h"
26#include "package_meta.h"
bd4e91a7 27#include "LogSingleton.h"
3c196821
RC
28#include "state.h"
29#include "resource.h"
4f591f9d 30#include <algorithm>
3c196821 31
666bf37d
RC
32using namespace std;
33
3c196821
RC
34/* a default class to avoid special casing empty packageversions */
35
36/* TODO place into the class header */
37class _defaultversion : public _packageversion
bb849dbd 38{
3c196821
RC
39public:
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 (){}
6e754226 59 void pick(bool const &newValue){/* Ignore attempts to pick this!. Throw an exception here if you want to detect such attemtps instead */}
ad646f43
RC
60 virtual void addScript(Script const &) {}
61 virtual std::vector <Script> &scripts() { scripts_.clear(); return scripts_;}
62 private:
63 std::vector <Script> scripts_;
bb849dbd 64};
3c196821
RC
65static _defaultversion defaultversion;
66
67/* the wrapper class */
68packageversion::packageversion() : data (&defaultversion)
69{
70 ++data->references;
71}
72
73/* Create from an actual package */
74packageversion::packageversion (_packageversion *pkg)
75{
76 if (pkg)
77 data = pkg;
78 else
79 data = &defaultversion;
80 ++data->references;
81}
82
83packageversion::packageversion (packageversion const &existing) :
84data(existing.data)
85{
86 ++data->references;
87}
88
89packageversion::~packageversion()
90{
91 if (--data->references == 0)
92 delete data;
93}
94
95packageversion &
96packageversion::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
105bool
106packageversion::operator ! () const
107{
108 return !data->Name().size();
109}
110
111packageversion::operator bool () const
112{
113 return data->Name().size();
114}
115
116bool
117packageversion::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
125bool
126packageversion::operator != (packageversion const &rhs) const
127{
128 return ! (*this == rhs);
129}
130
131bool
132packageversion::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
144String const
145packageversion::Name () const
146{
147 return data->Name ();
148}
149
150String const
151packageversion::Canonical_version() const
152{
153 return data->Canonical_version();
154}
155
156void
157packageversion::setCanonicalVersion (String const &ver)
158{
159 data->setCanonicalVersion (ver);
160}
161
162String const
163packageversion::getfirstfile ()
164{
165 return data->getfirstfile ();
166}
167
168String const
169packageversion::getnextfile ()
170{
171 return data->getnextfile ();
172}
173
174String const
175packageversion::SDesc () const
176{
177 return data->SDesc ();
178}
179
180void
181packageversion::set_sdesc (String const &sdesc)
182{
183 data->set_sdesc (sdesc);
184}
185
186String const
187packageversion::LDesc () const
188{
189 return data->LDesc ();
190}
191
192void
193packageversion::set_ldesc (String const &ldesc)
194{
195 data->set_ldesc (ldesc);
196}
197
198packageversion
199packageversion::sourcePackage()
200{
201 return data->sourcePackage();
202}
aa1e3b4d
RC
203
204PackageSpecification &
3c196821
RC
205packageversion::sourcePackageSpecification ()
206{
207 return data->sourcePackageSpecification ();
208}
209
210void
211packageversion::setSourcePackageSpecification (PackageSpecification const &spec)
212{
213 data->setSourcePackageSpecification(spec);
214}
215
216vector <vector <PackageSpecification *> *> *
217packageversion::depends()
218{
219 return &data->depends;
220}
221
222vector <vector <PackageSpecification *> *> *
223packageversion::predepends()
224{
225 return &data->predepends;
226}
227
228vector <vector <PackageSpecification *> *> *
229packageversion::recommends()
230{
231 return &data->recommends;
232}
233
234vector <vector <PackageSpecification *> *> *
235packageversion::suggests()
236{
237 return &data->suggests;
238}
239
240vector <vector <PackageSpecification *> *> *
241packageversion::replaces()
242{
243 return &data->replaces;
244}
245
246vector <vector <PackageSpecification *> *> *
247packageversion::conflicts()
248{
249 return &data->conflicts;
250}
251
252vector <vector <PackageSpecification *> *> *
253packageversion::provides()
254{
255 return &data->provides;
256}
257
b1ff53ed
RC
258vector <vector <PackageSpecification *> *> *
259packageversion::binaries()
260{
261 return &data->binaries;
262}
3c196821
RC
263
264bool
265packageversion::picked () const
266{
267 return data->picked;
268}
269
270void
271packageversion::pick (bool aBool)
272{
6e754226 273 data->pick(aBool);
3c196821
RC
274}
275
276bool
277packageversion::changeRequested () const
278{
279 return data->changeRequested ();
280}
281
282void
283packageversion::uninstall ()
284{
285 data->uninstall ();
286}
287
288packagesource *
289packageversion::source ()
290{
e5662e0a
RC
291 if (!data->sources.size())
292 data->sources.push_back (packagesource());
293 return &data->sources[0];
3c196821
RC
294}
295
ec13f13c
RC
296vector<packagesource> *
297packageversion::sources ()
298{
299 return &data->sources;
300}
301
3c196821
RC
302bool
303packageversion::accessible() const
304{
305 return data->accessible();
306}
307
4f591f9d
RC
308static bool
309checkForInstalled (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
323static bool
324checkForUpgradeable (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
337static bool
338checkForSatisfiable (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
05c5b8a6
RC
351/* Convenience class for now */
352class DependencyProcessor {
353public:
354 DependencyProcessor (trusts const &aTrust, int aDepth=0) : deftrust (aTrust), depth (aDepth) {}
355 trusts const deftrust;
356 size_t depth;
357};
358
359static int
360select (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
4f591f9d
RC
372static int
373processOneDependency(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);
05c5b8a6
RC
381 DependencyProcessor processor (deftrust, depth);
382
383 packageversion trusted = required->trustp(deftrust);
bd4e91a7
RC
384 if (spec->satisfies (trusted)) {
385 return select (processor,required,trusted);
386 }
387
388 log (LOG_TIMESTAMP) << "Warning, the default trust level for package "
c4e25cde
MB
389 << trusted.Name() << " does not meet this specification " << *spec
390 << endLog;
05c5b8a6 391
4f591f9d
RC
392 set <packageversion>::iterator v;
393 for (v = required->versions.begin();
394 v != required->versions.end() && !spec->satisfies (*v); ++v);
05c5b8a6
RC
395
396 if (v == required->versions.end())
397 /* assert ?! */
398 return 0;
399
400 return select (processor, required, *v);
4f591f9d
RC
401}
402
403int
666bf37d 404packageversion::set_requirements (trusts deftrust, size_t depth)
4f591f9d
RC
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
ad646f43
RC
455void
456packageversion::addScript(Script const &aScript)
457{
458 return data->addScript (aScript);
459}
460
461std::vector <Script> &
462packageversion::scripts()
463{
464 return data->scripts();
465}
466
3c196821
RC
467/* the parent data class */
468
469_packageversion::_packageversion ():picked (false), references (0)
470{
471}
472
473_packageversion::~_packageversion ()
474{
475}
476
477PackageSpecification &
478_packageversion::sourcePackageSpecification ()
aa1e3b4d
RC
479{
480 return _sourcePackage;
481}
482
483void
3c196821 484_packageversion::setSourcePackageSpecification (PackageSpecification const &spec)
aa1e3b4d
RC
485{
486 _sourcePackage = spec;
487}
3c196821
RC
488
489packageversion
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
514bool
515_packageversion::accessible() const
516{
e5662e0a
RC
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();
3c196821
RC
532}
533
534bool
535_packageversion::changeRequested ()
536{
537 return (picked || sourcePackage().picked());
538}
ad646f43
RC
539
540void
541_packageversion::addScript(Script const &aScript)
542{
543 scripts().push_back(aScript);
544}
545
546std::vector <Script> &
547_packageversion::scripts()
548{
549 return scripts_;
550}
This page took 0.084061 seconds and 5 git commands to generate.