1 // -*- mode: cpp; mode: fold -*-
3 /* ######################################################################
5 Simple wrapper around a std::set to provide a similar interface to
6 a set of cache structures as to the complete set of all structures
7 in the pkgCache. Currently only Package is supported.
9 ##################################################################### */
11 // Include Files /*{{{*/
14 #include <apt-pkg/aptconfiguration.h>
15 #include <apt-pkg/cachefile.h>
16 #include <apt-pkg/cachefilter.h>
17 #include <apt-pkg/cacheset.h>
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/strutl.h>
20 #include <apt-pkg/versionmatch.h>
21 #include <apt-pkg/pkgrecords.h>
22 #include <apt-pkg/policy.h>
31 // FromTask - Return all packages in the cache from a specific task /*{{{*/
32 bool PackageContainerInterface::FromTask(PackageContainerInterface
* const pci
, pkgCacheFile
&Cache
, std::string pattern
, CacheSetHelper
&helper
) {
33 size_t const archfound
= pattern
.find_last_of(':');
34 std::string arch
= "native";
35 if (archfound
!= std::string::npos
) {
36 arch
= pattern
.substr(archfound
+1);
37 pattern
.erase(archfound
);
40 if (pattern
[pattern
.length() -1] != '^')
42 pattern
.erase(pattern
.length()-1);
44 if (unlikely(Cache
.GetPkgCache() == 0 || Cache
.GetDepCache() == 0))
47 bool const wasEmpty
= pci
->empty();
49 pci
->setConstructor(TASK
);
52 pkgRecords
Recs(Cache
);
54 // build regexp for the task
57 snprintf(S
, sizeof(S
), "^Task:.*[, ]%s([, ]|$)", pattern
.c_str());
58 if(regcomp(&Pattern
,S
, REG_EXTENDED
| REG_NOSUB
| REG_NEWLINE
) != 0) {
59 _error
->Error("Failed to compile task regexp");
64 for (pkgCache::GrpIterator Grp
= Cache
->GrpBegin(); Grp
.end() == false; ++Grp
) {
65 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(arch
);
66 if (Pkg
.end() == true)
68 pkgCache::VerIterator ver
= Cache
[Pkg
].CandidateVerIter(Cache
);
72 pkgRecords::Parser
&parser
= Recs
.Lookup(ver
.FileList());
73 const char *start
, *end
;
74 parser
.GetRec(start
,end
);
75 unsigned int const length
= end
- start
;
77 strncpy(buf
, start
, length
);
79 if (regexec(&Pattern
, buf
, 0, 0, 0) != 0)
83 helper
.showTaskSelection(Pkg
, pattern
);
89 helper
.canNotFindTask(pci
, Cache
, pattern
);
90 pci
->setConstructor(UNKNOWN
);
94 if (wasEmpty
== false && pci
->getConstructor() != UNKNOWN
)
95 pci
->setConstructor(UNKNOWN
);
100 // FromRegEx - Return all packages in the cache matching a pattern /*{{{*/
101 bool PackageContainerInterface::FromRegEx(PackageContainerInterface
* const pci
, pkgCacheFile
&Cache
, std::string pattern
, CacheSetHelper
&helper
) {
102 static const char * const isregex
= ".?+*|[^$";
103 if (pattern
.find_first_of(isregex
) == std::string::npos
)
106 bool const wasEmpty
= pci
->empty();
107 if (wasEmpty
== true)
108 pci
->setConstructor(REGEX
);
110 size_t archfound
= pattern
.find_last_of(':');
111 std::string arch
= "native";
112 if (archfound
!= std::string::npos
) {
113 arch
= pattern
.substr(archfound
+1);
114 if (arch
.find_first_of(isregex
) == std::string::npos
)
115 pattern
.erase(archfound
);
120 if (unlikely(Cache
.GetPkgCache() == 0))
123 APT::CacheFilter::PackageNameMatchesRegEx
regexfilter(pattern
);
126 for (pkgCache::GrpIterator Grp
= Cache
.GetPkgCache()->GrpBegin(); Grp
.end() == false; ++Grp
) {
127 if (regexfilter(Grp
) == false)
129 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(arch
);
130 if (Pkg
.end() == true) {
131 if (archfound
== std::string::npos
) {
132 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
133 for (std::vector
<std::string
>::const_iterator a
= archs
.begin();
134 a
!= archs
.end() && Pkg
.end() != true; ++a
)
135 Pkg
= Grp
.FindPkg(*a
);
137 if (Pkg
.end() == true)
142 helper
.showRegExSelection(Pkg
, pattern
);
146 if (found
== false) {
147 helper
.canNotFindRegEx(pci
, Cache
, pattern
);
148 pci
->setConstructor(UNKNOWN
);
152 if (wasEmpty
== false && pci
->getConstructor() != UNKNOWN
)
153 pci
->setConstructor(UNKNOWN
);
158 // FromName - Returns the package defined by this string /*{{{*/
159 pkgCache::PkgIterator
PackageContainerInterface::FromName(pkgCacheFile
&Cache
,
160 std::string
const &str
, CacheSetHelper
&helper
) {
161 std::string pkg
= str
;
162 size_t archfound
= pkg
.find_last_of(':');
164 if (archfound
!= std::string::npos
) {
165 arch
= pkg
.substr(archfound
+1);
166 pkg
.erase(archfound
);
169 if (Cache
.GetPkgCache() == 0)
170 return pkgCache::PkgIterator(Cache
, 0);
172 pkgCache::PkgIterator
Pkg(Cache
, 0);
173 if (arch
.empty() == true) {
174 pkgCache::GrpIterator Grp
= Cache
.GetPkgCache()->FindGrp(pkg
);
175 if (Grp
.end() == false)
176 Pkg
= Grp
.FindPreferredPkg();
178 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
, arch
);
180 if (Pkg
.end() == true)
181 return helper
.canNotFindPkgName(Cache
, str
);
185 // FromString - Return all packages matching a specific string /*{{{*/
186 bool PackageContainerInterface::FromString(PackageContainerInterface
* const pci
, pkgCacheFile
&Cache
, std::string
const &str
, CacheSetHelper
&helper
) {
188 _error
->PushToStack();
190 pkgCache::PkgIterator Pkg
= FromName(Cache
, str
, helper
);
191 if (Pkg
.end() == false)
193 else if (FromTask(pci
, Cache
, str
, helper
) == false &&
194 FromRegEx(pci
, Cache
, str
, helper
) == false)
196 helper
.canNotFindPackage(pci
, Cache
, str
);
201 _error
->RevertToStack();
203 _error
->MergeWithStack();
207 // FromCommandLine - Return all packages specified on commandline /*{{{*/
208 bool PackageContainerInterface::FromCommandLine(PackageContainerInterface
* const pci
, pkgCacheFile
&Cache
, const char **cmdline
, CacheSetHelper
&helper
) {
210 for (const char **I
= cmdline
; *I
!= 0; ++I
)
211 found
|= PackageContainerInterface::FromString(pci
, Cache
, *I
, helper
);
215 // FromModifierCommandLine - helper doing the work for PKG:GroupedFromCommandLine /*{{{*/
216 bool PackageContainerInterface::FromModifierCommandLine(unsigned short &modID
, PackageContainerInterface
* const pci
,
217 pkgCacheFile
&Cache
, const char * cmdline
,
218 std::list
<Modifier
> const &mods
, CacheSetHelper
&helper
) {
219 std::string str
= cmdline
;
220 unsigned short fallback
= modID
;
221 bool modifierPresent
= false;
222 for (std::list
<Modifier
>::const_iterator mod
= mods
.begin();
223 mod
!= mods
.end(); ++mod
) {
224 size_t const alength
= strlen(mod
->Alias
);
226 case Modifier::POSTFIX
:
227 if (str
.compare(str
.length() - alength
, alength
,
228 mod
->Alias
, 0, alength
) != 0)
230 str
.erase(str
.length() - alength
);
233 case Modifier::PREFIX
:
238 modifierPresent
= true;
241 if (modifierPresent
== true) {
242 bool const errors
= helper
.showErrors(false);
243 pkgCache::PkgIterator Pkg
= FromName(Cache
, cmdline
, helper
);
244 helper
.showErrors(errors
);
245 if (Pkg
.end() == false) {
251 return FromString(pci
, Cache
, str
, helper
);
254 // FromModifierCommandLine - helper doing the work for VER:GroupedFromCommandLine /*{{{*/
255 bool VersionContainerInterface::FromModifierCommandLine(unsigned short &modID
,
256 VersionContainerInterface
* const vci
,
257 pkgCacheFile
&Cache
, const char * cmdline
,
258 std::list
<Modifier
> const &mods
,
259 CacheSetHelper
&helper
) {
260 Version select
= NEWEST
;
261 std::string str
= cmdline
;
262 bool modifierPresent
= false;
263 unsigned short fallback
= modID
;
264 for (std::list
<Modifier
>::const_iterator mod
= mods
.begin();
265 mod
!= mods
.end(); ++mod
) {
266 if (modID
== fallback
&& mod
->ID
== fallback
)
267 select
= mod
->SelectVersion
;
268 size_t const alength
= strlen(mod
->Alias
);
270 case Modifier::POSTFIX
:
271 if (str
.compare(str
.length() - alength
, alength
,
272 mod
->Alias
, 0, alength
) != 0)
274 str
.erase(str
.length() - alength
);
276 select
= mod
->SelectVersion
;
278 case Modifier::PREFIX
:
283 modifierPresent
= true;
286 if (modifierPresent
== true) {
287 bool const errors
= helper
.showErrors(false);
288 bool const found
= VersionContainerInterface::FromString(vci
, Cache
, cmdline
, select
, helper
, true);
289 helper
.showErrors(errors
);
295 return FromString(vci
, Cache
, str
, select
, helper
);
298 // FromCommandLine - Return all versions specified on commandline /*{{{*/
299 bool VersionContainerInterface::FromCommandLine(VersionContainerInterface
* const vci
,
300 pkgCacheFile
&Cache
, const char **cmdline
,
301 Version
const &fallback
, CacheSetHelper
&helper
) {
303 for (const char **I
= cmdline
; *I
!= 0; ++I
)
304 found
|= VersionContainerInterface::FromString(vci
, Cache
, *I
, fallback
, helper
);
308 // FromString - Returns all versions spedcified by a string /*{{{*/
309 bool VersionContainerInterface::FromString(VersionContainerInterface
* const vci
,
310 pkgCacheFile
&Cache
, std::string pkg
,
311 Version
const &fallback
, CacheSetHelper
&helper
,
312 bool const onlyFromName
) {
314 bool verIsRel
= false;
315 size_t const vertag
= pkg
.find_last_of("/=");
316 if (vertag
!= std::string::npos
) {
317 ver
= pkg
.substr(vertag
+1);
318 verIsRel
= (pkg
[vertag
] == '/');
322 if (onlyFromName
== false)
323 PackageContainerInterface::FromString(&pkgset
, Cache
, pkg
, helper
);
325 pkgset
.insert(PackageContainerInterface::FromName(Cache
, pkg
, helper
));
329 if (pkgset
.getConstructor() != PackageSet::UNKNOWN
)
330 errors
= helper
.showErrors(false);
333 for (PackageSet::const_iterator P
= pkgset
.begin();
334 P
!= pkgset
.end(); ++P
) {
335 if (vertag
== std::string::npos
) {
336 found
|= VersionContainerInterface::FromPackage(vci
, Cache
, P
, fallback
, helper
);
339 pkgCache::VerIterator V
;
340 if (ver
== "installed")
341 V
= getInstalledVer(Cache
, P
, helper
);
342 else if (ver
== "candidate")
343 V
= getCandidateVer(Cache
, P
, helper
);
344 else if (ver
== "newest") {
345 if (P
->VersionList
!= 0)
348 V
= helper
.canNotFindNewestVer(Cache
, P
);
350 pkgVersionMatch
Match(ver
, (verIsRel
== true ? pkgVersionMatch::Release
:
351 pkgVersionMatch::Version
));
353 if (V
.end() == true) {
354 if (verIsRel
== true)
355 _error
->Error(_("Release '%s' for '%s' was not found"),
356 ver
.c_str(), P
.FullName(true).c_str());
358 _error
->Error(_("Version '%s' for '%s' was not found"),
359 ver
.c_str(), P
.FullName(true).c_str());
365 helper
.showSelectedVersion(P
, V
, ver
, verIsRel
);
369 if (pkgset
.getConstructor() != PackageSet::UNKNOWN
)
370 helper
.showErrors(errors
);
374 // FromPackage - versions from package based on fallback /*{{{*/
375 bool VersionContainerInterface::FromPackage(VersionContainerInterface
* const vci
,
377 pkgCache::PkgIterator
const &P
,
378 Version
const &fallback
,
379 CacheSetHelper
&helper
) {
380 pkgCache::VerIterator V
;
385 if (P
->VersionList
!= 0)
386 for (V
= P
.VersionList(); V
.end() != true; ++V
)
387 found
|= vci
->insert(V
);
389 helper
.canNotFindAllVer(vci
, Cache
, P
);
392 found
|= vci
->insert(getInstalledVer(Cache
, P
, helper
));
393 found
|= vci
->insert(getCandidateVer(Cache
, P
, helper
));
396 found
|= vci
->insert(getCandidateVer(Cache
, P
, helper
));
399 found
|= vci
->insert(getInstalledVer(Cache
, P
, helper
));
402 showErrors
= helper
.showErrors(false);
403 V
= getCandidateVer(Cache
, P
, helper
);
405 V
= getInstalledVer(Cache
, P
, helper
);
406 helper
.showErrors(showErrors
);
407 if (V
.end() == false)
408 found
|= vci
->insert(V
);
410 helper
.canNotFindInstCandVer(vci
, Cache
, P
);
413 showErrors
= helper
.showErrors(false);
414 V
= getInstalledVer(Cache
, P
, helper
);
416 V
= getCandidateVer(Cache
, P
, helper
);
417 helper
.showErrors(showErrors
);
418 if (V
.end() == false)
419 found
|= vci
->insert(V
);
421 helper
.canNotFindInstCandVer(vci
, Cache
, P
);
424 if (P
->VersionList
!= 0)
425 found
|= vci
->insert(P
.VersionList());
427 helper
.canNotFindNewestVer(Cache
, P
);
433 // getCandidateVer - Returns the candidate version of the given package /*{{{*/
434 pkgCache::VerIterator
VersionContainerInterface::getCandidateVer(pkgCacheFile
&Cache
,
435 pkgCache::PkgIterator
const &Pkg
, CacheSetHelper
&helper
) {
436 pkgCache::VerIterator Cand
;
437 if (Cache
.IsPolicyBuilt() == true || Cache
.IsDepCacheBuilt() == false) {
438 if (unlikely(Cache
.GetPolicy() == 0))
439 return pkgCache::VerIterator(Cache
);
440 Cand
= Cache
.GetPolicy()->GetCandidateVer(Pkg
);
442 Cand
= Cache
[Pkg
].CandidateVerIter(Cache
);
444 if (Cand
.end() == true)
445 return helper
.canNotFindCandidateVer(Cache
, Pkg
);
449 // getInstalledVer - Returns the installed version of the given package /*{{{*/
450 pkgCache::VerIterator
VersionContainerInterface::getInstalledVer(pkgCacheFile
&Cache
,
451 pkgCache::PkgIterator
const &Pkg
, CacheSetHelper
&helper
) {
452 if (Pkg
->CurrentVer
== 0)
453 return helper
.canNotFindInstalledVer(Cache
, Pkg
);
454 return Pkg
.CurrentVer();
458 // canNotFindPkgName - handle the case no package has this name /*{{{*/
459 pkgCache::PkgIterator
CacheSetHelper::canNotFindPkgName(pkgCacheFile
&Cache
,
460 std::string
const &str
) {
461 if (ShowError
== true)
462 _error
->Insert(ErrorType
, _("Unable to locate package %s"), str
.c_str());
463 return pkgCache::PkgIterator(Cache
, 0);
466 // canNotFindTask - handle the case no package is found for a task /*{{{*/
467 void CacheSetHelper::canNotFindTask(PackageContainerInterface
* const pci
, pkgCacheFile
&Cache
, std::string pattern
) {
468 if (ShowError
== true)
469 _error
->Insert(ErrorType
, _("Couldn't find task '%s'"), pattern
.c_str());
472 // canNotFindRegEx - handle the case no package is found by a regex /*{{{*/
473 void CacheSetHelper::canNotFindRegEx(PackageContainerInterface
* const pci
, pkgCacheFile
&Cache
, std::string pattern
) {
474 if (ShowError
== true)
475 _error
->Insert(ErrorType
, _("Couldn't find any package by regex '%s'"), pattern
.c_str());
478 // canNotFindPackage - handle the case no package is found from a string/*{{{*/
479 void CacheSetHelper::canNotFindPackage(PackageContainerInterface
* const pci
, pkgCacheFile
&Cache
, std::string
const &str
) {
482 // canNotFindAllVer /*{{{*/
483 void CacheSetHelper::canNotFindAllVer(VersionContainerInterface
* const vci
, pkgCacheFile
&Cache
,
484 pkgCache::PkgIterator
const &Pkg
) {
485 if (ShowError
== true)
486 _error
->Insert(ErrorType
, _("Can't select versions from package '%s' as it is purely virtual"), Pkg
.FullName(true).c_str());
489 // canNotFindInstCandVer /*{{{*/
490 void CacheSetHelper::canNotFindInstCandVer(VersionContainerInterface
* const vci
, pkgCacheFile
&Cache
,
491 pkgCache::PkgIterator
const &Pkg
) {
492 if (ShowError
== true)
493 _error
->Insert(ErrorType
, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg
.FullName(true).c_str());
496 // canNotFindInstCandVer /*{{{*/
497 void CacheSetHelper::canNotFindCandInstVer(VersionContainerInterface
* const vci
, pkgCacheFile
&Cache
,
498 pkgCache::PkgIterator
const &Pkg
) {
499 if (ShowError
== true)
500 _error
->Insert(ErrorType
, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg
.FullName(true).c_str());
503 // canNotFindNewestVer /*{{{*/
504 pkgCache::VerIterator
CacheSetHelper::canNotFindNewestVer(pkgCacheFile
&Cache
,
505 pkgCache::PkgIterator
const &Pkg
) {
506 if (ShowError
== true)
507 _error
->Insert(ErrorType
, _("Can't select newest version from package '%s' as it is purely virtual"), Pkg
.FullName(true).c_str());
508 return pkgCache::VerIterator(Cache
, 0);
511 // canNotFindCandidateVer /*{{{*/
512 pkgCache::VerIterator
CacheSetHelper::canNotFindCandidateVer(pkgCacheFile
&Cache
,
513 pkgCache::PkgIterator
const &Pkg
) {
514 if (ShowError
== true)
515 _error
->Insert(ErrorType
, _("Can't select candidate version from package %s as it has no candidate"), Pkg
.FullName(true).c_str());
516 return pkgCache::VerIterator(Cache
, 0);
519 // canNotFindInstalledVer /*{{{*/
520 pkgCache::VerIterator
CacheSetHelper::canNotFindInstalledVer(pkgCacheFile
&Cache
,
521 pkgCache::PkgIterator
const &Pkg
) {
522 if (ShowError
== true)
523 _error
->Insert(ErrorType
, _("Can't select installed version from package %s as it is not installed"), Pkg
.FullName(true).c_str());
524 return pkgCache::VerIterator(Cache
, 0);
527 // showTaskSelection /*{{{*/
528 void CacheSetHelper::showTaskSelection(pkgCache::PkgIterator
const &pkg
,
529 std::string
const &pattern
) {
532 // showRegExSelection /*{{{*/
533 void CacheSetHelper::showRegExSelection(pkgCache::PkgIterator
const &pkg
,
534 std::string
const &pattern
) {
537 // showSelectedVersion /*{{{*/
538 void CacheSetHelper::showSelectedVersion(pkgCache::PkgIterator
const &Pkg
,
539 pkgCache::VerIterator
const Ver
,
540 std::string
const &ver
,
541 bool const verIsRel
) {