From afb1e2e3bb580077c6c917e6ea98baad8f3c39b3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 10 May 2005 08:27:59 +0000 Subject: * ported/cleaned up the "Automatic dependency handling" patch from Michael Hofmann --- apt-pkg/deb/dpkgpm.h | 2 +- apt-pkg/depcache.cc | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- apt-pkg/depcache.h | 6 ++++++ apt-pkg/pkgcache.h | 1 + apt-pkg/pkgcachegen.cc | 2 ++ 5 files changed, 58 insertions(+), 3 deletions(-) (limited to 'apt-pkg') 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..5da411e4d 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -16,6 +16,10 @@ #include #include #include + +#include +#include +#include #include /*}}}*/ @@ -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(); @@ -447,6 +454,35 @@ void pkgDepCache::Update(OpProgress *Prog) AddStates(I); } + // read the state file ------------------------------ + 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")); + } + } + //-------------------------------------- + + if (Prog != 0) Prog->Progress(Done); } @@ -582,7 +618,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 +791,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..f974bfacf 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,6 +194,7 @@ 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); 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 075af3eec..e90c1e50d 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -26,6 +26,8 @@ #include #include +#include + #include #include -- cgit v1.2.3 From a83d884db24933000f19dbff706529db057d50c1 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 23 Jun 2005 16:40:54 +0000 Subject: * cleanups --- apt-pkg/depcache.cc | 91 ++++++++++++++++++++++++++++++++++++----------------- apt-pkg/depcache.h | 4 +++ 2 files changed, 66 insertions(+), 29 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 5da411e4d..552a45a16 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -20,7 +20,7 @@ #include #include #include - +#include #include /*}}}*/ @@ -103,6 +103,66 @@ 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++) { + 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 @@ -454,34 +514,7 @@ void pkgDepCache::Update(OpProgress *Prog) AddStates(I); } - // read the state file ------------------------------ - 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")); - } - } - //-------------------------------------- - + readStateFile(Prog); if (Prog != 0) Prog->Progress(Done); diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index f974bfacf..e02ed72f0 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -198,6 +198,10 @@ class pkgDepCache : protected pkgCache::Namespace // 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;}; -- cgit v1.2.3 From 80fa0d8a1a77f4dab696dcf11d1908ecda761fab Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 24 Jun 2005 09:36:22 +0000 Subject: * moved most of the real work into depcache::writeStateFile --- apt-pkg/algorithms.cc | 11 +++++++++++ apt-pkg/depcache.cc | 11 +++++++++++ 2 files changed, 22 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 479927d65..2799c2fdd 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; } /*}}}*/ diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 552a45a16..c490d89bc 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -151,6 +151,17 @@ bool pkgDepCache::writeStateFile(OpProgress *prog) 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() -- cgit v1.2.3 From d36ab88eb8a5e490e4a817b87f20cb3f890e0da1 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 24 Jun 2005 09:58:47 +0000 Subject: * write the state file after a successfull commit from the pkgManager --- apt-pkg/packagemanager.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'apt-pkg') 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; } /*}}}*/ -- cgit v1.2.3 From db1e7193fa7d5b86656c05112b9d6ad6e75845b8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 24 Jun 2005 12:34:34 +0000 Subject: * moved the importend algorithm to algorithm.h as "pkgMarkUsed()" --- apt-pkg/algorithms.cc | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/algorithms.h | 4 ++ 2 files changed, 108 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 2799c2fdd..98bd8dd8b 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1243,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 \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 -- cgit v1.2.3 From 3c9b111f0fea7b57f1eebc2c03a057240e9b7a06 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 24 Jun 2005 19:46:26 +0000 Subject: * merged with the apt--improved-do-install patch Patches applied: * michael.vogt@ubuntu.com--2005/apt--improved-do-install--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-88 * michael.vogt@ubuntu.com--2005/apt--improved-do-install--0--patch-1 * merged with apt--fixes to make it build * michael.vogt@ubuntu.com--2005/apt--improved-do-install--0--patch-2 * added "DoInstall{Pre,Post}Fork()" --- apt-pkg/depcache.cc | 3 ++- apt-pkg/packagemanager.cc | 18 ------------------ apt-pkg/packagemanager.h | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 21 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index c490d89bc..269fe8543 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -140,7 +140,8 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) bool pkgDepCache::writeStateFile(OpProgress *prog) { - // write the auto-mark list ---------------------------------- + // FIXME: this function needs to be called inside the commit() + // of the package manager. so after FileFd StateFile; string state = _config->FindDir("Dir::State") + "pkgstates"; diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index a97c94fdf..71a0dd034 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -627,21 +627,3 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() return Completed; } /*}}}*/ -// PM::DoInstall - Does the installation /*{{{*/ -// --------------------------------------------------------------------- -/* This uses the filenames in FileNames and the information in the - DepCache to perform the installation of packages.*/ -pkgPackageManager::OrderResult pkgPackageManager::DoInstall() -{ - OrderResult Res = OrderInstall(); - 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/packagemanager.h b/apt-pkg/packagemanager.h index 43f2c4ace..da1f21e6c 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -29,6 +29,7 @@ #include #include +#include using std::string; @@ -70,13 +71,44 @@ class pkgPackageManager : protected pkgCache::Namespace virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;}; virtual bool Go(int statusFd=-1) {return true;}; virtual void Reset() {}; - + + // the result of the operation + OrderResult Res; + public: // Main action members bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources, pkgRecords *Recs); - OrderResult DoInstall(); + + // Do the installation + OrderResult DoInstall() { + if(DoInstallPreFork() == Failed) + return Failed; + + return DoInstallPostFork(); + } + + // stuff that needs to be done before the fork() of a library that + // uses apt + OrderResult DoInstallPreFork() { + Res = OrderInstall(); + return Res; + }; + + // stuff that needs to be done after the fork + OrderResult DoInstallPostFork(int statusFd=-1) { + bool goResult = Go(statusFd); + if(goResult == false) + return Failed; + + // if all was fine update the state file + if(Res == Completed) + Cache.writeStateFile(NULL); + + return Res; + }; + bool FixMissing(); pkgPackageManager(pkgDepCache *Cache); -- cgit v1.2.3 From 20edfd5399dada2d10ad791336797c4118eb60a8 Mon Sep 17 00:00:00 2001 From: Matt Zimmerman Date: Sun, 26 Jun 2005 20:13:10 +0000 Subject: Merge with mainline Patches applied: * apt@packages.debian.org/apt--main--0--patch-93 Merge with mvo * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-22 * added myself to uploaders, changelog is signed with mvo@debian.org and in sync with the debian/experimental upload * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-23 * apt-cache show shows all virtual packages instead of nothing (thanks to otavio) * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-24 * changelog updated * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-25 * make pinning on component work again (we just use the section, as apt-0.6 don't use per-section Release files anymore) * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-27 * updated the changelog * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-28 * merged with my apt--fixes--0 branch * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-29 * added a missing OpProgress::Done() in depCache::Init(), removed the show-virtual-packages patch in apt-cache because matt does not like him :/ * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-30 * fix a stupid bug in the depcache::Init() code * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-31 * merged/removed conflicts with apt--main--0 * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-32 * merged apt--main and make sure that the po files come from apt--main (because they are more recent) --- apt-pkg/deb/debindexfile.cc | 4 ++-- apt-pkg/deb/deblistparser.cc | 11 +++++++++-- apt-pkg/deb/deblistparser.h | 3 ++- apt-pkg/depcache.cc | 3 +++ 4 files changed, 16 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index f26265fff..ff8bce85d 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -24,7 +24,7 @@ #include #include #include - + #include /*}}}*/ @@ -290,7 +290,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const FileFd Rel(ReleaseFile,FileFd::ReadOnly); if (_error->PendingError() == true) return false; - Parser.LoadReleaseInfo(File,Rel); + Parser.LoadReleaseInfo(File,Rel,Section); } return true; diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 96a80582d..25b533773 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -564,13 +564,20 @@ bool debListParser::Step() // --------------------------------------------------------------------- /* */ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, - FileFd &File) + FileFd &File, string component) { pkgTagFile Tags(&File, File.Size() + 256); // XXX pkgTagSection Section; if (Tags.Step(Section) == false) return false; + //mvo: I don't think we need to fill that in (it's unused since apt-0.6) + //FileI->Architecture = WriteUniqString(Arch); + + // apt-secure does no longer download individual (per-section) Release + // file. to provide Component pinning we use the section name now + FileI->Component = WriteUniqString(component); + const char *Start; const char *Stop; if (Section.Find("Suite",Start,Stop) == true) @@ -589,7 +596,7 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, if (Section.FindFlag("NotAutomatic",FileI->Flags, pkgCache::Flag::NotAutomatic) == false) _error->Warning("Bad NotAutomatic flag"); - + return !_error->PendingError(); } /*}}}*/ diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 9f305211a..3a0e0421b 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -55,7 +55,8 @@ class debListParser : public pkgCacheGenerator::ListParser virtual bool Step(); - bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File); + bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File, + string section); static const char *ParseDepends(const char *Start,const char *Stop, string &Package,string &Ver,unsigned int &Op, diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index c6bf3185a..dd1c794c9 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -91,6 +91,9 @@ bool pkgDepCache::Init(OpProgress *Prog) } Update(Prog); + + if(Prog != 0) + Prog->Done(); return true; } -- cgit v1.2.3 From 29ba053e05b1a496500036dbd667002d1b8b5ec2 Mon Sep 17 00:00:00 2001 From: Matt Zimmerman Date: Sun, 26 Jun 2005 21:30:27 +0000 Subject: Merge with mvo Patches applied: * michael.vogt@ubuntu.com--2005/apt--bts225947--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-79 * michael.vogt@ubuntu.com--2005/apt--bts225947--0--patch-1 * merged with mainline and apt--fixes--0 * michael.vogt@ubuntu.com--2005/apt--bts225947--0--patch-2 * patch from aj (slighly modified to use auto_ptr<>) applied * michael.vogt@ubuntu.com--2005/apt--bts225947--0--patch-3 * changelog updated * michael.vogt@ubuntu.com--2005/apt--bts225947--0--patch-4 * work for arch=all packages too now * michael.vogt@ubuntu.com--2005/apt--fixes--0--patch-5 * merged with apt--main--0 * michael.vogt@ubuntu.com--2005/apt--fixes--0--patch-7 * fixed incorrect man-page example * michael.vogt@ubuntu.com--2005/apt--fixes--0--patch-8 * changelog udpate * michael.vogt@ubuntu.com--2005/apt--sane-handle-timeout--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-87 * michael.vogt@ubuntu.com--2005/apt--sane-handle-timeout--0--patch-1 * report timeouts (from Connect) and fail if they happen in pkgAcqMetaSig * michael.vogt@ubuntu.com--2005/apt--sane-handle-timeout--0--patch-2 * merged with the fixes branch to make it build again * michael.vogt@ubuntu.com--2005/apt--ubuntu--0--patch-1 tag of apt@packages.debian.org/apt--main--0--patch-88 * michael.vogt@ubuntu.com--2005/apt--ubuntu--0--patch-2 * merged apt--mvo (to make pining on components work again) * michael.vogt@ubuntu.com--2005/apt--ubuntu--0--patch-3 * merged with apt--fixes--0 (to make the building of the french manpages work and to fix a incorrect man-page example * michael.vogt@ubuntu.com--2005/apt--ubuntu--0--patch-4 * merged with the bts225947 code * michael.vogt@ubuntu.com--2005/apt--ubuntu--0--patch-5 * merged the imporoved timoeut handling patch * michael.vogt@ubuntu.com--2005/apt--ubuntu--0--patch-6 * merged with matt * michael.vogt@ubuntu.com--2005/apt--ubuntu--0--patch-7 * removed another conflict with apt--main --- apt-pkg/acquire-item.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index b2f896627..14acad85a 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -400,6 +400,12 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); unlink(Final.c_str()); + // if we get a timeout if fail + if(LookupTag(Message,"FailReason") == "Timeout") { + Item::Failed(Message,Cnf); + return; + } + // queue a pkgAcqMetaIndex with no sigfile new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc, "", IndexTargets, MetaIndexParser); -- cgit v1.2.3 From e004867d0979224adb9cbeb9705f156e16e3fe26 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 27 Jun 2005 16:29:16 +0000 Subject: * merged with mainline Patches applied: * andrelop@debian.org/apt--translation--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-79 * andrelop@debian.org/apt--translation--0--patch-1 Sync with Matt version. * andrelop@debian.org/apt--translation--0--patch-2 Update pt_BR translation * andrelop@debian.org/apt--translation--0--patch-3 Sync with bubulle's branch. * apt@packages.debian.org/apt--main--0--patch-89 Branch for Debian * apt@packages.debian.org/apt--main--0--patch-90 Update version in configure * apt@packages.debian.org/apt--main--0--patch-91 Fix French man page build * apt@packages.debian.org/apt--main--0--patch-92 Add the current Debian archive signing key * apt@packages.debian.org/apt--main--0--patch-93 Merge with mvo * apt@packages.debian.org/apt--main--0--patch-94 Update changelog * apt@packages.debian.org/apt--main--0--patch-95 Merge Christian's branch * apt@packages.debian.org/apt--main--0--patch-96 Update changelog * apt@packages.debian.org/apt--main--0--patch-97 Update priority of apt-utils to important, to match the override file * bubulle@debian.org--2005/apt--main--0--patch-82 Fix permissions * bubulle@debian.org--2005/apt--main--0--patch-83 French translation spellchecked * bubulle@debian.org--2005/apt--main--0--patch-84 Spell corrections in German translations * bubulle@debian.org--2005/apt--main--0--patch-85 Correct some file permissions * bubulle@debian.org--2005/apt--main--0--patch-86 Correct Hebrew translation * bubulle@debian.org--2005/apt--main--0--patch-87 Sync Portuguese translation with the POT file * bubulle@debian.org--2005/apt--main--0--patch-88 Updated Danish translation (not yet complete) * bubulle@debian.org--2005/apt--main--0--patch-89 Sync with Andre Luis Lopes and Otavio branches * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-22 * added myself to uploaders, changelog is signed with mvo@debian.org and in sync with the debian/experimental upload * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-23 * apt-cache show shows all virtual packages instead of nothing (thanks to otavio) * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-24 * changelog updated * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-25 * make pinning on component work again (we just use the section, as apt-0.6 don't use per-section Release files anymore) * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-27 * updated the changelog * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-28 * merged with my apt--fixes--0 branch * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-29 * added a missing OpProgress::Done() in depCache::Init(), removed the show-virtual-packages patch in apt-cache because matt does not like him :/ * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-30 * fix a stupid bug in the depcache::Init() code * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-31 * merged/removed conflicts with apt--main--0 * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-32 * merged apt--main and make sure that the po files come from apt--main (because they are more recent) --- apt-pkg/algorithms.cc | 11 ++++++----- apt-pkg/deb/debindexfile.cc | 4 ++-- apt-pkg/deb/deblistparser.cc | 11 +++++++++-- apt-pkg/deb/deblistparser.h | 3 ++- apt-pkg/depcache.cc | 3 +++ 5 files changed, 22 insertions(+), 10 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 98bd8dd8b..dd16b5dc8 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1330,11 +1330,12 @@ void pkgMarkPkgUsed(pkgDepCache &Cache, pkgCache::PkgIterator Pkg, 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; + if(_config->FindI("Debug::pkgAutoRemove",false) == true) + 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) diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index f26265fff..ff8bce85d 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -24,7 +24,7 @@ #include #include #include - + #include /*}}}*/ @@ -290,7 +290,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const FileFd Rel(ReleaseFile,FileFd::ReadOnly); if (_error->PendingError() == true) return false; - Parser.LoadReleaseInfo(File,Rel); + Parser.LoadReleaseInfo(File,Rel,Section); } return true; diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 96a80582d..25b533773 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -564,13 +564,20 @@ bool debListParser::Step() // --------------------------------------------------------------------- /* */ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, - FileFd &File) + FileFd &File, string component) { pkgTagFile Tags(&File, File.Size() + 256); // XXX pkgTagSection Section; if (Tags.Step(Section) == false) return false; + //mvo: I don't think we need to fill that in (it's unused since apt-0.6) + //FileI->Architecture = WriteUniqString(Arch); + + // apt-secure does no longer download individual (per-section) Release + // file. to provide Component pinning we use the section name now + FileI->Component = WriteUniqString(component); + const char *Start; const char *Stop; if (Section.Find("Suite",Start,Stop) == true) @@ -589,7 +596,7 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, if (Section.FindFlag("NotAutomatic",FileI->Flags, pkgCache::Flag::NotAutomatic) == false) _error->Warning("Bad NotAutomatic flag"); - + return !_error->PendingError(); } /*}}}*/ diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 9f305211a..3a0e0421b 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -55,7 +55,8 @@ class debListParser : public pkgCacheGenerator::ListParser virtual bool Step(); - bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File); + bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File, + string section); static const char *ParseDepends(const char *Start,const char *Stop, string &Package,string &Ver,unsigned int &Op, diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 269fe8543..54cfcb8bb 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -98,6 +98,9 @@ bool pkgDepCache::Init(OpProgress *Prog) } Update(Prog); + + if(Prog != 0) + Prog->Done(); return true; } -- cgit v1.2.3 From 120365cee294d00706928b0327ac755ab3448eca Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 28 Jun 2005 08:41:51 +0000 Subject: * cleanups, documentation updates (don't show any debug output if no Debug::pkgAutomaticRemove was set, don't remove if not APT::Get::AutomaticRemove (--automatic-remove) was set) --- apt-pkg/algorithms.cc | 7 +++++-- apt-pkg/depcache.cc | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index dd16b5dc8..5167d11eb 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1066,7 +1066,10 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) 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; + if(_config->FindI("Debug::pkgAutoRemove",false)) { + std::clog << "Resolve installed new pkg: " << I.Name() + << " (now marking it as auto)" << std::endl; + } Cache[I].Flags |= pkgCache::Flag::Auto; } } @@ -1333,7 +1336,7 @@ bool pkgMarkUsed(pkgDepCache &Cache) if(_config->FindI("Debug::pkgAutoRemove",false) == true) 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() + std::clog << "has auto-remove information: " << Pkg.Name() << " " << (int)Cache[Pkg].AutomaticRemove << std::endl; diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 54cfcb8bb..e30baa4b2 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -20,6 +20,8 @@ #include #include #include + +#include #include #include /*}}}*/ @@ -162,7 +164,8 @@ bool pkgDepCache::writeStateFile(OpProgress *prog) // check if we have new information if(PkgState[pkg->ID].Flags & pkgCache::Flag::Auto) { - std::cout << "pkg: " << pkg.Name() << " is auto-dep" << std::endl; + if(_config->FindI("Debug::pkgAutoRemove",false)) + std::clog << "pkg: " << pkg.Name() << " is auto-dep" << std::endl; PkgState[pkg->ID].AutomaticRemove = pkgCache::State::RemoveRequired; } @@ -172,7 +175,6 @@ bool pkgDepCache::writeStateFile(OpProgress *prog) << "\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; -- cgit v1.2.3 From be65f52793235fa0419af5bb6c867da28506c227 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 28 Jun 2005 09:16:51 +0000 Subject: * bumped the library version --- apt-pkg/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 5f48f0f52..8de7d945e 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -13,7 +13,7 @@ include ../buildlib/defaults.mak # methods/makefile - FIXME LIBRARY=apt-pkg LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER) -MAJOR=3.9 +MAJOR=3.10 MINOR=0 SLIBS=$(PTHREADLIB) $(INTLLIBS) APT_DOMAIN:=libapt-pkg$(MAJOR) -- cgit v1.2.3 From 0a57c0f0e4d0bc3474ce4d2101f36a997891d30d Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 29 Jun 2005 06:11:36 +0000 Subject: * use mark-and-sweep from aptitude now as GC algorithm --- apt-pkg/algorithms.cc | 245 +++++++++++++++++++++++++++++++++----------------- apt-pkg/depcache.cc | 43 ++++----- apt-pkg/depcache.h | 16 ++-- apt-pkg/pkgcache.h | 1 - 4 files changed, 190 insertions(+), 115 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 5167d11eb..bed90f5d0 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -20,7 +20,10 @@ #include #include #include +#include +#include #include + #include @@ -1248,106 +1251,186 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List) /*}}}*/ -// pkgMarkPkgUsed - Mark used packages as dirty /*{{{*/ -// --------------------------------------------------------------------- -/* Mark all reachable packages as dirty. */ -void pkgMarkPkgUsed(pkgDepCache &Cache, pkgCache::PkgIterator Pkg, - pkgCache::State::PkgRemoveState DirtLevel) +// mark a single package in Mark-and-Sweep +void pkgMarkPackage(pkgDepCache &Cache, + const pkgCache::PkgIterator &pkg, + const pkgCache::VerIterator &ver, + bool follow_recommends, + bool follow_suggests) { - // 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) + pkgDepCache::StateCache &state=Cache[pkg]; + pkgCache::VerIterator candver=state.CandidateVerIter(Cache); + pkgCache::VerIterator instver=state.InstVerIter(Cache); + +#if 0 + // If a package was garbage-collected but is now being marked, we + // should re-select it + // For cases when a pkg is set to upgrade and this trigger the + // removal of a no-longer used dependency. if the pkg is set to + // keep again later it will result in broken deps + if(state.Delete() && state.RemoveReason=pkgDepCache::Unused) { -// fprintf(stdout,"This one is not installed/virtual %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel); - return; + if(ver==candver) + mark_install(pkg, false, false, NULL); + else if(ver==pkg.CurrentVer()) + MarkKeep(pkg); + + instver=state.InstVerIter(*this); } +#endif - // 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); + // 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())) 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); + // if we are marked already we are done + if(state.Marked) 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) + + //std::cout << "Setting Marked for: " << pkg.Name() << std::endl; + state.Marked=true; + + if(!ver.end()) { -// fprintf(stdout,"We don't need %s %d %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel, Cache[Pkg].Dirty()); - return; + for(pkgCache::DepIterator d=ver.DependsList(); !d.end(); ++d) + { + if(d->Type==pkgCache::Dep::Depends || + d->Type==pkgCache::Dep::PreDepends || + (follow_recommends && + d->Type==pkgCache::Dep::Recommends) || + (follow_suggests && + d->Type==pkgCache::Dep::Suggests)) + { + // Try all versions of this package. + for(pkgCache::VerIterator V=d.TargetPkg().VersionList(); + !V.end(); ++V) + { + if(_system->VS->CheckDep(V.VerStr(),d->CompareOp, d.TargetVer())) + { + pkgMarkPackage(Cache, V.ParentPkg(), V, + follow_recommends, follow_suggests); + } + } + // Now try virtual packages + for(pkgCache::PrvIterator prv=d.TargetPkg().ProvidesList(); + !prv.end(); ++prv) + { + if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, + d.TargetVer())) + { + pkgMarkPackage(Cache, prv.OwnerPkg(), prv.OwnerVer(), + follow_recommends, follow_suggests); + } + } + } + } } +} - // 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) +bool pkgMarkUsed(pkgDepCache &Cache) +{ + bool follow_recommends; + bool follow_suggests; + + // init the states + for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p) { -// 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; + Cache[p].Marked=false; + Cache[p].Garbage=false; } - // 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()); + // init vars + follow_recommends=_config->FindB("APT::AutoRemove::RecommendsImportant",false); + follow_suggests=_config->FindB("APT::AutoRemove::SuggestsImportend", false); - switch(D->Type) + + // do the mark part + for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p) + { + if(Cache[p].InstallReason==pkgDepCache::Manual || + (p->Flags & pkgCache::Flag::Essential)) { - 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; + if(Cache[p].Keep() && !p.CurrentVer().end()) + pkgMarkPackage(Cache, p, p.CurrentVer(), + follow_recommends, follow_suggests); + else if(Cache[p].Install()) + pkgMarkPackage(Cache, p, Cache[p].InstVerIter(Cache), + follow_recommends, follow_suggests); } } -// fprintf(stdout,"We keep %s %d %d \n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel); -} - /*}}}*/ -bool pkgMarkUsed(pkgDepCache &Cache) -{ - // debug only - if(_config->FindI("Debug::pkgAutoRemove",false) == true) - for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg) - if(!Cache[Pkg].Dirty() && Cache[Pkg].AutomaticRemove > 0) - std::clog << "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); - + // do the sweep + for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p) + { + pkgDepCache::StateCache &state=Cache[p]; + + if(!state.Marked) + { + // mark installed but not yet marked stuff as garbage + if(p->CurrentVer != 0) { + state.Garbage=true; + std::cout << "Garbage: " << p.Name() << std::endl; + } + +#if 0 // mvo: the below bits still needs to be ported + + // Be sure not to re-delete already deleted packages. + if(delete_unused && (!p.CurrentVer().end() || state.Install()) && + !state.Delete()) + { + bool do_delete=true; + + // If the package is being upgraded, check if we're + // losing a versioned dep. If the dependency matches + // the previous version and not the new version, keep + // the package back instead of removing it. + if(!p.CurrentVer().end() && state.Install()) + { + const char *vs=p.CurrentVer().VerStr(); + + // Check direct revdeps only. THIS ASSUMES NO + // VERSIONED PROVIDES, but Debian probably won't + // have them for ages if ever. + for(pkgCache::DepIterator revdep=p.RevDependsList(); + !revdep.end(); ++revdep) + { + pkgCache::PkgIterator depender=revdep.ParentPkg(); + // Find which version of the depending package + // will be installed. + pkgCache::VerIterator instver=(*this)[depender].InstVerIter(*this); + + // Only pay attention to strong positive + // dependencies whose parents will be installed. + if(revdep.ParentVer()==instver && + (revdep->Type==pkgCache::Dep::Depends || + revdep->Type==pkgCache::Dep::PreDepends || + (revdep->Type==pkgCache::Dep::Recommends && + follow_recommends))) + { + // If the previous version matched, cancel the + // deletion. (note that I assume that the new + // version does NOT match; otherwise it would + // not be unused!) + if(_system->VS->CheckDep(vs, + revdep->CompareOp, + revdep.TargetVer())) + { + mark_keep(p, false, false, undo); + do_delete=false; + break; + } + } + } + } + + if(do_delete) + mark_delete(p, false, true, undo); + } +#endif + } + } return true; } diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index e30baa4b2..52b43d83d 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -78,9 +78,7 @@ 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; + State.InstallReason = Manual; // Figure out the install version State.CandidateVer = GetCandidateVer(I); @@ -116,7 +114,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) state_file.Open(state, FileFd::ReadOnly); int file_size = state_file.Size(); Prog->OverallProgress(0, file_size, 1, - _("Reading extended state information")); + _("Reading state information")); pkgTagFile tagfile(&state_file); pkgTagSection section; @@ -127,16 +125,17 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) // 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; + short reason = section.FindI("Install-Reason",pkgDepCache::Manual); + PkgState[pkg->ID].InstallReason = (ChangedReason)reason; + if(_config->FindB("Debug::pkgAutoRemove",false)) + std::cout << "Install-Reason for: " << pkgname + << " is " << reason << std::endl; amt+=section.size(); Prog->OverallProgress(amt, file_size, 1, - _("Reading extended state information")); + _("Reading state information")); } Prog->OverallProgress(file_size, file_size, 1, - _("Reading extended state information")); + _("Reading state information")); } } @@ -145,9 +144,6 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) bool pkgDepCache::writeStateFile(OpProgress *prog) { - // FIXME: this function needs to be called inside the commit() - // of the package manager. so after - FileFd StateFile; string state = _config->FindDir("Dir::State") + "pkgstates"; @@ -160,20 +156,20 @@ bool pkgDepCache::writeStateFile(OpProgress *prog) // clear out no longer installed pkg if(PkgState[pkg->ID].Delete() || pkg.CurrentVer() == NULL) - PkgState[pkg->ID].AutomaticRemove = pkgCache::State::RemoveUnknown; + PkgState[pkg->ID].InstallReason = Manual; // check if we have new information if(PkgState[pkg->ID].Flags & pkgCache::Flag::Auto) { if(_config->FindI("Debug::pkgAutoRemove",false)) std::clog << "pkg: " << pkg.Name() << " is auto-dep" << std::endl; - PkgState[pkg->ID].AutomaticRemove = pkgCache::State::RemoveRequired; + PkgState[pkg->ID].InstallReason = Libapt; } - if(PkgState[pkg->ID].AutomaticRemove != pkgCache::State::RemoveUnknown) { + if(PkgState[pkg->ID].InstallReason != Manual) { ostr.str(string("")); - ostr << "Package: " << pkg.Name() - << "\nRemove-Reason: " - << (int)(PkgState[pkg->ID].AutomaticRemove) << "\n\n"; + ostr << "Package: " << pkg.Name() + << "\nInstall-Reason: " + << (int)(PkgState[pkg->ID].InstallReason) << "\n\n"; StateFile.Write(ostr.str().c_str(), ostr.str().size()); } } @@ -841,15 +837,6 @@ 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 e02ed72f0..c91e09ab3 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -63,6 +63,10 @@ class pkgDepCache : protected pkgCache::Namespace enum VersionTypes {NowVersion, InstallVersion, CandidateVersion}; enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2}; + + // Flags for the GC + enum ChangedReason {Manual, UserAuto, Libapt, FromResolver, PkgIsUnused}; + struct StateCache { // Epoch stripped text versions of the two version fields @@ -79,9 +83,13 @@ 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; + // mark and sweep flags + ChangedReason InstallReason; +#if 0 + ChangedReason RemoveReason; +#endif + bool Marked; + bool Garbage; // Various tree indicators signed char Status; // -1,0,1,2 @@ -103,7 +111,6 @@ 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) @@ -194,7 +201,6 @@ 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); diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 083f20ac2..b07951dfb 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -75,7 +75,6 @@ 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 -- cgit v1.2.3 From bc80031f74e4acfca5b8ca7188b12ee885a713bd Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 29 Jun 2005 11:43:32 +0000 Subject: * fix a bug when readStateFile is called with no OpProgress object --- apt-pkg/depcache.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 05512e179..366687382 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -112,8 +112,9 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) if(FileExists(state)) { state_file.Open(state, FileFd::ReadOnly); int file_size = state_file.Size(); - Prog->OverallProgress(0, file_size, 1, - _("Reading state information")); + if(Prog != NULL) + Prog->OverallProgress(0, file_size, 1, + _("Reading state information")); pkgTagFile tagfile(&state_file); pkgTagSection section; @@ -131,11 +132,13 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) std::cout << "Install-Reason for: " << pkgname << " is " << reason << std::endl; amt+=section.size(); - Prog->OverallProgress(amt, file_size, 1, - _("Reading state information")); + if(Prog != NULL) + Prog->OverallProgress(amt, file_size, 1, + _("Reading state information")); } - Prog->OverallProgress(file_size, file_size, 1, - _("Reading state information")); + if(Prog != NULL) + Prog->OverallProgress(file_size, file_size, 1, + _("Reading state information")); } } -- cgit v1.2.3 From 2ac6ce927cda2847baf8e71a74e595e6b82c6d98 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 30 Jun 2005 08:02:37 +0000 Subject: * added a callback to pkgMarkUsed() so that frontend can extend the root-set of the auto-remover easily --- apt-pkg/algorithms.cc | 10 ++++++---- apt-pkg/algorithms.h | 18 +++++++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index c679e76f6..11f5b5671 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1329,7 +1329,7 @@ void pkgMarkPackage(pkgDepCache &Cache, } -bool pkgMarkUsed(pkgDepCache &Cache) +bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc func) { bool follow_recommends; bool follow_suggests; @@ -1343,14 +1343,16 @@ bool pkgMarkUsed(pkgDepCache &Cache) // init vars follow_recommends=_config->FindB("APT::AutoRemove::RecommendsImportant",false); - follow_suggests=_config->FindB("APT::AutoRemove::SuggestsImportend", false); + follow_suggests=_config->FindB("APT::AutoRemove::SuggestsImportant", false); // do the mark part for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p) { - if(!(Cache[p].Flags & pkgCache::Flag::Auto) || - (p->Flags & pkgCache::Flag::Essential)) + if( (func != NULL ? (*func)(p) : false) || + !(Cache[p].Flags & pkgCache::Flag::Auto) || + (p->Flags & pkgCache::Flag::Essential)) + { if(Cache[p].Keep() && !p.CurrentVer().end()) pkgMarkPackage(Cache, p, p.CurrentVer(), diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 210127ab9..82d7b7aad 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -133,8 +133,20 @@ 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); + +// callback function that can be used by the client to bring in +// certain own packages into the root set +typedef bool (*InRootSetFunc)(pkgCache::PkgIterator); + +// Mark all reachable packages with pkgDepCache::StateCache.Marked +// the root-set are all essential packages+everything that was installed +// manually +// +// If InRootSetFunc is set, it will be called for each PkgIterator. This +// is usefull for clients that have there own idea about the root-set +// +// Everything that is not reach can be removed +bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc f=NULL); + #endif -- cgit v1.2.3 From 22dcc318d978813b3c4d1ae1a1f41933d0e1d69b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 30 Jun 2005 08:53:45 +0000 Subject: * added APT::NeverAutoRemove (a list of regexp for package names that should never be automatically removed) --- apt-pkg/algorithms.cc | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 11f5b5671..8e55649ca 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -26,7 +26,8 @@ #include - +#include +#include #include /*}}}*/ using namespace std; @@ -1329,6 +1330,19 @@ void pkgMarkPackage(pkgDepCache &Cache, } +// Helper for APT::NeverAutoRemove, always include the packages matching +// this regexp into the root-set +inline bool +pkgMarkAlwaysInclude(pkgCache::PkgIterator p, vector alwaysMark) +{ + for(unsigned int i=0;iFindB("APT::AutoRemove::SuggestsImportant", false); + // init the "NeverAutoRemove" variable + vector neverAutoRemoveRegexp; + Configuration::Item const *Opts; + Opts = _config->Tree("APT::NeverAutoRemove"); + if (Opts != 0 && Opts->Child != 0) + { + Opts = Opts->Child; + for (; Opts != 0; Opts = Opts->Next) + { + if (Opts->Value.empty() == true) + continue; + + regex_t *p = new regex_t; + if(regcomp(p,Opts->Value.c_str(), + REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0) + { + regfree(p); + for(unsigned int i=0;iError("Regex compilation error for APT::NeverAutoRemove"); + } + neverAutoRemoveRegexp.push_back(p); + } + } + + // do the mark part for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p) { if( (func != NULL ? (*func)(p) : false) || + pkgMarkAlwaysInclude(p, neverAutoRemoveRegexp) || !(Cache[p].Flags & pkgCache::Flag::Auto) || (p->Flags & pkgCache::Flag::Essential)) @@ -1434,5 +1475,11 @@ bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc func) #endif } } + + // cleanup + for(unsigned int i=0;i Date: Thu, 30 Jun 2005 10:47:22 +0000 Subject: * some WS fixes --- apt-pkg/algorithms.cc | 6 ++++-- apt-pkg/algorithms.h | 9 +++++---- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 8e55649ca..8626d33dc 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1386,18 +1386,20 @@ bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc func) } - // do the mark part + // do the mark part, this is the core bit of the algorithm for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p) { if( (func != NULL ? (*func)(p) : false) || - pkgMarkAlwaysInclude(p, neverAutoRemoveRegexp) || + pkgMarkAlwaysInclude(p, neverAutoRemoveRegexp) || !(Cache[p].Flags & pkgCache::Flag::Auto) || (p->Flags & pkgCache::Flag::Essential)) { + // the package is installed (and set to keep) if(Cache[p].Keep() && !p.CurrentVer().end()) pkgMarkPackage(Cache, p, p.CurrentVer(), follow_recommends, follow_suggests); + // the package is to be installed else if(Cache[p].Install()) pkgMarkPackage(Cache, p, Cache[p].InstVerIter(Cache), follow_recommends, follow_suggests); diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 82d7b7aad..02b40e15f 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -135,12 +135,13 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List); // callback function that can be used by the client to bring in -// certain own packages into the root set +// certain own packages into the root set (if the client returns +// True the package will be considered as part of the root set) typedef bool (*InRootSetFunc)(pkgCache::PkgIterator); -// Mark all reachable packages with pkgDepCache::StateCache.Marked -// the root-set are all essential packages+everything that was installed -// manually +// Mark all reachable packages with "pkgDepCache::StateCache.Marked=1" +// the root-set are all essential packages+everything that was not +// installed automatically // // If InRootSetFunc is set, it will be called for each PkgIterator. This // is usefull for clients that have there own idea about the root-set -- cgit v1.2.3 From fc5aece9d8600b68cf8d654b379b6d840f2a5524 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 30 Jun 2005 10:50:08 +0000 Subject: * Install-Reason -> Auto-Installed in pkgstates --- apt-pkg/depcache.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 366687382..81c79d812 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -125,12 +125,11 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) // Silently ignore unknown packages and packages with no actual // version. if(!pkg.end() && !pkg.VersionList().end()) { - short reason = section.FindI("Install-Reason", 0); + short reason = section.FindI("Auto-Installed", 0); if(reason > 0) PkgState[pkg->ID].Flags |= pkgCache::Flag::Auto; if(_config->FindB("Debug::pkgAutoRemove",false)) - std::cout << "Install-Reason for: " << pkgname - << " is " << reason << std::endl; + std::cout << "Auto-Installed : " << pkgname << std::endl; amt+=section.size(); if(Prog != NULL) Prog->OverallProgress(amt, file_size, 1, @@ -165,7 +164,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog) std::clog << "AutoInstal: " << pkg.Name() << std::endl; ostr.str(string("")); ostr << "Package: " << pkg.Name() - << "\nInstall-Reason: 1\n\n"; + << "\nAuto-Installed: 1\n\n"; StateFile.Write(ostr.str().c_str(), ostr.str().size()); } } -- cgit v1.2.3 From f8ac1720a94468d1384e88a57729e6d9801b56fd Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 30 Jun 2005 13:34:32 +0000 Subject: * slighly more debug output, renamed "--automatic-remove" to "--auto-remove" --- apt-pkg/algorithms.cc | 16 ++++++++++------ apt-pkg/depcache.cc | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 8626d33dc..3978e7561 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1353,6 +1353,11 @@ bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc func) { Cache[p].Marked=false; Cache[p].Garbage=false; + + // debug output + if(_config->FindB("Debug::pkgAutoRemove",false) + && Cache[p].Flags & pkgCache::Flag::Auto) + std::clog << "AutoDep: " << p.Name() << std::endl; } // init vars @@ -1412,14 +1417,13 @@ bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc func) { pkgDepCache::StateCache &state=Cache[p]; - if(!state.Marked) + // if it is not marked and it is installed, it's garbage + if(!state.Marked && !p.CurrentVer().end()) { - // mark installed but not yet marked stuff as garbage - if(p->CurrentVer != 0) { - state.Garbage=true; + state.Garbage=true; + if(_config->FindB("Debug::pkgAutoRemove",false)) std::cout << "Garbage: " << p.Name() << std::endl; - } - + #if 0 // mvo: the below bits still needs to be ported // Be sure not to re-delete already deleted packages. diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 81c79d812..9adc4e390 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -127,7 +127,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) if(!pkg.end() && !pkg.VersionList().end()) { short reason = section.FindI("Auto-Installed", 0); if(reason > 0) - PkgState[pkg->ID].Flags |= pkgCache::Flag::Auto; + PkgState[pkg->ID].Flags |= Flag::Auto; if(_config->FindB("Debug::pkgAutoRemove",false)) std::cout << "Auto-Installed : " << pkgname << std::endl; amt+=section.size(); @@ -159,7 +159,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog) std::ostringstream ostr; for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end();pkg++) { - if(PkgState[pkg->ID].Flags & pkgCache::Flag::Auto) { + if(PkgState[pkg->ID].Flags & Flag::Auto) { if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "AutoInstal: " << pkg.Name() << std::endl; ostr.str(string("")); -- cgit v1.2.3 From 45f7495cf1b62d402616caffacd9f343ca71c44d Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 4 Jul 2005 16:38:42 +0000 Subject: * invert the auto-mark flag only for new installs (in MarkInstall()), keep it as it is for upgrades --- apt-pkg/depcache.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 9adc4e390..4c52c6c71 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -708,7 +708,9 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, P.Mode = ModeInstall; P.InstallVer = P.CandidateVer; - P.Flags &= ~Flag::Auto; + // invert the auto-flag only for new installs, not for upgrades + if(P.Status == 0) + P.Flags &= ~Flag::Auto; if (P.CandidateVer == (Version *)Pkg.CurrentVer()) P.Mode = ModeKeep; -- cgit v1.2.3 From 2a7e07c7578048abd9f7bfd4ce0ca5c3696b9f3a Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 18 Aug 2005 10:38:58 +0000 Subject: * merged from main Patches applied: * apt@packages.debian.org/apt--main--0--patch-100 Use debian.org address in mainline * apt@packages.debian.org/apt--main--0--patch-101 Update pot file * apt@packages.debian.org/apt--main--0--patch-102 Open 0.6.40 * apt@packages.debian.org/apt--main--0--patch-103 Patch from Jordi Mallach to mark some additional strings for translation * apt@packages.debian.org/apt--main--0--patch-104 Updated Catalan translation from Jordi Mallach * apt@packages.debian.org/apt--main--0--patch-105 Merge from bubulle@debian.org--2005/apt--main--0 * apt@packages.debian.org/apt--main--0--patch-106 Restore lost changelog entries * apt@packages.debian.org/apt--main--0--patch-107 Merge michael.vogt@ubuntu.com--2005/apt--progress-reporting--0 * apt@packages.debian.org/apt--main--0--patch-108 Merge michael.vogt@ubuntu.com--2005/apt--progress-reporting--0 * apt@packages.debian.org/apt--main--0--patch-109 Merge michael.vogt@ubuntu.com--2005/apt--progress-reporting--0 * apt@packages.debian.org/apt--main--0--patch-110 Merge michael.vogt@ubuntu.com--2005/apt--progress-reporting--0 * bubulle@debian.org--2005/apt--main--0--patch-90 Merge with Matt * bubulle@debian.org--2005/apt--main--0--patch-91 Updated Slovak translation * bubulle@debian.org--2005/apt--main--0--patch-92 Add apt-key French man page * bubulle@debian.org--2005/apt--main--0--patch-93 Update Greek translations * bubulle@debian.org--2005/apt--main--0--patch-94 Merge with Matt * bubulle@debian.org--2005/apt--main--0--patch-95 Sync PO files with the POT file/French translation update * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-85 * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-1 * inital proof of concept code, understands what dpkg tells it already * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-2 * progress reporting works now * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-3 * added "APT::Status-Fd" variable * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-4 * do i18n now too * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-5 * define N_(x) if it is not defined already * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-6 * PackageManager::DoInstall(int status_fd) added (does not break the ABI) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-7 * merged with apt--fixes--0 to make it build again * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-8 * added support for "error" and "conffile-prompt" messages from dpkg * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-9 merge with main * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-10 * use sizeof() for all snprintf() uses; fix a potential line break problem in the status reading code; changed the N_() to _() calls * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-11 * added APT::KeepFDs configuration list for file descriptors that apt should leave open (needed for various frontends like debconf, synaptic) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-12 * fixed a API breakage * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-13 * doc added, should be releasable now * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-14 * merged with apt--main--0 * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-15 * more source comments, added Debug::DpkgPM debug code to inspect the dpkg<->apt communication, broke the abi (ok with matt) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-16 * the progress reporting has it's own "Debug::pkgDPkgProgressReporting" debug variable now * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-17 * merged PackageOps and TranslatedPackageOps into a single Map with the new DpkgState struct * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-18 * clear the APT::Keep-Fds configuration when it's no longer needed * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-19 * rewrote the reading from dpkg so that it never blocks * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-20 * merged the two status arrays into one * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-21 * added support for download progress reporting too (for Kamion and base-config) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-22 * ABI break; added Configuration::Clear(string List, {int,string} value) added (to remove a single Value from a list); test/conf_clear.cc added * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-23 * remvoed a debug string * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-24 * soname changed, fixed a bug in the parsing code when dpkg send the same state more than once (at the end) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-25 * merged with apt@packages.debian.org/apt--main--0, added changelog entry for the 0.6.40.1 upload * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-26 * fix a bug when out-of-order states are send from dpkg * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-27 * changelog update * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-28 * a real changelog entry now * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-29 * changelog finalized * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-30 * propper (and sane) support for pmerror and pmconffile added --- apt-pkg/acquire.cc | 21 ++++ apt-pkg/contrib/configuration.cc | 45 +++++++- apt-pkg/contrib/configuration.h | 7 +- apt-pkg/contrib/fileutl.cc | 24 +++- apt-pkg/contrib/fileutl.h | 2 +- apt-pkg/deb/dpkgpm.cc | 242 ++++++++++++++++++++++++++++++++++----- apt-pkg/deb/dpkgpm.h | 9 +- apt-pkg/init.h | 2 +- apt-pkg/makefile | 2 +- apt-pkg/packagemanager.cc | 12 ++ apt-pkg/packagemanager.h | 7 +- 11 files changed, 331 insertions(+), 42 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 70dce4f54..62209e65b 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -803,6 +804,26 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) Time = NewTime; } + int fd = _config->FindI("APT::Status-Fd",-1); + if(fd > 0) + { + ostringstream status; + + char msg[200]; + long i = CurrentItems < TotalItems ? CurrentItems + 1 : CurrentItems; + unsigned long ETA = + (unsigned long)((TotalBytes - CurrentBytes) / CurrentCPS); + + snprintf(msg,sizeof(msg), _("Downloading file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str()); + + // build the status str + status << "dlstatus:" << i + << ":" << (CurrentBytes/float(TotalBytes)*100.0) + << ":" << msg + << endl; + write(fd, status.str().c_str(), status.str().size()); + } + return true; } /*}}}*/ diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 69f8d1dca..09e454be9 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -325,6 +325,47 @@ void Configuration::Set(const char *Name,int Value) char S[300]; snprintf(S,sizeof(S),"%i",Value); Itm->Value = S; +} + /*}}}*/ +// Configuration::Clear - Clear an single value from a list /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void Configuration::Clear(string Name, int Value) +{ + char S[300]; + snprintf(S,sizeof(S),"%i",Value); + Clear(Name, S); +} + /*}}}*/ +// Configuration::Clear - Clear an single value from a list /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void Configuration::Clear(string Name, string Value) +{ + Item *Top = Lookup(Name.c_str(),false); + if (Top == 0 || Top->Child == 0) + return; + + Item *Tmp, *Prev, *I; + Prev = I = Top->Child; + + while(I != NULL) + { + if(I->Value == Value) + { + Tmp = I; + // was first element, point parent to new first element + if(Top->Child == Tmp) + Top->Child = I->Next; + I = I->Next; + Prev->Next = I; + delete Tmp; + } else { + Prev = I; + I = I->Next; + } + } + } /*}}}*/ // Configuration::Clear - Clear an entire tree /*{{{*/ @@ -333,9 +374,9 @@ void Configuration::Set(const char *Name,int Value) void Configuration::Clear(string Name) { Item *Top = Lookup(Name.c_str(),false); - if (Top == 0) + if (Top == 0) return; - + Top->Value = string(); Item *Stop = Top; Top = Top->Child; diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index 0ed8f59d3..789bc82cf 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -87,8 +87,13 @@ class Configuration bool Exists(const char *Name) const; bool ExistsAny(const char *Name) const; + // clear a whole tree void Clear(string Name); - + + // remove a certain value from a list (e.g. the list of "APT::Keep-Fds") + void Clear(string List, string Value); + void Clear(string List, int Value); + inline const Item *Tree(const char *Name) const {return Lookup(Name);}; inline void Dump() { Dump(std::clog); }; diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 0ce0c9b9d..9fd71728e 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -32,6 +33,7 @@ #include #include #include +#include /*}}}*/ using namespace std; @@ -306,7 +308,7 @@ bool WaitFd(int Fd,bool write,unsigned long timeout) /* This is used if you want to cleanse the environment for the forked child, it fixes up the important signals and nukes all of the fds, otherwise acts like normal fork. */ -pid_t ExecFork(int dontCloseThisFd) +pid_t ExecFork() { // Fork off the process pid_t Process = fork(); @@ -326,11 +328,27 @@ pid_t ExecFork(int dontCloseThisFd) signal(SIGWINCH,SIG_DFL); signal(SIGCONT,SIG_DFL); signal(SIGTSTP,SIG_DFL); - + + set KeepFDs; + Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds"); + if (Opts != 0 && Opts->Child != 0) + { + Opts = Opts->Child; + for (; Opts != 0; Opts = Opts->Next) + { + if (Opts->Value.empty() == true) + continue; + int fd = atoi(Opts->Value.c_str()); + KeepFDs.insert(fd); + } + } + // Close all of our FDs - just in case for (int K = 3; K != 40; K++) - if(K != dontCloseThisFd) + { + if(KeepFDs.find(K) == KeepFDs.end()) fcntl(K,F_SETFD,FD_CLOEXEC); + } } return Process; diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 4716e261e..041aa3309 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -87,7 +87,7 @@ string SafeGetCWD(); void SetCloseExec(int Fd,bool Close); void SetNonBlock(int Fd,bool Block); bool WaitFd(int Fd,bool write = false,unsigned long timeout = 0); -pid_t ExecFork(int dontCloseThisFd=-1); +pid_t ExecFork(); bool ExecWait(pid_t Pid,const char *Name,bool Reap = false); // File string manipulators diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 61c48dcbb..fe8fbca74 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -25,7 +25,11 @@ #include #include #include -#include +#include +#include + +#include +#include /*}}}*/ using namespace std; @@ -325,8 +329,14 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) /*}}}*/ // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- -/* This globs the operations and calls dpkg */ -bool pkgDPkgPM::Go(int status_fd) +/* This globs the operations and calls dpkg + * + * If it is called with "OutStatusFd" set to a valid file descriptor + * apt will report the install progress over this fd. It maps the + * dpkg states a package goes through to human readable (and i10n-able) + * names and calculates a percentage for each step. +*/ +bool pkgDPkgPM::Go(int OutStatusFd) { unsigned int MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024); unsigned int MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024); @@ -336,7 +346,66 @@ bool pkgDPkgPM::Go(int status_fd) if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false) return false; + + // prepare the progress reporting + int Done = 0; + int Total = 0; + // map the dpkg states to the operations that are performed + // (this is sorted in the same way as Item::Ops) + static const struct DpkgState DpkgStatesOpMap[][5] = { + // Install operation + { + {"half-installed", _("Preparing %s")}, + {"unpacked", _("Unpacking %s") }, + {NULL, NULL} + }, + // Configure operation + { + {"unpacked",_("Preparing to configure %s") }, + {"half-configured", _("Configuring %s") }, + { "installed", _("Installed %s")}, + {NULL, NULL} + }, + // Remove operation + { + {"half-configured", _("Preparing for removal of %s")}, + {"half-installed", _("Removing %s")}, + {"config-files", _("Removed %s")}, + {NULL, NULL} + }, + // Purge operation + { + {"config-files", _("Preparing for remove with config %s")}, + {"not-installed", _("Removed with config %s")}, + {NULL, NULL} + }, + }; + // the dpkg states that the pkg will run through, the string is + // the package, the vector contains the dpkg states that the package + // will go through + map > PackageOps; + // the dpkg states that are already done; the string is the package + // the int is the state that is already done (e.g. a package that is + // going to be install is already in state "half-installed") + map PackageOpsDone; + + // init the PackageOps map, go over the list of packages that + // that will be [installed|configured|removed|purged] and add + // them to the PackageOps map (the dpkg states it goes through) + // and the PackageOpsTranslations (human readable strings) + for (vector::iterator I = List.begin(); I != List.end();I++) + { + string name = (*I).Pkg.Name(); + PackageOpsDone[name] = 0; + for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; i++) + { + PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]); + Total++; + } + } + + // this loop is runs once per operation for (vector::iterator I = List.begin(); I != List.end();) { vector::iterator J = I; @@ -367,16 +436,15 @@ bool pkgDPkgPM::Go(int status_fd) } } - // if we got a status_fd argument, we pass it to apt char status_fd_buf[20]; - if(status_fd > 0) - { - Args[n++] = "--status-fd"; - Size += strlen(Args[n-1]); - snprintf(status_fd_buf,20,"%i",status_fd); - Args[n++] = status_fd_buf; - Size += strlen(Args[n-1]); - } + int fd[2]; + pipe(fd); + + Args[n++] = "--status-fd"; + Size += strlen(Args[n-1]); + snprintf(status_fd_buf,sizeof(status_fd_buf),"%i", fd[1]); + Args[n++] = status_fd_buf; + Size += strlen(Args[n-1]); switch (I->Op) { @@ -449,17 +517,17 @@ bool pkgDPkgPM::Go(int status_fd) it doesn't die but we do! So we must also ignore it */ sighandler_t old_SIGQUIT = signal(SIGQUIT,SIG_IGN); sighandler_t old_SIGINT = signal(SIGINT,SIG_IGN); - - // Fork dpkg + + // Fork dpkg pid_t Child; - if(status_fd > 0) - Child = ExecFork(status_fd); - else - Child = ExecFork(); + _config->Set("APT::Keep-Fds::",fd[1]); + Child = ExecFork(); // This is the child if (Child == 0) { + close(fd[0]); // close the read end of the pipe + if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0) _exit(100); @@ -487,19 +555,141 @@ bool pkgDPkgPM::Go(int status_fd) _exit(100); } + // clear the Keep-Fd again + _config->Clear("APT::Keep-Fds",fd[1]); + // Wait for dpkg int Status = 0; - while (waitpid(Child,&Status,0) != Child) - { - if (errno == EINTR) + + // we read from dpkg here + int _dpkgin = fd[0]; + fcntl(_dpkgin, F_SETFL, O_NONBLOCK); + close(fd[1]); // close the write end of the pipe + + // the read buffers for the communication with dpkg + char line[1024] = {0,}; + char buf[2] = {0,0}; + + // the result of the waitpid call + int res; + + while ((res=waitpid(Child,&Status, WNOHANG)) != Child) { + if(res < 0) { + // FIXME: move this to a function or something, looks ugly here + // error handling, waitpid returned -1 + if (errno == EINTR) + continue; + RunScripts("DPkg::Post-Invoke"); + + // Restore sig int/quit + signal(SIGQUIT,old_SIGQUIT); + signal(SIGINT,old_SIGINT); + return _error->Errno("waitpid","Couldn't wait for subprocess"); + } + + // read a single char, make sure that the read can't block + // (otherwise we may leave zombies) + int len = read(_dpkgin, buf, 1); + + // nothing to read, wait a bit for more + if(len <= 0) + { + usleep(1000); continue; - RunScripts("DPkg::Post-Invoke"); + } + + // sanity check (should never happen) + if(strlen(line) >= sizeof(line)-10) + { + _error->Error("got a overlong line from dpkg: '%s'",line); + line[0]=0; + } + // append to line, check if we got a complete line + strcat(line, buf); + if(buf[0] != '\n') + continue; + + if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true) + std::clog << "got from dpkg '" << line << "'" << std::endl; + + // the status we output + ostringstream status; + + /* dpkg sends strings like this: + 'status: : ' + errors look like this: + 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data + and conffile-prompt like this + 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited + + */ + char* list[4]; + TokSplitString(':', line, list, 5); + char *pkg = list[1]; + char *action = _strstrip(list[2]); + + if(strncmp(action,"error",strlen("error")) == 0) + { + status << "pmerror:" << list[1] + << ":" << (Done/float(Total)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + write(OutStatusFd, status.str().c_str(), status.str().size()); + line[0]=0; + if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true) + std::clog << "send: '" << status.str() << "'" << endl; + continue; + } + if(strncmp(action,"conffile",strlen("conffile")) == 0) + { + status << "pmconffile:" << list[1] + << ":" << (Done/float(Total)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + write(OutStatusFd, status.str().c_str(), status.str().size()); + line[0]=0; + if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true) + std::clog << "send: '" << status.str() << "'" << endl; + continue; + } + + vector &states = PackageOps[pkg]; + const char *next_action = NULL; + if(PackageOpsDone[pkg] < states.size()) + next_action = states[PackageOpsDone[pkg]].state; + // check if the package moved to the next dpkg state + if(next_action && (strcmp(action, next_action) == 0)) + { + // only read the translation if there is actually a next + // action + const char *translation = states[PackageOpsDone[pkg]].str; + char s[200]; + snprintf(s, sizeof(s), translation, pkg); + + // we moved from one dpkg state to a new one, report that + PackageOpsDone[pkg]++; + Done++; + // build the status str + status << "pmstatus:" << pkg + << ":" << (Done/float(Total)*100.0) + << ":" << s + << endl; + if(OutStatusFd > 0) + write(OutStatusFd, status.str().c_str(), status.str().size()); + if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true) + std::clog << "send: '" << status.str() << "'" << endl; + + } + if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true) + std::clog << "(parsed from dpkg) pkg: " << pkg + << " action: " << action << endl; - // Restore sig int/quit - signal(SIGQUIT,old_SIGQUIT); - signal(SIGINT,old_SIGINT); - return _error->Errno("waitpid","Couldn't wait for subprocess"); + // reset the line buffer + line[0]=0; } + close(_dpkgin); // Restore sig int/quit signal(SIGQUIT,old_SIGQUIT); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 8bfdff5eb..0b181dc43 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -23,6 +23,13 @@ using std::vector; class pkgDPkgPM : public pkgPackageManager { protected: + + // used for progress reporting + struct DpkgState + { + const char *state; // the dpkg state (e.g. "unpack") + const char *str; // the human readable translation of the state + }; struct Item { @@ -45,7 +52,7 @@ class pkgDPkgPM : public pkgPackageManager virtual bool Install(PkgIterator Pkg,string File); virtual bool Configure(PkgIterator Pkg); virtual bool Remove(PkgIterator Pkg,bool Purge = false); - virtual bool Go(int status_fd=-1); + virtual bool Go(int StatusFd=-1); virtual void Reset(); public: diff --git a/apt-pkg/init.h b/apt-pkg/init.h index 74ac3a7ca..8255b406a 100644 --- a/apt-pkg/init.h +++ b/apt-pkg/init.h @@ -18,7 +18,7 @@ // See the makefile #define APT_PKG_MAJOR 3 -#define APT_PKG_MINOR 5 +#define APT_PKG_MINOR 11 #define APT_PKG_RELEASE 0 extern const char *pkgVersion; diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 8de7d945e..0e6aecc65 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -13,7 +13,7 @@ include ../buildlib/defaults.mak # methods/makefile - FIXME LIBRARY=apt-pkg LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER) -MAJOR=3.10 +MAJOR=3.11 MINOR=0 SLIBS=$(PTHREADLIB) $(INTLLIBS) APT_DOMAIN:=libapt-pkg$(MAJOR) diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 71a0dd034..87a21004f 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -627,3 +627,15 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() return Completed; } /*}}}*/ +// PM::DoInstall - Does the installation /*{{{*/ +// --------------------------------------------------------------------- +/* This uses the filenames in FileNames and the information in the + DepCache to perform the installation of packages.*/ +pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) +{ + if(DoInstallPreFork() == Failed) + return Failed; + + return DoInstallPostFork(); +} + /*}}}*/ diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index f95b2ab56..48f53576c 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -83,12 +83,7 @@ class pkgPackageManager : protected pkgCache::Namespace pkgRecords *Recs); // Do the installation - OrderResult DoInstall() { - if(DoInstallPreFork() == Failed) - return Failed; - - return DoInstallPostFork(); - } + OrderResult DoInstall(int statusFd=-1); // stuff that needs to be done before the fork() of a library that // uses apt -- cgit v1.2.3 From 331956f9b59c8c30cce977e8729991559d46005c Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 19 Aug 2005 08:50:57 +0000 Subject: * added a InRootSetFunc class for clients to add own packages to the mark'n'sweep root set --- apt-pkg/algorithms.cc | 10 ++++++++-- apt-pkg/algorithms.h | 14 ++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 3978e7561..82ea19c93 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1342,8 +1342,14 @@ pkgMarkAlwaysInclude(pkgCache::PkgIterator p, vector alwaysMark) return false; } +bool pkgMarkUsed(pkgDepCache &Cache) +{ + InRootSetFunc f; + return pkgMarkUsed(Cache, f); +} + // the main mark algorithm -bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc func) +bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc &userFunc) { bool follow_recommends; bool follow_suggests; @@ -1394,7 +1400,7 @@ bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc func) // do the mark part, this is the core bit of the algorithm for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p) { - if( (func != NULL ? (*func)(p) : false) || + if( userFunc.InRootSet(p) || pkgMarkAlwaysInclude(p, neverAutoRemoveRegexp) || !(Cache[p].Flags & pkgCache::Flag::Auto) || (p->Flags & pkgCache::Flag::Essential)) diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 02b40e15f..e539a410e 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -134,10 +134,16 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache); void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List); -// callback function that can be used by the client to bring in +// class that can be subclassed by the client to bring in // certain own packages into the root set (if the client returns // True the package will be considered as part of the root set) -typedef bool (*InRootSetFunc)(pkgCache::PkgIterator); +class InRootSetFunc +{ + public: + virtual bool InRootSet(const pkgCache::PkgIterator &pkg) {return false;}; + virtual ~InRootSetFunc() {}; +}; + // Mark all reachable packages with "pkgDepCache::StateCache.Marked=1" // the root-set are all essential packages+everything that was not @@ -147,7 +153,7 @@ typedef bool (*InRootSetFunc)(pkgCache::PkgIterator); // is usefull for clients that have there own idea about the root-set // // Everything that is not reach can be removed -bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc f=NULL); - +bool pkgMarkUsed(pkgDepCache &Cache); +bool pkgMarkUsed(pkgDepCache &Cache, InRootSetFunc &f); #endif -- cgit v1.2.3 From 74a05226eff7041cd8f2380fe599862d350a1ac3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 9 Nov 2005 11:39:27 +0000 Subject: * merged daniel burrows fixes for the auto-mark code Patches applied: * dburrows@debian.org--2005/apt--auto-mark--0--base-0 tag of michael.vogt@ubuntu.com--2005/apt--auto-mark--0--patch-22 * dburrows@debian.org--2005/apt--auto-mark--0--patch-1 doxygenize the new automark stuff * dburrows@debian.org--2005/apt--auto-mark--0--patch-2 Automatically update package markings after every state-changing public operation, and allow users of the dep-cache to group actions into a single action. * dburrows@debian.org--2005/apt--auto-mark--0--patch-3 Automatically update package markings after every state-changing public operation, and allow users of the dep-cache to group actions into a single action. * dburrows@debian.org--2005/apt--auto-mark--0--patch-4 Make action groups noncopyable * dburrows@debian.org--2005/apt--auto-mark--0--patch-5 Typo fix * dburrows@debian.org--2005/apt--auto-mark--0--patch-6 Add a FromUser flag to MarkKeep. * dburrows@debian.org--2005/apt--auto-mark--0--patch-7 Somehow the ActionGroup definition got duplicated; kill the duplicate. * dburrows@debian.org--2005/apt--auto-mark--0--patch-8 Cancel the automatic flag on packages that are being kept only if they are garbage. * dburrows@debian.org--2005/apt--auto-mark--0--patch-9 Don't clear the 'automatically installed' flag in MarkDelete. * dburrows@debian.org--2005/apt--auto-mark--0--patch-10 Add a FromUser flag to MarkInstall, and fix its handling of the Auto flag. * dburrows@debian.org--2005/apt--auto-mark--0--patch-11 Only clear the Auto flag on manual changes in MarkKeep. * dburrows@debian.org--2005/apt--auto-mark--0--patch-12 Make changes from the internal algorithms automatic. * dburrows@debian.org--2005/apt--auto-mark--0--patch-13 Use ActionGroups in algorithms that make lots of changes, and fix a compile error. * dburrows@debian.org--2005/apt--auto-mark--0--patch-14 Split the sweep code into a separate routine from pkgMarkUsed * dburrows@debian.org--2005/apt--auto-mark--0--patch-15 Update another call of MarkKeep to indicate that it's automatic. * dburrows@debian.org--2005/apt--auto-mark--0--patch-16 Move the mark-and-sweep code into pkgDepCache; call Sweep and document what it and Garbage are for; add a hook that can be used to generate a custom root-set function; move the big blob of regexp stuff into the custom root-set; fix the memory leak in the regexp stuff. * dburrows@debian.org--2005/apt--auto-mark--0--patch-17 Make ActionGroup take a reference instead of a pointer to the cache. * dburrows@debian.org--2005/apt--auto-mark--0--patch-18 Don't mark already-to-be-deleted packages as garbage, to imitate aptitude's behavior. * dburrows@debian.org--2005/apt--auto-mark--0--patch-19 Update apt-get for the new auto-mark protocol. * dburrows@debian.org--2005/apt--auto-mark--0--patch-20 Add a setter method for the Auto flag. * dburrows@debian.org--2005/apt--auto-mark--0--patch-21 Fix the test in apt-get about what to delete. * dburrows@debian.org--2005/apt--auto-mark--0--patch-22 Add a zero-argument mark-and-sweep routine and use it to do a mark-and-sweep on startup (so the garbage flags are initialized properly). * dburrows@debian.org--2005/apt--auto-mark--0--patch-23 Right, Status is 2 for new installs, not 0. * dburrows@debian.org--2005/apt--auto-mark--0--patch-24 POT updates. * dburrows@debian.org--2005/apt--auto-mark--0--patch-25 Actually initialize group_level to 0. * dburrows@debian.org--2005/apt--auto-mark--0--patch-26 Don't make an ActionGroup in Sweep, since there's no point and it also is an infinite loop. * dburrows@debian.org--2005/apt--auto-mark--0--patch-27 Add virtual hooks to control whether the garbage collector considers recommends and/or suggests to be strong links. * dburrows@debian.org--2005/apt--auto-mark--0--patch-28 Call the progress methods in the right order so we don't generate nonsensical progress notifications. * dburrows@debian.org--2005/apt--auto-mark--0--patch-29 Typo fix. * dburrows@debian.org--2005/apt--auto-mark--0--patch-30 Make RecommendsImportant default to true in apt, too. * dburrows@debian.org--2005/apt--auto-mark--0--patch-31 Add a release() method to action groups. * dburrows@debian.org--2005/apt--auto-mark--0--patch-32 Add an 'autoremove' command that is synonymous to '--auto-remove remove'. --- apt-pkg/algorithms.cc | 318 +++++++-------------------------------------- apt-pkg/algorithms.h | 23 ---- apt-pkg/depcache.cc | 322 ++++++++++++++++++++++++++++++++++++++++++---- apt-pkg/depcache.h | 212 +++++++++++++++++++++++++++++- apt-pkg/packagemanager.cc | 2 +- 5 files changed, 550 insertions(+), 327 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 82ea19c93..ac9d3be0b 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -20,14 +20,12 @@ #include #include #include -#include #include #include #include #include -#include #include /*}}}*/ using namespace std; @@ -224,6 +222,8 @@ void pkgSimulate::ShortBreaks() the necessary calculations to deal with the problems. */ bool pkgApplyStatus(pkgDepCache &Cache) { + pkgDepCache::ActionGroup group(Cache); + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) { if (I->VersionList == 0) @@ -234,13 +234,13 @@ bool pkgApplyStatus(pkgDepCache &Cache) I->InstState == pkgCache::State::HoldReInstReq) { if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); else { // Is this right? Will dpkg choke on an upgrade? if (Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable() == true) - Cache.MarkInstall(I); + Cache.MarkInstall(I, false, 0, false); else return _error->Error(_("The package %s needs to be reinstalled, " "but I can't find an archive for it."),I.Name()); @@ -257,12 +257,12 @@ bool pkgApplyStatus(pkgDepCache &Cache) case pkgCache::State::HalfConfigured: if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) || I.State() != pkgCache::PkgIterator::NeedsUnpack) - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); else { if (Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable() == true) - Cache.MarkInstall(I); + Cache.MarkInstall(I, true, 0, false); else Cache.MarkDelete(I); } @@ -288,10 +288,12 @@ bool pkgApplyStatus(pkgDepCache &Cache) on the result. */ bool pkgFixBroken(pkgDepCache &Cache) { + pkgDepCache::ActionGroup group(Cache); + // Auto upgrade all broken packages for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) if (Cache[I].NowBroken() == true) - Cache.MarkInstall(I,true); + Cache.MarkInstall(I, true, 0, false); /* Fix packages that are in a NeedArchive state but don't have a downloadable install version */ @@ -304,7 +306,7 @@ bool pkgFixBroken(pkgDepCache &Cache) if (Cache[I].InstVerIter(Cache).Downloadable() == false) continue; - Cache.MarkInstall(I,true); + Cache.MarkInstall(I, true, 0, false); } pkgProblemResolver Fix(&Cache); @@ -321,23 +323,25 @@ bool pkgFixBroken(pkgDepCache &Cache) */ bool pkgDistUpgrade(pkgDepCache &Cache) { + pkgDepCache::ActionGroup group(Cache); + /* Auto upgrade all installed packages, this provides the basis for the installation */ for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) if (I->CurrentVer != 0) - Cache.MarkInstall(I,true); + Cache.MarkInstall(I, true, 0, false); /* Now, auto upgrade all essential packages - this ensures that the essential packages are present and working */ for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) - Cache.MarkInstall(I,true); + Cache.MarkInstall(I, true, 0, false); /* We do it again over all previously installed packages to force conflict resolution on them all. */ for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) if (I->CurrentVer != 0) - Cache.MarkInstall(I,false); + Cache.MarkInstall(I, false, 0, false); pkgProblemResolver Fix(&Cache); @@ -349,7 +353,7 @@ bool pkgDistUpgrade(pkgDepCache &Cache) if (I->SelectedState == pkgCache::State::Hold) { Fix.Protect(I); - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); } } } @@ -364,6 +368,8 @@ bool pkgDistUpgrade(pkgDepCache &Cache) to install packages not marked for install */ bool pkgAllUpgrade(pkgDepCache &Cache) { + pkgDepCache::ActionGroup group(Cache); + pkgProblemResolver Fix(&Cache); if (Cache.BrokenCount() != 0) @@ -380,7 +386,7 @@ bool pkgAllUpgrade(pkgDepCache &Cache) continue; if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) - Cache.MarkInstall(I,false); + Cache.MarkInstall(I, false, 0, false); } return Fix.ResolveByKeep(); @@ -393,6 +399,8 @@ bool pkgAllUpgrade(pkgDepCache &Cache) the package is restored. */ bool pkgMinimizeUpgrade(pkgDepCache &Cache) { + pkgDepCache::ActionGroup group(Cache); + if (Cache.BrokenCount() != 0) return false; @@ -409,9 +417,9 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache) continue; // Keep it and see if that is OK - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); if (Cache.BrokenCount() != 0) - Cache.MarkInstall(I,false); + Cache.MarkInstall(I, false, 0, false); else { // If keep didnt actually do anything then there was no change.. @@ -569,6 +577,8 @@ void pkgProblemResolver::MakeScores() installable */ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) { + pkgDepCache::ActionGroup group(Cache); + if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false) return false; if ((Flags[Pkg->ID] & Protected) == Protected) @@ -577,7 +587,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) Flags[Pkg->ID] &= ~Upgradable; bool WasKept = Cache[Pkg].Keep(); - Cache.MarkInstall(Pkg,false); + Cache.MarkInstall(Pkg, false, 0, false); // This must be a virtual package or something like that. if (Cache[Pkg].InstVerIter(Cache).end() == true) @@ -662,7 +672,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) if (Fail == true) { if (WasKept == true) - Cache.MarkKeep(Pkg); + Cache.MarkKeep(Pkg, false, false); else Cache.MarkDelete(Pkg); return false; @@ -689,6 +699,8 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) upgrade packages to advoid problems. */ bool pkgProblemResolver::Resolve(bool BrokenFix) { + pkgDepCache::ActionGroup group(Cache); + unsigned long Size = Cache.Head().PackageCount; // Record which packages are marked for install @@ -704,7 +716,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) { if (Cache[I].InstBroken() == true && BrokenFix == true) { - Cache.MarkInstall(I,false); + Cache.MarkInstall(I, false, 0, false); if (Cache[I].Install() == true) Again = true; } @@ -770,14 +782,14 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) pkgCache::Version *OldVer = Cache[I].InstallVer; Flags[I->ID] &= ReInstateTried; - Cache.MarkInstall(I,false); + Cache.MarkInstall(I, false, 0, false); if (Cache[I].InstBroken() == true || OldBreaks < Cache.BrokenCount()) { if (OldVer == 0) Cache.MarkDelete(I); else - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); } else if (Debug == true) @@ -822,7 +834,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) { if (Debug == true) clog << " Or group keep for " << I.Name() << endl; - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); Change = true; } } @@ -872,7 +884,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) } Change = true; - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); break; } @@ -909,7 +921,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) /* See if a keep will do, unless the package is protected, then installing it will be necessary */ bool Installed = Cache[I].Install(); - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); if (Cache[I].InstBroken() == false) { // Unwind operation will be keep now @@ -918,7 +930,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) // Restore if (InOr == true && Installed == true) - Cache.MarkInstall(I,false); + Cache.MarkInstall(I, false, 0, false); if (Debug == true) clog << " Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl; @@ -990,7 +1002,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) // Restore if (InOr == true && Installed == true) - Cache.MarkInstall(I,false); + Cache.MarkInstall(I, false, 0, false); if (Debug == true) clog << " Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl; @@ -1035,7 +1047,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) { if (Debug == true) clog << " Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl; - Cache.MarkKeep(J->Pkg); + Cache.MarkKeep(J->Pkg, false, false); } if (Counter > 1) @@ -1089,6 +1101,8 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) system was non-broken previously. */ bool pkgProblemResolver::ResolveByKeep() { + pkgDepCache::ActionGroup group(Cache); + unsigned long Size = Cache.Head().PackageCount; if (Debug == true) @@ -1122,7 +1136,7 @@ bool pkgProblemResolver::ResolveByKeep() { if (Debug == true) clog << "Keeping package " << I.Name() << endl; - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); if (Cache[I].InstBroken() == false) { K = PList - 1; @@ -1170,7 +1184,7 @@ bool pkgProblemResolver::ResolveByKeep() { if (Debug == true) clog << " Keeping Package " << Pkg.Name() << " due to dep" << endl; - Cache.MarkKeep(Pkg); + Cache.MarkKeep(Pkg, false, false); } if (Cache[I].InstBroken() == false) @@ -1207,6 +1221,8 @@ bool pkgProblemResolver::ResolveByKeep() /* This is used to make sure protected packages are installed */ void pkgProblemResolver::InstallProtect() { + pkgDepCache::ActionGroup group(Cache); + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) { if ((Flags[I->ID] & Protected) == Protected) @@ -1214,7 +1230,7 @@ void pkgProblemResolver::InstallProtect() if ((Flags[I->ID] & ToRemove) == ToRemove) Cache.MarkDelete(I); else - Cache.MarkInstall(I,false); + Cache.MarkInstall(I, false, 0, false); } } } @@ -1251,247 +1267,3 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List) } /*}}}*/ - -// mark a single package in Mark-and-Sweep -void pkgMarkPackage(pkgDepCache &Cache, - const pkgCache::PkgIterator &pkg, - const pkgCache::VerIterator &ver, - bool follow_recommends, - bool follow_suggests) -{ - pkgDepCache::StateCache &state=Cache[pkg]; - pkgCache::VerIterator candver=state.CandidateVerIter(Cache); - pkgCache::VerIterator instver=state.InstVerIter(Cache); - -#if 0 - // If a package was garbage-collected but is now being marked, we - // should re-select it - // For cases when a pkg is set to upgrade and this trigger the - // removal of a no-longer used dependency. if the pkg is set to - // keep again later it will result in broken deps - if(state.Delete() && state.RemoveReason=pkgDepCache::Unused) - { - if(ver==candver) - mark_install(pkg, false, false, NULL); - else if(ver==pkg.CurrentVer()) - MarkKeep(pkg); - - 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())) - return; - - // if we are marked already we are done - if(state.Marked) - return; - - //std::cout << "Setting Marked for: " << pkg.Name() << std::endl; - state.Marked=true; - - if(!ver.end()) - { - for(pkgCache::DepIterator d=ver.DependsList(); !d.end(); ++d) - { - if(d->Type==pkgCache::Dep::Depends || - d->Type==pkgCache::Dep::PreDepends || - (follow_recommends && - d->Type==pkgCache::Dep::Recommends) || - (follow_suggests && - d->Type==pkgCache::Dep::Suggests)) - { - // Try all versions of this package. - for(pkgCache::VerIterator V=d.TargetPkg().VersionList(); - !V.end(); ++V) - { - if(_system->VS->CheckDep(V.VerStr(),d->CompareOp, d.TargetVer())) - { - pkgMarkPackage(Cache, V.ParentPkg(), V, - follow_recommends, follow_suggests); - } - } - // Now try virtual packages - for(pkgCache::PrvIterator prv=d.TargetPkg().ProvidesList(); - !prv.end(); ++prv) - { - if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, - d.TargetVer())) - { - pkgMarkPackage(Cache, prv.OwnerPkg(), prv.OwnerVer(), - follow_recommends, follow_suggests); - } - } - } - } - } -} - - -// Helper for APT::NeverAutoRemove, always include the packages matching -// this regexp into the root-set -inline bool -pkgMarkAlwaysInclude(pkgCache::PkgIterator p, vector alwaysMark) -{ - for(unsigned int i=0;iFindB("Debug::pkgAutoRemove",false) - && Cache[p].Flags & pkgCache::Flag::Auto) - std::clog << "AutoDep: " << p.Name() << std::endl; - } - - // init vars - follow_recommends=_config->FindB("APT::AutoRemove::RecommendsImportant",false); - follow_suggests=_config->FindB("APT::AutoRemove::SuggestsImportant", false); - - - // init the "NeverAutoRemove" variable - vector neverAutoRemoveRegexp; - Configuration::Item const *Opts; - Opts = _config->Tree("APT::NeverAutoRemove"); - if (Opts != 0 && Opts->Child != 0) - { - Opts = Opts->Child; - for (; Opts != 0; Opts = Opts->Next) - { - if (Opts->Value.empty() == true) - continue; - - regex_t *p = new regex_t; - if(regcomp(p,Opts->Value.c_str(), - REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0) - { - regfree(p); - for(unsigned int i=0;iError("Regex compilation error for APT::NeverAutoRemove"); - } - neverAutoRemoveRegexp.push_back(p); - } - } - - - // do the mark part, this is the core bit of the algorithm - for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p) - { - if( userFunc.InRootSet(p) || - pkgMarkAlwaysInclude(p, neverAutoRemoveRegexp) || - !(Cache[p].Flags & pkgCache::Flag::Auto) || - (p->Flags & pkgCache::Flag::Essential)) - - { - // the package is installed (and set to keep) - if(Cache[p].Keep() && !p.CurrentVer().end()) - pkgMarkPackage(Cache, p, p.CurrentVer(), - follow_recommends, follow_suggests); - // the package is to be installed - else if(Cache[p].Install()) - pkgMarkPackage(Cache, p, Cache[p].InstVerIter(Cache), - follow_recommends, follow_suggests); - } - } - - - // do the sweep - for(pkgCache::PkgIterator p=Cache.PkgBegin(); !p.end(); ++p) - { - pkgDepCache::StateCache &state=Cache[p]; - - // if it is not marked and it is installed, it's garbage - if(!state.Marked && !p.CurrentVer().end()) - { - state.Garbage=true; - if(_config->FindB("Debug::pkgAutoRemove",false)) - std::cout << "Garbage: " << p.Name() << std::endl; - -#if 0 // mvo: the below bits still needs to be ported - - // Be sure not to re-delete already deleted packages. - if(delete_unused && (!p.CurrentVer().end() || state.Install()) && - !state.Delete()) - { - bool do_delete=true; - - // If the package is being upgraded, check if we're - // losing a versioned dep. If the dependency matches - // the previous version and not the new version, keep - // the package back instead of removing it. - if(!p.CurrentVer().end() && state.Install()) - { - const char *vs=p.CurrentVer().VerStr(); - - // Check direct revdeps only. THIS ASSUMES NO - // VERSIONED PROVIDES, but Debian probably won't - // have them for ages if ever. - for(pkgCache::DepIterator revdep=p.RevDependsList(); - !revdep.end(); ++revdep) - { - pkgCache::PkgIterator depender=revdep.ParentPkg(); - // Find which version of the depending package - // will be installed. - pkgCache::VerIterator instver=(*this)[depender].InstVerIter(*this); - - // Only pay attention to strong positive - // dependencies whose parents will be installed. - if(revdep.ParentVer()==instver && - (revdep->Type==pkgCache::Dep::Depends || - revdep->Type==pkgCache::Dep::PreDepends || - (revdep->Type==pkgCache::Dep::Recommends && - follow_recommends))) - { - // If the previous version matched, cancel the - // deletion. (note that I assume that the new - // version does NOT match; otherwise it would - // not be unused!) - if(_system->VS->CheckDep(vs, - revdep->CompareOp, - revdep.TargetVer())) - { - mark_keep(p, false, false, undo); - do_delete=false; - break; - } - } - } - } - - if(do_delete) - mark_delete(p, false, true, undo); - } -#endif - } - } - - // cleanup - for(unsigned int i=0;i #include +#include #include #include #include #include - /*}}}*/ + +pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) : + cache(cache), released(false) +{ + ++cache.group_level; +} + +void pkgDepCache::ActionGroup::release() +{ + if(!released) + { + if(cache.group_level == 0) + std::cerr << "W: Unbalanced action groups, expect badness" << std::endl; + else + { + --cache.group_level; + + if(cache.group_level == 0) + cache.MarkAndSweep(); + } + + released = false; + } +} + +pkgDepCache::ActionGroup::~ActionGroup() +{ + release(); +} // DepCache::pkgDepCache - Constructors /*{{{*/ // --------------------------------------------------------------------- /* */ pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) : - Cache(pCache), PkgState(0), DepState(0) + group_level(0), Cache(pCache), PkgState(0), DepState(0) { delLocalPolicy = 0; LocalPolicy = Plcy; @@ -53,6 +82,10 @@ pkgDepCache::~pkgDepCache() /* This allocats the extension buffers and initializes them. */ bool pkgDepCache::Init(OpProgress *Prog) { + // Suppress mark updates during this operation (just in case) and + // run a mark operation when Init terminates. + ActionGroup actions(*this); + delete [] PkgState; delete [] DepState; PkgState = new StateCache[Head().PackageCount]; @@ -100,7 +133,7 @@ bool pkgDepCache::Init(OpProgress *Prog) if(Prog != 0) Prog->Done(); - + return true; } /*}}}*/ @@ -161,7 +194,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog) if(PkgState[pkg->ID].Flags & Flag::Auto) { if(_config->FindB("Debug::pkgAutoRemove",false)) - std::clog << "AutoInstal: " << pkg.Name() << std::endl; + std::clog << "AutoInstall: " << pkg.Name() << std::endl; ostr.str(string("")); ostr << "Package: " << pkg.Name() << "\nAuto-Installed: 1\n\n"; @@ -522,16 +555,16 @@ void pkgDepCache::Update(OpProgress *Prog) AddStates(I); } - readStateFile(Prog); - if (Prog != 0) Prog->Progress(Done); + + readStateFile(Prog); } /*}}}*/ // DepCache::Update - Update the deps list of a package /*{{{*/ // --------------------------------------------------------------------- /* This is a helper for update that only does the dep portion of the scan. - It is mainly ment to scan reverse dependencies. */ + It is mainly meant to scan reverse dependencies. */ void pkgDepCache::Update(DepIterator D) { // Update the reverse deps @@ -583,7 +616,7 @@ void pkgDepCache::Update(PkgIterator const &Pkg) // DepCache::MarkKeep - Put the package in the keep state /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft) +void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser) { // Simplifies other routines. if (Pkg.end() == true) @@ -595,6 +628,9 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft) Pkg.CurrentVer().Downloadable() == false) return; + /** \todo Can this be moved later in the method? */ + ActionGroup group(*this); + /* We changed the soft state all the time so the UI is a bit nicer to use */ StateCache &P = PkgState[Pkg->ID]; @@ -611,7 +647,8 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft) if (Pkg->VersionList == 0) return; - P.Flags &= ~Flag::Auto; + if(FromUser && !P.Marked) + P.Flags &= ~Flag::Auto; RemoveSizes(Pkg); RemoveStates(Pkg); @@ -637,6 +674,8 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge) if (Pkg.end() == true) return; + ActionGroup group(*this); + // Check that it is not already marked for delete StateCache &P = PkgState[Pkg->ID]; P.iFlags &= ~(AutoKept | Purge); @@ -659,8 +698,6 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge) else P.Mode = ModeDelete; P.InstallVer = 0; - // This was not inverted before, but I think it should be - P.Flags &= ~Flag::Auto; AddStates(Pkg); Update(Pkg); @@ -671,7 +708,7 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge) // --------------------------------------------------------------------- /* */ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, - unsigned long Depth) + unsigned long Depth, bool FromUser) { if (Depth > 100) return; @@ -680,6 +717,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, if (Pkg.end() == true) return; + ActionGroup group(*this); + /* Check that it is not already marked for install and that it can be installed */ StateCache &P = PkgState[Pkg->ID]; @@ -688,7 +727,7 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, P.CandidateVer == (Version *)Pkg.CurrentVer())) { if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0) - MarkKeep(Pkg); + MarkKeep(Pkg, false, FromUser); return; } @@ -708,9 +747,20 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, P.Mode = ModeInstall; P.InstallVer = P.CandidateVer; - // invert the auto-flag only for new installs, not for upgrades - if(P.Status == 0) - P.Flags &= ~Flag::Auto; + + if(FromUser) + { + // Set it to manual if it's a new install or cancelling the + // removal of a garbage package. + if(P.Status == 2 || (!Pkg.CurrentVer().end() && !P.Marked)) + P.Flags &= ~Flag::Auto; + } + else + { + // Set it to auto if this is a new install. + if(P.Status == 2) + P.Flags |= Flag::Auto; + } if (P.CandidateVer == (Version *)Pkg.CurrentVer()) P.Mode = ModeKeep; @@ -788,13 +838,7 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, } if (InstPkg.end() == false) - { - MarkInstall(InstPkg,true,Depth + 1); - - // Set the autoflag, after MarkInstall because MarkInstall unsets it - if (P->CurrentVer == 0) - PkgState[InstPkg->ID].Flags |= Flag::Auto; - } + MarkInstall(InstPkg, true, Depth + 1, false); continue; } @@ -809,7 +853,6 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, PkgIterator Pkg = Ver.ParentPkg(); MarkDelete(Pkg); - PkgState[Pkg->ID].Flags |= Flag::Auto; } continue; } @@ -821,6 +864,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, /* */ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To) { + ActionGroup group(*this); + RemoveSizes(Pkg); RemoveStates(Pkg); @@ -839,9 +884,11 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To) /* */ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer) { + ActionGroup group(*this); + pkgCache::PkgIterator Pkg = TargetVer.ParentPkg(); StateCache &P = PkgState[Pkg->ID]; - + RemoveSizes(Pkg); RemoveStates(Pkg); @@ -854,6 +901,18 @@ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer) Update(Pkg); AddSizes(Pkg); } + +void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto) +{ + StateCache &state = PkgState[Pkg->ID]; + + ActionGroup group(*this); + + if(Auto) + state.Flags |= Flag::Auto; + else + state.Flags &= ~Flag::Auto; +} /*}}}*/ // StateCache::Update - Compute the various static display things /*{{{*/ // --------------------------------------------------------------------- @@ -944,3 +1003,216 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep) return Dep.IsCritical(); } /*}}}*/ + +pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc() + : constructedSuccessfully(false) +{ + Configuration::Item const *Opts; + Opts = _config->Tree("APT::NeverAutoRemove"); + if (Opts != 0 && Opts->Child != 0) + { + Opts = Opts->Child; + for (; Opts != 0; Opts = Opts->Next) + { + if (Opts->Value.empty() == true) + continue; + + regex_t *p = new regex_t; + if(regcomp(p,Opts->Value.c_str(), + REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0) + { + regfree(p); + delete p; + _error->Error("Regex compilation error for APT::NeverAutoRemove"); + return; + } + + rootSetRegexp.push_back(p); + } + } + + constructedSuccessfully = true; +} + +pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc() +{ + for(unsigned int i = 0; i < rootSetRegexp.size(); i++) + { + regfree(rootSetRegexp[i]); + delete rootSetRegexp[i]; + } +} + + +bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg) +{ + for(unsigned int i = 0; i < rootSetRegexp.size(); i++) + if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0) + return true; + + return false; +} + +pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc() +{ + DefaultRootSetFunc *f = new DefaultRootSetFunc; + if(f->wasConstructedSuccessfully()) + return f; + else + { + delete f; + return NULL; + } +} + +bool pkgDepCache::MarkFollowsRecommends() +{ + return _config->FindB("APT::AutoRemove::RecommendsImportant", true); +} + +bool pkgDepCache::MarkFollowsSuggests() +{ + return _config->FindB("APT::AutoRemove::SuggestsImportant", false); +} + +// the main mark algorithm +bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) +{ + bool follow_recommends; + bool follow_suggests; + + // init the states + for(PkgIterator p = PkgBegin(); !p.end(); ++p) + { + PkgState[p->ID].Marked = false; + PkgState[p->ID].Garbage = false; + + // debug output + if(_config->FindB("Debug::pkgAutoRemove",false) + && PkgState[p->ID].Flags & Flag::Auto) + std::clog << "AutoDep: " << p.Name() << std::endl; + } + + // init vars + follow_recommends = MarkFollowsRecommends(); + follow_suggests = MarkFollowsSuggests(); + + + + // do the mark part, this is the core bit of the algorithm + for(PkgIterator p = PkgBegin(); !p.end(); ++p) + { + if(!(PkgState[p->ID].Flags & Flag::Auto) || + (p->Flags & Flag::Essential) || + userFunc.InRootSet(p)) + + { + // the package is installed (and set to keep) + if(PkgState[p->ID].Keep() && !p.CurrentVer().end()) + MarkPackage(p, p.CurrentVer(), + follow_recommends, follow_suggests); + // the package is to be installed + else if(PkgState[p->ID].Install()) + MarkPackage(p, PkgState[p->ID].InstVerIter(*this), + follow_recommends, follow_suggests); + } + } + + return true; +} + +// mark a single package in Mark-and-Sweep +void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, + const pkgCache::VerIterator &ver, + bool follow_recommends, + bool follow_suggests) +{ + pkgDepCache::StateCache &state = PkgState[pkg->ID]; + VerIterator candver = state.CandidateVerIter(*this); + VerIterator instver = state.InstVerIter(*this); + +#if 0 + // If a package was garbage-collected but is now being marked, we + // should re-select it + // For cases when a pkg is set to upgrade and this trigger the + // removal of a no-longer used dependency. if the pkg is set to + // keep again later it will result in broken deps + if(state.Delete() && state.RemoveReason = Unused) + { + if(ver==candver) + mark_install(pkg, false, false, NULL); + else if(ver==pkg.CurrentVer()) + MarkKeep(pkg, false, false); + + 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())) + return; + + // if we are marked already we are done + if(state.Marked) + return; + + //std::cout << "Setting Marked for: " << pkg.Name() << std::endl; + state.Marked=true; + + if(!ver.end()) + { + for(DepIterator d = ver.DependsList(); !d.end(); ++d) + { + if(d->Type == Dep::Depends || + d->Type == Dep::PreDepends || + (follow_recommends && + d->Type == Dep::Recommends) || + (follow_suggests && + d->Type == Dep::Suggests)) + { + // Try all versions of this package. + for(VerIterator V = d.TargetPkg().VersionList(); + !V.end(); ++V) + { + if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer())) + { + MarkPackage(V.ParentPkg(), V, + follow_recommends, follow_suggests); + } + } + // Now try virtual packages + for(PrvIterator prv=d.TargetPkg().ProvidesList(); + !prv.end(); ++prv) + { + if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, + d.TargetVer())) + { + MarkPackage(prv.OwnerPkg(), prv.OwnerVer(), + follow_recommends, follow_suggests); + } + } + } + } + } +} + +bool pkgDepCache::Sweep() +{ + // do the sweep + for(PkgIterator p=PkgBegin(); !p.end(); ++p) + { + StateCache &state=PkgState[p->ID]; + + // if it is not marked and it is installed, it's garbage + if(!state.Marked && (!p.CurrentVer().end() || state.Install()) && + !state.Delete()) + { + state.Garbage=true; + if(_config->FindB("Debug::pkgAutoRemove",false)) + std::cout << "Garbage: " << p.Name() << std::endl; + } + } + + return true; +} diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 619daf8f6..fd935c268 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -1,4 +1,4 @@ -// -*- mode: cpp; mode: fold -*- +// -*- mode: c++; mode: fold -*- // Description /*{{{*/ // $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### @@ -45,9 +45,71 @@ #include #include +#include + +#include + class pkgDepCache : protected pkgCache::Namespace { public: + + /** \brief An arbitrary predicate on packages. */ + class InRootSetFunc + { + public: + virtual bool InRootSet(const pkgCache::PkgIterator &pkg) {return false;}; + virtual ~InRootSetFunc() {}; + }; + + private: + /** \brief Mark a single package and all its unmarked important + * dependencies during mark-and-sweep. + * + * Recursively invokes itself to mark all dependencies of the + * package. + * + * \param pkg The package to mark. + * + * \param ver The version of the package that is to be marked. + * + * \param follow_recommends If \b true, recommendations of the + * package will be recursively marked. + * + * \param follow_suggests If \b true, suggestions of the package + * will be recursively marked. + */ + void MarkPackage(const pkgCache::PkgIterator &pkg, + const pkgCache::VerIterator &ver, + bool follow_recommends, + bool follow_suggests); + + /** \brief Update the Marked field of all packages. + * + * Each package's StateCache::Marked field will be set to \b true + * if and only if it can be reached from the root set. By + * default, the root set consists of the set of manually installed + * or essential packages, but it can be extended using the + * parameter #rootFunc. + * + * \param rootFunc A callback that can be used to add extra + * packages to the root set. + * + * \return \b false if an error occured. + */ + bool MarkRequired(InRootSetFunc &rootFunc); + + /** \brief Set the StateCache::Garbage flag on all packages that + * should be removed. + * + * Packages that were not marked by the last call to #MarkRequired + * are tested to see whether they are actually garbage. If so, + * they are marked as such. + * + * \return \b false if an error occured. + */ + bool Sweep(); + + public: // These flags are used in DepState enum DepFlags {DepNow = (1 << 0),DepInstall = (1 << 1),DepCVer = (1 << 2), @@ -64,6 +126,83 @@ class pkgDepCache : protected pkgCache::Namespace enum VersionTypes {NowVersion, InstallVersion, CandidateVersion}; enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2}; + /** \brief Represents an active action group. + * + * An action group is a group of actions that are currently being + * performed. While an active group is active, certain routine + * clean-up actions that would normally be performed after every + * cache operation are delayed until the action group is + * completed. This is necessary primarily to avoid inefficiencies + * when modifying a large number of packages at once. + * + * This class represents an active action group. Creating an + * instance will create an action group; destroying one will + * destroy the corresponding action group. + * + * The following operations are suppressed by this class: + * + * - Keeping the Marked and Garbage flags up to date. + * + * \note This can be used in the future to easily accumulate + * atomic actions for undo or to display "what apt did anyway"; + * e.g., change the counter of how many action groups are active + * to a std::set of pointers to them and use those to store + * information about what happened in a group in the group. + */ + class ActionGroup + { + pkgDepCache &cache; + + bool released; + + /** Action groups are noncopyable. */ + ActionGroup(const ActionGroup &other); + public: + /** \brief Create a new ActionGroup. + * + * \param cache The cache that this ActionGroup should + * manipulate. + * + * As long as this object exists, no automatic cleanup + * operations will be undertaken. + */ + ActionGroup(pkgDepCache &cache); + + /** \brief Clean up the action group before it is destroyed. + * + * If it is destroyed later, no second cleanup wil be run. + */ + void release(); + + /** \brief Destroy the action group. + * + * If this is the last action group, the automatic cache + * cleanup operations will be undertaken. + */ + ~ActionGroup(); + }; + + /** \brief Returns \b true for packages matching a regular + * expression in APT::NeverAutoRemove. + */ + class DefaultRootSetFunc : public InRootSetFunc + { + std::vector rootSetRegexp; + bool constructedSuccessfully; + + public: + DefaultRootSetFunc(); + ~DefaultRootSetFunc(); + + /** \return \b true if the class initialized successfully, \b + * false otherwise. Used to avoid throwing an exception, since + * APT classes generally don't. + */ + bool wasConstructedSuccessfully() const { return constructedSuccessfully; } + + bool InRootSet(const pkgCache::PkgIterator &pkg); + }; + struct StateCache { // Epoch stripped text versions of the two version fields @@ -80,8 +219,15 @@ class pkgDepCache : protected pkgCache::Namespace unsigned short Flags; unsigned short iFlags; // Internal flags - // mark and sweep flags + /** \brief \b true if this package can be reached from the root set. */ bool Marked; + + /** \brief \b true if this package is unused and should be removed. + * + * This differs from !#Marked, because it is possible that some + * unreachable packages will be protected from becoming + * garbage. + */ bool Garbage; // Various tree indicators @@ -124,6 +270,14 @@ class pkgDepCache : protected pkgCache::Namespace virtual ~Policy() {}; }; + + private: + /** The number of open "action groups"; certain post-action + * operations are suppressed if this number is > 0. + */ + int group_level; + + friend class ActionGroup; protected: @@ -187,13 +341,61 @@ class pkgDepCache : protected pkgCache::Namespace inline StateCache &operator [](PkgIterator const &I) {return PkgState[I->ID];}; inline unsigned char &operator [](DepIterator const &I) {return DepState[I->ID];}; - // Manipulators - void MarkKeep(PkgIterator const &Pkg,bool Soft = false); + /** \return A function identifying packages in the root set other + * than manually installed packages and essential packages, or \b + * NULL if an error occurs. + * + * \todo Is this the best place for this function? Perhaps the + * settings for mark-and-sweep should be stored in a single + * external class? + */ + virtual InRootSetFunc *GetRootSetFunc(); + + /** \return \b true if the garbage collector should follow recommendations. + */ + virtual bool MarkFollowsRecommends(); + + /** \return \b true if the garbage collector should follow suggestions. + */ + virtual bool MarkFollowsSuggests(); + + /** \brief Update the Marked and Garbage fields of all packages. + * + * This routine is implicitly invoked after all state manipulators + * and when an ActionGroup is destroyed. It invokes #MarkRequired + * and #Sweep to do its dirty work. + * + * \param rootFunc A predicate that returns \b true for packages + * that should be added to the root set. + */ + bool MarkAndSweep(InRootSetFunc &rootFunc) + { + return MarkRequired(rootFunc) && Sweep(); + } + + bool MarkAndSweep() + { + std::auto_ptr f(GetRootSetFunc()); + if(f.get() != NULL) + return MarkAndSweep(*f.get()); + else + return false; + } + + /** \name State Manipulators + */ + // @{ + void MarkKeep(PkgIterator const &Pkg, bool Soft = false, + bool FromUser = true); void MarkDelete(PkgIterator const &Pkg,bool Purge = false); void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true, - unsigned long Depth = 0); + unsigned long Depth = 0, bool FromUser = true); void SetReInstall(PkgIterator const &Pkg,bool To); void SetCandidateVersion(VerIterator TargetVer); + + /** Set the "is automatically installed" flag of Pkg. */ + void MarkAuto(const PkgIterator &Pkg, bool Auto); + // @} // This is for debuging void Update(OpProgress *Prog = 0); diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 87a21004f..05615db79 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -106,7 +106,7 @@ bool pkgPackageManager::FixMissing() // Okay, this file is missing and we need it. Mark it for keep Bad = true; - Cache.MarkKeep(I); + Cache.MarkKeep(I, false, false); } // We have to empty the list otherwise it will not have the new changes -- cgit v1.2.3 From d4c5f11f8ef619ec56ae1e532416bb3817442b1c Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 27 May 2006 14:13:31 +0200 Subject: * added Debug::pkgDepCache::AutoInstall debug option --- apt-pkg/depcache.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index dd1c794c9..58d1d25e5 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -16,7 +16,8 @@ #include #include #include - +#include + #include /*}}}*/ @@ -712,6 +713,10 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, if (InstPkg.end() == false) { + if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true) + std::clog << "Installing " << InstPkg.Name() + << " as dep of " << Pkg.Name() + << std::endl; MarkInstall(InstPkg,true,Depth + 1); // Set the autoflag, after MarkInstall because MarkInstall unsets it -- cgit v1.2.3 From c08447c8eef91499920ca51276313526888939ec Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 9 Jun 2006 15:47:50 +0200 Subject: * merge the patch from Steinar --- apt-pkg/tagfile.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg') diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index dc1ba3f9e..9763d96a3 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -98,7 +98,7 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset) iOffset = Offset; Start = Buffer + iOffset; - if (Tag.Scan(Start,End - Start) == false) + if (Start != End && Tag.Scan(Start,End - Start) == false) return _error->Error(_("Unable to parse package file %s (2)"),Fd.Name().c_str()); return true; -- cgit v1.2.3 From aac2e51078714d5130861035e9b3b5d4d6b84471 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 26 Jun 2006 06:33:22 +0200 Subject: * apt-pkg/depcache.cc: - renamed "pkgstates" file to "extended_states" --- apt-pkg/depcache.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 6eb6c1d85..4e9488121 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -142,7 +142,7 @@ bool pkgDepCache::Init(OpProgress *Prog) bool pkgDepCache::readStateFile(OpProgress *Prog) { FileFd state_file; - string state = _config->FindDir("Dir::State") + "pkgstates"; + string state = _config->FindDir("Dir::State") + "extended_states"; if(FileExists(state)) { state_file.Open(state, FileFd::ReadOnly); int file_size = state_file.Size(); @@ -181,7 +181,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) bool pkgDepCache::writeStateFile(OpProgress *prog) { FileFd StateFile; - string state = _config->FindDir("Dir::State") + "pkgstates"; + string state = _config->FindDir("Dir::State") + "extended_states"; if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "pkgDepCache::writeStateFile()" << std::endl; -- cgit v1.2.3 From b1a8717ae8e07101cfae03b978d57b793884a3d9 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 26 Jun 2006 09:17:05 +0200 Subject: * cmdline/apt-mark: - very simple tool to manipulate the extended_states for autoinstall * apt-pkg/depcache.cc: - keep exisiting data in "extended_states" to make other tools happy --- apt-pkg/depcache.cc | 62 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 9 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 4e9488121..7663d3881 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -24,6 +24,7 @@ #include #include +#include #include @@ -180,28 +181,71 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) bool pkgDepCache::writeStateFile(OpProgress *prog) { - FileFd StateFile; - string state = _config->FindDir("Dir::State") + "extended_states"; - if(_config->FindB("Debug::pkgAutoRemove",false)) std::clog << "pkgDepCache::writeStateFile()" << std::endl; - if(!StateFile.Open(state, FileFd::WriteEmpty)) - return _error->Error(_("Failed to write StateFile %s"), + FileFd StateFile; + string state = _config->FindDir("Dir::State") + "extended_states"; + if(!StateFile.Open(state, FileFd::ReadOnly)) + return _error->Error(_("Failed to open StateFile %s"), state.c_str()); + FILE *OutFile; + string outfile = state + ".tmp"; + if((OutFile = fopen(outfile.c_str(),"w")) == NULL) + return _error->Error(_("Failed to write temporary StateFile %s"), + outfile.c_str()); + + // first merge with the existing sections + pkgTagFile tagfile(&StateFile); + pkgTagSection section; + std::set pkgs_seen; + const char *nullreorderlist[] = {0}; + while(tagfile.Step(section)) { + string pkgname = section.FindS("Package"); + // Silently ignore unknown packages and packages with no actual + // version. + 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: " + << pkg.Name() << std::endl; + TFRewriteData rewrite[2]; + rewrite[0].Tag = "Auto-Installed"; + rewrite[0].Rewrite = newAuto ? "1" : "0"; + rewrite[0].NewTag = 0; + rewrite[1].Tag = 0; + TFRewrite(OutFile, section, nullreorderlist, rewrite); + fprintf(OutFile,"\n"); + pkgs_seen.insert(pkgname); + } + + // then write the ones we have not seen yet std::ostringstream ostr; - for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end();pkg++) { - + for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) { if(PkgState[pkg->ID].Flags & Flag::Auto) { + if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) { + if(_config->FindB("Debug::pkgAutoRemove",false)) + std::clog << "Skipping already written " << pkg.Name() << std::endl; + continue; + } if(_config->FindB("Debug::pkgAutoRemove",false)) - std::clog << "AutoInstall: " << pkg.Name() << std::endl; + std::clog << "Writing new AutoInstall: " + << pkg.Name() << std::endl; ostr.str(string("")); ostr << "Package: " << pkg.Name() << "\nAuto-Installed: 1\n\n"; - StateFile.Write(ostr.str().c_str(), ostr.str().size()); + fprintf(OutFile,ostr.str().c_str()); + fprintf(OutFile,"\n"); } } + + // move the outfile over the real file + rename(outfile.c_str(), state.c_str()); + return true; } -- cgit v1.2.3 From 6b6afec3673bd1685e62a5c4b1803531a44add82 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 26 Jun 2006 09:28:51 +0200 Subject: * apt-pkg/init.h: - increased lib-version to 3.13 --- apt-pkg/init.h | 2 +- apt-pkg/makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/init.h b/apt-pkg/init.h index 8255b406a..6a832bddf 100644 --- a/apt-pkg/init.h +++ b/apt-pkg/init.h @@ -18,7 +18,7 @@ // See the makefile #define APT_PKG_MAJOR 3 -#define APT_PKG_MINOR 11 +#define APT_PKG_MINOR 13 #define APT_PKG_RELEASE 0 extern const char *pkgVersion; diff --git a/apt-pkg/makefile b/apt-pkg/makefile index ab0ff8005..7093d23ce 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -13,7 +13,7 @@ include ../buildlib/defaults.mak # methods/makefile - FIXME LIBRARY=apt-pkg LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER) -MAJOR=3.12 +MAJOR=3.13 MINOR=0 SLIBS=$(PTHREADLIB) $(INTLLIBS) APT_DOMAIN:=libapt-pkg$(MAJOR) -- cgit v1.2.3