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"
33 /* a default class to avoid special casing empty packageversions */
35 /* TODO place into the class header */
36 class _defaultversion
: public _packageversion
41 // never try to free me!
44 String
const Name(){return String();}
45 String
const Vendor_version() {return String();}
46 String
const Package_version() {return String();}
47 String
const Canonical_version() {return String();}
48 void setCanonicalVersion (String
const &) {}
49 package_status_t
Status (){return package_notinstalled
;}
50 package_type_t
Type () {return package_binary
;}
51 String
const getfirstfile () {return String();}
52 String
const getnextfile () {return String();}
53 String
const SDesc () {return String();}
54 void set_sdesc (String
const &) {}
55 String
const LDesc () {return String();}
56 void set_ldesc (String
const &) {}
59 static _defaultversion defaultversion
;
61 /* the wrapper class */
62 packageversion::packageversion() : data (&defaultversion
)
67 /* Create from an actual package */
68 packageversion::packageversion (_packageversion
*pkg
)
73 data
= &defaultversion
;
77 packageversion::packageversion (packageversion
const &existing
) :
83 packageversion::~packageversion()
85 if (--data
->references
== 0)
90 packageversion::operator= (packageversion
const &rhs
)
92 ++rhs
.data
->references
;
93 if (--data
->references
== 0)
100 packageversion::operator ! () const
102 return !data
->Name().size();
105 packageversion::operator bool () const
107 return data
->Name().size();
111 packageversion::operator == (packageversion
const &rhs
) const
113 if (this == &rhs
|| data
== rhs
.data
)
116 return data
->Name () == rhs
.data
->Name() && data
->Canonical_version () == rhs
.data
->Canonical_version();
120 packageversion::operator != (packageversion
const &rhs
) const
122 return ! (*this == rhs
);
126 packageversion::operator < (packageversion
const &rhs
) const
128 int t
= data
->Name ().casecompare (rhs
.data
->Name());
133 else if (data
->Canonical_version().casecompare (rhs
.data
->Canonical_version()) < 0)
139 packageversion::Name () const
141 return data
->Name ();
145 packageversion::Canonical_version() const
147 return data
->Canonical_version();
151 packageversion::setCanonicalVersion (String
const &ver
)
153 data
->setCanonicalVersion (ver
);
157 packageversion::getfirstfile ()
159 return data
->getfirstfile ();
163 packageversion::getnextfile ()
165 return data
->getnextfile ();
169 packageversion::SDesc () const
171 return data
->SDesc ();
175 packageversion::set_sdesc (String
const &sdesc
)
177 data
->set_sdesc (sdesc
);
181 packageversion::LDesc () const
183 return data
->LDesc ();
187 packageversion::set_ldesc (String
const &ldesc
)
189 data
->set_ldesc (ldesc
);
193 packageversion::sourcePackage()
195 return data
->sourcePackage();
198 PackageSpecification
&
199 packageversion::sourcePackageSpecification ()
201 return data
->sourcePackageSpecification ();
205 packageversion::setSourcePackageSpecification (PackageSpecification
const &spec
)
207 data
->setSourcePackageSpecification(spec
);
210 vector
<vector
<PackageSpecification
*> *> *
211 packageversion::depends()
213 return &data
->depends
;
216 vector
<vector
<PackageSpecification
*> *> *
217 packageversion::predepends()
219 return &data
->predepends
;
222 vector
<vector
<PackageSpecification
*> *> *
223 packageversion::recommends()
225 return &data
->recommends
;
228 vector
<vector
<PackageSpecification
*> *> *
229 packageversion::suggests()
231 return &data
->suggests
;
234 vector
<vector
<PackageSpecification
*> *> *
235 packageversion::replaces()
237 return &data
->replaces
;
240 vector
<vector
<PackageSpecification
*> *> *
241 packageversion::conflicts()
243 return &data
->conflicts
;
246 vector
<vector
<PackageSpecification
*> *> *
247 packageversion::provides()
249 return &data
->provides
;
252 vector
<vector
<PackageSpecification
*> *> *
253 packageversion::binaries()
255 return &data
->binaries
;
259 packageversion::picked () const
265 packageversion::pick (bool aBool
)
267 data
->picked
= aBool
;
271 packageversion::changeRequested () const
273 return data
->changeRequested ();
277 packageversion::uninstall ()
283 packageversion::source ()
285 if (!data
->sources
.size())
286 data
->sources
.push_back (packagesource());
287 return &data
->sources
[0];
290 vector
<packagesource
> *
291 packageversion::sources ()
293 return &data
->sources
;
297 packageversion::accessible() const
299 return data
->accessible();
303 checkForInstalled (PackageSpecification
*spec
)
306 packagemeta
*required
= db
.findBinary (*spec
);
309 if (spec
->satisfies (required
->installed
)
310 && required
->desired
== required
->installed
)
311 /* done, found a satisfactory installed version that will remain
318 checkForUpgradeable (PackageSpecification
*spec
)
321 packagemeta
*required
= db
.findBinary (*spec
);
322 if (!required
|| !required
->installed
)
324 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
325 i
!= required
->versions
.end(); ++i
)
326 if (spec
->satisfies (*i
))
332 checkForSatisfiable (PackageSpecification
*spec
)
335 packagemeta
*required
= db
.findBinary (*spec
);
338 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
339 i
!= required
->versions
.end(); ++i
)
340 if (spec
->satisfies (*i
))
345 /* Convenience class for now */
346 class DependencyProcessor
{
348 DependencyProcessor (trusts
const &aTrust
, int aDepth
=0) : deftrust (aTrust
), depth (aDepth
) {}
349 trusts
const deftrust
;
354 select (DependencyProcessor
&processor
, packagemeta
*required
, packageversion
const &aVersion
)
356 /* preserve source */
357 bool sourceticked
= required
->desired
.sourcePackage().picked();
358 /* install this version */
359 required
->desired
= aVersion
;
360 required
->desired
.pick (required
->installed
!= required
->desired
);
361 required
->desired
.sourcePackage().pick (sourceticked
);
362 /* does this requirement have requirements? */
363 return required
->set_requirements (processor
.deftrust
, processor
.depth
+ 1);
367 processOneDependency(trusts deftrust
, size_t depth
, PackageSpecification
*spec
)
369 /* TODO: add this to a set of packages to be offered to meet the
370 requirement. For now, simply set the install to the first
371 satisfactory version. The user can step through the list if
374 packagemeta
*required
= db
.findBinary (*spec
);
375 DependencyProcessor
processor (deftrust
, depth
);
377 packageversion trusted
= required
->trustp(deftrust
);
378 if (spec
->satisfies (trusted
))
379 select (processor
,required
,trusted
);
381 set
<packageversion
>::iterator v
;
382 for (v
= required
->versions
.begin();
383 v
!= required
->versions
.end() && !spec
->satisfies (*v
); ++v
);
385 if (v
== required
->versions
.end())
389 return select (processor
, required
, *v
);
393 packageversion::set_requirements (trusts deftrust
, size_t depth
)
396 vector
<vector
<PackageSpecification
*> *>::iterator dp
= depends ()->begin();
397 /* cheap test for too much recursion */
400 /* walk through each and clause */
401 while (dp
!= depends ()->end())
404 1) is a satisfactory or clause installed?
405 2) is an unsatisfactory version of an or clause which has
406 a satisfactory version available installed?
407 3) is a satisfactory package available?
409 /* check each or clause for an installed match */
410 vector
<PackageSpecification
*>::iterator i
=
411 find_if ((*dp
)->begin(), (*dp
)->end(), checkForInstalled
);
412 if (i
!= (*dp
)->end())
414 /* we found an installed ok package */
415 /* next and clause */
419 /* check each or clause for an upgradeable version */
420 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForUpgradeable
);
421 if (i
!= (*dp
)->end())
423 /* we found a package that can be up/downgraded to meet the
424 requirement. (*i is the packagespec that can be satisfied.)
427 changed
+= processOneDependency (deftrust
, depth
, *i
) + 1;
430 /* check each or clause for an installable version */
431 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForSatisfiable
);
432 if (i
!= (*dp
)->end())
434 /* we found a package that can be installed to meet the requirement */
436 changed
+= processOneDependency (deftrust
, depth
, *i
) + 1;
444 /* the parent data class */
446 _packageversion::_packageversion ():picked (false), references (0)
450 _packageversion::~_packageversion ()
454 PackageSpecification
&
455 _packageversion::sourcePackageSpecification ()
457 return _sourcePackage
;
461 _packageversion::setSourcePackageSpecification (PackageSpecification
const &spec
)
463 _sourcePackage
= spec
;
467 _packageversion::sourcePackage ()
473 pkg
= db
.findSource (_sourcePackage
);
474 /* no valid source meta available, just return the default
475 (blank) package version
478 return sourceVersion
;
479 set
<packageversion
>::iterator i
=pkg
->versions
.begin();
480 while (i
!= pkg
->versions
.end())
482 packageversion
const & ver
= * i
;
483 if (_sourcePackage
.satisfies (ver
))
488 return sourceVersion
;
492 _packageversion::accessible() const
495 for (vector
<packagesource
>::const_iterator i
= sources
.begin();
496 i
!=sources
.end(); ++i
)
501 if (::source
== IDC_SOURCE_CWD
)
503 unsigned int retrievable
= 0;
504 for (vector
<packagesource
>::const_iterator i
= sources
.begin();
505 i
!=sources
.end(); ++i
)
506 if (i
->sites
.size() || i
->Cached ())
508 return retrievable
== sources
.size();
512 _packageversion::changeRequested ()
514 return (picked
|| sourcePackage().picked());