2 * Copyright (c) 2001, Robert Collins.
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.
9 * A copy of the GNU General Public License can be found at
12 * Written by Robert Collins <rbtcollins@hotmail.com>
16 /* this is the parent class for all package operations.
20 static const char *cvsid
=
24 #include "package_version.h"
25 #include "package_db.h"
26 #include "package_meta.h"
27 #include "LogSingleton.h"
34 /* a default class to avoid special casing empty packageversions */
36 /* TODO place into the class header */
37 class _defaultversion
: public _packageversion
42 // never try to free me!
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 &) {}
60 static _defaultversion defaultversion
;
62 /* the wrapper class */
63 packageversion::packageversion() : data (&defaultversion
)
68 /* Create from an actual package */
69 packageversion::packageversion (_packageversion
*pkg
)
74 data
= &defaultversion
;
78 packageversion::packageversion (packageversion
const &existing
) :
84 packageversion::~packageversion()
86 if (--data
->references
== 0)
91 packageversion::operator= (packageversion
const &rhs
)
93 ++rhs
.data
->references
;
94 if (--data
->references
== 0)
101 packageversion::operator ! () const
103 return !data
->Name().size();
106 packageversion::operator bool () const
108 return data
->Name().size();
112 packageversion::operator == (packageversion
const &rhs
) const
114 if (this == &rhs
|| data
== rhs
.data
)
117 return data
->Name () == rhs
.data
->Name() && data
->Canonical_version () == rhs
.data
->Canonical_version();
121 packageversion::operator != (packageversion
const &rhs
) const
123 return ! (*this == rhs
);
127 packageversion::operator < (packageversion
const &rhs
) const
129 int t
= data
->Name ().casecompare (rhs
.data
->Name());
134 else if (data
->Canonical_version().casecompare (rhs
.data
->Canonical_version()) < 0)
140 packageversion::Name () const
142 return data
->Name ();
146 packageversion::Canonical_version() const
148 return data
->Canonical_version();
152 packageversion::setCanonicalVersion (String
const &ver
)
154 data
->setCanonicalVersion (ver
);
158 packageversion::getfirstfile ()
160 return data
->getfirstfile ();
164 packageversion::getnextfile ()
166 return data
->getnextfile ();
170 packageversion::SDesc () const
172 return data
->SDesc ();
176 packageversion::set_sdesc (String
const &sdesc
)
178 data
->set_sdesc (sdesc
);
182 packageversion::LDesc () const
184 return data
->LDesc ();
188 packageversion::set_ldesc (String
const &ldesc
)
190 data
->set_ldesc (ldesc
);
194 packageversion::sourcePackage()
196 return data
->sourcePackage();
199 PackageSpecification
&
200 packageversion::sourcePackageSpecification ()
202 return data
->sourcePackageSpecification ();
206 packageversion::setSourcePackageSpecification (PackageSpecification
const &spec
)
208 data
->setSourcePackageSpecification(spec
);
211 vector
<vector
<PackageSpecification
*> *> *
212 packageversion::depends()
214 return &data
->depends
;
217 vector
<vector
<PackageSpecification
*> *> *
218 packageversion::predepends()
220 return &data
->predepends
;
223 vector
<vector
<PackageSpecification
*> *> *
224 packageversion::recommends()
226 return &data
->recommends
;
229 vector
<vector
<PackageSpecification
*> *> *
230 packageversion::suggests()
232 return &data
->suggests
;
235 vector
<vector
<PackageSpecification
*> *> *
236 packageversion::replaces()
238 return &data
->replaces
;
241 vector
<vector
<PackageSpecification
*> *> *
242 packageversion::conflicts()
244 return &data
->conflicts
;
247 vector
<vector
<PackageSpecification
*> *> *
248 packageversion::provides()
250 return &data
->provides
;
253 vector
<vector
<PackageSpecification
*> *> *
254 packageversion::binaries()
256 return &data
->binaries
;
260 packageversion::picked () const
266 packageversion::pick (bool aBool
)
268 data
->picked
= aBool
;
272 packageversion::changeRequested () const
274 return data
->changeRequested ();
278 packageversion::uninstall ()
284 packageversion::source ()
286 if (!data
->sources
.size())
287 data
->sources
.push_back (packagesource());
288 return &data
->sources
[0];
291 vector
<packagesource
> *
292 packageversion::sources ()
294 return &data
->sources
;
298 packageversion::accessible() const
300 return data
->accessible();
304 checkForInstalled (PackageSpecification
*spec
)
307 packagemeta
*required
= db
.findBinary (*spec
);
310 if (spec
->satisfies (required
->installed
)
311 && required
->desired
== required
->installed
)
312 /* done, found a satisfactory installed version that will remain
319 checkForUpgradeable (PackageSpecification
*spec
)
322 packagemeta
*required
= db
.findBinary (*spec
);
323 if (!required
|| !required
->installed
)
325 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
326 i
!= required
->versions
.end(); ++i
)
327 if (spec
->satisfies (*i
))
333 checkForSatisfiable (PackageSpecification
*spec
)
336 packagemeta
*required
= db
.findBinary (*spec
);
339 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
340 i
!= required
->versions
.end(); ++i
)
341 if (spec
->satisfies (*i
))
346 /* Convenience class for now */
347 class DependencyProcessor
{
349 DependencyProcessor (trusts
const &aTrust
, int aDepth
=0) : deftrust (aTrust
), depth (aDepth
) {}
350 trusts
const deftrust
;
355 select (DependencyProcessor
&processor
, packagemeta
*required
, packageversion
const &aVersion
)
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);
368 processOneDependency(trusts deftrust
, size_t depth
, PackageSpecification
*spec
)
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
375 packagemeta
*required
= db
.findBinary (*spec
);
376 DependencyProcessor
processor (deftrust
, depth
);
378 packageversion trusted
= required
->trustp(deftrust
);
379 if (spec
->satisfies (trusted
)) {
380 return select (processor
,required
,trusted
);
383 log (LOG_TIMESTAMP
) << "Warning, the default trust level for package "
384 << trusted
.Name() << " does not meet this specification " << *spec
<< endl
;
386 set
<packageversion
>::iterator v
;
387 for (v
= required
->versions
.begin();
388 v
!= required
->versions
.end() && !spec
->satisfies (*v
); ++v
);
390 if (v
== required
->versions
.end())
394 return select (processor
, required
, *v
);
398 packageversion::set_requirements (trusts deftrust
, size_t depth
)
401 vector
<vector
<PackageSpecification
*> *>::iterator dp
= depends ()->begin();
402 /* cheap test for too much recursion */
405 /* walk through each and clause */
406 while (dp
!= depends ()->end())
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?
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())
419 /* we found an installed ok package */
420 /* next and clause */
424 /* check each or clause for an upgradeable version */
425 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForUpgradeable
);
426 if (i
!= (*dp
)->end())
428 /* we found a package that can be up/downgraded to meet the
429 requirement. (*i is the packagespec that can be satisfied.)
432 changed
+= processOneDependency (deftrust
, depth
, *i
) + 1;
435 /* check each or clause for an installable version */
436 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForSatisfiable
);
437 if (i
!= (*dp
)->end())
439 /* we found a package that can be installed to meet the requirement */
441 changed
+= processOneDependency (deftrust
, depth
, *i
) + 1;
449 /* the parent data class */
451 _packageversion::_packageversion ():picked (false), references (0)
455 _packageversion::~_packageversion ()
459 PackageSpecification
&
460 _packageversion::sourcePackageSpecification ()
462 return _sourcePackage
;
466 _packageversion::setSourcePackageSpecification (PackageSpecification
const &spec
)
468 _sourcePackage
= spec
;
472 _packageversion::sourcePackage ()
478 pkg
= db
.findSource (_sourcePackage
);
479 /* no valid source meta available, just return the default
480 (blank) package version
483 return sourceVersion
;
484 set
<packageversion
>::iterator i
=pkg
->versions
.begin();
485 while (i
!= pkg
->versions
.end())
487 packageversion
const & ver
= * i
;
488 if (_sourcePackage
.satisfies (ver
))
493 return sourceVersion
;
497 _packageversion::accessible() const
500 for (vector
<packagesource
>::const_iterator i
= sources
.begin();
501 i
!=sources
.end(); ++i
)
506 if (::source
== IDC_SOURCE_CWD
)
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 ())
513 return retrievable
== sources
.size();
517 _packageversion::changeRequested ()
519 return (picked
|| sourcePackage().picked());