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/error.h>
14 #include <apt-pkg/strutl.h>
15 #include <apt-pkg/versionmatch.h>
26 // FromTask - Return all packages in the cache from a specific task /*{{{*/
27 PackageSet
PackageSet::FromTask(pkgCacheFile
&Cache
, std::string pattern
, std::ostream
&out
) {
29 if (Cache
.BuildCaches() == false || Cache
.BuildDepCache() == false)
32 size_t archfound
= pattern
.find_last_of(':');
33 std::string arch
= "native";
34 if (archfound
!= std::string::npos
) {
35 arch
= pattern
.substr(archfound
+1);
36 pattern
.erase(archfound
);
39 if (pattern
[pattern
.length() -1] != '^')
41 pattern
.erase(pattern
.length()-1);
44 pkgRecords
Recs(Cache
);
46 // build regexp for the task
49 snprintf(S
, sizeof(S
), "^Task:.*[, ]%s([, ]|$)", pattern
.c_str());
50 if(regcomp(&Pattern
,S
, REG_EXTENDED
| REG_NOSUB
| REG_NEWLINE
) != 0) {
51 _error
->Error("Failed to compile task regexp");
55 for (pkgCache::GrpIterator Grp
= Cache
->GrpBegin(); Grp
.end() == false; ++Grp
) {
56 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(arch
);
57 if (Pkg
.end() == true)
59 pkgCache::VerIterator ver
= Cache
[Pkg
].CandidateVerIter(Cache
);
63 pkgRecords::Parser
&parser
= Recs
.Lookup(ver
.FileList());
64 const char *start
, *end
;
65 parser
.GetRec(start
,end
);
66 unsigned int const length
= end
- start
;
68 strncpy(buf
, start
, length
);
70 if (regexec(&Pattern
, buf
, 0, 0, 0) == 0)
74 if (pkgset
.empty() == true)
75 _error
->Error(_("Couldn't find task %s"), pattern
.c_str());
81 // FromRegEx - Return all packages in the cache matching a pattern /*{{{*/
82 PackageSet
PackageSet::FromRegEx(pkgCacheFile
&Cache
, std::string pattern
, std::ostream
&out
) {
84 static const char * const isregex
= ".?+*|[^$";
86 if (pattern
.find_first_of(isregex
) == std::string::npos
)
89 size_t archfound
= pattern
.find_last_of(':');
90 std::string arch
= "native";
91 if (archfound
!= std::string::npos
) {
92 arch
= pattern
.substr(archfound
+1);
93 if (arch
.find_first_of(isregex
) == std::string::npos
)
94 pattern
.erase(archfound
);
101 if ((Res
= regcomp(&Pattern
, pattern
.c_str() , REG_EXTENDED
| REG_ICASE
| REG_NOSUB
)) != 0) {
103 regerror(Res
, &Pattern
, Error
, sizeof(Error
));
104 _error
->Error(_("Regex compilation error - %s"), Error
);
108 for (pkgCache::GrpIterator Grp
= Cache
.GetPkgCache()->GrpBegin(); Grp
.end() == false; ++Grp
)
110 if (regexec(&Pattern
, Grp
.Name(), 0, 0, 0) != 0)
112 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(arch
);
113 if (Pkg
.end() == true) {
114 if (archfound
== std::string::npos
) {
115 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
116 for (std::vector
<std::string
>::const_iterator a
= archs
.begin();
117 a
!= archs
.end() && Pkg
.end() != true; ++a
)
118 Pkg
= Grp
.FindPkg(*a
);
120 if (Pkg
.end() == true)
124 ioprintf(out
, _("Note, selecting %s for regex '%s'\n"),
125 Pkg
.FullName(true).c_str(), pattern
.c_str());
135 // GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/
136 std::map
<unsigned short, PackageSet
> PackageSet::GroupedFromCommandLine(
137 pkgCacheFile
&Cache
, const char **cmdline
,
138 std::list
<PackageSet::Modifier
> const &mods
,
139 unsigned short const &fallback
, std::ostream
&out
) {
140 std::map
<unsigned short, PackageSet
> pkgsets
;
141 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
142 unsigned short modID
= fallback
;
143 std::string str
= *I
;
144 for (std::list
<PackageSet::Modifier
>::const_iterator mod
= mods
.begin();
145 mod
!= mods
.end(); ++mod
) {
146 size_t const alength
= strlen(mod
->Alias
);
148 case PackageSet::Modifier::POSTFIX
:
149 if (str
.compare(str
.length() - alength
, alength
,
150 mod
->Alias
, 0, alength
) != 0)
152 str
.erase(str
.length() - alength
);
155 case PackageSet::Modifier::PREFIX
:
157 case PackageSet::Modifier::NONE
:
162 PackageSet pset
= PackageSet::FromString(Cache
, str
, out
);
163 pkgsets
[modID
].insert(pset
.begin(), pset
.end());
168 // FromCommandLine - Return all packages specified on commandline /*{{{*/
169 PackageSet
PackageSet::FromCommandLine(pkgCacheFile
&Cache
, const char **cmdline
, std::ostream
&out
) {
171 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
172 PackageSet pset
= FromString(Cache
, *I
, out
);
173 pkgset
.insert(pset
.begin(), pset
.end());
178 // FromString - Return all packages matching a specific string /*{{{*/
179 PackageSet
PackageSet::FromString(pkgCacheFile
&Cache
, std::string
const &str
, std::ostream
&out
) {
180 std::string pkg
= str
;
181 size_t archfound
= pkg
.find_last_of(':');
183 if (archfound
!= std::string::npos
) {
184 arch
= pkg
.substr(archfound
+1);
185 pkg
.erase(archfound
);
188 pkgCache::PkgIterator Pkg
;
189 if (arch
.empty() == true) {
190 pkgCache::GrpIterator Grp
= Cache
.GetPkgCache()->FindGrp(pkg
);
191 if (Grp
.end() == false)
192 Pkg
= Grp
.FindPreferredPkg();
194 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
, arch
);
196 if (Pkg
.end() == false) {
201 PackageSet pset
= FromTask(Cache
, str
, out
);
202 if (pset
.empty() == false)
205 pset
= FromRegEx(Cache
, str
, out
);
206 if (pset
.empty() == false)
209 _error
->Warning(_("Unable to locate package %s"), str
.c_str());
213 // GroupedFromCommandLine - Return all versions specified on commandline/*{{{*/
214 std::map
<unsigned short, VersionSet
> VersionSet::GroupedFromCommandLine(
215 pkgCacheFile
&Cache
, const char **cmdline
,
216 std::list
<VersionSet::Modifier
> const &mods
,
217 unsigned short const &fallback
, std::ostream
&out
) {
218 std::map
<unsigned short, VersionSet
> versets
;
219 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
220 unsigned short modID
= fallback
;
221 VersionSet::Version select
= VersionSet::NEWEST
;
222 std::string str
= *I
;
223 for (std::list
<VersionSet::Modifier
>::const_iterator mod
= mods
.begin();
224 mod
!= mods
.end(); ++mod
) {
225 if (modID
== fallback
&& mod
->ID
== fallback
)
226 select
= mod
->SelectVersion
;
227 size_t const alength
= strlen(mod
->Alias
);
229 case VersionSet::Modifier::POSTFIX
:
230 if (str
.compare(str
.length() - alength
, alength
,
231 mod
->Alias
, 0, alength
) != 0)
233 str
.erase(str
.length() - alength
);
235 select
= mod
->SelectVersion
;
237 case VersionSet::Modifier::PREFIX
:
239 case VersionSet::Modifier::NONE
:
244 VersionSet vset
= VersionSet::FromString(Cache
, str
, select
, out
);
245 versets
[modID
].insert(vset
.begin(), vset
.end());
250 // FromCommandLine - Return all versions specified on commandline /*{{{*/
251 APT::VersionSet
VersionSet::FromCommandLine(pkgCacheFile
&Cache
, const char **cmdline
,
252 APT::VersionSet::Version
const &fallback
, std::ostream
&out
) {
254 for (const char **I
= cmdline
; *I
!= 0; ++I
) {
255 VersionSet vset
= VersionSet::FromString(Cache
, *I
, fallback
, out
);
256 verset
.insert(vset
.begin(), vset
.end());
261 // FromString - Returns all versions spedcified by a string /*{{{*/
262 APT::VersionSet
VersionSet::FromString(pkgCacheFile
&Cache
, std::string pkg
,
263 APT::VersionSet::Version
const &fallback
, std::ostream
&out
) {
265 bool verIsRel
= false;
266 size_t const vertag
= pkg
.find_last_of("/=");
267 if (vertag
!= string::npos
) {
268 ver
= pkg
.substr(vertag
+1);
269 verIsRel
= (pkg
[vertag
] == '/');
272 PackageSet pkgset
= PackageSet::FromString(Cache
, pkg
.c_str(), out
);
274 for (PackageSet::const_iterator P
= pkgset
.begin();
275 P
!= pkgset
.end(); ++P
) {
276 if (vertag
== string::npos
) {
277 AddSelectedVersion(Cache
, verset
, P
, fallback
);
280 pkgCache::VerIterator V
;
281 if (ver
== "installed")
282 V
= getInstalledVer(Cache
, P
);
283 else if (ver
== "candidate")
284 V
= getCandidateVer(Cache
, P
);
286 pkgVersionMatch
Match(ver
, (verIsRel
== true ? pkgVersionMatch::Release
:
287 pkgVersionMatch::Version
));
289 if (V
.end() == true) {
290 if (verIsRel
== true)
291 _error
->Error(_("Release '%s' for '%s' was not found"),
292 ver
.c_str(), P
.FullName(true).c_str());
294 _error
->Error(_("Version '%s' for '%s' was not found"),
295 ver
.c_str(), P
.FullName(true).c_str());
301 if (ver
!= V
.VerStr())
302 ioprintf(out
, _("Selected version '%s' (%s) for '%s'\n"),
303 V
.VerStr(), V
.RelStr().c_str(), P
.FullName(true).c_str());
309 // AddSelectedVersion - add version from package based on fallback /*{{{*/
310 bool VersionSet::AddSelectedVersion(pkgCacheFile
&Cache
, VersionSet
&verset
,
311 pkgCache::PkgIterator
const &P
, VersionSet::Version
const &fallback
,
312 bool const &AllowError
) {
313 pkgCache::VerIterator V
;
315 case VersionSet::ALL
:
316 if (P
->VersionList
!= 0)
317 for (V
= P
.VersionList(); V
.end() != true; ++V
)
319 else if (AllowError
== false)
320 return _error
->Error(_("Can't select versions from package '%s' as it purely virtual"), P
.FullName(true).c_str());
324 case VersionSet::CANDANDINST
:
325 verset
.insert(getInstalledVer(Cache
, P
, AllowError
));
326 verset
.insert(getCandidateVer(Cache
, P
, AllowError
));
328 case VersionSet::CANDIDATE
:
329 verset
.insert(getCandidateVer(Cache
, P
, AllowError
));
331 case VersionSet::INSTALLED
:
332 verset
.insert(getInstalledVer(Cache
, P
, AllowError
));
334 case VersionSet::CANDINST
:
335 V
= getCandidateVer(Cache
, P
, true);
337 V
= getInstalledVer(Cache
, P
, true);
338 if (V
.end() == false)
340 else if (AllowError
== false)
341 return _error
->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), P
.FullName(true).c_str());
345 case VersionSet::INSTCAND
:
346 V
= getInstalledVer(Cache
, P
, true);
348 V
= getCandidateVer(Cache
, P
, true);
349 if (V
.end() == false)
351 else if (AllowError
== false)
352 return _error
->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), P
.FullName(true).c_str());
356 case VersionSet::NEWEST
:
357 if (P
->VersionList
!= 0)
358 verset
.insert(P
.VersionList());
359 else if (AllowError
== false)
360 return _error
->Error(_("Can't select newest version from package '%s' as it is purely virtual"), P
.FullName(true).c_str());
368 // getCandidateVer - Returns the candidate version of the given package /*{{{*/
369 pkgCache::VerIterator
VersionSet::getCandidateVer(pkgCacheFile
&Cache
,
370 pkgCache::PkgIterator
const &Pkg
, bool const &AllowError
) {
371 pkgCache::VerIterator Cand
;
372 if (Cache
.IsDepCacheBuilt() == true)
373 Cand
= Cache
[Pkg
].CandidateVerIter(Cache
);
375 if (unlikely(Cache
.BuildPolicy() == false))
376 return pkgCache::VerIterator(*Cache
);
377 Cand
= Cache
.GetPolicy()->GetCandidateVer(Pkg
);
379 if (AllowError
== false && Cand
.end() == true)
380 _error
->Error(_("Can't select candidate version from package %s as it has no candidate"), Pkg
.FullName(true).c_str());
384 // getInstalledVer - Returns the installed version of the given package /*{{{*/
385 pkgCache::VerIterator
VersionSet::getInstalledVer(pkgCacheFile
&Cache
,
386 pkgCache::PkgIterator
const &Pkg
, bool const &AllowError
) {
387 if (AllowError
== false && Pkg
->CurrentVer
== 0)
388 _error
->Error(_("Can't select installed version from package %s as it is not installed"), Pkg
.FullName(true).c_str());
389 return Pkg
.CurrentVer();