summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/algorithms.cc115
-rw-r--r--apt-pkg/algorithms.h4
-rw-r--r--apt-pkg/deb/dpkgpm.h2
-rw-r--r--apt-pkg/depcache.cc96
-rw-r--r--apt-pkg/depcache.h10
-rw-r--r--apt-pkg/packagemanager.cc5
-rw-r--r--apt-pkg/pkgcache.h1
-rw-r--r--apt-pkg/pkgcachegen.cc2
8 files changed, 231 insertions, 4 deletions
diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index 479927d65..98bd8dd8b 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -1061,6 +1061,17 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
return _error->Error(_("Unable to correct problems, you have held broken packages."));
}
+ // set the auto-flags (mvo: I'm not sure if we _really_ need this, but
+ // I didn't managed
+ pkgCache::PkgIterator I = Cache.PkgBegin();
+ for (;I.end() != true; I++) {
+ if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
+ std::cout << "Resolve installed new pkg: " << I.Name() << " (now marking it as auto)" << std::endl;
+ Cache[I].Flags |= pkgCache::Flag::Auto;
+ }
+ }
+
+
return true;
}
/*}}}*/
@@ -1232,3 +1243,107 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
qsort(List,Count,sizeof(*List),PrioComp);
}
/*}}}*/
+
+
+// pkgMarkPkgUsed - Mark used packages as dirty /*{{{*/
+// ---------------------------------------------------------------------
+/* Mark all reachable packages as dirty. */
+void pkgMarkPkgUsed(pkgDepCache &Cache, pkgCache::PkgIterator Pkg,
+ pkgCache::State::PkgRemoveState DirtLevel)
+{
+ // If it is not installed, and we are in manual mode, ignore it
+ if ((Pkg->CurrentVer == 0 && Cache[Pkg].Install() == false || Cache[Pkg].Delete() == true) &&
+ DirtLevel == pkgCache::State::RemoveManual)
+ {
+// fprintf(stdout,"This one is not installed/virtual %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+ return;
+ }
+
+ // If it is not installed, and it is not virtual, ignore it
+ if ((Pkg->CurrentVer == 0 && Cache[Pkg].Install() == false || Cache[Pkg].Delete() == true) &&
+ Pkg->VersionList != 0)
+ {
+// fprintf(stdout,"This one is not installed %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+ return;
+ }
+
+ // If it is similar or more dirty than we are ;-), because we've been here already, don't mark it
+ // This is necessary because virtual packages just relay the current level,
+ // so it may be possible e.g. that this was already seen with ::RemoveSuggested, but
+ // we are ::RemoveRequired
+ if (Cache[Pkg].Dirty() >= DirtLevel)
+ {
+ //fprintf(stdout,"Seen already %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+ return;
+ }
+
+ // If it is less important than the current DirtLevel, don't mark it
+ if (Cache[Pkg].AutomaticRemove != pkgCache::State::RemoveManual &&
+ Cache[Pkg].AutomaticRemove > DirtLevel)
+ {
+// fprintf(stdout,"We don't need %s %d %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel, Cache[Pkg].Dirty());
+ return;
+ }
+
+ // Mark it as used
+ Cache.SetDirty(Pkg, DirtLevel);
+
+ //fprintf(stdout,"We keep %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+
+ // We are a virtual package
+ if (Pkg->VersionList == 0)
+ {
+// fprintf(stdout,"We are virtual %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+ for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); ! Prv.end(); ++Prv)
+ pkgMarkPkgUsed (Cache, Prv.OwnerPkg(), DirtLevel);
+ return;
+ }
+
+ // Depending on the type of dependency, follow it
+ for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); ! D.end(); ++D)
+ {
+// fprintf(stdout,"We depend on %s %s\n", D.TargetPkg().Name(), D.DepType());
+
+ switch(D->Type)
+ {
+ case pkgCache::Dep::Depends:
+ case pkgCache::Dep::PreDepends:
+ pkgMarkPkgUsed (Cache, D.TargetPkg(), pkgCache::State::RemoveRequired);
+ break;
+ case pkgCache::Dep::Recommends:
+ pkgMarkPkgUsed (Cache, D.TargetPkg(), pkgCache::State::RemoveRecommended);
+ break;
+ case pkgCache::Dep::Suggests:
+ pkgMarkPkgUsed (Cache, D.TargetPkg(), pkgCache::State::RemoveSuggested);
+ break;
+ case pkgCache::Dep::Conflicts:
+ case pkgCache::Dep::Replaces:
+ case pkgCache::Dep::Obsoletes:
+ // We don't handle these here
+ break;
+ }
+ }
+// fprintf(stdout,"We keep %s %d %d <END>\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+}
+ /*}}}*/
+
+bool pkgMarkUsed(pkgDepCache &Cache)
+{
+ // debug only
+ for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg)
+ if(!Cache[Pkg].Dirty() && Cache[Pkg].AutomaticRemove > 0)
+ std::cout << "has auto-remove information: " << Pkg.Name()
+ << " " << (int)Cache[Pkg].AutomaticRemove
+ << std::endl;
+
+ // init with defaults
+ for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg)
+ Cache.SetDirty(Pkg, pkgCache::State::RemoveUnknown);
+
+ // go recursive over the cache
+ for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg)
+ pkgMarkPkgUsed (Cache, Pkg, pkgCache::State::RemoveManual);
+
+
+ return true;
+}
diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h
index 174a7f58d..210127ab9 100644
--- a/apt-pkg/algorithms.h
+++ b/apt-pkg/algorithms.h
@@ -132,5 +132,9 @@ bool pkgAllUpgrade(pkgDepCache &Cache);
bool pkgMinimizeUpgrade(pkgDepCache &Cache);
void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List);
+
+// mark all reachable packages, everything that is not reach can
+// be removed
+bool pkgMarkUsed(pkgDepCache &Cache);
#endif
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index b59b9dc93..8bfdff5eb 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -40,7 +40,7 @@ class pkgDPkgPM : public pkgPackageManager
bool RunScripts(const char *Cnf);
bool RunScriptsWithPkgs(const char *Cnf);
bool SendV2Pkgs(FILE *F);
-
+
// The Actuall installation implementation
virtual bool Install(PkgIterator Pkg,string File);
virtual bool Configure(PkgIterator Pkg);
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index c6bf3185a..c490d89bc 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -16,7 +16,11 @@
#include <apt-pkg/error.h>
#include <apt-pkg/sptr.h>
#include <apt-pkg/algorithms.h>
-
+
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/tagfile.h>
+#include <sstream>
#include <apti18n.h>
/*}}}*/
@@ -72,7 +76,10 @@ bool pkgDepCache::Init(OpProgress *Prog)
// Find the proper cache slot
StateCache &State = PkgState[I->ID];
State.iFlags = 0;
-
+ State.DirtyState = pkgCache::State::RemoveUnknown;
+ //State.AutomaticRemove = I->AutomaticRemove;
+ State.AutomaticRemove = pkgCache::State::RemoveUnknown;
+
// Figure out the install version
State.CandidateVer = GetCandidateVer(I);
State.InstallVer = I.CurrentVer();
@@ -96,6 +103,77 @@ bool pkgDepCache::Init(OpProgress *Prog)
}
/*}}}*/
+bool pkgDepCache::readStateFile(OpProgress *Prog)
+{
+ FileFd state_file;
+ string state = _config->FindDir("Dir::State") + "pkgstates";
+ if(FileExists(state)) {
+ state_file.Open(state, FileFd::ReadOnly);
+ int file_size = state_file.Size();
+ Prog->OverallProgress(0, file_size, 1,
+ _("Reading extended state information"));
+
+ pkgTagFile tagfile(&state_file);
+ pkgTagSection section;
+ int amt=0;
+ while(tagfile.Step(section)) {
+ string pkgname = section.FindS("Package");
+ pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
+ // Silently ignore unknown packages and packages with no actual
+ // version.
+ if(!pkg.end() && !pkg.VersionList().end()) {
+ short reason = section.FindI("Remove-Reason",
+ pkgCache::State::RemoveManual);
+ PkgState[pkg->ID].AutomaticRemove = reason;
+ //std::cout << "Set: " << pkgname << " to " << reason << std::endl;
+ amt+=section.size();
+ Prog->OverallProgress(amt, file_size, 1,
+ _("Reading extended state information"));
+ }
+ Prog->OverallProgress(file_size, file_size, 1,
+ _("Reading extended state information"));
+ }
+ }
+
+ return true;
+}
+
+bool pkgDepCache::writeStateFile(OpProgress *prog)
+{
+ // write the auto-mark list ----------------------------------
+
+ FileFd StateFile;
+ string state = _config->FindDir("Dir::State") + "pkgstates";
+
+ if(!StateFile.Open(state, FileFd::WriteEmpty))
+ return _error->Error(_("Failed to write StateFile %s"),
+ state.c_str());
+
+ std::ostringstream ostr;
+ for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end();pkg++) {
+
+ // clear out no longer installed pkg
+ if(PkgState[pkg->ID].Delete() || pkg.CurrentVer() == NULL)
+ PkgState[pkg->ID].AutomaticRemove = pkgCache::State::RemoveUnknown;
+
+ // check if we have new information
+ if(PkgState[pkg->ID].Flags & pkgCache::Flag::Auto) {
+ std::cout << "pkg: " << pkg.Name() << " is auto-dep" << std::endl;
+ PkgState[pkg->ID].AutomaticRemove = pkgCache::State::RemoveRequired;
+ }
+
+ if(PkgState[pkg->ID].AutomaticRemove != pkgCache::State::RemoveUnknown) {
+ ostr.str(string(""));
+ ostr << "Package: " << pkg.Name()
+ << "\nRemove-Reason: "
+ << (int)(PkgState[pkg->ID].AutomaticRemove) << "\n\n";
+ StateFile.Write(ostr.str().c_str(), ostr.str().size());
+ //std::cout << "Writing auto-mark: " << ostr.str() << endl;
+ }
+ }
+ return true;
+}
+
// DepCache::CheckDep - Checks a single dependency /*{{{*/
// ---------------------------------------------------------------------
/* This first checks the dependency against the main target package and
@@ -447,6 +525,8 @@ void pkgDepCache::Update(OpProgress *Prog)
AddStates(I);
}
+ readStateFile(Prog);
+
if (Prog != 0)
Prog->Progress(Done);
}
@@ -582,7 +662,8 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
else
P.Mode = ModeDelete;
P.InstallVer = 0;
- P.Flags &= Flag::Auto;
+ // This was not inverted before, but I think it should be
+ P.Flags &= ~Flag::Auto;
AddStates(Pkg);
Update(Pkg);
@@ -754,6 +835,15 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
AddSizes(Pkg);
}
/*}}}*/
+// DepCache::SetDirty - Switch the package between dirty states /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgDepCache::SetDirty(PkgIterator const &Pkg, pkgCache::State::PkgRemoveState To)
+{
+ StateCache &P = PkgState[Pkg->ID];
+ P.DirtyState = To;
+}
+ /*}}}*/
// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
// ---------------------------------------------------------------------
/* */
diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h
index 6d51920e9..e02ed72f0 100644
--- a/apt-pkg/depcache.h
+++ b/apt-pkg/depcache.h
@@ -79,6 +79,10 @@ class pkgDepCache : protected pkgCache::Namespace
unsigned short Flags;
unsigned short iFlags; // Internal flags
+ // Traversal status and state for automatic removal
+ unsigned char DirtyState;
+ unsigned char AutomaticRemove;
+
// Various tree indicators
signed char Status; // -1,0,1,2
unsigned char Mode; // ModeList
@@ -99,6 +103,7 @@ class pkgDepCache : protected pkgCache::Namespace
inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;};
inline bool InstBroken() const {return (DepState & DepInstMin) != DepInstMin;};
inline bool Install() const {return Mode == ModeInstall;};
+ inline unsigned char Dirty() const {return DirtyState;};
inline VerIterator InstVerIter(pkgCache &Cache)
{return VerIterator(Cache,InstallVer);};
inline VerIterator CandidateVerIter(pkgCache &Cache)
@@ -189,9 +194,14 @@ class pkgDepCache : protected pkgCache::Namespace
unsigned long Depth = 0);
void SetReInstall(PkgIterator const &Pkg,bool To);
void SetCandidateVersion(VerIterator TargetVer);
+ void SetDirty(PkgIterator const &Pkg, pkgCache::State::PkgRemoveState To);
// This is for debuging
void Update(OpProgress *Prog = 0);
+
+ // read persistent states
+ bool readStateFile(OpProgress *prog);
+ bool writeStateFile(OpProgress *prog);
// Size queries
inline double UsrSize() {return iUsrSize;};
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
index a08ccd602..a97c94fdf 100644
--- a/apt-pkg/packagemanager.cc
+++ b/apt-pkg/packagemanager.cc
@@ -637,6 +637,11 @@ pkgPackageManager::OrderResult pkgPackageManager::DoInstall()
if (Res != Failed)
if (Go() == false)
return Failed;
+
+ // if all was fine update the state file
+ if(Res == Completed)
+ Cache.writeStateFile(NULL);
+
return Res;
}
/*}}}*/
diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h
index b07951dfb..083f20ac2 100644
--- a/apt-pkg/pkgcache.h
+++ b/apt-pkg/pkgcache.h
@@ -75,6 +75,7 @@ class pkgCache
enum PkgInstState {Ok=0,ReInstReq=1,HoldInst=2,HoldReInstReq=3};
enum PkgCurrentState {NotInstalled=0,UnPacked=1,HalfConfigured=2,
HalfInstalled=4,ConfigFiles=5,Installed=6};
+ enum PkgRemoveState {RemoveUnknown=0, RemoveManual=1,RemoveSuggested=2,RemoveRecommended=3,RemoveRequired=4};
};
struct Flag
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index 2340f97fd..04904057f 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -26,6 +26,8 @@
#include <apt-pkg/sptr.h>
#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/tagfile.h>
+
#include <apti18n.h>
#include <vector>