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/cachefilter.h>
16 #include <apt-pkg/cacheset.h>
17 #include <apt-pkg/error.h>
18 #include <apt-pkg/strutl.h>
19 #include <apt-pkg/versionmatch.h>
28 // FromTask - Return all packages in the cache from a specific task /*{{{*/
29 PackageSet
PackageSet::FromTask(pkgCacheFile
&Cache
, std::string pattern
, CacheSetHelper
&helper
) {
30 size_t const archfound
= pattern
.find_last_of(':');
31 std::string arch
= "native";
32 if (archfound
!= std::string::npos
) {
33 arch
= pattern
.substr(archfound
+1);
34 pattern
.erase(archfound
);
37 if (pattern
[pattern
.length() -1] != '^')
38 return APT::PackageSet(TASK
);
39 pattern
.erase(pattern
.length()-1);
41 if (unlikely(Cache
.GetPkgCache() == 0 || Cache
.GetDepCache() == 0))
42 return APT::PackageSet(TASK
);
44 PackageSet
pkgset(TASK
);
46 pkgRecords
Recs(Cache
);
48 // build regexp for the task
51 snprintf(S
, sizeof(S
), "^Task:.*[, ]%s([, ]|$)", pattern
.c_str());
52 if(regcomp(&Pattern
,S
, REG_EXTENDED
| REG_NOSUB
| REG_NEWLINE
) != 0) {
53 _error
->Error("Failed to compile task regexp");
57 for (pkgCache::GrpIterator Grp
= Cache
->GrpBegin(); Grp
.end() == false; ++Grp
) {
58 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(arch
);
59 if (Pkg
.end() == true)
61 pkgCache::VerIterator ver
= Cache
[Pkg
].CandidateVerIter(Cache
);
65 pkgRecords::Parser
&parser
= Recs
.Lookup(ver
.FileList());
66 const char *start
, *end
;
67 parser
.GetRec(start
,end
);
68 unsigned int const length
= end
- start
;
70 strncpy(buf
, start
, length
);
72 if (regexec(&Pattern
, buf
, 0, 0, 0) != 0)
79 if (pkgset
.empty() == true)
80 return helper
.canNotFindTask(Cache
, pattern
);
82 helper
.showTaskSelection(pkgset
, pattern
);
86 // FromRegEx - Return all packages in the cache matching a pattern /*{{{*/
87 PackageSet
PackageSet::FromRegEx(pkgCacheFile
&Cache
, std::string pattern
, CacheSetHelper
&helper
) {
88 static const char * const isregex
= ".?+*|[^$";
89 if (pattern
.find_first_of(isregex
) == std::string::npos
)
90 return PackageSet(REGEX
);
92 size_t archfound
= pattern
.find_last_of(':');
93 std::string arch
= "native";
94 if (archfound
!= std::string::npos
) {
95 arch
= pattern
.substr(archfound
+1);
96 if (arch
.find_first_of(isregex
) == std::string::npos
)
97 pattern
.erase(archfound
);
102 if (unlikely(Cache
.GetPkgCache() == 0))
103 return PackageSet(REGEX
);
105 APT::CacheFilter::PackageNameMatchesRegEx
regexfilter(pattern
);
107 PackageSet
pkgset(REGEX
);
108 for (pkgCache::GrpIterator Grp
= Cache
.GetPkgCache()->GrpBegin(); Grp
.end() == false; ++Grp
) {
109 if (regexfilter(Grp
) == false)
111 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(arch
);
112 if (Pkg
.end() == true) {
113 if (archfound
== std::string::npos
) {
114 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
115 for (std::vector
<std::string
>::const_iterator a
= archs
.begin();
116 a
!= archs
.end() && Pkg
.end() != true; ++a
)
117 Pkg
= Grp
.FindPkg(*a
);
119 if (Pkg
.end() == true)
126 if (pkgset
.empty() == true)
127 return helper
.canNotFindRegEx(Cache
, pattern
);
129 helper
.showRegExSelection(pkgset
, pattern
);
133 // FromName - Returns the package defined by this string /*{{{*/
134 pkgCache::PkgIterator
PackageSet::FromName(pkgCacheFile
&Cache
,
135 std::string
const &str
, CacheSetHelper
&helper
) {
136 std::string pkg
= str
;
137 size_t archfound
= pkg
.find_last_of(':');
139 if (archfound
!= std::string::npos
) {
140 arch
= pkg
.substr(archfound
+1);
141 pkg
.erase(archfound
);
144 if (Cache
.GetPkgCache() == 0)
145 return pkgCache::PkgIterator(Cache
, 0);
147 pkgCache::PkgIterator
Pkg(Cache
, 0);
148 if (arch
.empty() == true) {
149 pkgCache::GrpIterator Grp
= Cache
.GetPkgCache()->FindGrp(pkg
);
150 if (Grp
.end() == false)
151 Pkg
= Grp
.FindPreferredPkg();
153 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
, arch
);
155 if (Pkg
.end() == true)
156 return helper
.canNotFindPkgName(Cache
, str
);
160 // GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/
161 std::map
<unsigned short, PackageSet
> PackageSet::GroupedFromCommandLine(
162 pkgCacheFile
&Cache
, const char **cmdline
,
163 std::list
<PackageSet::Modifier
> const &mods
,
164 unsigned short const &fallback
, CacheSetHelper
&helper
) {
165 std::map
<unsigned short, PackageSet
> pkgsets
;
166 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
167 unsigned short modID
= fallback
;
168 std::string str
= *I
;
169 bool modifierPresent
= false;
170 for (std::list
<PackageSet::Modifier
>::const_iterator mod
= mods
.begin();
171 mod
!= mods
.end(); ++mod
) {
172 size_t const alength
= strlen(mod
->Alias
);
174 case PackageSet::Modifier::POSTFIX
:
175 if (str
.compare(str
.length() - alength
, alength
,
176 mod
->Alias
, 0, alength
) != 0)
178 str
.erase(str
.length() - alength
);
181 case PackageSet::Modifier::PREFIX
:
183 case PackageSet::Modifier::NONE
:
186 modifierPresent
= true;
189 if (modifierPresent
== true) {
190 bool const errors
= helper
.showErrors(false);
191 pkgCache::PkgIterator Pkg
= FromName(Cache
, *I
, helper
);
192 helper
.showErrors(errors
);
193 if (Pkg
.end() == false) {
194 pkgsets
[fallback
].insert(Pkg
);
198 pkgsets
[modID
].insert(PackageSet::FromString(Cache
, str
, helper
));
203 // FromCommandLine - Return all packages specified on commandline /*{{{*/
204 PackageSet
PackageSet::FromCommandLine(pkgCacheFile
&Cache
, const char **cmdline
, CacheSetHelper
&helper
) {
206 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
207 PackageSet pset
= FromString(Cache
, *I
, helper
);
208 pkgset
.insert(pset
.begin(), pset
.end());
213 // FromString - Return all packages matching a specific string /*{{{*/
214 PackageSet
PackageSet::FromString(pkgCacheFile
&Cache
, std::string
const &str
, CacheSetHelper
&helper
) {
215 _error
->PushToStack();
218 pkgCache::PkgIterator Pkg
= FromName(Cache
, str
, helper
);
219 if (Pkg
.end() == false)
222 pkgset
= FromTask(Cache
, str
, helper
);
223 if (pkgset
.empty() == true) {
224 pkgset
= FromRegEx(Cache
, str
, helper
);
225 if (pkgset
.empty() == true)
226 pkgset
= helper
.canNotFindPackage(Cache
, str
);
230 if (pkgset
.empty() == false)
231 _error
->RevertToStack();
233 _error
->MergeWithStack();
237 // GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/
238 std::map
<unsigned short, VersionSet
> VersionSet::GroupedFromCommandLine(
239 pkgCacheFile
&Cache
, const char **cmdline
,
240 std::list
<VersionSet::Modifier
> const &mods
,
241 unsigned short const &fallback
, CacheSetHelper
&helper
) {
242 std::map
<unsigned short, VersionSet
> versets
;
243 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
244 unsigned short modID
= fallback
;
245 VersionSet::Version select
= VersionSet::NEWEST
;
246 std::string str
= *I
;
247 bool modifierPresent
= false;
248 for (std::list
<VersionSet::Modifier
>::const_iterator mod
= mods
.begin();
249 mod
!= mods
.end(); ++mod
) {
250 if (modID
== fallback
&& mod
->ID
== fallback
)
251 select
= mod
->SelectVersion
;
252 size_t const alength
= strlen(mod
->Alias
);
254 case VersionSet::Modifier::POSTFIX
:
255 if (str
.compare(str
.length() - alength
, alength
,
256 mod
->Alias
, 0, alength
) != 0)
258 str
.erase(str
.length() - alength
);
260 select
= mod
->SelectVersion
;
262 case VersionSet::Modifier::PREFIX
:
264 case VersionSet::Modifier::NONE
:
267 modifierPresent
= true;
271 if (modifierPresent
== true) {
272 bool const errors
= helper
.showErrors(false);
273 VersionSet
const vset
= VersionSet::FromString(Cache
, std::string(*I
), select
, helper
, true);
274 helper
.showErrors(errors
);
275 if (vset
.empty() == false) {
276 versets
[fallback
].insert(vset
);
280 versets
[modID
].insert(VersionSet::FromString(Cache
, str
, select
, helper
));
285 // FromCommandLine - Return all versions specified on commandline /*{{{*/
286 APT::VersionSet
VersionSet::FromCommandLine(pkgCacheFile
&Cache
, const char **cmdline
,
287 APT::VersionSet::Version
const &fallback
, CacheSetHelper
&helper
) {
289 for (const char **I
= cmdline
; *I
!= 0; ++I
)
290 verset
.insert(VersionSet::FromString(Cache
, *I
, fallback
, helper
));
294 // FromString - Returns all versions spedcified by a string /*{{{*/
295 APT::VersionSet
VersionSet::FromString(pkgCacheFile
&Cache
, std::string pkg
,
296 APT::VersionSet::Version
const &fallback
, CacheSetHelper
&helper
,
297 bool const &onlyFromName
) {
299 bool verIsRel
= false;
300 size_t const vertag
= pkg
.find_last_of("/=");
301 if (vertag
!= string::npos
) {
302 ver
= pkg
.substr(vertag
+1);
303 verIsRel
= (pkg
[vertag
] == '/');
307 if (onlyFromName
== false)
308 pkgset
= PackageSet::FromString(Cache
, pkg
, helper
);
310 pkgset
.insert(PackageSet::FromName(Cache
, pkg
, helper
));
315 if (pkgset
.getConstructor() != PackageSet::UNKNOWN
)
316 errors
= helper
.showErrors(false);
317 for (PackageSet::const_iterator P
= pkgset
.begin();
318 P
!= pkgset
.end(); ++P
) {
319 if (vertag
== string::npos
) {
320 verset
.insert(VersionSet::FromPackage(Cache
, P
, fallback
, helper
));
323 pkgCache::VerIterator V
;
324 if (ver
== "installed")
325 V
= getInstalledVer(Cache
, P
, helper
);
326 else if (ver
== "candidate")
327 V
= getCandidateVer(Cache
, P
, helper
);
328 else if (ver
== "newest") {
329 if (P
->VersionList
!= 0)
332 V
= helper
.canNotFindNewestVer(Cache
, P
);
334 pkgVersionMatch
Match(ver
, (verIsRel
== true ? pkgVersionMatch::Release
:
335 pkgVersionMatch::Version
));
337 if (V
.end() == true) {
338 if (verIsRel
== true)
339 _error
->Error(_("Release '%s' for '%s' was not found"),
340 ver
.c_str(), P
.FullName(true).c_str());
342 _error
->Error(_("Version '%s' for '%s' was not found"),
343 ver
.c_str(), P
.FullName(true).c_str());
349 helper
.showSelectedVersion(P
, V
, ver
, verIsRel
);
352 if (pkgset
.getConstructor() != PackageSet::UNKNOWN
)
353 helper
.showErrors(errors
);
357 // FromPackage - versions from package based on fallback /*{{{*/
358 VersionSet
VersionSet::FromPackage(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &P
,
359 VersionSet::Version
const &fallback
, CacheSetHelper
&helper
) {
361 pkgCache::VerIterator V
;
364 case VersionSet::ALL
:
365 if (P
->VersionList
!= 0)
366 for (V
= P
.VersionList(); V
.end() != true; ++V
)
369 verset
.insert(helper
.canNotFindAllVer(Cache
, P
));
371 case VersionSet::CANDANDINST
:
372 verset
.insert(getInstalledVer(Cache
, P
, helper
));
373 verset
.insert(getCandidateVer(Cache
, P
, helper
));
375 case VersionSet::CANDIDATE
:
376 verset
.insert(getCandidateVer(Cache
, P
, helper
));
378 case VersionSet::INSTALLED
:
379 verset
.insert(getInstalledVer(Cache
, P
, helper
));
381 case VersionSet::CANDINST
:
382 showErrors
= helper
.showErrors(false);
383 V
= getCandidateVer(Cache
, P
, helper
);
385 V
= getInstalledVer(Cache
, P
, helper
);
386 helper
.showErrors(showErrors
);
387 if (V
.end() == false)
390 verset
.insert(helper
.canNotFindInstCandVer(Cache
, P
));
392 case VersionSet::INSTCAND
:
393 showErrors
= helper
.showErrors(false);
394 V
= getInstalledVer(Cache
, P
, helper
);
396 V
= getCandidateVer(Cache
, P
, helper
);
397 helper
.showErrors(showErrors
);
398 if (V
.end() == false)
401 verset
.insert(helper
.canNotFindInstCandVer(Cache
, P
));
403 case VersionSet::NEWEST
:
404 if (P
->VersionList
!= 0)
405 verset
.insert(P
.VersionList());
407 verset
.insert(helper
.canNotFindNewestVer(Cache
, P
));
413 // getCandidateVer - Returns the candidate version of the given package /*{{{*/
414 pkgCache::VerIterator
VersionSet::getCandidateVer(pkgCacheFile
&Cache
,
415 pkgCache::PkgIterator
const &Pkg
, CacheSetHelper
&helper
) {
416 pkgCache::VerIterator Cand
;
417 if (Cache
.IsPolicyBuilt() == true || Cache
.IsDepCacheBuilt() == false)
419 if (unlikely(Cache
.GetPolicy() == 0))
420 return pkgCache::VerIterator(Cache
);
421 Cand
= Cache
.GetPolicy()->GetCandidateVer(Pkg
);
423 Cand
= Cache
[Pkg
].CandidateVerIter(Cache
);
425 if (Cand
.end() == true)
426 return helper
.canNotFindCandidateVer(Cache
, Pkg
);
430 // getInstalledVer - Returns the installed version of the given package /*{{{*/
431 pkgCache::VerIterator
VersionSet::getInstalledVer(pkgCacheFile
&Cache
,
432 pkgCache::PkgIterator
const &Pkg
, CacheSetHelper
&helper
) {
433 if (Pkg
->CurrentVer
== 0)
434 return helper
.canNotFindInstalledVer(Cache
, Pkg
);
435 return Pkg
.CurrentVer();
438 // canNotFindPkgName - handle the case no package has this name /*{{{*/
439 pkgCache::PkgIterator
CacheSetHelper::canNotFindPkgName(pkgCacheFile
&Cache
,
440 std::string
const &str
) {
441 if (ShowError
== true)
442 _error
->Insert(ErrorType
, _("Unable to locate package %s"), str
.c_str());
443 return pkgCache::PkgIterator(Cache
, 0);
446 // canNotFindTask - handle the case no package is found for a task /*{{{*/
447 PackageSet
CacheSetHelper::canNotFindTask(pkgCacheFile
&Cache
, std::string pattern
) {
448 if (ShowError
== true)
449 _error
->Insert(ErrorType
, _("Couldn't find task '%s'"), pattern
.c_str());
453 // canNotFindRegEx - handle the case no package is found by a regex /*{{{*/
454 PackageSet
CacheSetHelper::canNotFindRegEx(pkgCacheFile
&Cache
, std::string pattern
) {
455 if (ShowError
== true)
456 _error
->Insert(ErrorType
, _("Couldn't find any package by regex '%s'"), pattern
.c_str());
460 // canNotFindPackage - handle the case no package is found from a string/*{{{*/
461 PackageSet
CacheSetHelper::canNotFindPackage(pkgCacheFile
&Cache
, std::string
const &str
) {
465 // canNotFindAllVer /*{{{*/
466 VersionSet
CacheSetHelper::canNotFindAllVer(pkgCacheFile
&Cache
,
467 pkgCache::PkgIterator
const &Pkg
) {
468 if (ShowError
== true)
469 _error
->Insert(ErrorType
, _("Can't select versions from package '%s' as it is purely virtual"), Pkg
.FullName(true).c_str());
473 // canNotFindInstCandVer /*{{{*/
474 VersionSet
CacheSetHelper::canNotFindInstCandVer(pkgCacheFile
&Cache
,
475 pkgCache::PkgIterator
const &Pkg
) {
476 if (ShowError
== true)
477 _error
->Insert(ErrorType
, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg
.FullName(true).c_str());
481 // canNotFindInstCandVer /*{{{*/
482 VersionSet
CacheSetHelper::canNotFindCandInstVer(pkgCacheFile
&Cache
,
483 pkgCache::PkgIterator
const &Pkg
) {
484 if (ShowError
== true)
485 _error
->Insert(ErrorType
, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg
.FullName(true).c_str());
489 // canNotFindNewestVer /*{{{*/
490 pkgCache::VerIterator
CacheSetHelper::canNotFindNewestVer(pkgCacheFile
&Cache
,
491 pkgCache::PkgIterator
const &Pkg
) {
492 if (ShowError
== true)
493 _error
->Insert(ErrorType
, _("Can't select newest version from package '%s' as it is purely virtual"), Pkg
.FullName(true).c_str());
494 return pkgCache::VerIterator(Cache
, 0);
497 // canNotFindCandidateVer /*{{{*/
498 pkgCache::VerIterator
CacheSetHelper::canNotFindCandidateVer(pkgCacheFile
&Cache
,
499 pkgCache::PkgIterator
const &Pkg
) {
500 if (ShowError
== true)
501 _error
->Insert(ErrorType
, _("Can't select candidate version from package %s as it has no candidate"), Pkg
.FullName(true).c_str());
502 return pkgCache::VerIterator(Cache
, 0);
505 // canNotFindInstalledVer /*{{{*/
506 pkgCache::VerIterator
CacheSetHelper::canNotFindInstalledVer(pkgCacheFile
&Cache
,
507 pkgCache::PkgIterator
const &Pkg
) {
508 if (ShowError
== true)
509 _error
->Insert(ErrorType
, _("Can't select installed version from package %s as it is not installed"), Pkg
.FullName(true).c_str());
510 return pkgCache::VerIterator(Cache
, 0);