0b099f4426df31aba0742511c1869aea5dd2f787
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 /*{{{*/
12 #include <apt-pkg/aptconfiguration.h>
13 #include <apt-pkg/cachefilter.h>
14 #include <apt-pkg/error.h>
15 #include <apt-pkg/strutl.h>
16 #include <apt-pkg/versionmatch.h>
27 // FromTask - Return all packages in the cache from a specific task /*{{{*/
28 PackageSet
PackageSet::FromTask(pkgCacheFile
&Cache
, std::string pattern
, CacheSetHelper
&helper
) {
29 size_t const archfound
= pattern
.find_last_of(':');
30 std::string arch
= "native";
31 if (archfound
!= std::string::npos
) {
32 arch
= pattern
.substr(archfound
+1);
33 pattern
.erase(archfound
);
36 if (pattern
[pattern
.length() -1] != '^')
37 return APT::PackageSet(TASK
);
38 pattern
.erase(pattern
.length()-1);
40 if (unlikely(Cache
.GetPkgCache() == 0 || Cache
.GetDepCache() == 0))
41 return APT::PackageSet(TASK
);
43 PackageSet
pkgset(TASK
);
45 pkgRecords
Recs(Cache
);
47 // build regexp for the task
50 snprintf(S
, sizeof(S
), "^Task:.*[, ]%s([, ]|$)", pattern
.c_str());
51 if(regcomp(&Pattern
,S
, REG_EXTENDED
| REG_NOSUB
| REG_NEWLINE
) != 0) {
52 _error
->Error("Failed to compile task regexp");
56 for (pkgCache::GrpIterator Grp
= Cache
->GrpBegin(); Grp
.end() == false; ++Grp
) {
57 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(arch
);
58 if (Pkg
.end() == true)
60 pkgCache::VerIterator ver
= Cache
[Pkg
].CandidateVerIter(Cache
);
64 pkgRecords::Parser
&parser
= Recs
.Lookup(ver
.FileList());
65 const char *start
, *end
;
66 parser
.GetRec(start
,end
);
67 unsigned int const length
= end
- start
;
69 strncpy(buf
, start
, length
);
71 if (regexec(&Pattern
, buf
, 0, 0, 0) != 0)
78 if (pkgset
.empty() == true)
79 return helper
.canNotFindTask(Cache
, pattern
);
81 helper
.showTaskSelection(pkgset
, pattern
);
85 // FromRegEx - Return all packages in the cache matching a pattern /*{{{*/
86 PackageSet
PackageSet::FromRegEx(pkgCacheFile
&Cache
, std::string pattern
, CacheSetHelper
&helper
) {
87 static const char * const isregex
= ".?+*|[^$";
88 if (pattern
.find_first_of(isregex
) == std::string::npos
)
89 return PackageSet(REGEX
);
91 size_t archfound
= pattern
.find_last_of(':');
92 std::string arch
= "native";
93 if (archfound
!= std::string::npos
) {
94 arch
= pattern
.substr(archfound
+1);
95 if (arch
.find_first_of(isregex
) == std::string::npos
)
96 pattern
.erase(archfound
);
101 if (unlikely(Cache
.GetPkgCache() == 0))
102 return PackageSet(REGEX
);
104 APT::CacheFilter::PackageNameMatchesRegEx
regexfilter(pattern
);
106 PackageSet
pkgset(REGEX
);
107 for (pkgCache::GrpIterator Grp
= Cache
.GetPkgCache()->GrpBegin(); Grp
.end() == false; ++Grp
) {
108 if (regexfilter(Grp
) == false)
110 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(arch
);
111 if (Pkg
.end() == true) {
112 if (archfound
== std::string::npos
) {
113 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
114 for (std::vector
<std::string
>::const_iterator a
= archs
.begin();
115 a
!= archs
.end() && Pkg
.end() != true; ++a
)
116 Pkg
= Grp
.FindPkg(*a
);
118 if (Pkg
.end() == true)
125 if (pkgset
.empty() == true)
126 return helper
.canNotFindRegEx(Cache
, pattern
);
128 helper
.showRegExSelection(pkgset
, pattern
);
132 // FromName - Returns the package defined by this string /*{{{*/
133 pkgCache::PkgIterator
PackageSet::FromName(pkgCacheFile
&Cache
,
134 std::string
const &str
, CacheSetHelper
&helper
) {
135 std::string pkg
= str
;
136 size_t archfound
= pkg
.find_last_of(':');
138 if (archfound
!= std::string::npos
) {
139 arch
= pkg
.substr(archfound
+1);
140 pkg
.erase(archfound
);
143 if (Cache
.GetPkgCache() == 0)
144 return pkgCache::PkgIterator(Cache
, 0);
146 pkgCache::PkgIterator
Pkg(Cache
, 0);
147 if (arch
.empty() == true) {
148 pkgCache::GrpIterator Grp
= Cache
.GetPkgCache()->FindGrp(pkg
);
149 if (Grp
.end() == false)
150 Pkg
= Grp
.FindPreferredPkg();
152 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
, arch
);
154 if (Pkg
.end() == true)
155 return helper
.canNotFindPkgName(Cache
, str
);
159 // GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/
160 std::map
<unsigned short, PackageSet
> PackageSet::GroupedFromCommandLine(
161 pkgCacheFile
&Cache
, const char **cmdline
,
162 std::list
<PackageSet::Modifier
> const &mods
,
163 unsigned short const &fallback
, CacheSetHelper
&helper
) {
164 std::map
<unsigned short, PackageSet
> pkgsets
;
165 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
166 unsigned short modID
= fallback
;
167 std::string str
= *I
;
168 bool modifierPresent
= false;
169 for (std::list
<PackageSet::Modifier
>::const_iterator mod
= mods
.begin();
170 mod
!= mods
.end(); ++mod
) {
171 size_t const alength
= strlen(mod
->Alias
);
173 case PackageSet::Modifier::POSTFIX
:
174 if (str
.compare(str
.length() - alength
, alength
,
175 mod
->Alias
, 0, alength
) != 0)
177 str
.erase(str
.length() - alength
);
180 case PackageSet::Modifier::PREFIX
:
182 case PackageSet::Modifier::NONE
:
185 modifierPresent
= true;
188 if (modifierPresent
== true) {
189 bool const errors
= helper
.showErrors(false);
190 pkgCache::PkgIterator Pkg
= FromName(Cache
, *I
, helper
);
191 helper
.showErrors(errors
);
192 if (Pkg
.end() == false) {
193 pkgsets
[fallback
].insert(Pkg
);
197 pkgsets
[modID
].insert(PackageSet::FromString(Cache
, str
, helper
));
202 // FromCommandLine - Return all packages specified on commandline /*{{{*/
203 PackageSet
PackageSet::FromCommandLine(pkgCacheFile
&Cache
, const char **cmdline
, CacheSetHelper
&helper
) {
205 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
206 PackageSet pset
= FromString(Cache
, *I
, helper
);
207 pkgset
.insert(pset
.begin(), pset
.end());
212 // FromString - Return all packages matching a specific string /*{{{*/
213 PackageSet
PackageSet::FromString(pkgCacheFile
&Cache
, std::string
const &str
, CacheSetHelper
&helper
) {
214 _error
->PushToStack();
217 pkgCache::PkgIterator Pkg
= FromName(Cache
, str
, helper
);
218 if (Pkg
.end() == false)
221 pkgset
= FromTask(Cache
, str
, helper
);
222 if (pkgset
.empty() == true) {
223 pkgset
= FromRegEx(Cache
, str
, helper
);
224 if (pkgset
.empty() == true)
225 pkgset
= helper
.canNotFindPackage(Cache
, str
);
229 if (pkgset
.empty() == false)
230 _error
->RevertToStack();
232 _error
->MergeWithStack();
236 // GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/
237 std::map
<unsigned short, VersionSet
> VersionSet::GroupedFromCommandLine(
238 pkgCacheFile
&Cache
, const char **cmdline
,
239 std::list
<VersionSet::Modifier
> const &mods
,
240 unsigned short const &fallback
, CacheSetHelper
&helper
) {
241 std::map
<unsigned short, VersionSet
> versets
;
242 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
243 unsigned short modID
= fallback
;
244 VersionSet::Version select
= VersionSet::NEWEST
;
245 std::string str
= *I
;
246 bool modifierPresent
= false;
247 for (std::list
<VersionSet::Modifier
>::const_iterator mod
= mods
.begin();
248 mod
!= mods
.end(); ++mod
) {
249 if (modID
== fallback
&& mod
->ID
== fallback
)
250 select
= mod
->SelectVersion
;
251 size_t const alength
= strlen(mod
->Alias
);
253 case VersionSet::Modifier::POSTFIX
:
254 if (str
.compare(str
.length() - alength
, alength
,
255 mod
->Alias
, 0, alength
) != 0)
257 str
.erase(str
.length() - alength
);
259 select
= mod
->SelectVersion
;
261 case VersionSet::Modifier::PREFIX
:
263 case VersionSet::Modifier::NONE
:
266 modifierPresent
= true;
270 if (modifierPresent
== true) {
271 bool const errors
= helper
.showErrors(false);
272 VersionSet
const vset
= VersionSet::FromString(Cache
, std::string(*I
), select
, helper
, true);
273 helper
.showErrors(errors
);
274 if (vset
.empty() == false) {
275 versets
[fallback
].insert(vset
);
279 versets
[modID
].insert(VersionSet::FromString(Cache
, str
, select
, helper
));
284 // FromCommandLine - Return all versions specified on commandline /*{{{*/
285 APT::VersionSet
VersionSet::FromCommandLine(pkgCacheFile
&Cache
, const char **cmdline
,
286 APT::VersionSet::Version
const &fallback
, CacheSetHelper
&helper
) {
288 for (const char **I
= cmdline
; *I
!= 0; ++I
)
289 verset
.insert(VersionSet::FromString(Cache
, *I
, fallback
, helper
));
293 // FromString - Returns all versions spedcified by a string /*{{{*/
294 APT::VersionSet
VersionSet::FromString(pkgCacheFile
&Cache
, std::string pkg
,
295 APT::VersionSet::Version
const &fallback
, CacheSetHelper
&helper
,
296 bool const &onlyFromName
) {
298 bool verIsRel
= false;
299 size_t const vertag
= pkg
.find_last_of("/=");
300 if (vertag
!= string::npos
) {
301 ver
= pkg
.substr(vertag
+1);
302 verIsRel
= (pkg
[vertag
] == '/');
306 if (onlyFromName
== false)
307 pkgset
= PackageSet::FromString(Cache
, pkg
, helper
);
309 pkgset
.insert(PackageSet::FromName(Cache
, pkg
, helper
));
314 if (pkgset
.getConstructor() != PackageSet::UNKNOWN
)
315 errors
= helper
.showErrors(false);
316 for (PackageSet::const_iterator P
= pkgset
.begin();
317 P
!= pkgset
.end(); ++P
) {
318 if (vertag
== string::npos
) {
319 verset
.insert(VersionSet::FromPackage(Cache
, P
, fallback
, helper
));
322 pkgCache::VerIterator V
;
323 if (ver
== "installed")
324 V
= getInstalledVer(Cache
, P
, helper
);
325 else if (ver
== "candidate")
326 V
= getCandidateVer(Cache
, P
, helper
);
328 pkgVersionMatch
Match(ver
, (verIsRel
== true ? pkgVersionMatch::Release
:
329 pkgVersionMatch::Version
));
331 if (V
.end() == true) {
332 if (verIsRel
== true)
333 _error
->Error(_("Release '%s' for '%s' was not found"),
334 ver
.c_str(), P
.FullName(true).c_str());
336 _error
->Error(_("Version '%s' for '%s' was not found"),
337 ver
.c_str(), P
.FullName(true).c_str());
343 helper
.showSelectedVersion(P
, V
, ver
, verIsRel
);
346 if (pkgset
.getConstructor() != PackageSet::UNKNOWN
)
347 helper
.showErrors(errors
);
351 // FromPackage - versions from package based on fallback /*{{{*/
352 VersionSet
VersionSet::FromPackage(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &P
,
353 VersionSet::Version
const &fallback
, CacheSetHelper
&helper
) {
355 pkgCache::VerIterator V
;
358 case VersionSet::ALL
:
359 if (P
->VersionList
!= 0)
360 for (V
= P
.VersionList(); V
.end() != true; ++V
)
363 verset
.insert(helper
.canNotFindAllVer(Cache
, P
));
365 case VersionSet::CANDANDINST
:
366 verset
.insert(getInstalledVer(Cache
, P
, helper
));
367 verset
.insert(getCandidateVer(Cache
, P
, helper
));
369 case VersionSet::CANDIDATE
:
370 verset
.insert(getCandidateVer(Cache
, P
, helper
));
372 case VersionSet::INSTALLED
:
373 verset
.insert(getInstalledVer(Cache
, P
, helper
));
375 case VersionSet::CANDINST
:
376 showErrors
= helper
.showErrors(false);
377 V
= getCandidateVer(Cache
, P
, helper
);
379 V
= getInstalledVer(Cache
, P
, helper
);
380 helper
.showErrors(showErrors
);
381 if (V
.end() == false)
384 verset
.insert(helper
.canNotFindInstCandVer(Cache
, P
));
386 case VersionSet::INSTCAND
:
387 showErrors
= helper
.showErrors(false);
388 V
= getInstalledVer(Cache
, P
, helper
);
390 V
= getCandidateVer(Cache
, P
, helper
);
391 helper
.showErrors(showErrors
);
392 if (V
.end() == false)
395 verset
.insert(helper
.canNotFindInstCandVer(Cache
, P
));
397 case VersionSet::NEWEST
:
398 if (P
->VersionList
!= 0)
399 verset
.insert(P
.VersionList());
401 verset
.insert(helper
.canNotFindNewestVer(Cache
, P
));
407 // getCandidateVer - Returns the candidate version of the given package /*{{{*/
408 pkgCache::VerIterator
VersionSet::getCandidateVer(pkgCacheFile
&Cache
,
409 pkgCache::PkgIterator
const &Pkg
, CacheSetHelper
&helper
) {
410 pkgCache::VerIterator Cand
;
411 if (Cache
.IsPolicyBuilt() == true || Cache
.IsDepCacheBuilt() == false)
413 if (unlikely(Cache
.GetPolicy() == 0))
414 return pkgCache::VerIterator(Cache
);
415 Cand
= Cache
.GetPolicy()->GetCandidateVer(Pkg
);
417 Cand
= Cache
[Pkg
].CandidateVerIter(Cache
);
419 if (Cand
.end() == true)
420 return helper
.canNotFindCandidateVer(Cache
, Pkg
);
424 // getInstalledVer - Returns the installed version of the given package /*{{{*/
425 pkgCache::VerIterator
VersionSet::getInstalledVer(pkgCacheFile
&Cache
,
426 pkgCache::PkgIterator
const &Pkg
, CacheSetHelper
&helper
) {
427 if (Pkg
->CurrentVer
== 0)
428 return helper
.canNotFindInstalledVer(Cache
, Pkg
);
429 return Pkg
.CurrentVer();
432 // canNotFindPkgName - handle the case no package has this name /*{{{*/
433 pkgCache::PkgIterator
CacheSetHelper::canNotFindPkgName(pkgCacheFile
&Cache
,
434 std::string
const &str
) {
435 if (ShowError
== true)
436 _error
->Error(_("Unable to locate package %s"), str
.c_str());
437 return pkgCache::PkgIterator(Cache
, 0);
440 // canNotFindTask - handle the case no package is found for a task /*{{{*/
441 PackageSet
CacheSetHelper::canNotFindTask(pkgCacheFile
&Cache
, std::string pattern
) {
442 if (ShowError
== true)
443 _error
->Error(_("Couldn't find task '%s'"), pattern
.c_str());
447 // canNotFindRegEx - handle the case no package is found by a regex /*{{{*/
448 PackageSet
CacheSetHelper::canNotFindRegEx(pkgCacheFile
&Cache
, std::string pattern
) {
449 if (ShowError
== true)
450 _error
->Error(_("Couldn't find any package by regex '%s'"), pattern
.c_str());
454 // canNotFindPackage - handle the case no package is found from a string/*{{{*/
455 PackageSet
CacheSetHelper::canNotFindPackage(pkgCacheFile
&Cache
, std::string
const &str
) {
459 // canNotFindAllVer /*{{{*/
460 VersionSet
CacheSetHelper::canNotFindAllVer(pkgCacheFile
&Cache
,
461 pkgCache::PkgIterator
const &Pkg
) {
462 if (ShowError
== true)
463 _error
->Error(_("Can't select versions from package '%s' as it purely virtual"), Pkg
.FullName(true).c_str());
467 // canNotFindInstCandVer /*{{{*/
468 VersionSet
CacheSetHelper::canNotFindInstCandVer(pkgCacheFile
&Cache
,
469 pkgCache::PkgIterator
const &Pkg
) {
470 if (ShowError
== true)
471 _error
->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg
.FullName(true).c_str());
475 // canNotFindInstCandVer /*{{{*/
476 VersionSet
CacheSetHelper::canNotFindCandInstVer(pkgCacheFile
&Cache
,
477 pkgCache::PkgIterator
const &Pkg
) {
478 if (ShowError
== true)
479 _error
->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg
.FullName(true).c_str());
483 // canNotFindNewestVer /*{{{*/
484 pkgCache::VerIterator
CacheSetHelper::canNotFindNewestVer(pkgCacheFile
&Cache
,
485 pkgCache::PkgIterator
const &Pkg
) {
486 if (ShowError
== true)
487 _error
->Error(_("Can't select newest version from package '%s' as it is purely virtual"), Pkg
.FullName(true).c_str());
488 return pkgCache::VerIterator(Cache
, 0);
491 // canNotFindCandidateVer /*{{{*/
492 pkgCache::VerIterator
CacheSetHelper::canNotFindCandidateVer(pkgCacheFile
&Cache
,
493 pkgCache::PkgIterator
const &Pkg
) {
494 if (ShowError
== true)
495 _error
->Error(_("Can't select candidate version from package %s as it has no candidate"), Pkg
.FullName(true).c_str());
496 return pkgCache::VerIterator(Cache
, 0);
499 // canNotFindInstalledVer /*{{{*/
500 pkgCache::VerIterator
CacheSetHelper::canNotFindInstalledVer(pkgCacheFile
&Cache
,
501 pkgCache::PkgIterator
const &Pkg
) {
502 if (ShowError
== true)
503 _error
->Error(_("Can't select installed version from package %s as it is not installed"), Pkg
.FullName(true).c_str());
504 return pkgCache::VerIterator(Cache
, 0);