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 */}
60 virtual void addScript(Script
const &) {}
61 virtual std::vector
<Script
> &scripts() { scripts_
.clear(); return scripts_
;}
63 std::vector
<Script
> scripts_
;
65 static _defaultversion defaultversion
;
67 /* the wrapper class */
68 packageversion::packageversion() : data (&defaultversion
)
73 /* Create from an actual package */
74 packageversion::packageversion (_packageversion
*pkg
)
79 data
= &defaultversion
;
83 packageversion::packageversion (packageversion
const &existing
) :
89 packageversion::~packageversion()
91 if (--data
->references
== 0)
96 packageversion::operator= (packageversion
const &rhs
)
98 ++rhs
.data
->references
;
99 if (--data
->references
== 0)
106 packageversion::operator ! () const
108 return !data
->Name().size();
111 packageversion::operator bool () const
113 return data
->Name().size();
117 packageversion::operator == (packageversion
const &rhs
) const
119 if (this == &rhs
|| data
== rhs
.data
)
122 return data
->Name () == rhs
.data
->Name() && data
->Canonical_version () == rhs
.data
->Canonical_version();
126 packageversion::operator != (packageversion
const &rhs
) const
128 return ! (*this == rhs
);
132 packageversion::operator < (packageversion
const &rhs
) const
134 int t
= data
->Name ().casecompare (rhs
.data
->Name());
139 else if (data
->Canonical_version().casecompare (rhs
.data
->Canonical_version()) < 0)
145 packageversion::Name () const
147 return data
->Name ();
151 packageversion::Canonical_version() const
153 return data
->Canonical_version();
157 packageversion::setCanonicalVersion (String
const &ver
)
159 data
->setCanonicalVersion (ver
);
163 packageversion::getfirstfile ()
165 return data
->getfirstfile ();
169 packageversion::getnextfile ()
171 return data
->getnextfile ();
175 packageversion::SDesc () const
177 return data
->SDesc ();
181 packageversion::set_sdesc (String
const &sdesc
)
183 data
->set_sdesc (sdesc
);
187 packageversion::LDesc () const
189 return data
->LDesc ();
193 packageversion::set_ldesc (String
const &ldesc
)
195 data
->set_ldesc (ldesc
);
199 packageversion::sourcePackage()
201 return data
->sourcePackage();
204 PackageSpecification
&
205 packageversion::sourcePackageSpecification ()
207 return data
->sourcePackageSpecification ();
211 packageversion::setSourcePackageSpecification (PackageSpecification
const &spec
)
213 data
->setSourcePackageSpecification(spec
);
216 vector
<vector
<PackageSpecification
*> *> *
217 packageversion::depends()
219 return &data
->depends
;
222 vector
<vector
<PackageSpecification
*> *> *
223 packageversion::predepends()
225 return &data
->predepends
;
228 vector
<vector
<PackageSpecification
*> *> *
229 packageversion::recommends()
231 return &data
->recommends
;
234 vector
<vector
<PackageSpecification
*> *> *
235 packageversion::suggests()
237 return &data
->suggests
;
240 vector
<vector
<PackageSpecification
*> *> *
241 packageversion::replaces()
243 return &data
->replaces
;
246 vector
<vector
<PackageSpecification
*> *> *
247 packageversion::conflicts()
249 return &data
->conflicts
;
252 vector
<vector
<PackageSpecification
*> *> *
253 packageversion::provides()
255 return &data
->provides
;
258 vector
<vector
<PackageSpecification
*> *> *
259 packageversion::binaries()
261 return &data
->binaries
;
265 packageversion::picked () const
271 packageversion::pick (bool aBool
)
277 packageversion::changeRequested () const
279 return data
->changeRequested ();
283 packageversion::uninstall ()
289 packageversion::source ()
291 if (!data
->sources
.size())
292 data
->sources
.push_back (packagesource());
293 return &data
->sources
[0];
296 vector
<packagesource
> *
297 packageversion::sources ()
299 return &data
->sources
;
303 packageversion::accessible() const
305 return data
->accessible();
309 checkForInstalled (PackageSpecification
*spec
)
312 packagemeta
*required
= db
.findBinary (*spec
);
315 if (spec
->satisfies (required
->installed
)
316 && required
->desired
== required
->installed
)
317 /* done, found a satisfactory installed version that will remain
324 checkForUpgradeable (PackageSpecification
*spec
)
327 packagemeta
*required
= db
.findBinary (*spec
);
328 if (!required
|| !required
->installed
)
330 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
331 i
!= required
->versions
.end(); ++i
)
332 if (spec
->satisfies (*i
))
338 checkForSatisfiable (PackageSpecification
*spec
)
341 packagemeta
*required
= db
.findBinary (*spec
);
344 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
345 i
!= required
->versions
.end(); ++i
)
346 if (spec
->satisfies (*i
))
351 /* Convenience class for now */
352 class DependencyProcessor
{
354 DependencyProcessor (trusts
const &aTrust
, int aDepth
=0) : deftrust (aTrust
), depth (aDepth
) {}
355 trusts
const deftrust
;
360 select (DependencyProcessor
&processor
, packagemeta
*required
, packageversion
const &aVersion
)
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);
373 processOneDependency(trusts deftrust
, size_t depth
, PackageSpecification
*spec
)
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
380 packagemeta
*required
= db
.findBinary (*spec
);
381 DependencyProcessor
processor (deftrust
, depth
);
383 packageversion trusted
= required
->trustp(deftrust
);
384 if (spec
->satisfies (trusted
)) {
385 return select (processor
,required
,trusted
);
388 log (LOG_TIMESTAMP
) << "Warning, the default trust level for package "
389 << trusted
.Name() << " does not meet this specification " << *spec
392 set
<packageversion
>::iterator v
;
393 for (v
= required
->versions
.begin();
394 v
!= required
->versions
.end() && !spec
->satisfies (*v
); ++v
);
396 if (v
== required
->versions
.end())
400 return select (processor
, required
, *v
);
404 packageversion::set_requirements (trusts deftrust
, size_t depth
)
407 vector
<vector
<PackageSpecification
*> *>::iterator dp
= depends ()->begin();
408 /* cheap test for too much recursion */
411 /* walk through each and clause */
412 while (dp
!= depends ()->end())
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?
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())
425 /* we found an installed ok package */
426 /* next and clause */
430 /* check each or clause for an upgradeable version */
431 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForUpgradeable
);
432 if (i
!= (*dp
)->end())
434 /* we found a package that can be up/downgraded to meet the
435 requirement. (*i is the packagespec that can be satisfied.)
438 changed
+= processOneDependency (deftrust
, depth
, *i
) + 1;
441 /* check each or clause for an installable version */
442 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForSatisfiable
);
443 if (i
!= (*dp
)->end())
445 /* we found a package that can be installed to meet the requirement */
447 changed
+= processOneDependency (deftrust
, depth
, *i
) + 1;
456 packageversion::addScript(Script
const &aScript
)
458 return data
->addScript (aScript
);
461 std::vector
<Script
> &
462 packageversion::scripts()
464 return data
->scripts();
467 /* the parent data class */
469 _packageversion::_packageversion ():picked (false), references (0)
473 _packageversion::~_packageversion ()
477 PackageSpecification
&
478 _packageversion::sourcePackageSpecification ()
480 return _sourcePackage
;
484 _packageversion::setSourcePackageSpecification (PackageSpecification
const &spec
)
486 _sourcePackage
= spec
;
490 _packageversion::sourcePackage ()
496 pkg
= db
.findSource (_sourcePackage
);
497 /* no valid source meta available, just return the default
498 (blank) package version
501 return sourceVersion
;
502 set
<packageversion
>::iterator i
=pkg
->versions
.begin();
503 while (i
!= pkg
->versions
.end())
505 packageversion
const & ver
= * i
;
506 if (_sourcePackage
.satisfies (ver
))
511 return sourceVersion
;
515 _packageversion::accessible() const
518 for (vector
<packagesource
>::const_iterator i
= sources
.begin();
519 i
!=sources
.end(); ++i
)
524 if (::source
== IDC_SOURCE_CWD
)
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 ())
531 return retrievable
== sources
.size();
535 _packageversion::changeRequested ()
537 return (picked
|| sourcePackage().picked());
541 _packageversion::addScript(Script
const &aScript
)
543 scripts().push_back(aScript
);
546 std::vector
<Script
> &
547 _packageversion::scripts()