#include <sstream>
#include <set>
+#include <sys/stat.h>
+
#include <apti18n.h>
+// helper for Install-Recommends-Sections and Never-MarkAuto-Sections
+static bool
+ConfigValueInSubTree(const char* SubTree, const char *needle)
+{
+ Configuration::Item const *Opts;
+ Opts = _config->Tree(SubTree);
+ if (Opts != 0 && Opts->Child != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+ if (strcmp(needle, Opts->Value.c_str()) == 0)
+ return true;
+ }
+ }
+ return false;
+}
+
+
pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
cache(cache), released(false)
{
return true;
}
-bool pkgDepCache::writeStateFile(OpProgress *prog)
+bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
{
if(_config->FindB("Debug::pkgAutoRemove",false))
std::clog << "pkgDepCache::writeStateFile()" << std::endl;
pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
if(pkg.end() || pkg.VersionList().end())
continue;
- bool oldAuto = section.FindI("Auto-Installed");
bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
if(_config->FindB("Debug::pkgAutoRemove",false))
std::clog << "Update exisiting AutoInstall info: "
std::clog << "Skipping already written " << pkg.Name() << std::endl;
continue;
}
+ // skip not installed ones if requested
+ if(InstalledOnly && pkg->CurrentVer == 0)
+ continue;
if(_config->FindB("Debug::pkgAutoRemove",false))
std::clog << "Writing new AutoInstall: "
<< pkg.Name() << std::endl;
}
fclose(OutFile);
- // move the outfile over the real file
+ // move the outfile over the real file and set permissions
rename(outfile.c_str(), state.c_str());
+ chmod(state.c_str(), 0644);
return true;
}
if (IsImportantDep(Start) == false)
continue;
- /* check if any ImportantDep() (but not Critial) where added
- * since we installed the package
+ /* Check if any ImportantDep() (but not Critical) were added
+ * since we installed the package. Also check for deps that
+ * were satisfied in the past: for instance, if a version
+ * restriction in a Recommends was tightened, upgrading the
+ * package should follow that Recommends rather than causing the
+ * dependency to be removed. (bug #470115)
*/
bool isNewImportantDep = false;
+ bool isPreviouslySatisfiedImportantDep = false;
if(!ForceImportantDeps && !Start.IsCritical())
{
bool found=false;
VerIterator instVer = Pkg.CurrentVer();
if(!instVer.end())
{
- for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
- {
+ for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
+ {
//FIXME: deal better with or-groups(?)
DepIterator LocalStart = D;
-
- if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
- found=true;
- }
+
+ if(IsImportantDep(D) && !D.IsCritical() &&
+ Start.TargetPkg() == D.TargetPkg())
+ {
+ if(!isPreviouslySatisfiedImportantDep)
+ {
+ DepIterator D2 = D;
+ while((D2->CompareOp & Dep::Or) != 0)
+ ++D2;
+
+ isPreviouslySatisfiedImportantDep =
+ (((*this)[D2] & DepGNow) != 0);
+ }
+
+ found=true;
+ }
+ }
// this is a new dep if it was not found to be already
// a important dep of the installed pacakge
isNewImportantDep = !found;
if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
std::clog << "new important dependency: "
<< Start.TargetPkg().Name() << std::endl;
+ if(isPreviouslySatisfiedImportantDep)
+ if(_config->FindB("Debug::pkgDepCache::AutoInstall", false) == true)
+ std::clog << "previously satisfied important dependency on "
+ << Start.TargetPkg().Name() << std::endl;
// skip important deps if the package is already installed
if (Pkg->CurrentVer != 0 && Start.IsCritical() == false
- && !isNewImportantDep && !ForceImportantDeps)
+ && !isNewImportantDep && !isPreviouslySatisfiedImportantDep
+ && !ForceImportantDeps)
continue;
/* If we are in an or group locate the first or that can
<< " as dep of " << Pkg.Name()
<< std::endl;
// now check if we should consider it a automatic dependency or not
- string sec = _config->Find("APT::Never-MarkAuto-Section","");
- if(Pkg.Section() && (string(Pkg.Section()) == sec))
+ if(Pkg.Section() && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
{
if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
- std::clog << "Setting NOT as auto-installed because its a direct dep of a package in section " << sec << std::endl;
+ std::clog << "Setting NOT as auto-installed (direct dep of pkg in APT::Never-MarkAuto-Section)" << std::endl;
MarkInstall(InstPkg,true,Depth + 1, true);
}
else
return Last;
}
/*}}}*/
+
// Policy::IsImportantDep - True if the dependency is important /*{{{*/
// ---------------------------------------------------------------------
/* */
// sections
// FIXME: this is a meant as a temporarly solution until the
// recommends are cleaned up
- string s = _config->Find("APT::Install-Recommends-Section","");
- if(s.size() > 0)
- {
- const char *sec = Dep.TargetPkg().Section();
- if (sec && strcmp(sec, s.c_str()) == 0)
- return true;
- }
+ const char *sec = Dep.ParentVer().Section();
+ if (sec && ConfigValueInSubTree("APT::Install-Recommends-Sections", sec))
+ return true;
}
else if(Dep->Type == pkgCache::Dep::Suggests)
return _config->FindB("APT::Install-Suggests", false);
{
// the package is installed (and set to keep)
if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
- MarkPackage(p, p.CurrentVer(),
+ MarkPackage(p, p.CurrentVer(),
follow_recommends, follow_suggests);
// the package is to be installed
else if(PkgState[p->ID].Install())
bool follow_suggests)
{
pkgDepCache::StateCache &state = PkgState[pkg->ID];
+ VerIterator currver = pkg.CurrentVer();
VerIterator candver = state.CandidateVerIter(*this);
VerIterator instver = state.InstVerIter(*this);
}
#endif
- // Ignore versions other than the InstVer, and ignore packages
- // that are already going to be removed or just left uninstalled.
- if(!(ver == instver && !instver.end()))
+ // For packages that are not going to be removed, ignore versions
+ // other than the InstVer. For packages that are going to be
+ // removed, ignore versions other than the current version.
+ if(!(ver == instver && !instver.end()) &&
+ !(ver == currver && instver.end() && !ver.end()))
return;
// if we are marked already we are done
if(state.Marked)
return;
- //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
+ if(_config->FindB("Debug::pkgAutoRemove",false))
+ {
+ std::clog << "Marking: " << pkg.Name();
+ if(!ver.end())
+ std::clog << " " << ver.VerStr();
+ if(!currver.end())
+ std::clog << ", Curr=" << currver.VerStr();
+ if(!instver.end())
+ std::clog << ", Inst=" << instver.VerStr();
+ std::clog << std::endl;
+ }
+
state.Marked=true;
if(!ver.end())
{
if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
{
+ if(_config->FindB("Debug::pkgAutoRemove",false))
+ {
+ std::clog << "Following dep: " << d.ParentPkg().Name()
+ << " " << d.ParentVer().VerStr() << " "
+ << d.DepType() << " "
+ << d.TargetPkg().Name();
+ if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
+ {
+ std::clog << " (" << d.CompType() << " "
+ << d.TargetVer() << ")";
+ }
+ std::clog << std::endl;
+ }
MarkPackage(V.ParentPkg(), V,
follow_recommends, follow_suggests);
}
if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp,
d.TargetVer()))
{
+ if(_config->FindB("Debug::pkgAutoRemove",false))
+ {
+ std::clog << "Following dep: " << d.ParentPkg().Name()
+ << " " << d.ParentVer().VerStr() << " "
+ << d.DepType() << " "
+ << d.TargetPkg().Name();
+ if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
+ {
+ std::clog << " (" << d.CompType() << " "
+ << d.TargetVer() << ")";
+ }
+ std::clog << ", provided by "
+ << prv.OwnerPkg().Name() << " "
+ << prv.OwnerVer().VerStr()
+ << std::endl;
+ }
+
MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
follow_recommends, follow_suggests);
}