8
8
##################################################################### */
10
10
// Include Files /*{{{*/
12
#pragma implementation "apt-pkg/depcache.h"
14
11
#include <apt-pkg/depcache.h>
15
12
#include <apt-pkg/version.h>
16
13
#include <apt-pkg/error.h>
17
14
#include <apt-pkg/sptr.h>
18
15
#include <apt-pkg/algorithms.h>
17
#include <apt-pkg/fileutl.h>
19
18
#include <apt-pkg/configuration.h>
19
#include <apt-pkg/pkgsystem.h>
20
#include <apt-pkg/tagfile.h>
21
26
#include <apti18n.h>
28
pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
29
cache(cache), released(false)
34
void pkgDepCache::ActionGroup::release()
38
if(cache.group_level == 0)
39
std::cerr << "W: Unbalanced action groups, expect badness" << std::endl;
44
if(cache.group_level == 0)
52
pkgDepCache::ActionGroup::~ActionGroup()
24
57
// DepCache::pkgDepCache - Constructors /*{{{*/
25
58
// ---------------------------------------------------------------------
27
60
pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
28
Cache(pCache), PkgState(0), DepState(0)
61
group_level(0), Cache(pCache), PkgState(0), DepState(0)
30
63
delLocalPolicy = 0;
31
64
LocalPolicy = Plcy;
140
bool pkgDepCache::readStateFile(OpProgress *Prog)
143
string state = _config->FindDir("Dir::State") + "extended_states";
144
if(FileExists(state)) {
145
state_file.Open(state, FileFd::ReadOnly);
146
int file_size = state_file.Size();
148
Prog->OverallProgress(0, file_size, 1,
149
_("Reading state information"));
151
pkgTagFile tagfile(&state_file);
152
pkgTagSection section;
154
while(tagfile.Step(section)) {
155
string pkgname = section.FindS("Package");
156
pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
157
// Silently ignore unknown packages and packages with no actual
159
if(!pkg.end() && !pkg.VersionList().end()) {
160
short reason = section.FindI("Auto-Installed", 0);
162
PkgState[pkg->ID].Flags |= Flag::Auto;
163
if(_config->FindB("Debug::pkgAutoRemove",false))
164
std::cout << "Auto-Installed : " << pkgname << std::endl;
167
Prog->OverallProgress(amt, file_size, 1,
168
_("Reading state information"));
171
Prog->OverallProgress(file_size, file_size, 1,
172
_("Reading state information"));
179
bool pkgDepCache::writeStateFile(OpProgress *prog)
181
if(_config->FindB("Debug::pkgAutoRemove",false))
182
std::clog << "pkgDepCache::writeStateFile()" << std::endl;
185
string state = _config->FindDir("Dir::State") + "extended_states";
187
// if it does not exist, create a empty one
188
if(!FileExists(state))
190
StateFile.Open(state, FileFd::WriteEmpty);
195
if(!StateFile.Open(state, FileFd::ReadOnly))
196
return _error->Error(_("Failed to open StateFile %s"),
200
string outfile = state + ".tmp";
201
if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
202
return _error->Error(_("Failed to write temporary StateFile %s"),
205
// first merge with the existing sections
206
pkgTagFile tagfile(&StateFile);
207
pkgTagSection section;
208
std::set<string> pkgs_seen;
209
const char *nullreorderlist[] = {0};
210
while(tagfile.Step(section)) {
211
string pkgname = section.FindS("Package");
212
// Silently ignore unknown packages and packages with no actual
214
pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
215
if(pkg.end() || pkg.VersionList().end())
217
bool oldAuto = section.FindI("Auto-Installed");
218
bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
219
if(_config->FindB("Debug::pkgAutoRemove",false))
220
std::clog << "Update exisiting AutoInstall info: "
221
<< pkg.Name() << std::endl;
222
TFRewriteData rewrite[2];
223
rewrite[0].Tag = "Auto-Installed";
224
rewrite[0].Rewrite = newAuto ? "1" : "0";
225
rewrite[0].NewTag = 0;
227
TFRewrite(OutFile, section, nullreorderlist, rewrite);
228
fprintf(OutFile,"\n");
229
pkgs_seen.insert(pkgname);
232
// then write the ones we have not seen yet
233
std::ostringstream ostr;
234
for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
235
if(PkgState[pkg->ID].Flags & Flag::Auto) {
236
if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
237
if(_config->FindB("Debug::pkgAutoRemove",false))
238
std::clog << "Skipping already written " << pkg.Name() << std::endl;
241
if(_config->FindB("Debug::pkgAutoRemove",false))
242
std::clog << "Writing new AutoInstall: "
243
<< pkg.Name() << std::endl;
244
ostr.str(string(""));
245
ostr << "Package: " << pkg.Name()
246
<< "\nAuto-Installed: 1\n\n";
247
fprintf(OutFile,ostr.str().c_str());
248
fprintf(OutFile,"\n");
253
// move the outfile over the real file
254
rename(outfile.c_str(), state.c_str());
103
259
// DepCache::CheckDep - Checks a single dependency /*{{{*/
104
260
// ---------------------------------------------------------------------
105
261
/* This first checks the dependency against the main target package and
667
864
/* Check if this dep should be consider for install. If it is a user
668
865
defined important dep and we are installed a new package then
669
it will be installed. Otherwise we only worry about critical deps */
866
it will be installed. Otherwise we only check for important
867
deps that have changed from the installed version
670
869
if (IsImportantDep(Start) == false)
672
if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
872
/* check if any ImportantDep() (but not Critial) where added
873
* since we installed the package
875
bool isNewImportantDep = false;
876
if(!ForceImportantDeps && !Start.IsCritical())
879
VerIterator instVer = Pkg.CurrentVer();
882
for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
884
//FIXME: deal better with or-groups(?)
885
DepIterator LocalStart = D;
887
if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
890
// this is a new dep if it was not found to be already
891
// a important dep of the installed pacakge
892
isNewImportantDep = !found;
895
if(isNewImportantDep)
896
if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
897
std::clog << "new important dependency: "
898
<< Start.TargetPkg().Name() << std::endl;
900
// skip important deps if the package is already installed
901
if (Pkg->CurrentVer != 0 && Start.IsCritical() == false
902
&& !isNewImportantDep && !ForceImportantDeps)
675
905
/* If we are in an or group locate the first or that can
714
if (InstPkg.end() == false)
945
if (InstPkg.end() == false)
716
947
if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
717
948
std::clog << "Installing " << InstPkg.Name()
718
949
<< " as dep of " << Pkg.Name()
720
MarkInstall(InstPkg,true,Depth + 1);
722
// Set the autoflag, after MarkInstall because MarkInstall unsets it
723
if (P->CurrentVer == 0)
724
PkgState[InstPkg->ID].Flags |= Flag::Auto;
951
// now check if we should consider it a automatic dependency or not
952
string sec = _config->Find("APT::Never-MarkAuto-Section","");
953
if(Pkg.Section() && (string(Pkg.Section()) == sec))
955
if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
956
std::clog << "Setting NOT as auto-installed because its a direct dep of a package in section " << sec << std::endl;
957
MarkInstall(InstPkg,true,Depth + 1, true);
961
// mark automatic dependency
962
MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
963
// Set the autoflag, after MarkInstall because MarkInstall unsets it
964
if (P->CurrentVer == 0)
965
PkgState[InstPkg->ID].Flags |= Flag::Auto;
730
971
/* For conflicts we just de-install the package and mark as auto,
731
Conflicts may not have or groups */
732
if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
972
Conflicts may not have or groups. For dpkg's Breaks we try to
973
upgrade the package. */
974
if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes ||
975
Start->Type == Dep::DpkgBreaks)
734
977
for (Version **I = List; *I != 0; I++)
736
979
VerIterator Ver(*this,*I);
737
980
PkgIterator Pkg = Ver.ParentPkg();
740
PkgState[Pkg->ID].Flags |= Flag::Auto;
982
if (Start->Type != Dep::DpkgBreaks)
985
if (PkgState[Pkg->ID].CandidateVer != *I)
986
MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
870
1132
bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
872
return Dep.IsCritical();
1134
if(Dep.IsCritical())
1136
else if(Dep->Type == pkgCache::Dep::Recommends)
1138
if ( _config->FindB("APT::Install-Recommends", false))
1140
// we suport a special mode to only install-recommends for certain
1142
// FIXME: this is a meant as a temporarly solution until the
1143
// recommends are cleaned up
1144
string s = _config->Find("APT::Install-Recommends-Section","");
1147
const char *sec = Dep.TargetPkg().Section();
1148
if (sec && strcmp(sec, s.c_str()) == 0)
1152
else if(Dep->Type == pkgCache::Dep::Suggests)
1153
return _config->FindB("APT::Install-Suggests", false);
1159
pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
1160
: constructedSuccessfully(false)
1162
Configuration::Item const *Opts;
1163
Opts = _config->Tree("APT::NeverAutoRemove");
1164
if (Opts != 0 && Opts->Child != 0)
1167
for (; Opts != 0; Opts = Opts->Next)
1169
if (Opts->Value.empty() == true)
1172
regex_t *p = new regex_t;
1173
if(regcomp(p,Opts->Value.c_str(),
1174
REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
1178
_error->Error("Regex compilation error for APT::NeverAutoRemove");
1182
rootSetRegexp.push_back(p);
1186
constructedSuccessfully = true;
1189
pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
1191
for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
1193
regfree(rootSetRegexp[i]);
1194
delete rootSetRegexp[i];
1199
bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
1201
for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
1202
if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
1208
pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
1210
DefaultRootSetFunc *f = new DefaultRootSetFunc;
1211
if(f->wasConstructedSuccessfully())
1220
bool pkgDepCache::MarkFollowsRecommends()
1222
return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
1225
bool pkgDepCache::MarkFollowsSuggests()
1227
return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
1230
// the main mark algorithm
1231
bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
1233
bool follow_recommends;
1234
bool follow_suggests;
1237
for(PkgIterator p = PkgBegin(); !p.end(); ++p)
1239
PkgState[p->ID].Marked = false;
1240
PkgState[p->ID].Garbage = false;
1243
if(_config->FindB("Debug::pkgAutoRemove",false)
1244
&& PkgState[p->ID].Flags & Flag::Auto)
1245
std::clog << "AutoDep: " << p.Name() << std::endl;
1249
follow_recommends = MarkFollowsRecommends();
1250
follow_suggests = MarkFollowsSuggests();
1254
// do the mark part, this is the core bit of the algorithm
1255
for(PkgIterator p = PkgBegin(); !p.end(); ++p)
1257
if(!(PkgState[p->ID].Flags & Flag::Auto) ||
1258
(p->Flags & Flag::Essential) ||
1259
userFunc.InRootSet(p))
1262
// the package is installed (and set to keep)
1263
if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
1264
MarkPackage(p, p.CurrentVer(),
1265
follow_recommends, follow_suggests);
1266
// the package is to be installed
1267
else if(PkgState[p->ID].Install())
1268
MarkPackage(p, PkgState[p->ID].InstVerIter(*this),
1269
follow_recommends, follow_suggests);
1276
// mark a single package in Mark-and-Sweep
1277
void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
1278
const pkgCache::VerIterator &ver,
1279
bool follow_recommends,
1280
bool follow_suggests)
1282
pkgDepCache::StateCache &state = PkgState[pkg->ID];
1283
VerIterator candver = state.CandidateVerIter(*this);
1284
VerIterator instver = state.InstVerIter(*this);
1287
// If a package was garbage-collected but is now being marked, we
1288
// should re-select it
1289
// For cases when a pkg is set to upgrade and this trigger the
1290
// removal of a no-longer used dependency. if the pkg is set to
1291
// keep again later it will result in broken deps
1292
if(state.Delete() && state.RemoveReason = Unused)
1295
mark_install(pkg, false, false, NULL);
1296
else if(ver==pkg.CurrentVer())
1297
MarkKeep(pkg, false, false);
1299
instver=state.InstVerIter(*this);
1303
// Ignore versions other than the InstVer, and ignore packages
1304
// that are already going to be removed or just left uninstalled.
1305
if(!(ver == instver && !instver.end()))
1308
// if we are marked already we are done
1312
//std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
1317
for(DepIterator d = ver.DependsList(); !d.end(); ++d)
1319
if(d->Type == Dep::Depends ||
1320
d->Type == Dep::PreDepends ||
1321
(follow_recommends &&
1322
d->Type == Dep::Recommends) ||
1324
d->Type == Dep::Suggests))
1326
// Try all versions of this package.
1327
for(VerIterator V = d.TargetPkg().VersionList();
1330
if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
1332
MarkPackage(V.ParentPkg(), V,
1333
follow_recommends, follow_suggests);
1336
// Now try virtual packages
1337
for(PrvIterator prv=d.TargetPkg().ProvidesList();
1340
if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp,
1343
MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
1344
follow_recommends, follow_suggests);
1352
bool pkgDepCache::Sweep()
1355
for(PkgIterator p=PkgBegin(); !p.end(); ++p)
1357
StateCache &state=PkgState[p->ID];
1359
// skip required packages
1360
if (!p.CurrentVer().end() &&
1361
(p.CurrentVer()->Priority == pkgCache::State::Required))
1364
// if it is not marked and it is installed, it's garbage
1365
if(!state.Marked && (!p.CurrentVer().end() || state.Install()))
1368
if(_config->FindB("Debug::pkgAutoRemove",false))
1369
std::cout << "Garbage: " << p.Name() << std::endl;