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 &) {}
59 void pick(bool const &newValue
){/* Ignore attempts to pick this!. Throw an exception here if you want to detect such attemtps instead */}
61 static _defaultversion defaultversion
;
63 /* the wrapper class */
64 packageversion::packageversion() : data (&defaultversion
)
69 /* Create from an actual package */
70 packageversion::packageversion (_packageversion
*pkg
)
75 data
= &defaultversion
;
79 packageversion::packageversion (packageversion
const &existing
) :
85 packageversion::~packageversion()
87 if (--data
->references
== 0)
92 packageversion::operator= (packageversion
const &rhs
)
94 ++rhs
.data
->references
;
95 if (--data
->references
== 0)
102 packageversion::operator ! () const
104 return !data
->Name().size();
107 packageversion::operator bool () const
109 return data
->Name().size();
113 packageversion::operator == (packageversion
const &rhs
) const
115 if (this == &rhs
|| data
== rhs
.data
)
118 return data
->Name () == rhs
.data
->Name() && data
->Canonical_version () == rhs
.data
->Canonical_version();
122 packageversion::operator != (packageversion
const &rhs
) const
124 return ! (*this == rhs
);
128 packageversion::operator < (packageversion
const &rhs
) const
130 int t
= data
->Name ().casecompare (rhs
.data
->Name());
135 else if (data
->Canonical_version().casecompare (rhs
.data
->Canonical_version()) < 0)
141 packageversion::Name () const
143 return data
->Name ();
147 packageversion::Canonical_version() const
149 return data
->Canonical_version();
153 packageversion::setCanonicalVersion (String
const &ver
)
155 data
->setCanonicalVersion (ver
);
159 packageversion::getfirstfile ()
161 return data
->getfirstfile ();
165 packageversion::getnextfile ()
167 return data
->getnextfile ();
171 packageversion::SDesc () const
173 return data
->SDesc ();
177 packageversion::set_sdesc (String
const &sdesc
)
179 data
->set_sdesc (sdesc
);
183 packageversion::LDesc () const
185 return data
->LDesc ();
189 packageversion::set_ldesc (String
const &ldesc
)
191 data
->set_ldesc (ldesc
);
195 packageversion::sourcePackage()
197 return data
->sourcePackage();
200 PackageSpecification
&
201 packageversion::sourcePackageSpecification ()
203 return data
->sourcePackageSpecification ();
207 packageversion::setSourcePackageSpecification (PackageSpecification
const &spec
)
209 data
->setSourcePackageSpecification(spec
);
212 vector
<vector
<PackageSpecification
*> *> *
213 packageversion::depends()
215 return &data
->depends
;
218 vector
<vector
<PackageSpecification
*> *> *
219 packageversion::predepends()
221 return &data
->predepends
;
224 vector
<vector
<PackageSpecification
*> *> *
225 packageversion::recommends()
227 return &data
->recommends
;
230 vector
<vector
<PackageSpecification
*> *> *
231 packageversion::suggests()
233 return &data
->suggests
;
236 vector
<vector
<PackageSpecification
*> *> *
237 packageversion::replaces()
239 return &data
->replaces
;
242 vector
<vector
<PackageSpecification
*> *> *
243 packageversion::conflicts()
245 return &data
->conflicts
;
248 vector
<vector
<PackageSpecification
*> *> *
249 packageversion::provides()
251 return &data
->provides
;
254 vector
<vector
<PackageSpecification
*> *> *
255 packageversion::binaries()
257 return &data
->binaries
;
261 packageversion::picked () const
267 packageversion::pick (bool aBool
)
273 packageversion::changeRequested () const
275 return data
->changeRequested ();
279 packageversion::uninstall ()
285 packageversion::source ()
287 if (!data
->sources
.size())
288 data
->sources
.push_back (packagesource());
289 return &data
->sources
[0];
292 vector
<packagesource
> *
293 packageversion::sources ()
295 return &data
->sources
;
299 packageversion::accessible() const
301 return data
->accessible();
305 checkForInstalled (PackageSpecification
*spec
)
308 packagemeta
*required
= db
.findBinary (*spec
);
311 if (spec
->satisfies (required
->installed
)
312 && required
->desired
== required
->installed
)
313 /* done, found a satisfactory installed version that will remain
320 checkForUpgradeable (PackageSpecification
*spec
)
323 packagemeta
*required
= db
.findBinary (*spec
);
324 if (!required
|| !required
->installed
)
326 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
327 i
!= required
->versions
.end(); ++i
)
328 if (spec
->satisfies (*i
))
334 checkForSatisfiable (PackageSpecification
*spec
)
337 packagemeta
*required
= db
.findBinary (*spec
);
340 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
341 i
!= required
->versions
.end(); ++i
)
342 if (spec
->satisfies (*i
))
347 /* Convenience class for now */
348 class DependencyProcessor
{
350 DependencyProcessor (trusts
const &aTrust
, int aDepth
=0) : deftrust (aTrust
), depth (aDepth
) {}
351 trusts
const deftrust
;
356 select (DependencyProcessor
&processor
, packagemeta
*required
, packageversion
const &aVersion
)
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);
369 processOneDependency(trusts deftrust
, size_t depth
, PackageSpecification
*spec
)
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
376 packagemeta
*required
= db
.findBinary (*spec
);
377 DependencyProcessor
processor (deftrust
, depth
);
379 packageversion trusted
= required
->trustp(deftrust
);
380 if (spec
->satisfies (trusted
)) {
381 return select (processor
,required
,trusted
);
384 log (LOG_TIMESTAMP
) << "Warning, the default trust level for package "
385 << trusted
.Name() << " does not meet this specification " << *spec
388 set
<packageversion
>::iterator v
;
389 for (v
= required
->versions
.begin();
390 v
!= required
->versions
.end() && !spec
->satisfies (*v
); ++v
);
392 if (v
== required
->versions
.end())
396 return select (processor
, required
, *v
);
400 packageversion::set_requirements (trusts deftrust
, size_t depth
)
403 vector
<vector
<PackageSpecification
*> *>::iterator dp
= depends ()->begin();
404 /* cheap test for too much recursion */
407 /* walk through each and clause */
408 while (dp
!= depends ()->end())
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?
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())
421 /* we found an installed ok package */
422 /* next and clause */
426 /* check each or clause for an upgradeable version */
427 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForUpgradeable
);
428 if (i
!= (*dp
)->end())
430 /* we found a package that can be up/downgraded to meet the
431 requirement. (*i is the packagespec that can be satisfied.)
434 changed
+= processOneDependency (deftrust
, depth
, *i
) + 1;
437 /* check each or clause for an installable version */
438 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForSatisfiable
);
439 if (i
!= (*dp
)->end())
441 /* we found a package that can be installed to meet the requirement */
443 changed
+= processOneDependency (deftrust
, depth
, *i
) + 1;
451 /* the parent data class */
453 _packageversion::_packageversion ():picked (false), references (0)
457 _packageversion::~_packageversion ()
461 PackageSpecification
&
462 _packageversion::sourcePackageSpecification ()
464 return _sourcePackage
;
468 _packageversion::setSourcePackageSpecification (PackageSpecification
const &spec
)
470 _sourcePackage
= spec
;
474 _packageversion::sourcePackage ()
480 pkg
= db
.findSource (_sourcePackage
);
481 /* no valid source meta available, just return the default
482 (blank) package version
485 return sourceVersion
;
486 set
<packageversion
>::iterator i
=pkg
->versions
.begin();
487 while (i
!= pkg
->versions
.end())
489 packageversion
const & ver
= * i
;
490 if (_sourcePackage
.satisfies (ver
))
495 return sourceVersion
;
499 _packageversion::accessible() const
502 for (vector
<packagesource
>::const_iterator i
= sources
.begin();
503 i
!=sources
.end(); ++i
)
508 if (::source
== IDC_SOURCE_CWD
)
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 ())
515 return retrievable
== sources
.size();
519 _packageversion::changeRequested ()
521 return (picked
|| sourcePackage().picked());