From 6d38011bb93451dd9da3294614d821c77ac91687 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 30 Mar 2011 17:23:43 +0200 Subject: add a first round of stuff needed for talking between APT and solvers based on a very early draft for EDSP by Stefano APT can now write a scenario as well as load most stuff from it. --- apt-pkg/algorithms.cc | 33 +++++++++-- apt-pkg/algorithms.h | 2 + apt-pkg/deb/debindexfile.h | 4 +- apt-pkg/deb/deblistparser.h | 8 +-- apt-pkg/depcache.cc | 6 ++ apt-pkg/depcache.h | 4 +- apt-pkg/edsp/edspindexfile.cc | 74 +++++++++++++++++++++++ apt-pkg/edsp/edspindexfile.h | 25 ++++++++ apt-pkg/edsp/edsplistparser.cc | 109 ++++++++++++++++++++++++++++++++++ apt-pkg/edsp/edsplistparser.h | 38 ++++++++++++ apt-pkg/edsp/edspsystem.cc | 117 +++++++++++++++++++++++++++++++++++++ apt-pkg/edsp/edspsystem.h | 38 ++++++++++++ apt-pkg/edsp/edspwriter.cc | 130 +++++++++++++++++++++++++++++++++++++++++ apt-pkg/edsp/edspwriter.h | 19 ++++++ apt-pkg/makefile | 7 ++- apt-pkg/pkgcachegen.cc | 2 +- apt-pkg/policy.cc | 4 ++ apt-pkg/policy.h | 7 +-- 18 files changed, 609 insertions(+), 18 deletions(-) create mode 100644 apt-pkg/edsp/edspindexfile.cc create mode 100644 apt-pkg/edsp/edspindexfile.h create mode 100644 apt-pkg/edsp/edsplistparser.cc create mode 100644 apt-pkg/edsp/edsplistparser.h create mode 100644 apt-pkg/edsp/edspsystem.cc create mode 100644 apt-pkg/edsp/edspsystem.h create mode 100644 apt-pkg/edsp/edspwriter.cc create mode 100644 apt-pkg/edsp/edspwriter.h diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 0b4366e5e..2ca3404a0 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -20,12 +20,15 @@ #include #include #include - +#include + #include #include #include #include #include + +#include /*}}}*/ using namespace std; @@ -731,7 +734,25 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) return true; } /*}}}*/ -// ProblemResolver::Resolve - Run the resolution pass /*{{{*/ +// ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool pkgProblemResolver::Resolve(bool BrokenFix) +{ + std::string const solver = _config->Find("APT::Solver::Name", "internal"); + if (solver != "internal") + { + FILE* output = fopen("/tmp/universe.log", "w"); + edspWriter::WriteUniverse(Cache, output); + fclose(output); + output = fopen("/tmp/request.log", "w"); + edspWriter::WriteRequest(Cache, output); + fclose(output); + } + return ResolveInternal(BrokenFix); +} + /*}}}*/ +// ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/ // --------------------------------------------------------------------- /* This routines works by calculating a score for each package. The score is derived by considering the package's priority and all reverse @@ -745,12 +766,10 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) The BrokenFix flag enables a mode where the algorithm tries to upgrade packages to advoid problems. */ -bool pkgProblemResolver::Resolve(bool BrokenFix) +bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) { pkgDepCache::ActionGroup group(Cache); - unsigned long Size = Cache.Head().PackageCount; - // Record which packages are marked for install bool Again = false; do @@ -780,7 +799,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) clog << "Starting" << endl; MakeScores(); - + + unsigned long const Size = Cache.Head().PackageCount; + /* We have to order the packages so that the broken fixing pass operates from highest score to lowest. This prevents problems when high score packages cause the removal of lower score packages that diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index ebe31cc10..0778ec722 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -105,6 +105,8 @@ class pkgProblemResolver /*{{{*/ void MakeScores(); bool DoUpgrade(pkgCache::PkgIterator Pkg); + + bool ResolveInternal(bool const BrokenFix = false); public: diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index b5085992d..6697c5f26 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -22,8 +22,9 @@ class debStatusIndex : public pkgIndexFile { + protected: string File; - + public: virtual const Type *GetType() const; @@ -36,6 +37,7 @@ class debStatusIndex : public pkgIndexFile virtual bool HasPackages() const {return true;}; virtual unsigned long Size() const; virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog, unsigned long const Flag) const; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; debStatusIndex(string File); diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index d62ce641c..8b8aff788 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -25,9 +25,9 @@ class debListParser : public pkgCacheGenerator::ListParser const char *Str; unsigned char Val; }; - - private: - + + protected: + pkgTagFile Tags; pkgTagSection Section; unsigned long iOffset; @@ -36,7 +36,7 @@ class debListParser : public pkgCacheGenerator::ListParser bool MultiArchEnabled; unsigned long UniqFindTagWrite(const char *Tag); - bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); + virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag, unsigned int Type); bool ParseProvides(pkgCache::VerIterator &Ver); diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 07803d7bf..2790080a1 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1578,6 +1578,12 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) return false; } /*}}}*/ +// Policy::GetPriority - Get the priority of the package pin /*{{{*/ +signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgIterator const &Pkg) +{ return 0; }; +signed short pkgDepCache::Policy::GetPriority(pkgCache::PkgFileIterator const &File) +{ return 0; }; + /*}}}*/ pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc() /*{{{*/ { DefaultRootSetFunc *f = new DefaultRootSetFunc; diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 750da3d6f..b15cd527d 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -258,7 +258,9 @@ class pkgDepCache : protected pkgCache::Namespace virtual VerIterator GetCandidateVer(PkgIterator const &Pkg); virtual bool IsImportantDep(DepIterator const &Dep); - + virtual signed short GetPriority(PkgIterator const &Pkg); + virtual signed short GetPriority(PkgFileIterator const &File); + virtual ~Policy() {}; }; diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc new file mode 100644 index 000000000..5a9d5aacd --- /dev/null +++ b/apt-pkg/edsp/edspindexfile.cc @@ -0,0 +1,74 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + The universe file is designed to work as an intermediate file between + APT and the resolver. Its on propose very similar to a dpkg status file + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + /*}}}*/ + +// edspIndex::edspIndex - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +edspIndex::edspIndex(string File) : debStatusIndex(File) +{ +} + /*}}}*/ +// StatusIndex::Merge - Load the index file into a cache /*{{{*/ +bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const +{ + FileFd Pkg(File,FileFd::ReadOnlyGzip); + if (_error->PendingError() == true) + return false; + edspListParser Parser(&Pkg); + if (_error->PendingError() == true) + return false; + + if (Prog != NULL) + Prog->SubProgress(0,File); + if (Gen.SelectFile(File,string(),*this) == false) + return _error->Error("Problem with SelectFile %s",File.c_str()); + + // Store the IMS information + pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); + struct stat St; + if (fstat(Pkg.Fd(),&St) != 0) + return _error->Errno("fstat","Failed to stat"); + CFile->Size = St.st_size; + CFile->mtime = St.st_mtime; + CFile->Archive = Gen.WriteUniqString("universe"); + + if (Gen.MergeList(Parser) == false) + return _error->Error("Problem with MergeList %s",File.c_str()); + return true; +} + /*}}}*/ +// Index File types for APT /*{{{*/ +class edspIFType: public pkgIndexFile::Type +{ + public: + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + { + // we don't have a record parser for this type as the file is not presistent + return NULL; + }; + edspIFType() {Label = "APT universe file";}; +}; +static edspIFType _apt_Universe; + +const pkgIndexFile::Type *edspIndex::GetType() const +{ + return &_apt_Universe; +} + /*}}}*/ diff --git a/apt-pkg/edsp/edspindexfile.h b/apt-pkg/edsp/edspindexfile.h new file mode 100644 index 000000000..4ef7787e7 --- /dev/null +++ b/apt-pkg/edsp/edspindexfile.h @@ -0,0 +1,25 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + The universe file is designed to work as an intermediate file between + APT and the resolver. Its on propose very similar to a dpkg status file + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_EDSPINDEXFILE_H +#define PKGLIB_EDSPINDEXFILE_H + +#include +#include + +class edspIndex : public debStatusIndex +{ + public: + + virtual const Type *GetType() const; + + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + + edspIndex(string File); +}; + +#endif diff --git a/apt-pkg/edsp/edsplistparser.cc b/apt-pkg/edsp/edsplistparser.cc new file mode 100644 index 000000000..3e57ea822 --- /dev/null +++ b/apt-pkg/edsp/edsplistparser.cc @@ -0,0 +1,109 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Package Cache Generator - Generator for the cache structure. + + This builds the cache structure from the abstract package list parser. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include +#include +#include +#include +#include +#include + /*}}}*/ + +// ListParser::edspListParser - Constructor /*{{{*/ +edspListParser::edspListParser(FileFd *File, string const &Arch) : debListParser(File, Arch) +{} + /*}}}*/ +// ListParser::NewVersion - Fill in the version structure /*{{{*/ +bool edspListParser::NewVersion(pkgCache::VerIterator &Ver) +{ + Ver->ID = Section.FindI("APT-ID", Ver->ID); + return debListParser::NewVersion(Ver); +} + /*}}}*/ +// ListParser::Description - Return the description string /*{{{*/ +// --------------------------------------------------------------------- +/* Sorry, no description for the resolvers… */ +string edspListParser::Description() +{ + return ""; +} +string edspListParser::DescriptionLanguage() +{ + return ""; +} +MD5SumValue edspListParser::Description_md5() +{ + return MD5SumValue(""); +} + /*}}}*/ +// ListParser::VersionHash - Compute a unique hash for this version /*{{{*/ +// --------------------------------------------------------------------- +/* */ +unsigned short edspListParser::VersionHash() +{ + if (Section.Exists("APT-Hash") == true) + return Section.FindI("APT-Hash"); + else if (Section.Exists("APT-ID") == true) + return Section.FindI("APT-ID"); + return 0; +} + /*}}}*/ +// ListParser::ParseStatus - Parse the status field /*{{{*/ +// --------------------------------------------------------------------- +/* The Status: line here is not a normal dpkg one but just one which tells + use if the package is installed or not, where missing means not. */ +bool edspListParser::ParseStatus(pkgCache::PkgIterator &Pkg, + pkgCache::VerIterator &Ver) +{ + const char *Start; + const char *Stop; + if (Section.Find("Status",Start,Stop) == false) + return true; + + // UsePackage() is responsible for setting the flag in the default case + bool const static essential = _config->Find("pkgCacheGen::Essential", "") == "installed"; + if (essential == true && + Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false) + return false; + + // Isolate the first word + const char *I = Start; + for(; I < Stop && *I != ' '; I++); + + // Process the flag field + WordList StatusList[] = {{"installed",pkgCache::State::Installed}, + {}}; + if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false) + return _error->Error("Malformed Status line"); + + /* A Status line marks the package as indicating the current + version as well. Only if it is actually installed.. Otherwise + the interesting dpkg handling of the status file creates bogus + entries. */ + if (!(Pkg->CurrentState == pkgCache::State::NotInstalled || + Pkg->CurrentState == pkgCache::State::ConfigFiles)) + { + if (Ver.end() == true) + _error->Warning("Encountered status field in a non-version description"); + else + Pkg->CurrentVer = Ver.Index(); + } + + return true; +} + /*}}}*/ +// ListParser::LoadReleaseInfo - Load the release information /*{{{*/ +bool edspListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, + FileFd &File, string component) +{ + return true; +} + /*}}}*/ diff --git a/apt-pkg/edsp/edsplistparser.h b/apt-pkg/edsp/edsplistparser.h new file mode 100644 index 000000000..ec9f09905 --- /dev/null +++ b/apt-pkg/edsp/edsplistparser.h @@ -0,0 +1,38 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + EDSP Package List Parser - This implements the abstract parser + interface for the APT specific intermediate format which is passed + to external resolvers + + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_EDSPLISTPARSER_H +#define PKGLIB_EDSPLISTPARSER_H + +#include +#include +#include +#include + +class edspListParser : public debListParser +{ + public: + virtual bool NewVersion(pkgCache::VerIterator &Ver); + virtual string Description(); + virtual string DescriptionLanguage(); + virtual MD5SumValue Description_md5(); + virtual unsigned short VersionHash(); + + bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File, + string section); + + edspListParser(FileFd *File, string const &Arch = ""); + + protected: + virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); + +}; + +#endif diff --git a/apt-pkg/edsp/edspsystem.cc b/apt-pkg/edsp/edspsystem.cc new file mode 100644 index 000000000..579ffc656 --- /dev/null +++ b/apt-pkg/edsp/edspsystem.cc @@ -0,0 +1,117 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + This system provides the abstraction to use the universe file as the + only source of package information to be able to feed the created file + back to APT for its own consumption (eat your own dogfood). + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + /*}}}*/ + +edspSystem edspSys; + +// System::debSystem - Constructor /*{{{*/ +edspSystem::edspSystem() +{ + StatusFile = 0; + + Label = "Debian APT solver interface"; + VS = &debVS; +} + /*}}}*/ +// System::~debSystem - Destructor /*{{{*/ +edspSystem::~edspSystem() +{ + delete StatusFile; +} + /*}}}*/ +// System::Lock - Get the lock /*{{{*/ +bool edspSystem::Lock() +{ + return true; +} + /*}}}*/ +// System::UnLock - Drop a lock /*{{{*/ +bool edspSystem::UnLock(bool NoErrors) +{ + return true; +} + /*}}}*/ +// System::CreatePM - Create the underlying package manager /*{{{*/ +// --------------------------------------------------------------------- +/* we can't use edsp input as input for real installations - just a + simulation can work, but everything else will fail bigtime */ +pkgPackageManager *edspSystem::CreatePM(pkgDepCache *Cache) const +{ + return NULL; +} + /*}}}*/ +// System::Initialize - Setup the configuration space.. /*{{{*/ +bool edspSystem::Initialize(Configuration &Cnf) +{ + Cnf.Set("Dir::State::extended_states", "/dev/null"); + Cnf.Set("Dir::State::status","/dev/null"); + Cnf.Set("Dir::State::lists","/dev/null"); + + Cnf.Set("Debug::NoLocking", "true"); + Cnf.Set("APT::Get::Simulate", "true"); + + if (StatusFile) { + delete StatusFile; + StatusFile = 0; + } + return true; +} + /*}}}*/ +// System::ArchiveSupported - Is a file format supported /*{{{*/ +bool edspSystem::ArchiveSupported(const char *Type) +{ + return false; +} + /*}}}*/ +// System::Score - Determine if we should use the edsp system /*{{{*/ +signed edspSystem::Score(Configuration const &Cnf) +{ + if (FileExists(Cnf.FindFile("Dir::State::universe","")) == true) + return 1000; + return -1000; +} + /*}}}*/ +// System::AddStatusFiles - Register the status files /*{{{*/ +bool edspSystem::AddStatusFiles(vector &List) +{ + if (StatusFile == 0) + StatusFile = new edspIndex(_config->FindFile("Dir::State::universe")); + List.push_back(StatusFile); + return true; +} + /*}}}*/ +// System::FindIndex - Get an index file for status files /*{{{*/ +bool edspSystem::FindIndex(pkgCache::PkgFileIterator File, + pkgIndexFile *&Found) const +{ + if (StatusFile == 0) + return false; + if (StatusFile->FindInCache(*File.Cache()) == File) + { + Found = StatusFile; + return true; + } + + return false; +} + /*}}}*/ diff --git a/apt-pkg/edsp/edspsystem.h b/apt-pkg/edsp/edspsystem.h new file mode 100644 index 000000000..bc5be61d1 --- /dev/null +++ b/apt-pkg/edsp/edspsystem.h @@ -0,0 +1,38 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: debsystem.h,v 1.4 2003/01/11 07:16:33 jgg Exp $ +/* ###################################################################### + + System - Debian version of the System Class + + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_EDSPSYSTEM_H +#define PKGLIB_EDSPSYSTEM_H + +#include + +class edspIndex; +class edspSystem : public pkgSystem +{ + edspIndex *StatusFile; + + public: + + virtual bool Lock(); + virtual bool UnLock(bool NoErrors = false); + virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const; + virtual bool Initialize(Configuration &Cnf); + virtual bool ArchiveSupported(const char *Type); + virtual signed Score(Configuration const &Cnf); + virtual bool AddStatusFiles(std::vector &List); + virtual bool FindIndex(pkgCache::PkgFileIterator File, + pkgIndexFile *&Found) const; + + edspSystem(); + ~edspSystem(); +}; + +extern edspSystem edspSys; + +#endif diff --git a/apt-pkg/edsp/edspwriter.cc b/apt-pkg/edsp/edspwriter.cc new file mode 100644 index 000000000..38d0d82c5 --- /dev/null +++ b/apt-pkg/edsp/edspwriter.cc @@ -0,0 +1,130 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + Set of methods to help writing and reading everything needed for EDSP + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include +#include +#include +#include +#include + +#include +#include + +#include + /*}}}*/ + +// edspWriter::WriteUniverse - to the given file descriptor /*{{{*/ +bool edspWriter::WriteUniverse(pkgDepCache &Cache, FILE* output) +{ + // we could use pkgCache::DepType and ::Priority, but these would be lokalized strings… + const char * const PrioMap[] = {0, "important", "required", "standard", + "optional", "extra"}; + const char * const DepMap[] = {"", "Depends", "PreDepends", "Suggests", + "Recommends" , "Conflicts", "Replaces", + "Obsoletes", "Breaks", "Enhances"}; + + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + { + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) + { + fprintf(output, "Package: %s\n", Pkg.Name()); + fprintf(output, "Architecture: %s\n", Ver.Arch()); + fprintf(output, "Version: %s\n", Ver.VerStr()); + if (Pkg.CurrentVer() == Ver) + fprintf(output, "Installed: yes\n"); + if (Pkg->SelectedState == pkgCache::State::Hold) + fprintf(output, "Hold: yes\n"); + fprintf(output, "APT-ID: %u\n", Ver->ID); + fprintf(output, "Priority: %s\n", PrioMap[Ver->Priority]); + if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + fprintf(output, "Essential: yes\n"); + fprintf(output, "Section: %s\n", Ver.Section()); + if (Ver->MultiArch == pkgCache::Version::Allowed || Ver->MultiArch == pkgCache::Version::AllAllowed) + fprintf(output, "Multi-Arch: allowed\n"); + else if (Ver->MultiArch == pkgCache::Version::Foreign || Ver->MultiArch == pkgCache::Version::AllForeign) + fprintf(output, "Multi-Arch: foreign\n"); + else if (Ver->MultiArch == pkgCache::Version::Same) + fprintf(output, "Multi-Arch: same\n"); + signed short Pin = std::numeric_limits::min(); + for (pkgCache::VerFileIterator File = Ver.FileList(); File.end() == false; ++File) { + signed short const p = Cache.GetPolicy().GetPriority(File.File()); + if (Pin < p) + Pin = p; + } + fprintf(output, "APT-Pin: %d\n", Pin); + if (Cache.GetCandidateVer(Pkg) == Ver) + fprintf(output, "APT-Candidate: yes\n"); + if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) + fprintf(output, "APT-Automatic: yes\n"); + std::string dependencies[pkgCache::Dep::Enhances + 1]; + bool orGroup = false; + for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) + { + // Ignore implicit dependencies for multiarch here + if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0) + continue; + if (orGroup == false) + dependencies[Dep->Type].append(", "); + dependencies[Dep->Type].append(Dep.TargetPkg().Name()); + if (Dep->Version != 0) + dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); + if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) + { + dependencies[Dep->Type].append(" | "); + orGroup = true; + } + else + orGroup = false; + } + for (int i = 1; i < pkgCache::Dep::Enhances + 1; ++i) + if (dependencies[i].empty() == false) + fprintf(output, "%s: %s\n", DepMap[i], dependencies[i].c_str()+2); + string provides; + for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; ++Prv) + { + // Ignore implicit provides for multiarch here + if (strcmp(Pkg.Arch(), Prv.ParentPkg().Arch()) != 0 || strcmp(Pkg.Name(),Prv.Name()) == 0) + continue; + provides.append(", ").append(Prv.Name()); + } + if (provides.empty() == false) + fprintf(output, "Provides: %s\n", provides.c_str()+2); + + + fprintf(output, "\n"); + } + } + return true; +} + /*}}}*/ +// edspWriter::WriteRequest - to the given file descriptor /*{{{*/ +bool edspWriter::WriteRequest(pkgDepCache &Cache, FILE* output) +{ + string del, inst, upgrade; + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + { + string* req; + if (Cache[Pkg].Delete() == true) + req = &del; + else if (Cache[Pkg].NewInstall() == true) + req = &inst; + else if (Cache[Pkg].Upgrade() == true) + req = &upgrade; + else + continue; + req->append(", ").append(Pkg.FullName()); + } + if (del.empty() == false) + fprintf(output, "Remove: %s\n", del.c_str()+2); + if (inst.empty() == false) + fprintf(output, "Install: %s\n", inst.c_str()+2); + if (upgrade.empty() == false) + fprintf(output, "Upgrade: %s\n", upgrade.c_str()+2); + + return true; +} + /*}}}*/ diff --git a/apt-pkg/edsp/edspwriter.h b/apt-pkg/edsp/edspwriter.h new file mode 100644 index 000000000..52923ff73 --- /dev/null +++ b/apt-pkg/edsp/edspwriter.h @@ -0,0 +1,19 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + Set of methods to help writing and reading everything needed for EDSP + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_EDSPWRITER_H +#define PKGLIB_EDSPWRITER_H + +#include + +class edspWriter /*{{{*/ +{ +public: + bool static WriteUniverse(pkgDepCache &Cache, FILE* output); + bool static WriteRequest(pkgDepCache &Cache, FILE* output); +}; + /*}}}*/ +#endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 4e5ec107f..a7880e81c 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -3,7 +3,7 @@ BASE=.. SUBDIR=apt-pkg # Header location -SUBDIRS = deb contrib +SUBDIRS = deb edsp contrib HEADER_TARGETDIRS = apt-pkg # Bring in the default rules @@ -53,6 +53,11 @@ SOURCE+= deb/deblistparser.cc deb/debrecords.cc deb/dpkgpm.cc \ HEADERS+= debversion.h debsrcrecords.h dpkgpm.h debrecords.h \ deblistparser.h debsystem.h debindexfile.h debmetaindex.h +# Source code for the APT resolver interface specific components +SOURCE+= edsp/edsplistparser.cc edsp/edspindexfile.cc edsp/edspsystem.cc \ + edsp/edspwriter.cc +HEADERS+= edsplistparser.h edspindexfile.h edspsystem.h edspwriter.h + HEADERS := $(addprefix apt-pkg/,$(HEADERS)) include $(LIBRARY_H) diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index b0ee04554..46dd22007 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -641,7 +641,7 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress) bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same); for (vector::const_iterator A = archs.begin(); A != archs.end(); ++A) { - if (*A == Arch) + if (Arch == 0 || *A == Arch) continue; /* We allow only one installed arch at the time per group, therefore each group member conflicts diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 94c7fd4af..4e4077feb 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -269,6 +269,10 @@ signed short pkgPolicy::GetPriority(pkgCache::PkgIterator const &Pkg) } return 0; +} +signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &File) +{ + return PFPriority[File->ID]; } /*}}}*/ // PreferenceSection class - Overriding the default TrimRecord method /*{{{*/ diff --git a/apt-pkg/policy.h b/apt-pkg/policy.h index f8b2678de..e7f36d618 100644 --- a/apt-pkg/policy.h +++ b/apt-pkg/policy.h @@ -69,14 +69,13 @@ class pkgPolicy : public pkgDepCache::Policy // Things for manipulating pins void CreatePin(pkgVersionMatch::MatchType Type,string Pkg, string Data,signed short Priority); - inline signed short GetPriority(pkgCache::PkgFileIterator const &File) - {return PFPriority[File->ID];}; - signed short GetPriority(pkgCache::PkgIterator const &Pkg); pkgCache::VerIterator GetMatch(pkgCache::PkgIterator const &Pkg); // Things for the cache interface. virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator const &Pkg); - virtual bool IsImportantDep(pkgCache::DepIterator const &Dep) {return pkgDepCache::Policy::IsImportantDep(Dep);}; + virtual signed short GetPriority(pkgCache::PkgIterator const &Pkg); + virtual signed short GetPriority(pkgCache::PkgFileIterator const &File); + bool InitDefaults(); pkgPolicy(pkgCache *Owner); -- cgit v1.2.3 From e3674d91d27a7290d2b01e14eb2540e10be9d883 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 30 Mar 2011 22:15:40 +0200 Subject: be able to write solutions, too --- apt-pkg/algorithms.cc | 6 ++++++ apt-pkg/edsp/edspwriter.cc | 20 ++++++++++++++++++++ apt-pkg/edsp/edspwriter.h | 1 + 3 files changed, 27 insertions(+) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 2ca3404a0..35752a5c4 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -748,6 +748,12 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) output = fopen("/tmp/request.log", "w"); edspWriter::WriteRequest(Cache, output); fclose(output); + if (ResolveInternal(BrokenFix) == false) + return false; + output = fopen("/tmp/solution.log", "w"); + edspWriter::WriteSolution(Cache, output); + fclose(output); + return true; } return ResolveInternal(BrokenFix); } diff --git a/apt-pkg/edsp/edspwriter.cc b/apt-pkg/edsp/edspwriter.cc index 38d0d82c5..ea46065c2 100644 --- a/apt-pkg/edsp/edspwriter.cc +++ b/apt-pkg/edsp/edspwriter.cc @@ -125,6 +125,26 @@ bool edspWriter::WriteRequest(pkgDepCache &Cache, FILE* output) if (upgrade.empty() == false) fprintf(output, "Upgrade: %s\n", upgrade.c_str()+2); + return true; +} + /*}}}*/ +// edspWriter::WriteSolution - to the given file descriptor /*{{{*/ +bool edspWriter::WriteSolution(pkgDepCache &Cache, FILE* output) +{ + bool const Debug = _config->FindB("Debug::EDSPWriter::WriteSolution", false); + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + { + if (Cache[Pkg].Delete() == true) + fprintf(output, "Remove: %d\n", Cache.GetCandidateVer(Pkg)->ID); + else if (Cache[Pkg].NewInstall() == true || Cache[Pkg].Upgrade() == true) + fprintf(output, "Install: %d\n", Cache.GetCandidateVer(Pkg)->ID); + else + continue; + if (Debug == true) + fprintf(output, "Package: %s\nVersion: %s\n", Pkg.FullName().c_str(), Cache.GetCandidateVer(Pkg).VerStr()); + fprintf(output, "\n"); + } + return true; } /*}}}*/ diff --git a/apt-pkg/edsp/edspwriter.h b/apt-pkg/edsp/edspwriter.h index 52923ff73..c42dfd398 100644 --- a/apt-pkg/edsp/edspwriter.h +++ b/apt-pkg/edsp/edspwriter.h @@ -14,6 +14,7 @@ class edspWriter /*{{{*/ public: bool static WriteUniverse(pkgDepCache &Cache, FILE* output); bool static WriteRequest(pkgDepCache &Cache, FILE* output); + bool static WriteSolution(pkgDepCache &Cache, FILE* output); }; /*}}}*/ #endif -- cgit v1.2.3 From 41ceaf02483a826d5797cf0bd61bd7b6013733a8 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 31 Mar 2011 11:47:01 +0200 Subject: add a special scenario filename for using stdin --- apt-pkg/edsp/edspindexfile.cc | 6 +++++- apt-pkg/edsp/edspsystem.cc | 11 +++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index 5a9d5aacd..366325d0f 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -28,7 +28,11 @@ edspIndex::edspIndex(string File) : debStatusIndex(File) // StatusIndex::Merge - Load the index file into a cache /*{{{*/ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const { - FileFd Pkg(File,FileFd::ReadOnlyGzip); + FileFd Pkg; + if (File != "stdin") + Pkg.Open(File, FileFd::ReadOnly); + else + Pkg.OpenDescriptor(STDIN_FILENO, FileFd::ReadOnly); if (_error->PendingError() == true) return false; edspListParser Parser(&Pkg); diff --git a/apt-pkg/edsp/edspsystem.cc b/apt-pkg/edsp/edspsystem.cc index 579ffc656..c8e417b1d 100644 --- a/apt-pkg/edsp/edspsystem.cc +++ b/apt-pkg/edsp/edspsystem.cc @@ -86,8 +86,10 @@ bool edspSystem::ArchiveSupported(const char *Type) // System::Score - Determine if we should use the edsp system /*{{{*/ signed edspSystem::Score(Configuration const &Cnf) { + if (Cnf.Find("Dir::State::universe", "") == "stdin") + return 1000; if (FileExists(Cnf.FindFile("Dir::State::universe","")) == true) - return 1000; + return 1000; return -1000; } /*}}}*/ @@ -95,7 +97,12 @@ signed edspSystem::Score(Configuration const &Cnf) bool edspSystem::AddStatusFiles(vector &List) { if (StatusFile == 0) - StatusFile = new edspIndex(_config->FindFile("Dir::State::universe")); + { + if (_config->Find("Dir::State::universe", "") == "stdin") + StatusFile = new edspIndex("stdin"); + else + StatusFile = new edspIndex(_config->FindFile("Dir::State::universe")); + } List.push_back(StatusFile); return true; } -- cgit v1.2.3 From e0a78caad639a3fa8d50edf3374a06805ab86315 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 31 Mar 2011 11:58:24 +0200 Subject: rename the 'universe' to 'scenario' to reflect the naming in the draft --- apt-pkg/algorithms.cc | 4 ++-- apt-pkg/edsp/edspindexfile.cc | 6 +++--- apt-pkg/edsp/edspindexfile.h | 2 +- apt-pkg/edsp/edspsystem.cc | 10 +++++----- apt-pkg/edsp/edspwriter.cc | 2 +- apt-pkg/edsp/edspwriter.h | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 35752a5c4..b55ff2897 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -742,8 +742,8 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) std::string const solver = _config->Find("APT::Solver::Name", "internal"); if (solver != "internal") { - FILE* output = fopen("/tmp/universe.log", "w"); - edspWriter::WriteUniverse(Cache, output); + FILE* output = fopen("/tmp/scenario.log", "w"); + edspWriter::WriteScenario(Cache, output); fclose(output); output = fopen("/tmp/request.log", "w"); edspWriter::WriteRequest(Cache, output); diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index 366325d0f..f5881e663 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -1,7 +1,7 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ /* ###################################################################### - The universe file is designed to work as an intermediate file between + The scenario file is designed to work as an intermediate file between APT and the resolver. Its on propose very similar to a dpkg status file ##################################################################### */ /*}}}*/ @@ -51,7 +51,7 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const return _error->Errno("fstat","Failed to stat"); CFile->Size = St.st_size; CFile->mtime = St.st_mtime; - CFile->Archive = Gen.WriteUniqString("universe"); + CFile->Archive = Gen.WriteUniqString("edsp::scenario"); if (Gen.MergeList(Parser) == false) return _error->Error("Problem with MergeList %s",File.c_str()); @@ -67,7 +67,7 @@ class edspIFType: public pkgIndexFile::Type // we don't have a record parser for this type as the file is not presistent return NULL; }; - edspIFType() {Label = "APT universe file";}; + edspIFType() {Label = "EDSP scenario file";}; }; static edspIFType _apt_Universe; diff --git a/apt-pkg/edsp/edspindexfile.h b/apt-pkg/edsp/edspindexfile.h index 4ef7787e7..87c06557c 100644 --- a/apt-pkg/edsp/edspindexfile.h +++ b/apt-pkg/edsp/edspindexfile.h @@ -1,7 +1,7 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ /* ###################################################################### - The universe file is designed to work as an intermediate file between + The scenario file is designed to work as an intermediate file between APT and the resolver. Its on propose very similar to a dpkg status file ##################################################################### */ /*}}}*/ diff --git a/apt-pkg/edsp/edspsystem.cc b/apt-pkg/edsp/edspsystem.cc index c8e417b1d..3a0494e19 100644 --- a/apt-pkg/edsp/edspsystem.cc +++ b/apt-pkg/edsp/edspsystem.cc @@ -2,7 +2,7 @@ // Description /*{{{*/ /* ###################################################################### - This system provides the abstraction to use the universe file as the + This system provides the abstraction to use the scenario file as the only source of package information to be able to feed the created file back to APT for its own consumption (eat your own dogfood). @@ -86,9 +86,9 @@ bool edspSystem::ArchiveSupported(const char *Type) // System::Score - Determine if we should use the edsp system /*{{{*/ signed edspSystem::Score(Configuration const &Cnf) { - if (Cnf.Find("Dir::State::universe", "") == "stdin") + if (Cnf.Find("Dir::State::edsp::scenario", "") == "stdin") return 1000; - if (FileExists(Cnf.FindFile("Dir::State::universe","")) == true) + if (FileExists(Cnf.FindFile("Dir::State::edsp::scenario","")) == true) return 1000; return -1000; } @@ -98,10 +98,10 @@ bool edspSystem::AddStatusFiles(vector &List) { if (StatusFile == 0) { - if (_config->Find("Dir::State::universe", "") == "stdin") + if (_config->Find("Dir::State::edsp::scenario", "") == "stdin") StatusFile = new edspIndex("stdin"); else - StatusFile = new edspIndex(_config->FindFile("Dir::State::universe")); + StatusFile = new edspIndex(_config->FindFile("Dir::State::edsp::scenario")); } List.push_back(StatusFile); return true; diff --git a/apt-pkg/edsp/edspwriter.cc b/apt-pkg/edsp/edspwriter.cc index ea46065c2..5c741c45d 100644 --- a/apt-pkg/edsp/edspwriter.cc +++ b/apt-pkg/edsp/edspwriter.cc @@ -18,7 +18,7 @@ /*}}}*/ // edspWriter::WriteUniverse - to the given file descriptor /*{{{*/ -bool edspWriter::WriteUniverse(pkgDepCache &Cache, FILE* output) +bool edspWriter::WriteScenario(pkgDepCache &Cache, FILE* output) { // we could use pkgCache::DepType and ::Priority, but these would be lokalized strings… const char * const PrioMap[] = {0, "important", "required", "standard", diff --git a/apt-pkg/edsp/edspwriter.h b/apt-pkg/edsp/edspwriter.h index c42dfd398..2b417956e 100644 --- a/apt-pkg/edsp/edspwriter.h +++ b/apt-pkg/edsp/edspwriter.h @@ -12,7 +12,7 @@ class edspWriter /*{{{*/ { public: - bool static WriteUniverse(pkgDepCache &Cache, FILE* output); + bool static WriteScenario(pkgDepCache &Cache, FILE* output); bool static WriteRequest(pkgDepCache &Cache, FILE* output); bool static WriteSolution(pkgDepCache &Cache, FILE* output); }; -- cgit v1.2.3 From b195733d0f3476ae92f2689ba5c584a69171f170 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 31 Mar 2011 12:17:39 +0200 Subject: parse the state of the package from the scenario file correctly --- apt-pkg/edsp/edsplistparser.cc | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/apt-pkg/edsp/edsplistparser.cc b/apt-pkg/edsp/edsplistparser.cc index 3e57ea822..913455efa 100644 --- a/apt-pkg/edsp/edsplistparser.cc +++ b/apt-pkg/edsp/edsplistparser.cc @@ -63,40 +63,18 @@ unsigned short edspListParser::VersionHash() bool edspListParser::ParseStatus(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver) { - const char *Start; - const char *Stop; - if (Section.Find("Status",Start,Stop) == false) - return true; - - // UsePackage() is responsible for setting the flag in the default case - bool const static essential = _config->Find("pkgCacheGen::Essential", "") == "installed"; - if (essential == true && - Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false) + if (Section.FindFlag("Hold",Pkg->Flags,pkgCache::State::Installed) == false) return false; - // Isolate the first word - const char *I = Start; - for(; I < Stop && *I != ' '; I++); - - // Process the flag field - WordList StatusList[] = {{"installed",pkgCache::State::Installed}, - {}}; - if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false) - return _error->Error("Malformed Status line"); - - /* A Status line marks the package as indicating the current - version as well. Only if it is actually installed.. Otherwise - the interesting dpkg handling of the status file creates bogus - entries. */ - if (!(Pkg->CurrentState == pkgCache::State::NotInstalled || - Pkg->CurrentState == pkgCache::State::ConfigFiles)) + unsigned long state = 0; + if (Section.FindFlag("Installed",state,pkgCache::State::Installed) == false) + return false; + if (state != 0) { - if (Ver.end() == true) - _error->Warning("Encountered status field in a non-version description"); - else - Pkg->CurrentVer = Ver.Index(); + Pkg->CurrentState = pkgCache::State::Installed; + Pkg->CurrentVer = Ver.Index(); } - + return true; } /*}}}*/ -- cgit v1.2.3 From 85bcab87a3c6f8d4b1369a5a4bd5a73a28f41dce Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 31 Mar 2011 14:50:34 +0200 Subject: strip the Dir::state from the config name as it will never be there --- apt-pkg/edsp/edspsystem.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apt-pkg/edsp/edspsystem.cc b/apt-pkg/edsp/edspsystem.cc index 3a0494e19..ac0bb8beb 100644 --- a/apt-pkg/edsp/edspsystem.cc +++ b/apt-pkg/edsp/edspsystem.cc @@ -86,9 +86,9 @@ bool edspSystem::ArchiveSupported(const char *Type) // System::Score - Determine if we should use the edsp system /*{{{*/ signed edspSystem::Score(Configuration const &Cnf) { - if (Cnf.Find("Dir::State::edsp::scenario", "") == "stdin") + if (Cnf.Find("edsp::scenario", "") == "stdin") return 1000; - if (FileExists(Cnf.FindFile("Dir::State::edsp::scenario","")) == true) + if (FileExists(Cnf.FindFile("edsp::scenario","")) == true) return 1000; return -1000; } @@ -98,10 +98,10 @@ bool edspSystem::AddStatusFiles(vector &List) { if (StatusFile == 0) { - if (_config->Find("Dir::State::edsp::scenario", "") == "stdin") + if (_config->Find("edsp::scenario", "") == "stdin") StatusFile = new edspIndex("stdin"); else - StatusFile = new edspIndex(_config->FindFile("Dir::State::edsp::scenario")); + StatusFile = new edspIndex(_config->FindFile("edsp::scenario")); } List.push_back(StatusFile); return true; -- cgit v1.2.3 From 29099cb6855af2e465d26e888160e4f97bda4f0b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 31 Mar 2011 14:56:10 +0200 Subject: add the methods we will need to write to make working with EDSP possible --- apt-pkg/edsp/edspwriter.cc | 12 +++++++++++- apt-pkg/edsp/edspwriter.h | 14 +++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/apt-pkg/edsp/edspwriter.cc b/apt-pkg/edsp/edspwriter.cc index 5c741c45d..2f6bde5a1 100644 --- a/apt-pkg/edsp/edspwriter.cc +++ b/apt-pkg/edsp/edspwriter.cc @@ -17,7 +17,7 @@ #include /*}}}*/ -// edspWriter::WriteUniverse - to the given file descriptor /*{{{*/ +// edspWriter::WriteScenario - to the given file descriptor /*{{{*/ bool edspWriter::WriteScenario(pkgDepCache &Cache, FILE* output) { // we could use pkgCache::DepType and ::Priority, but these would be lokalized strings… @@ -128,6 +128,15 @@ bool edspWriter::WriteRequest(pkgDepCache &Cache, FILE* output) return true; } /*}}}*/ +bool edspWriter::ReadResponse(FILE* input, pkgDepCache &Cache) { return false; } + +bool edspWriter::ReadRequest(FILE* input, std::list &install, + std::list &remove) +{ return false; } +bool edspWriter::ApplyRequest(std::list const &install, + std::list const &remove, + pkgDepCache &Cache) +{ return false; } // edspWriter::WriteSolution - to the given file descriptor /*{{{*/ bool edspWriter::WriteSolution(pkgDepCache &Cache, FILE* output) { @@ -148,3 +157,4 @@ bool edspWriter::WriteSolution(pkgDepCache &Cache, FILE* output) return true; } /*}}}*/ +bool edspWriter::WriteError(std::string const &message, FILE* output) { return false; } diff --git a/apt-pkg/edsp/edspwriter.h b/apt-pkg/edsp/edspwriter.h index 2b417956e..c5eed788f 100644 --- a/apt-pkg/edsp/edspwriter.h +++ b/apt-pkg/edsp/edspwriter.h @@ -9,12 +9,24 @@ #include +#include + class edspWriter /*{{{*/ { public: - bool static WriteScenario(pkgDepCache &Cache, FILE* output); bool static WriteRequest(pkgDepCache &Cache, FILE* output); + bool static WriteScenario(pkgDepCache &Cache, FILE* output); + bool static ReadResponse(FILE* input, pkgDepCache &Cache); + + // ReadScenario is provided by the listparser infrastructure + bool static ReadRequest(FILE* input, std::list &install, + std::list &remove); + bool static ApplyRequest(std::list const &install, + std::list const &remove, + pkgDepCache &Cache); bool static WriteSolution(pkgDepCache &Cache, FILE* output); + bool static WriteError(std::string const &message, FILE* output); + }; /*}}}*/ #endif -- cgit v1.2.3 From c3b851268e6e900be2bf0bd715435db9010fd591 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 31 Mar 2011 15:10:13 +0200 Subject: =?UTF-8?q?rename=20edspwriter=20to=20straight=20edsp=20in=20tople?= =?UTF-8?q?vel=20as=20it=20does=20more=20than=20just=20writing=20stuff?= =?UTF-8?q?=E2=80=A6=20it=20also=20reads=20and=20can=20work=20for=20both:?= =?UTF-8?q?=20-=20APT=20talking=20to=20an=20external=20solver=20-=20an=20e?= =?UTF-8?q?xternal=20solver=20(understanding=20EDSP)=20talking=20to=20APT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apt-pkg/algorithms.cc | 8 +-- apt-pkg/edsp.cc | 160 +++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/edsp.h | 32 +++++++++ apt-pkg/edsp/edspwriter.cc | 160 --------------------------------------------- apt-pkg/edsp/edspwriter.h | 32 --------- apt-pkg/makefile | 9 ++- 6 files changed, 200 insertions(+), 201 deletions(-) create mode 100644 apt-pkg/edsp.cc create mode 100644 apt-pkg/edsp.h delete mode 100644 apt-pkg/edsp/edspwriter.cc delete mode 100644 apt-pkg/edsp/edspwriter.h diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index b55ff2897..00f558420 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -743,15 +743,15 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if (solver != "internal") { FILE* output = fopen("/tmp/scenario.log", "w"); - edspWriter::WriteScenario(Cache, output); + EDSP::WriteScenario(Cache, output); fclose(output); output = fopen("/tmp/request.log", "w"); - edspWriter::WriteRequest(Cache, output); + EDSP::WriteRequest(Cache, output); fclose(output); if (ResolveInternal(BrokenFix) == false) return false; output = fopen("/tmp/solution.log", "w"); - edspWriter::WriteSolution(Cache, output); + EDSP::WriteSolution(Cache, output); fclose(output); return true; } diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc new file mode 100644 index 000000000..1af5aed53 --- /dev/null +++ b/apt-pkg/edsp.cc @@ -0,0 +1,160 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + Set of methods to help writing and reading everything needed for EDSP + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include +#include +#include +#include +#include + +#include +#include + +#include + /*}}}*/ + +// EDSP::WriteScenario - to the given file descriptor /*{{{*/ +bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output) +{ + // we could use pkgCache::DepType and ::Priority, but these would be lokalized strings… + const char * const PrioMap[] = {0, "important", "required", "standard", + "optional", "extra"}; + const char * const DepMap[] = {"", "Depends", "PreDepends", "Suggests", + "Recommends" , "Conflicts", "Replaces", + "Obsoletes", "Breaks", "Enhances"}; + + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + { + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) + { + fprintf(output, "Package: %s\n", Pkg.Name()); + fprintf(output, "Architecture: %s\n", Ver.Arch()); + fprintf(output, "Version: %s\n", Ver.VerStr()); + if (Pkg.CurrentVer() == Ver) + fprintf(output, "Installed: yes\n"); + if (Pkg->SelectedState == pkgCache::State::Hold) + fprintf(output, "Hold: yes\n"); + fprintf(output, "APT-ID: %u\n", Ver->ID); + fprintf(output, "Priority: %s\n", PrioMap[Ver->Priority]); + if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + fprintf(output, "Essential: yes\n"); + fprintf(output, "Section: %s\n", Ver.Section()); + if (Ver->MultiArch == pkgCache::Version::Allowed || Ver->MultiArch == pkgCache::Version::AllAllowed) + fprintf(output, "Multi-Arch: allowed\n"); + else if (Ver->MultiArch == pkgCache::Version::Foreign || Ver->MultiArch == pkgCache::Version::AllForeign) + fprintf(output, "Multi-Arch: foreign\n"); + else if (Ver->MultiArch == pkgCache::Version::Same) + fprintf(output, "Multi-Arch: same\n"); + signed short Pin = std::numeric_limits::min(); + for (pkgCache::VerFileIterator File = Ver.FileList(); File.end() == false; ++File) { + signed short const p = Cache.GetPolicy().GetPriority(File.File()); + if (Pin < p) + Pin = p; + } + fprintf(output, "APT-Pin: %d\n", Pin); + if (Cache.GetCandidateVer(Pkg) == Ver) + fprintf(output, "APT-Candidate: yes\n"); + if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) + fprintf(output, "APT-Automatic: yes\n"); + std::string dependencies[pkgCache::Dep::Enhances + 1]; + bool orGroup = false; + for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) + { + // Ignore implicit dependencies for multiarch here + if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0) + continue; + if (orGroup == false) + dependencies[Dep->Type].append(", "); + dependencies[Dep->Type].append(Dep.TargetPkg().Name()); + if (Dep->Version != 0) + dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); + if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) + { + dependencies[Dep->Type].append(" | "); + orGroup = true; + } + else + orGroup = false; + } + for (int i = 1; i < pkgCache::Dep::Enhances + 1; ++i) + if (dependencies[i].empty() == false) + fprintf(output, "%s: %s\n", DepMap[i], dependencies[i].c_str()+2); + string provides; + for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; ++Prv) + { + // Ignore implicit provides for multiarch here + if (strcmp(Pkg.Arch(), Prv.ParentPkg().Arch()) != 0 || strcmp(Pkg.Name(),Prv.Name()) == 0) + continue; + provides.append(", ").append(Prv.Name()); + } + if (provides.empty() == false) + fprintf(output, "Provides: %s\n", provides.c_str()+2); + + + fprintf(output, "\n"); + } + } + return true; +} + /*}}}*/ +// EDSP::WriteRequest - to the given file descriptor /*{{{*/ +bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output) +{ + string del, inst, upgrade; + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + { + string* req; + if (Cache[Pkg].Delete() == true) + req = &del; + else if (Cache[Pkg].NewInstall() == true) + req = &inst; + else if (Cache[Pkg].Upgrade() == true) + req = &upgrade; + else + continue; + req->append(", ").append(Pkg.FullName()); + } + if (del.empty() == false) + fprintf(output, "Remove: %s\n", del.c_str()+2); + if (inst.empty() == false) + fprintf(output, "Install: %s\n", inst.c_str()+2); + if (upgrade.empty() == false) + fprintf(output, "Upgrade: %s\n", upgrade.c_str()+2); + + return true; +} + /*}}}*/ +bool EDSP::ReadResponse(FILE* input, pkgDepCache &Cache) { return false; } + +bool EDSP::ReadRequest(FILE* input, std::list &install, + std::list &remove) +{ return false; } +bool EDSP::ApplyRequest(std::list const &install, + std::list const &remove, + pkgDepCache &Cache) +{ return false; } +// EDSP::WriteSolution - to the given file descriptor /*{{{*/ +bool EDSP::WriteSolution(pkgDepCache &Cache, FILE* output) +{ + bool const Debug = _config->FindB("Debug::EDSPWriter::WriteSolution", false); + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + { + if (Cache[Pkg].Delete() == true) + fprintf(output, "Remove: %d\n", Cache.GetCandidateVer(Pkg)->ID); + else if (Cache[Pkg].NewInstall() == true || Cache[Pkg].Upgrade() == true) + fprintf(output, "Install: %d\n", Cache.GetCandidateVer(Pkg)->ID); + else + continue; + if (Debug == true) + fprintf(output, "Package: %s\nVersion: %s\n", Pkg.FullName().c_str(), Cache.GetCandidateVer(Pkg).VerStr()); + fprintf(output, "\n"); + } + + return true; +} + /*}}}*/ +bool EDSP::WriteError(std::string const &message, FILE* output) { return false; } diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h new file mode 100644 index 000000000..ef137b8f6 --- /dev/null +++ b/apt-pkg/edsp.h @@ -0,0 +1,32 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + Set of methods to help writing and reading everything needed for EDSP + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_EDSP_H +#define PKGLIB_EDSP_H + +#include + +#include + +class EDSP /*{{{*/ +{ +public: + bool static WriteRequest(pkgDepCache &Cache, FILE* output); + bool static WriteScenario(pkgDepCache &Cache, FILE* output); + bool static ReadResponse(FILE* input, pkgDepCache &Cache); + + // ReadScenario is provided by the listparser infrastructure + bool static ReadRequest(FILE* input, std::list &install, + std::list &remove); + bool static ApplyRequest(std::list const &install, + std::list const &remove, + pkgDepCache &Cache); + bool static WriteSolution(pkgDepCache &Cache, FILE* output); + bool static WriteError(std::string const &message, FILE* output); + +}; + /*}}}*/ +#endif diff --git a/apt-pkg/edsp/edspwriter.cc b/apt-pkg/edsp/edspwriter.cc deleted file mode 100644 index 2f6bde5a1..000000000 --- a/apt-pkg/edsp/edspwriter.cc +++ /dev/null @@ -1,160 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -/* ###################################################################### - Set of methods to help writing and reading everything needed for EDSP - ##################################################################### */ - /*}}}*/ -// Include Files /*{{{*/ -#include -#include -#include -#include -#include - -#include -#include - -#include - /*}}}*/ - -// edspWriter::WriteScenario - to the given file descriptor /*{{{*/ -bool edspWriter::WriteScenario(pkgDepCache &Cache, FILE* output) -{ - // we could use pkgCache::DepType and ::Priority, but these would be lokalized strings… - const char * const PrioMap[] = {0, "important", "required", "standard", - "optional", "extra"}; - const char * const DepMap[] = {"", "Depends", "PreDepends", "Suggests", - "Recommends" , "Conflicts", "Replaces", - "Obsoletes", "Breaks", "Enhances"}; - - for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) - { - for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) - { - fprintf(output, "Package: %s\n", Pkg.Name()); - fprintf(output, "Architecture: %s\n", Ver.Arch()); - fprintf(output, "Version: %s\n", Ver.VerStr()); - if (Pkg.CurrentVer() == Ver) - fprintf(output, "Installed: yes\n"); - if (Pkg->SelectedState == pkgCache::State::Hold) - fprintf(output, "Hold: yes\n"); - fprintf(output, "APT-ID: %u\n", Ver->ID); - fprintf(output, "Priority: %s\n", PrioMap[Ver->Priority]); - if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) - fprintf(output, "Essential: yes\n"); - fprintf(output, "Section: %s\n", Ver.Section()); - if (Ver->MultiArch == pkgCache::Version::Allowed || Ver->MultiArch == pkgCache::Version::AllAllowed) - fprintf(output, "Multi-Arch: allowed\n"); - else if (Ver->MultiArch == pkgCache::Version::Foreign || Ver->MultiArch == pkgCache::Version::AllForeign) - fprintf(output, "Multi-Arch: foreign\n"); - else if (Ver->MultiArch == pkgCache::Version::Same) - fprintf(output, "Multi-Arch: same\n"); - signed short Pin = std::numeric_limits::min(); - for (pkgCache::VerFileIterator File = Ver.FileList(); File.end() == false; ++File) { - signed short const p = Cache.GetPolicy().GetPriority(File.File()); - if (Pin < p) - Pin = p; - } - fprintf(output, "APT-Pin: %d\n", Pin); - if (Cache.GetCandidateVer(Pkg) == Ver) - fprintf(output, "APT-Candidate: yes\n"); - if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) - fprintf(output, "APT-Automatic: yes\n"); - std::string dependencies[pkgCache::Dep::Enhances + 1]; - bool orGroup = false; - for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) - { - // Ignore implicit dependencies for multiarch here - if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0) - continue; - if (orGroup == false) - dependencies[Dep->Type].append(", "); - dependencies[Dep->Type].append(Dep.TargetPkg().Name()); - if (Dep->Version != 0) - dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); - if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) - { - dependencies[Dep->Type].append(" | "); - orGroup = true; - } - else - orGroup = false; - } - for (int i = 1; i < pkgCache::Dep::Enhances + 1; ++i) - if (dependencies[i].empty() == false) - fprintf(output, "%s: %s\n", DepMap[i], dependencies[i].c_str()+2); - string provides; - for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; ++Prv) - { - // Ignore implicit provides for multiarch here - if (strcmp(Pkg.Arch(), Prv.ParentPkg().Arch()) != 0 || strcmp(Pkg.Name(),Prv.Name()) == 0) - continue; - provides.append(", ").append(Prv.Name()); - } - if (provides.empty() == false) - fprintf(output, "Provides: %s\n", provides.c_str()+2); - - - fprintf(output, "\n"); - } - } - return true; -} - /*}}}*/ -// edspWriter::WriteRequest - to the given file descriptor /*{{{*/ -bool edspWriter::WriteRequest(pkgDepCache &Cache, FILE* output) -{ - string del, inst, upgrade; - for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) - { - string* req; - if (Cache[Pkg].Delete() == true) - req = &del; - else if (Cache[Pkg].NewInstall() == true) - req = &inst; - else if (Cache[Pkg].Upgrade() == true) - req = &upgrade; - else - continue; - req->append(", ").append(Pkg.FullName()); - } - if (del.empty() == false) - fprintf(output, "Remove: %s\n", del.c_str()+2); - if (inst.empty() == false) - fprintf(output, "Install: %s\n", inst.c_str()+2); - if (upgrade.empty() == false) - fprintf(output, "Upgrade: %s\n", upgrade.c_str()+2); - - return true; -} - /*}}}*/ -bool edspWriter::ReadResponse(FILE* input, pkgDepCache &Cache) { return false; } - -bool edspWriter::ReadRequest(FILE* input, std::list &install, - std::list &remove) -{ return false; } -bool edspWriter::ApplyRequest(std::list const &install, - std::list const &remove, - pkgDepCache &Cache) -{ return false; } -// edspWriter::WriteSolution - to the given file descriptor /*{{{*/ -bool edspWriter::WriteSolution(pkgDepCache &Cache, FILE* output) -{ - bool const Debug = _config->FindB("Debug::EDSPWriter::WriteSolution", false); - for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) - { - if (Cache[Pkg].Delete() == true) - fprintf(output, "Remove: %d\n", Cache.GetCandidateVer(Pkg)->ID); - else if (Cache[Pkg].NewInstall() == true || Cache[Pkg].Upgrade() == true) - fprintf(output, "Install: %d\n", Cache.GetCandidateVer(Pkg)->ID); - else - continue; - if (Debug == true) - fprintf(output, "Package: %s\nVersion: %s\n", Pkg.FullName().c_str(), Cache.GetCandidateVer(Pkg).VerStr()); - fprintf(output, "\n"); - } - - return true; -} - /*}}}*/ -bool edspWriter::WriteError(std::string const &message, FILE* output) { return false; } diff --git a/apt-pkg/edsp/edspwriter.h b/apt-pkg/edsp/edspwriter.h deleted file mode 100644 index c5eed788f..000000000 --- a/apt-pkg/edsp/edspwriter.h +++ /dev/null @@ -1,32 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -/* ###################################################################### - Set of methods to help writing and reading everything needed for EDSP - ##################################################################### */ - /*}}}*/ -#ifndef PKGLIB_EDSPWRITER_H -#define PKGLIB_EDSPWRITER_H - -#include - -#include - -class edspWriter /*{{{*/ -{ -public: - bool static WriteRequest(pkgDepCache &Cache, FILE* output); - bool static WriteScenario(pkgDepCache &Cache, FILE* output); - bool static ReadResponse(FILE* input, pkgDepCache &Cache); - - // ReadScenario is provided by the listparser infrastructure - bool static ReadRequest(FILE* input, std::list &install, - std::list &remove); - bool static ApplyRequest(std::list const &install, - std::list const &remove, - pkgDepCache &Cache); - bool static WriteSolution(pkgDepCache &Cache, FILE* output); - bool static WriteError(std::string const &message, FILE* output); - -}; - /*}}}*/ -#endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index a7880e81c..e6bcf8524 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -35,7 +35,7 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \ srcrecords.cc cachefile.cc versionmatch.cc policy.cc \ pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \ - aptconfiguration.cc cachefilter.cc cacheset.cc + aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ orderlist.h sourcelist.h packagemanager.h tagfile.h \ init.h pkgcache.h version.h progress.h pkgrecords.h \ @@ -43,7 +43,7 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ clean.h srcrecords.h cachefile.h versionmatch.h policy.h \ pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \ - cachefilter.h cacheset.h + cachefilter.h cacheset.h edsp.h # Source code for the debian specific components # In theory the deb headers do not need to be exported.. @@ -54,9 +54,8 @@ HEADERS+= debversion.h debsrcrecords.h dpkgpm.h debrecords.h \ deblistparser.h debsystem.h debindexfile.h debmetaindex.h # Source code for the APT resolver interface specific components -SOURCE+= edsp/edsplistparser.cc edsp/edspindexfile.cc edsp/edspsystem.cc \ - edsp/edspwriter.cc -HEADERS+= edsplistparser.h edspindexfile.h edspsystem.h edspwriter.h +SOURCE+= edsp/edsplistparser.cc edsp/edspindexfile.cc edsp/edspsystem.cc +HEADERS+= edsplistparser.h edspindexfile.h edspsystem.h HEADERS := $(addprefix apt-pkg/,$(HEADERS)) -- cgit v1.2.3 From 93794bc92e8d2fd84c6e596e3238c31d0832c271 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 31 Mar 2011 15:32:55 +0200 Subject: WriteRequest according to current EDSP draft --- apt-pkg/edsp.cc | 24 +++++++++++++++++------- apt-pkg/edsp.h | 5 ++++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 1af5aed53..db0e2466c 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -102,28 +102,38 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output) } /*}}}*/ // EDSP::WriteRequest - to the given file descriptor /*{{{*/ -bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output) +bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, + bool const DistUpgrade, bool const AutoRemove) { - string del, inst, upgrade; + string del, inst; for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) { string* req; if (Cache[Pkg].Delete() == true) req = &del; - else if (Cache[Pkg].NewInstall() == true) + else if (Cache[Pkg].NewInstall() == true || Cache[Pkg].Upgrade() == true) req = &inst; - else if (Cache[Pkg].Upgrade() == true) - req = &upgrade; else continue; req->append(", ").append(Pkg.FullName()); } + fprintf(output, "Request: EDSP 0.2\n"); if (del.empty() == false) fprintf(output, "Remove: %s\n", del.c_str()+2); if (inst.empty() == false) fprintf(output, "Install: %s\n", inst.c_str()+2); - if (upgrade.empty() == false) - fprintf(output, "Upgrade: %s\n", upgrade.c_str()+2); + if (Upgrade == true) + fprintf(output, "Upgrade: yes\n"); + if (DistUpgrade == true) + fprintf(output, "Dist-Upgrade: yes\n"); + if (AutoRemove == true) + fprintf(output, "Autoremove: yes\n"); + if (_config->FindB("APT::Solver::Strict-Pinning", true) == false) + fprintf(output, "Strict-Pinning: no\n"); + string solverpref("APT::Solver::"); + solverpref.append(_config->Find("APT::Solver::Name", "internal")).append("::Preferences"); + if (_config->Exists(solverpref) == false) + fprintf(output, "Preferences: %s\n", _config->Find(solverpref,"").c_str()); return true; } diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index ef137b8f6..04d8c255f 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -14,7 +14,10 @@ class EDSP /*{{{*/ { public: - bool static WriteRequest(pkgDepCache &Cache, FILE* output); + bool static WriteRequest(pkgDepCache &Cache, FILE* output, + bool const Upgrade = false, + bool const DistUpgrade = false, + bool const AutoRemove = false); bool static WriteScenario(pkgDepCache &Cache, FILE* output); bool static ReadResponse(FILE* input, pkgDepCache &Cache); -- cgit v1.2.3 From 6d5bd6147e210bfb93e4ce0009d4e71c5995eab1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 1 Apr 2011 12:04:13 +0200 Subject: Read and apply install/remove requests correctly --- apt-pkg/algorithms.cc | 4 +- apt-pkg/edsp.cc | 101 ++++++++++++++++++++++++++++++++++++++++++++++---- apt-pkg/edsp.h | 4 +- 3 files changed, 97 insertions(+), 12 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 00f558420..aabb511a2 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -743,10 +743,8 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if (solver != "internal") { FILE* output = fopen("/tmp/scenario.log", "w"); - EDSP::WriteScenario(Cache, output); - fclose(output); - output = fopen("/tmp/request.log", "w"); EDSP::WriteRequest(Cache, output); + EDSP::WriteScenario(Cache, output); fclose(output); if (ResolveInternal(BrokenFix) == false) return false; diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index db0e2466c..6f084ce04 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -115,13 +115,13 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, req = &inst; else continue; - req->append(", ").append(Pkg.FullName()); + req->append(" ").append(Pkg.FullName()); } fprintf(output, "Request: EDSP 0.2\n"); if (del.empty() == false) - fprintf(output, "Remove: %s\n", del.c_str()+2); + fprintf(output, "Remove: %s\n", del.c_str()+1); if (inst.empty() == false) - fprintf(output, "Install: %s\n", inst.c_str()+2); + fprintf(output, "Install: %s\n", inst.c_str()+1); if (Upgrade == true) fprintf(output, "Upgrade: yes\n"); if (DistUpgrade == true) @@ -132,25 +132,110 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, fprintf(output, "Strict-Pinning: no\n"); string solverpref("APT::Solver::"); solverpref.append(_config->Find("APT::Solver::Name", "internal")).append("::Preferences"); - if (_config->Exists(solverpref) == false) + if (_config->Exists(solverpref) == true) fprintf(output, "Preferences: %s\n", _config->Find(solverpref,"").c_str()); + fprintf(output, "\n"); return true; } /*}}}*/ bool EDSP::ReadResponse(FILE* input, pkgDepCache &Cache) { return false; } -bool EDSP::ReadRequest(FILE* input, std::list &install, +// EDSP::ReadLine - first line from the given file descriptor /*{{{*/ +// --------------------------------------------------------------------- +/* Little helper method to read a complete line into a string. Similar to + fgets but we need to use the low-level read() here as otherwise the + listparser will be confused later on as mixing of fgets and read isn't + a supported action according to the manpages and result are undefined */ +bool EDSP::ReadLine(int const input, std::string &line) { + char one; + ssize_t data = 0; + line.erase(); + line.reserve(100); + while ((data = read(input, &one, sizeof(one))) != -1) { + if (data != 1) + continue; + if (one == '\n') + return true; + if (one == '\r') + continue; + if (line.empty() == true && isblank(one) != 0) + continue; + line += one; + } + return false; +} + /*}}}*/ +// EDSP::ReadRequest - first stanza from the given file descriptor /*{{{*/ +bool EDSP::ReadRequest(int const input, std::list &install, std::list &remove) -{ return false; } +{ + std::string line; + while (ReadLine(input, line) == true) + { + // Skip empty lines before request + if (line.empty() == true) + continue; + // The first Tag must be a request, so search for it + if (line.compare(0,8, "Request:") != 0) + continue; + + while (ReadLine(input, line) == true) + { + // empty lines are the end of the request + if (line.empty() == true) + return true; + + std::list *request = NULL; + if (line.compare(0,8, "Install:") == 0) + { + line.erase(0,8); + request = &install; + } + if (line.compare(0,7, "Remove:") == 0) + { + line.erase(0,7); + request = &remove; + } + if (request == NULL) + continue; + size_t end = line.length(); + do { + size_t begin = line.rfind(' '); + if (begin == std::string::npos) + { + request->push_back(line.substr(0,end)); + break; + } + else if (begin < end) + request->push_back(line.substr(begin + 1, end)); + line.erase(begin); + end = line.find_last_not_of(' '); + } while (end != std::string::npos); + } + } + return false; +} + /*}}}*/ +// EDSP::ApplyRequest - first stanza from the given file descriptor /*{{{*/ bool EDSP::ApplyRequest(std::list const &install, std::list const &remove, pkgDepCache &Cache) -{ return false; } +{ + for (std::list::const_iterator i = install.begin(); + i != install.end(); ++i) + Cache.MarkInstall(Cache.FindPkg(*i), false); + + for (std::list::const_iterator i = remove.begin(); + i != remove.end(); ++i) + Cache.MarkDelete(Cache.FindPkg(*i)); + return true; +} + /*}}}*/ // EDSP::WriteSolution - to the given file descriptor /*{{{*/ bool EDSP::WriteSolution(pkgDepCache &Cache, FILE* output) { - bool const Debug = _config->FindB("Debug::EDSPWriter::WriteSolution", false); + bool const Debug = _config->FindB("Debug::EDSP::WriteSolution", false); for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) { if (Cache[Pkg].Delete() == true) diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 04d8c255f..742d89b43 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -13,6 +13,8 @@ class EDSP /*{{{*/ { + bool static ReadLine(int const input, std::string &line); + public: bool static WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade = false, @@ -22,7 +24,7 @@ public: bool static ReadResponse(FILE* input, pkgDepCache &Cache); // ReadScenario is provided by the listparser infrastructure - bool static ReadRequest(FILE* input, std::list &install, + bool static ReadRequest(int const input, std::list &install, std::list &remove); bool static ApplyRequest(std::list const &install, std::list const &remove, -- cgit v1.2.3 From 40795fca99c72b0b43124cdfffb40e8fa3c4d952 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 1 Apr 2011 13:21:38 +0200 Subject: parse also the action flags Upgrade, Dist-Upgrade and alike from the request --- apt-pkg/edsp.cc | 44 +++++++++++++++++++++++++++++++++++++------- apt-pkg/edsp.h | 10 ++++++---- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 6f084ce04..d93b05411 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -166,10 +166,31 @@ bool EDSP::ReadLine(int const input, std::string &line) { return false; } /*}}}*/ +// EDSP::StringToBool - convert yes/no to bool /*{{{*/ +// --------------------------------------------------------------------- +/* we are not as lazy as we are in the global StringToBool as we really + only accept yes/no here - but we will ignore leading spaces */ +bool EDSP::StringToBool(char const *answer, bool const defValue) { + for (; isspace(*answer) != 0; ++answer); + if (strncasecmp(answer, "yes", 3) == 0) + return true; + else if (strncasecmp(answer, "no", 2) == 0) + return false; + else + _error->Warning("Value '%s' is not a boolean 'yes' or 'no'!", answer); + return defValue; +} + /*}}}*/ // EDSP::ReadRequest - first stanza from the given file descriptor /*{{{*/ bool EDSP::ReadRequest(int const input, std::list &install, - std::list &remove) + std::list &remove, bool &upgrade, + bool &distUpgrade, bool &autoRemove) { + install.clear(); + remove.clear(); + upgrade = false; + distUpgrade = false; + autoRemove = false; std::string line; while (ReadLine(input, line) == true) { @@ -177,7 +198,7 @@ bool EDSP::ReadRequest(int const input, std::list &install, if (line.empty() == true) continue; // The first Tag must be a request, so search for it - if (line.compare(0,8, "Request:") != 0) + if (line.compare(0, 8, "Request:") != 0) continue; while (ReadLine(input, line) == true) @@ -187,16 +208,25 @@ bool EDSP::ReadRequest(int const input, std::list &install, return true; std::list *request = NULL; - if (line.compare(0,8, "Install:") == 0) + if (line.compare(0, 8, "Install:") == 0) { - line.erase(0,8); + line.erase(0, 8); request = &install; } - if (line.compare(0,7, "Remove:") == 0) + else if (line.compare(0, 7, "Remove:") == 0) { - line.erase(0,7); + line.erase(0, 7); request = &remove; } + else if (line.compare(0, 8, "Upgrade:") == 0) + upgrade = EDSP::StringToBool(line.c_str() + 9, false); + else if (line.compare(0, 13, "Dist-Upgrade:") == 0) + distUpgrade = EDSP::StringToBool(line.c_str() + 14, false); + else if (line.compare(0, 11, "Autoremove:") == 0) + autoRemove = EDSP::StringToBool(line.c_str() + 12, false); + else + _error->Warning("Unknown line in EDSP Request stanza: %s", line.c_str()); + if (request == NULL) continue; size_t end = line.length(); @@ -204,7 +234,7 @@ bool EDSP::ReadRequest(int const input, std::list &install, size_t begin = line.rfind(' '); if (begin == std::string::npos) { - request->push_back(line.substr(0,end)); + request->push_back(line.substr(0, end)); break; } else if (begin < end) diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 742d89b43..75733c2d2 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -14,18 +14,20 @@ class EDSP /*{{{*/ { bool static ReadLine(int const input, std::string &line); + bool static StringToBool(char const *answer, bool const defValue); public: bool static WriteRequest(pkgDepCache &Cache, FILE* output, - bool const Upgrade = false, - bool const DistUpgrade = false, - bool const AutoRemove = false); + bool const upgrade = false, + bool const distUpgrade = false, + bool const autoRemove = false); bool static WriteScenario(pkgDepCache &Cache, FILE* output); bool static ReadResponse(FILE* input, pkgDepCache &Cache); // ReadScenario is provided by the listparser infrastructure bool static ReadRequest(int const input, std::list &install, - std::list &remove); + std::list &remove, bool &upgrade, + bool &distUpgrade, bool &autoRemove); bool static ApplyRequest(std::list const &install, std::list const &remove, pkgDepCache &Cache); -- cgit v1.2.3 From 4128c84679e54e2afda7913946facaf9c52cd3eb Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 1 Apr 2011 16:14:24 +0200 Subject: add a small wrapper to use the internal apt solver as an external one --- cmdline/apt-internal-solver.cc | 129 +++++++++++++++++++++++++++++++++++++++++ cmdline/makefile | 7 +++ 2 files changed, 136 insertions(+) create mode 100644 cmdline/apt-internal-solver.cc diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc new file mode 100644 index 000000000..83d79e42a --- /dev/null +++ b/cmdline/apt-internal-solver.cc @@ -0,0 +1,129 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ##################################################################### + + cover around the internal solver to be able to run it like an external + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + /*}}}*/ + +// ShowHelp - Show a help screen /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool ShowHelp(CommandLine &CmdL) { + ioprintf(std::cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION, + COMMON_ARCH,__DATE__,__TIME__); + + std::cout << + _("Usage: apt-internal-resolver\n" + "\n" + "apt-internal-resolver is an interface to use the current internal\n" + "like an external resolver for the APT family for debugging or alike\n" + "\n" + "Options:\n" + " -h This help text.\n" + " -q Loggable output - no progress indicator\n" + " -c=? Read this configuration file\n" + " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n" + "apt.conf(5) manual pages for more information and options.\n" + " This APT has Super Cow Powers.\n"); + return true; +} + /*}}}*/ +int main(int argc,const char *argv[]) /*{{{*/ +{ + CommandLine::Args Args[] = { + {'h',"help","help",0}, + {'v',"version","version",0}, + {'q',"quiet","quiet",CommandLine::IntLevel}, + {'q',"silent","quiet",CommandLine::IntLevel}, + {0,0,0,0}}; + + CommandLine CmdL(Args,_config); + if (pkgInitConfig(*_config) == false || + CmdL.Parse(argc,argv) == false) { + _error->DumpErrors(); + return 2; + } + + // See if the help should be shown + if (_config->FindB("help") == true || + _config->FindB("version") == true) { + ShowHelp(CmdL); + return 1; + } + + // Deal with stdout not being a tty + if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) + _config->Set("quiet","1"); + + if (_config->FindI("quiet", 0) < 1) + _config->Set("Debug::EDSP::WriteSolution", true); + + _config->Set("APT::Solver::Name", "internal"); + _config->Set("edsp::scenario", "stdin"); + int input = STDIN_FILENO; + FILE* output = stdout; + SetNonBlock(input, false); + + if (pkgInitSystem(*_config,_system) == false) { + std::cerr << "System could not be initialized!" << std::endl; + return 1; + } + + if (WaitFd(input, false, 5) == false) + std::cerr << "WAIT timed out in the resolver" << std::endl; + + std::list install, remove; + bool upgrade, distUpgrade, autoRemove; + if (EDSP::ReadRequest(input, install, remove, upgrade, distUpgrade, autoRemove) == false) { + std::cerr << "Parsing the request failed!" << std::endl; + return 2; + } + + pkgCacheFile CacheFile; + CacheFile.Open(NULL, false); + + if (EDSP::ApplyRequest(install, remove, CacheFile) == false) { + std::cerr << "Failed to apply request to depcache!" << std::endl; + return 3; + } + for (std::list::const_iterator i = install.begin(); + i != install.end(); ++i) + CacheFile->MarkInstall(CacheFile->FindPkg(*i), true); + + pkgProblemResolver Fix(CacheFile); + if (Fix.Resolve() == false) { + EDSP::WriteError("An error occured", output); + return 0; + } + + if (EDSP::WriteSolution(CacheFile, output) == false) { + std::cerr << "Failed to output the solution!" << std::endl; + return 4; + } + + bool const Errors = _error->PendingError(); + if (_config->FindI("quiet",0) > 0) + _error->DumpErrors(); + else + _error->DumpErrors(GlobalError::DEBUG); + return Errors == true ? 100 : 0; +} + /*}}}*/ diff --git a/cmdline/makefile b/cmdline/makefile index 917ccc96a..4462ccaf4 100644 --- a/cmdline/makefile +++ b/cmdline/makefile @@ -64,3 +64,10 @@ include $(COPY_H) #TO=$(BIN) #TARGET=program #include $(COPY_H) + +# The internal solver acting as an external +PROGRAM=apt-internal-solver +SLIBS = -lapt-pkg $(INTLLIBS) +LIB_MAKES = apt-pkg/makefile +SOURCE = apt-internal-solver.cc +include $(PROGRAM_H) -- cgit v1.2.3 From 2029276f0343c96481d0d3cbbc367420b4a5f864 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 2 Apr 2011 15:47:14 +0200 Subject: send the scenario through a pipe to the solver and get the solution back The solution is NOT interpreted so far. --- apt-pkg/algorithms.cc | 42 +++++++++++++++++++++++++++++++++++------- apt-pkg/edsp.cc | 28 ++++++++++++++++++++++++++-- apt-pkg/edsp.h | 2 +- 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index aabb511a2..bbe315ef7 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -740,18 +740,46 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) bool pkgProblemResolver::Resolve(bool BrokenFix) { std::string const solver = _config->Find("APT::Solver::Name", "internal"); + if (solver != "internal") { - FILE* output = fopen("/tmp/scenario.log", "w"); +// std::string const file = _config->FindDir("Dir::Bin::Solvers") + solver; + std::string const file = solver; + if (RealFileExists(file.c_str()) == false) + return _error->Error("Can't call external solver '%s' as it is not available: %s", solver.c_str(), file.c_str()); + int external[4] = {-1, -1, -1, -1}; + if (pipe(external) != 0 || pipe(external + 2) != 0) + return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); + for (int i = 0; i < 4; ++i) + SetCloseExec(external[i], true); + + pid_t Solver = ExecFork(); + if (Solver == 0) + { + dup2(external[0], STDIN_FILENO); + dup2(external[3], STDOUT_FILENO); + const char* calling[2] = { file.c_str(), 0 }; + execv(calling[0], (char**) calling); + std::cerr << "Failed to execute solver '" << solver << "'!" << std::endl; + _exit(100); + } + close(external[0]); + close(external[3]); + + if (WaitFd(external[1], true, 5) == false) + return _error->Errno("Resolve", "Waiting on availability of solver stdin timed out"); + + FILE* output = fdopen(external[1], "w"); + if (output == NULL) + return _error->Errno("Resolve", "fdopen on solver stdin failed"); EDSP::WriteRequest(Cache, output); EDSP::WriteScenario(Cache, output); fclose(output); - if (ResolveInternal(BrokenFix) == false) - return false; - output = fopen("/tmp/solution.log", "w"); - EDSP::WriteSolution(Cache, output); - fclose(output); - return true; + + if (EDSP::ReadResponse(external[2], Cache) == false) + return _error->Error("Reading solver response failed"); + + return ExecWait(Solver, solver.c_str(), false); } return ResolveInternal(BrokenFix); } diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index d93b05411..e6dc16536 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -139,14 +140,37 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, return true; } /*}}}*/ -bool EDSP::ReadResponse(FILE* input, pkgDepCache &Cache) { return false; } +// EDSP::ReadResponse - from the given file descriptor /*{{{*/ +bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { + FileFd in; + in.OpenDescriptor(input, FileFd::ReadOnly); + pkgTagFile response(&in); + pkgTagSection section; + while (response.Step(section) == true) { + std::string type; + if (section.Exists("Install") == true) + type = "Install"; + else if (section.Exists("Remove") == true) + type = "Remove"; + //FIXME: handle progress + else + continue; + + int const id = section.FindI(type.c_str(), -1); + if (id == -1) + return _error->Error("Unable to parse %s request!", type.c_str()); + //FIXME: find version by id and mark it correctly + } + return true; +} + /*}}}*/ // EDSP::ReadLine - first line from the given file descriptor /*{{{*/ // --------------------------------------------------------------------- /* Little helper method to read a complete line into a string. Similar to fgets but we need to use the low-level read() here as otherwise the listparser will be confused later on as mixing of fgets and read isn't - a supported action according to the manpages and result are undefined */ + a supported action according to the manpages and results are undefined */ bool EDSP::ReadLine(int const input, std::string &line) { char one; ssize_t data = 0; diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 75733c2d2..31f8891f3 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -22,7 +22,7 @@ public: bool const distUpgrade = false, bool const autoRemove = false); bool static WriteScenario(pkgDepCache &Cache, FILE* output); - bool static ReadResponse(FILE* input, pkgDepCache &Cache); + bool static ReadResponse(int const input, pkgDepCache &Cache); // ReadScenario is provided by the listparser infrastructure bool static ReadRequest(int const input, std::list &install, -- cgit v1.2.3 From 56d53b54e795479194eb653741c5a816698db43f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 2 Apr 2011 15:51:37 +0200 Subject: disable the error discarding as it destroyes the error reporting about failures with external solvers for now as long as i can't see a reason for it --- cmdline/apt-get.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 6ffecd777..a1264f54a 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1887,7 +1887,7 @@ bool DoInstall(CommandLine &CmdL) // Call the scored problem resolver Fix->InstallProtect(); if (Fix->Resolve(true) == false) - _error->Discard(); + ; //FIXME: is there a valid reason for? _error->Discard(); delete Fix; } -- cgit v1.2.3 From 3f248168dca69008fd8b7f8338dc76d767b47b43 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 2 Apr 2011 15:54:39 +0200 Subject: disable automatical installation of dependencies in MarkInstall if we will not use the default internal resolver later on --- apt-pkg/depcache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 2790080a1..ed9e2084c 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1056,7 +1056,7 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, Update(Pkg); AddSizes(Pkg); - if (AutoInst == false) + if (AutoInst == false || _config->Find("APT::Solver::Name", "internal") != "internal") return; if (DebugMarker == true) -- cgit v1.2.3 From 69a788359e1ff895efd32348ab6d610bc72794dd Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 19 Apr 2011 11:51:47 +0200 Subject: Interpret Remove and Install lines in Responses correctly --- apt-pkg/edsp.cc | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index e6dc16536..f8deef8b8 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -39,7 +39,7 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output) fprintf(output, "Installed: yes\n"); if (Pkg->SelectedState == pkgCache::State::Hold) fprintf(output, "Hold: yes\n"); - fprintf(output, "APT-ID: %u\n", Ver->ID); + fprintf(output, "APT-ID: %lu\n", Ver.Index()); fprintf(output, "Priority: %s\n", PrioMap[Ver->Priority]); if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) fprintf(output, "Essential: yes\n"); @@ -156,11 +156,18 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { else continue; - int const id = section.FindI(type.c_str(), -1); - if (id == -1) - return _error->Error("Unable to parse %s request!", type.c_str()); + size_t const index = section.FindULL(type.c_str(), 0); + if (index == 0) { + _error->Warning("Unable to parse %s request with id value '%s'!", type.c_str(), section.FindS(type.c_str()).c_str()); + continue; + } - //FIXME: find version by id and mark it correctly + pkgCache::VerIterator Ver(Cache.GetCache(), Cache.GetCache().VerP + index); + Cache.SetCandidateVersion(Ver); + if (type == "Install") + Cache.MarkInstall(Ver.ParentPkg(), false, false); + else if (type == "Remove") + Cache.MarkDelete(Ver.ParentPkg(), false); } return true; } -- cgit v1.2.3 From d9933172b31e21862b660c182f7c747802dbaa73 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 19 Apr 2011 11:52:47 +0200 Subject: set hint flags for the problem resolver according to request --- cmdline/apt-internal-solver.cc | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc index 83d79e42a..83a671a96 100644 --- a/cmdline/apt-internal-solver.cc +++ b/cmdline/apt-internal-solver.cc @@ -104,11 +104,28 @@ int main(int argc,const char *argv[]) /*{{{*/ std::cerr << "Failed to apply request to depcache!" << std::endl; return 3; } + + pkgProblemResolver Fix(CacheFile); + for (std::list::const_iterator i = remove.begin(); + i != remove.end(); ++i) { + pkgCache::PkgIterator P = CacheFile->FindPkg(*i); + Fix.Clear(P); + Fix.Protect(P); + Fix.Remove(P); + } + + for (std::list::const_iterator i = install.begin(); + i != install.end(); ++i) { + pkgCache::PkgIterator P = CacheFile->FindPkg(*i); + Fix.Clear(P); + Fix.Protect(P); + } + for (std::list::const_iterator i = install.begin(); i != install.end(); ++i) CacheFile->MarkInstall(CacheFile->FindPkg(*i), true); - pkgProblemResolver Fix(CacheFile); + if (Fix.Resolve() == false) { EDSP::WriteError("An error occured", output); return 0; -- cgit v1.2.3 From 2a33cb16d6be42b253e9a4169e2c725e17cf7c1a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 19 Apr 2011 15:26:21 +0200 Subject: use the version id instead of the mmap offset as APT-ID This leads to a small performance decrease as we need to build this mapping now while interpreting the Response but a (buggy) solver can't point us to dangerous memory locations anymore this way and VersionCount remains useful for other mapping proposes --- apt-pkg/edsp.cc | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index f8deef8b8..55bc0a0d9 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -39,7 +39,7 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output) fprintf(output, "Installed: yes\n"); if (Pkg->SelectedState == pkgCache::State::Hold) fprintf(output, "Hold: yes\n"); - fprintf(output, "APT-ID: %lu\n", Ver.Index()); + fprintf(output, "APT-ID: %d\n", Ver->ID); fprintf(output, "Priority: %s\n", PrioMap[Ver->Priority]); if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) fprintf(output, "Essential: yes\n"); @@ -146,6 +146,17 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { in.OpenDescriptor(input, FileFd::ReadOnly); pkgTagFile response(&in); pkgTagSection section; + + /* We build an map id to mmap offset here + In theory we could use the offset as ID, but then VersionCount + couldn't be used to create other versionmappings anymore and it + would be too easy for a (buggy) solver to segfault APT… */ + unsigned long long const VersionCount = Cache.Head().VersionCount; + unsigned long VerIdx[VersionCount]; + for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; ++P) + for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V) + VerIdx[V->ID] = V.Index(); + while (response.Step(section) == true) { std::string type; if (section.Exists("Install") == true) @@ -156,13 +167,16 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { else continue; - size_t const index = section.FindULL(type.c_str(), 0); - if (index == 0) { + size_t const id = section.FindULL(type.c_str(), VersionCount); + if (id == VersionCount) { _error->Warning("Unable to parse %s request with id value '%s'!", type.c_str(), section.FindS(type.c_str()).c_str()); continue; + } else if (id > Cache.Head().VersionCount) { + _error->Warning("ID value '%s' in %s request stanza is to high to refer to a known version!", section.FindS(type.c_str()).c_str(), type.c_str()); + continue; } - pkgCache::VerIterator Ver(Cache.GetCache(), Cache.GetCache().VerP + index); + pkgCache::VerIterator Ver(Cache.GetCache(), Cache.GetCache().VerP + VerIdx[id]); Cache.SetCandidateVersion(Ver); if (type == "Install") Cache.MarkInstall(Ver.ParentPkg(), false, false); -- cgit v1.2.3 From d4f626ff09383873c7b1ae42b744293c940c9c2c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 25 Apr 2011 15:59:19 +0200 Subject: reorganize WriteScenario to add a WriteLimitedScenario in which a scenario can be limited to a subset of packages with only relevant dependencies --- apt-pkg/edsp.cc | 255 ++++++++++++++++++++++++++++++++++++++------------------ apt-pkg/edsp.h | 17 ++++ 2 files changed, 192 insertions(+), 80 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 55bc0a0d9..aec43c7e8 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -18,90 +18,169 @@ #include /*}}}*/ +// we could use pkgCache::DepType and ::Priority, but these would be localized strings… +const char * const EDSP::PrioMap[] = {0, "important", "required", "standard", + "optional", "extra"}; +const char * const EDSP::DepMap[] = {"", "Depends", "PreDepends", "Suggests", + "Recommends" , "Conflicts", "Replaces", + "Obsoletes", "Breaks", "Enhances"}; + // EDSP::WriteScenario - to the given file descriptor /*{{{*/ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output) { - // we could use pkgCache::DepType and ::Priority, but these would be lokalized strings… - const char * const PrioMap[] = {0, "important", "required", "standard", - "optional", "extra"}; - const char * const DepMap[] = {"", "Depends", "PreDepends", "Suggests", - "Recommends" , "Conflicts", "Replaces", - "Obsoletes", "Breaks", "Enhances"}; - for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) - { for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) { - fprintf(output, "Package: %s\n", Pkg.Name()); - fprintf(output, "Architecture: %s\n", Ver.Arch()); - fprintf(output, "Version: %s\n", Ver.VerStr()); - if (Pkg.CurrentVer() == Ver) - fprintf(output, "Installed: yes\n"); - if (Pkg->SelectedState == pkgCache::State::Hold) - fprintf(output, "Hold: yes\n"); - fprintf(output, "APT-ID: %d\n", Ver->ID); - fprintf(output, "Priority: %s\n", PrioMap[Ver->Priority]); - if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) - fprintf(output, "Essential: yes\n"); - fprintf(output, "Section: %s\n", Ver.Section()); - if (Ver->MultiArch == pkgCache::Version::Allowed || Ver->MultiArch == pkgCache::Version::AllAllowed) - fprintf(output, "Multi-Arch: allowed\n"); - else if (Ver->MultiArch == pkgCache::Version::Foreign || Ver->MultiArch == pkgCache::Version::AllForeign) - fprintf(output, "Multi-Arch: foreign\n"); - else if (Ver->MultiArch == pkgCache::Version::Same) - fprintf(output, "Multi-Arch: same\n"); - signed short Pin = std::numeric_limits::min(); - for (pkgCache::VerFileIterator File = Ver.FileList(); File.end() == false; ++File) { - signed short const p = Cache.GetPolicy().GetPriority(File.File()); - if (Pin < p) - Pin = p; - } - fprintf(output, "APT-Pin: %d\n", Pin); - if (Cache.GetCandidateVer(Pkg) == Ver) - fprintf(output, "APT-Candidate: yes\n"); - if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) - fprintf(output, "APT-Automatic: yes\n"); - std::string dependencies[pkgCache::Dep::Enhances + 1]; - bool orGroup = false; - for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) - { - // Ignore implicit dependencies for multiarch here - if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0) - continue; - if (orGroup == false) - dependencies[Dep->Type].append(", "); - dependencies[Dep->Type].append(Dep.TargetPkg().Name()); - if (Dep->Version != 0) - dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); - if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) - { - dependencies[Dep->Type].append(" | "); - orGroup = true; - } - else - orGroup = false; - } - for (int i = 1; i < pkgCache::Dep::Enhances + 1; ++i) - if (dependencies[i].empty() == false) - fprintf(output, "%s: %s\n", DepMap[i], dependencies[i].c_str()+2); - string provides; - for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; ++Prv) - { - // Ignore implicit provides for multiarch here - if (strcmp(Pkg.Arch(), Prv.ParentPkg().Arch()) != 0 || strcmp(Pkg.Name(),Prv.Name()) == 0) - continue; - provides.append(", ").append(Prv.Name()); - } - if (provides.empty() == false) - fprintf(output, "Provides: %s\n", provides.c_str()+2); - - + WriteScenarioVersion(Cache, output, Pkg, Ver); + WriteScenarioDependency(Cache, output, Pkg, Ver); fprintf(output, "\n"); } - } return true; } /*}}}*/ +// EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/ +bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output, + APT::PackageSet const &pkgset) +{ + for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) + { + WriteScenarioVersion(Cache, output, Pkg, Ver); + WriteScenarioLimitedDependency(Cache, output, Pkg, Ver, pkgset); + fprintf(output, "\n"); + } + return true; +} + /*}}}*/ +// EDSP::WriteScenarioVersion /*{{{*/ +void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg, + pkgCache::VerIterator const &Ver) +{ + fprintf(output, "Package: %s\n", Pkg.Name()); + fprintf(output, "Architecture: %s\n", Ver.Arch()); + fprintf(output, "Version: %s\n", Ver.VerStr()); + if (Pkg.CurrentVer() == Ver) + fprintf(output, "Installed: yes\n"); + if (Pkg->SelectedState == pkgCache::State::Hold) + fprintf(output, "Hold: yes\n"); + fprintf(output, "APT-ID: %d\n", Ver->ID); + fprintf(output, "Priority: %s\n", PrioMap[Ver->Priority]); + if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + fprintf(output, "Essential: yes\n"); + fprintf(output, "Section: %s\n", Ver.Section()); + if (Ver->MultiArch == pkgCache::Version::Allowed || Ver->MultiArch == pkgCache::Version::AllAllowed) + fprintf(output, "Multi-Arch: allowed\n"); + else if (Ver->MultiArch == pkgCache::Version::Foreign || Ver->MultiArch == pkgCache::Version::AllForeign) + fprintf(output, "Multi-Arch: foreign\n"); + else if (Ver->MultiArch == pkgCache::Version::Same) + fprintf(output, "Multi-Arch: same\n"); + signed short Pin = std::numeric_limits::min(); + for (pkgCache::VerFileIterator File = Ver.FileList(); File.end() == false; ++File) { + signed short const p = Cache.GetPolicy().GetPriority(File.File()); + if (Pin < p) + Pin = p; + } + fprintf(output, "APT-Pin: %d\n", Pin); + if (Cache.GetCandidateVer(Pkg) == Ver) + fprintf(output, "APT-Candidate: yes\n"); + if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) + fprintf(output, "APT-Automatic: yes\n"); +} + /*}}}*/ +// EDSP::WriteScenarioDependency /*{{{*/ +void EDSP::WriteScenarioDependency(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg, + pkgCache::VerIterator const &Ver) +{ + std::string dependencies[pkgCache::Dep::Enhances + 1]; + bool orGroup = false; + for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) + { + // Ignore implicit dependencies for multiarch here + if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0) + continue; + if (orGroup == false) + dependencies[Dep->Type].append(", "); + dependencies[Dep->Type].append(Dep.TargetPkg().Name()); + if (Dep->Version != 0) + dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); + if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) + { + dependencies[Dep->Type].append(" | "); + orGroup = true; + } + else + orGroup = false; + } + for (int i = 1; i < pkgCache::Dep::Enhances + 1; ++i) + if (dependencies[i].empty() == false) + fprintf(output, "%s: %s\n", DepMap[i], dependencies[i].c_str()+2); + string provides; + for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; ++Prv) + { + // Ignore implicit provides for multiarch here + if (strcmp(Pkg.Arch(), Prv.ParentPkg().Arch()) != 0 || strcmp(Pkg.Name(),Prv.Name()) == 0) + continue; + provides.append(", ").append(Prv.Name()); + } + if (provides.empty() == false) + fprintf(output, "Provides: %s\n", provides.c_str()+2); +} + /*}}}*/ +// EDSP::WriteScenarioLimitedDependency /*{{{*/ +void EDSP::WriteScenarioLimitedDependency(pkgDepCache &Cache, FILE* output, + pkgCache::PkgIterator const &Pkg, + pkgCache::VerIterator const &Ver, + APT::PackageSet const &pkgset) +{ + std::string dependencies[pkgCache::Dep::Enhances + 1]; + bool orGroup = false; + for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) + { + // Ignore implicit dependencies for multiarch here + if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0) + continue; + if (orGroup == false) + { + if (pkgset.find(Dep.TargetPkg()) == pkgset.end()) + continue; + dependencies[Dep->Type].append(", "); + } + else if (pkgset.find(Dep.TargetPkg()) == pkgset.end()) + { + if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) + continue; + dependencies[Dep->Type].erase(dependencies[Dep->Type].end()-3, dependencies[Dep->Type].end()); + orGroup = false; + continue; + } + dependencies[Dep->Type].append(Dep.TargetPkg().Name()); + if (Dep->Version != 0) + dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); + if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) + { + dependencies[Dep->Type].append(" | "); + orGroup = true; + } + else + orGroup = false; + } + for (int i = 1; i < pkgCache::Dep::Enhances + 1; ++i) + if (dependencies[i].empty() == false) + fprintf(output, "%s: %s\n", DepMap[i], dependencies[i].c_str()+2); + string provides; + for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; ++Prv) + { + // Ignore implicit provides for multiarch here + if (strcmp(Pkg.Arch(), Prv.ParentPkg().Arch()) != 0 || strcmp(Pkg.Name(),Prv.Name()) == 0) + continue; + if (pkgset.find(Prv.ParentPkg()) == pkgset.end()) + continue; + provides.append(", ").append(Prv.Name()); + } + if (provides.empty() == false) + fprintf(output, "Provides: %s\n", provides.c_str()+2); +} + /*}}}*/ // EDSP::WriteRequest - to the given file descriptor /*{{{*/ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, bool const DistUpgrade, bool const AutoRemove) @@ -298,12 +377,22 @@ bool EDSP::ApplyRequest(std::list const &install, pkgDepCache &Cache) { for (std::list::const_iterator i = install.begin(); - i != install.end(); ++i) - Cache.MarkInstall(Cache.FindPkg(*i), false); + i != install.end(); ++i) { + pkgCache::PkgIterator P = Cache.FindPkg(*i); + if (P.end() == true) + _error->Warning("Package %s is not known, so can't be installed", i->c_str()); + else + Cache.MarkInstall(P, false); + } for (std::list::const_iterator i = remove.begin(); - i != remove.end(); ++i) - Cache.MarkDelete(Cache.FindPkg(*i)); + i != remove.end(); ++i) { + pkgCache::PkgIterator P = Cache.FindPkg(*i); + if (P.end() == true) + _error->Warning("Package %s is not known, so can't be installed", i->c_str()); + else + Cache.MarkDelete(P); + } return true; } /*}}}*/ @@ -314,13 +403,19 @@ bool EDSP::WriteSolution(pkgDepCache &Cache, FILE* output) for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) { if (Cache[Pkg].Delete() == true) - fprintf(output, "Remove: %d\n", Cache.GetCandidateVer(Pkg)->ID); + { + fprintf(output, "Remove: %d\n", Pkg.CurrentVer()->ID); + if (Debug == true) + fprintf(output, "Package: %s\nVersion: %s\n", Pkg.FullName().c_str(), Pkg.CurrentVer().VerStr()); + } else if (Cache[Pkg].NewInstall() == true || Cache[Pkg].Upgrade() == true) + { fprintf(output, "Install: %d\n", Cache.GetCandidateVer(Pkg)->ID); + if (Debug == true) + fprintf(output, "Package: %s\nVersion: %s\n", Pkg.FullName().c_str(), Cache.GetCandidateVer(Pkg).VerStr()); + } else continue; - if (Debug == true) - fprintf(output, "Package: %s\nVersion: %s\n", Pkg.FullName().c_str(), Cache.GetCandidateVer(Pkg).VerStr()); fprintf(output, "\n"); } diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 31f8891f3..db4f06a7c 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -8,20 +8,37 @@ #define PKGLIB_EDSP_H #include +#include #include class EDSP /*{{{*/ { + // we could use pkgCache::DepType and ::Priority, but these would be localized strings… + static const char * const PrioMap[]; + static const char * const DepMap[]; + bool static ReadLine(int const input, std::string &line); bool static StringToBool(char const *answer, bool const defValue); + void static WriteScenarioVersion(pkgDepCache &Cache, FILE* output, + pkgCache::PkgIterator const &Pkg, + pkgCache::VerIterator const &Ver); + void static WriteScenarioDependency(pkgDepCache &Cache, FILE* output, + pkgCache::PkgIterator const &Pkg, + pkgCache::VerIterator const &Ver); + void static WriteScenarioLimitedDependency(pkgDepCache &Cache, FILE* output, + pkgCache::PkgIterator const &Pkg, + pkgCache::VerIterator const &Ver, + APT::PackageSet const &pkgset); public: bool static WriteRequest(pkgDepCache &Cache, FILE* output, bool const upgrade = false, bool const distUpgrade = false, bool const autoRemove = false); bool static WriteScenario(pkgDepCache &Cache, FILE* output); + bool static WriteLimitedScenario(pkgDepCache &Cache, FILE* output, + APT::PackageSet const &pkgset); bool static ReadResponse(int const input, pkgDepCache &Cache); // ReadScenario is provided by the listparser infrastructure -- cgit v1.2.3 From 904be3525223633721dc7b5bff22ae7d8db8cb95 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 25 Apr 2011 15:59:45 +0200 Subject: add scenario command to output a complete or limited scenario --- cmdline/apt-internal-solver.cc | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc index 83a671a96..68489e213 100644 --- a/cmdline/apt-internal-solver.cc +++ b/cmdline/apt-internal-solver.cc @@ -53,6 +53,8 @@ int main(int argc,const char *argv[]) /*{{{*/ {'v',"version","version",0}, {'q',"quiet","quiet",CommandLine::IntLevel}, {'q',"silent","quiet",CommandLine::IntLevel}, + {'c',"config-file",0,CommandLine::ConfigFile}, + {'o',"option",0,CommandLine::ArbItem}, {0,0,0,0}}; CommandLine CmdL(Args,_config); @@ -69,6 +71,25 @@ int main(int argc,const char *argv[]) /*{{{*/ return 1; } + if (CmdL.FileList[0] != 0 && strcmp(CmdL.FileList[0], "scenario") == 0) + { + if (pkgInitSystem(*_config,_system) == false) { + std::cerr << "System could not be initialized!" << std::endl; + return 1; + } + pkgCacheFile CacheFile; + CacheFile.Open(NULL, false); + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1); + FILE* output = stdout; + if (pkgset.empty() == true) + EDSP::WriteScenario(CacheFile, output); + else + EDSP::WriteLimitedScenario(CacheFile, output, pkgset); + fclose(output); + _error->DumpErrors(std::cerr); + return 0; + } + // Deal with stdout not being a tty if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) _config->Set("quiet","1"); @@ -138,9 +159,9 @@ int main(int argc,const char *argv[]) /*{{{*/ bool const Errors = _error->PendingError(); if (_config->FindI("quiet",0) > 0) - _error->DumpErrors(); + _error->DumpErrors(std::cerr); else - _error->DumpErrors(GlobalError::DEBUG); + _error->DumpErrors(std::cerr, GlobalError::DEBUG); return Errors == true ? 100 : 0; } /*}}}*/ -- cgit v1.2.3 From 7ca70a9af1bc6af753ee3012d1840d5ddfafe37c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 2 May 2011 10:41:38 +0200 Subject: merge single-arch :arch fix from my sid branch --- apt-pkg/pkgcache.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index c6326abf1..93d09a18e 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -211,11 +211,14 @@ pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name) // --------------------------------------------------------------------- /* Returns 0 on error, pointer to the package otherwise */ pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) { - if (MultiArchCache() == false) - return SingleArchFindPkg(Name); size_t const found = Name.find(':'); if (found == string::npos) - return FindPkg(Name, "native"); + { + if (MultiArchCache() == false) + return SingleArchFindPkg(Name); + else + return FindPkg(Name, "native"); + } string const Arch = Name.substr(found+1); if (Arch == "any") return FindPkg(Name, "any"); -- cgit v1.2.3 From e876223c704d8cac6246b4aff4bf683fb8b053e3 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 2 May 2011 11:51:44 +0200 Subject: implement optional Progress report in EDSP --- apt-pkg/edsp.cc | 21 +++++++++++++++++++-- apt-pkg/edsp.h | 1 + cmdline/apt-internal-solver.cc | 13 +++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index aec43c7e8..6343b57cd 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -242,8 +242,16 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { type = "Install"; else if (section.Exists("Remove") == true) type = "Remove"; - //FIXME: handle progress - else + else if (section.Exists("Progress") == true) { + ioprintf(std::clog, "[ %3d%% ] ", section.FindI("Percentage", 0)); + std::clog << section.FindS("Progress") << " - "; + string const msg = section.FindS("Message"); + if (msg.empty() == true) + std::clog << "Solver is still working on the solution" << std::endl; + else + std::clog << msg << std::endl; + continue; + } else continue; size_t const id = section.FindULL(type.c_str(), VersionCount); @@ -422,4 +430,13 @@ bool EDSP::WriteSolution(pkgDepCache &Cache, FILE* output) return true; } /*}}}*/ +// EDSP::WriteProgess - pulse to the given file descriptor /*{{{*/ +bool EDSP::WriteProgress(unsigned short const percent, const char* const message, FILE* output) { + fprintf(output, "Progress: %s\n", TimeRFC1123(time(NULL)).c_str()); + fprintf(output, "Percentage: %d\n", percent); + fprintf(output, "Message: %s\n\n", message); + fflush(output); + return true; +} + /*}}}*/ bool EDSP::WriteError(std::string const &message, FILE* output) { return false; } diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index db4f06a7c..a05de9448 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -49,6 +49,7 @@ public: std::list const &remove, pkgDepCache &Cache); bool static WriteSolution(pkgDepCache &Cache, FILE* output); + bool static WriteProgress(unsigned short const percent, const char* const message, FILE* output); bool static WriteError(std::string const &message, FILE* output); }; diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc index 68489e213..0aa218d52 100644 --- a/cmdline/apt-internal-solver.cc +++ b/cmdline/apt-internal-solver.cc @@ -103,11 +103,15 @@ int main(int argc,const char *argv[]) /*{{{*/ FILE* output = stdout; SetNonBlock(input, false); + EDSP::WriteProgress(0, "Start up solver…", output); + if (pkgInitSystem(*_config,_system) == false) { std::cerr << "System could not be initialized!" << std::endl; return 1; } + EDSP::WriteProgress(1, "Read request…", output); + if (WaitFd(input, false, 5) == false) std::cerr << "WAIT timed out in the resolver" << std::endl; @@ -118,9 +122,13 @@ int main(int argc,const char *argv[]) /*{{{*/ return 2; } + EDSP::WriteProgress(5, "Read scenario…", output); + pkgCacheFile CacheFile; CacheFile.Open(NULL, false); + EDSP::WriteProgress(50, "Apply request on scenario…", output); + if (EDSP::ApplyRequest(install, remove, CacheFile) == false) { std::cerr << "Failed to apply request to depcache!" << std::endl; return 3; @@ -146,17 +154,22 @@ int main(int argc,const char *argv[]) /*{{{*/ i != install.end(); ++i) CacheFile->MarkInstall(CacheFile->FindPkg(*i), true); + EDSP::WriteProgress(60, "Call problemresolver on current scenario…", output); if (Fix.Resolve() == false) { EDSP::WriteError("An error occured", output); return 0; } + EDSP::WriteProgress(95, "Write solution…", output); + if (EDSP::WriteSolution(CacheFile, output) == false) { std::cerr << "Failed to output the solution!" << std::endl; return 4; } + EDSP::WriteProgress(100, "Done", output); + bool const Errors = _error->PendingError(); if (_config->FindI("quiet",0) > 0) _error->DumpErrors(std::cerr); -- cgit v1.2.3 From c80a49f556ae565e280637b4617d6492a1d5a3b8 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 2 May 2011 11:52:28 +0200 Subject: move the mapping generation to the top as the response reading is currently waiting for the solver to complete and not non-blocking so we can generate the map while waiting for the solver --- apt-pkg/edsp.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 6343b57cd..9dbbbaf26 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -221,11 +221,6 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, /*}}}*/ // EDSP::ReadResponse - from the given file descriptor /*{{{*/ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { - FileFd in; - in.OpenDescriptor(input, FileFd::ReadOnly); - pkgTagFile response(&in); - pkgTagSection section; - /* We build an map id to mmap offset here In theory we could use the offset as ID, but then VersionCount couldn't be used to create other versionmappings anymore and it @@ -236,6 +231,11 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V) VerIdx[V->ID] = V.Index(); + FileFd in; + in.OpenDescriptor(input, FileFd::ReadOnly); + pkgTagFile response(&in); + pkgTagSection section; + while (response.Step(section) == true) { std::string type; if (section.Exists("Install") == true) -- cgit v1.2.3 From 288a76d2dcb19aaf0aca6fc9d4898701e5379f5c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 2 May 2011 12:23:13 +0200 Subject: reduce the buffer size so we get a sort of realtime progress report and print the time of output at the front of the progress report so we can see the delay --- apt-pkg/edsp.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 9dbbbaf26..170e2a4c6 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -233,7 +233,7 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { FileFd in; in.OpenDescriptor(input, FileFd::ReadOnly); - pkgTagFile response(&in); + pkgTagFile response(&in, 100); pkgTagSection section; while (response.Step(section) == true) { @@ -243,6 +243,7 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { else if (section.Exists("Remove") == true) type = "Remove"; else if (section.Exists("Progress") == true) { + std::clog << TimeRFC1123(time(NULL)) << " "; ioprintf(std::clog, "[ %3d%% ] ", section.FindI("Percentage", 0)); std::clog << section.FindS("Progress") << " - "; string const msg = section.FindS("Message"); -- cgit v1.2.3 From 98d6aaa8fd2e5c3e9671560781ab23c99f66d7a4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 2 May 2011 13:22:14 +0200 Subject: handle Dir::Bin::Solvers as a list of directories and find the solver in this list of directories --- apt-pkg/algorithms.cc | 16 ++++++++++++---- apt-pkg/init.cc | 2 ++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index bbe315ef7..e40f74122 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -743,10 +743,18 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if (solver != "internal") { -// std::string const file = _config->FindDir("Dir::Bin::Solvers") + solver; - std::string const file = solver; - if (RealFileExists(file.c_str()) == false) - return _error->Error("Can't call external solver '%s' as it is not available: %s", solver.c_str(), file.c_str()); + std::vector const solverDirs = _config->FindVector("Dir::Bin::Solvers"); + std::string file; + for (std::vector::const_iterator dir = solverDirs.begin(); + dir != solverDirs.end(); ++dir) { + file = flCombine(*dir, solver); + if (RealFileExists(file.c_str()) == true) + break; + file.clear(); + } + + if (file.empty() == true) + return _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver.c_str()); int external[4] = {-1, -1, -1, -1}; if (pipe(external) != 0 || pipe(external + 2) != 0) return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index a30f27844..aff585e3b 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -72,7 +72,9 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.Set("Dir::Etc::preferencesparts","preferences.d"); Cnf.Set("Dir::Etc::trusted", "trusted.gpg"); Cnf.Set("Dir::Etc::trustedparts","trusted.gpg.d"); + Cnf.Set("Dir::Bin::methods","/usr/lib/apt/methods"); + Cnf.Set("Dir::Bin::solvers::","/usr/lib/apt/solvers"); Cnf.Set("Dir::Media::MountPath","/media/apt"); // State -- cgit v1.2.3 From ac5fbff8c55db2bd1cde194600115a874d9d0c73 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 2 May 2011 13:55:51 +0200 Subject: refactor: move solver execution into his own EDSP method --- apt-pkg/algorithms.cc | 42 +++++------------------------------------- apt-pkg/edsp.cc | 42 ++++++++++++++++++++++++++++++++++++++++++ apt-pkg/edsp.h | 1 + 3 files changed, 48 insertions(+), 37 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index e40f74122..82b1d608d 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -743,51 +743,19 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if (solver != "internal") { - std::vector const solverDirs = _config->FindVector("Dir::Bin::Solvers"); - std::string file; - for (std::vector::const_iterator dir = solverDirs.begin(); - dir != solverDirs.end(); ++dir) { - file = flCombine(*dir, solver); - if (RealFileExists(file.c_str()) == true) - break; - file.clear(); - } - - if (file.empty() == true) - return _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver.c_str()); - int external[4] = {-1, -1, -1, -1}; - if (pipe(external) != 0 || pipe(external + 2) != 0) - return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); - for (int i = 0; i < 4; ++i) - SetCloseExec(external[i], true); - - pid_t Solver = ExecFork(); - if (Solver == 0) - { - dup2(external[0], STDIN_FILENO); - dup2(external[3], STDOUT_FILENO); - const char* calling[2] = { file.c_str(), 0 }; - execv(calling[0], (char**) calling); - std::cerr << "Failed to execute solver '" << solver << "'!" << std::endl; - _exit(100); - } - close(external[0]); - close(external[3]); - - if (WaitFd(external[1], true, 5) == false) - return _error->Errno("Resolve", "Waiting on availability of solver stdin timed out"); + int solver_in, solver_out; + if (EDSP::ExecuteSolver(solver.c_str(), &solver_in, &solver_out) == false) + return false; - FILE* output = fdopen(external[1], "w"); + FILE* output = fdopen(solver_in, "w"); if (output == NULL) return _error->Errno("Resolve", "fdopen on solver stdin failed"); EDSP::WriteRequest(Cache, output); EDSP::WriteScenario(Cache, output); fclose(output); - if (EDSP::ReadResponse(external[2], Cache) == false) + if (EDSP::ReadResponse(solver_out, Cache) == false) return _error->Error("Reading solver response failed"); - - return ExecWait(Solver, solver.c_str(), false); } return ResolveInternal(BrokenFix); } diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 170e2a4c6..c3e608d17 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -441,3 +441,45 @@ bool EDSP::WriteProgress(unsigned short const percent, const char* const message } /*}}}*/ bool EDSP::WriteError(std::string const &message, FILE* output) { return false; } + +// EDSP::ExecuteSolver - fork requested solver and setup ipc pipes {{{*/ +bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) { + std::vector const solverDirs = _config->FindVector("Dir::Bin::Solvers"); + std::string file; + for (std::vector::const_iterator dir = solverDirs.begin(); + dir != solverDirs.end(); ++dir) { + file = flCombine(*dir, solver); + if (RealFileExists(file.c_str()) == true) + break; + file.clear(); + } + + if (file.empty() == true) + return _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver); + int external[4] = {-1, -1, -1, -1}; + if (pipe(external) != 0 || pipe(external + 2) != 0) + return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); + for (int i = 0; i < 4; ++i) + SetCloseExec(external[i], true); + + pid_t Solver = ExecFork(); + if (Solver == 0) + { + dup2(external[0], STDIN_FILENO); + dup2(external[3], STDOUT_FILENO); + const char* calling[2] = { file.c_str(), 0 }; + execv(calling[0], (char**) calling); + std::cerr << "Failed to execute solver '" << solver << "'!" << std::endl; + _exit(100); + } + close(external[0]); + close(external[3]); + + if (WaitFd(external[1], true, 5) == false) + return _error->Errno("Resolve", "Timed out while Waiting on availability of solver stdin"); + + *solver_in = external[1]; + *solver_out = external[2]; + return true; +} + /*}}}*/ diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index a05de9448..df6e1d21c 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -52,6 +52,7 @@ public: bool static WriteProgress(unsigned short const percent, const char* const message, FILE* output); bool static WriteError(std::string const &message, FILE* output); + bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); }; /*}}}*/ #endif -- cgit v1.2.3 From 76d4aab06d3c5edd60362fd14b38eb43416616f0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 2 May 2011 17:06:47 +0200 Subject: doesn't execute autoremove marker setting if an external solver is called and instead rely on the Autoremove tagging to show us what could be done. (apt-internal-solver doesn't support this currently as it doesn't load the auto-information into the cache) --- apt-pkg/algorithms.cc | 2 ++ apt-pkg/depcache.cc | 3 +++ apt-pkg/edsp.cc | 20 ++++++++++++++++++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 82b1d608d..fea9e92e1 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -756,6 +756,8 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if (EDSP::ReadResponse(solver_out, Cache) == false) return _error->Error("Reading solver response failed"); + + return true; } return ResolveInternal(BrokenFix); } diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index ed9e2084c..31410e2a6 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1609,6 +1609,9 @@ bool pkgDepCache::MarkFollowsSuggests() // pkgDepCache::MarkRequired - the main mark algorithm /*{{{*/ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) { + if (_config->Find("APT::Solver::Name", "internal") != "internal") + return true; + bool follow_recommends; bool follow_suggests; bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index c3e608d17..f35570c12 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -227,9 +227,12 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { would be too easy for a (buggy) solver to segfault APT… */ unsigned long long const VersionCount = Cache.Head().VersionCount; unsigned long VerIdx[VersionCount]; - for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; ++P) + for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; ++P) { for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V) VerIdx[V->ID] = V.Index(); + Cache[P].Marked = true; + Cache[P].Garbage = false; + } FileFd in; in.OpenDescriptor(input, FileFd::ReadOnly); @@ -252,7 +255,9 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { else std::clog << msg << std::endl; continue; - } else + } else if (section.Exists("Autoremove") == true) + type = "Autoremove"; + else continue; size_t const id = section.FindULL(type.c_str(), VersionCount); @@ -270,6 +275,10 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { Cache.MarkInstall(Ver.ParentPkg(), false, false); else if (type == "Remove") Cache.MarkDelete(Ver.ParentPkg(), false); + else if (type == "Autoremove") { + Cache[Ver.ParentPkg()].Marked = false; + Cache[Ver.ParentPkg()].Garbage = true; + } } return true; } @@ -423,6 +432,13 @@ bool EDSP::WriteSolution(pkgDepCache &Cache, FILE* output) if (Debug == true) fprintf(output, "Package: %s\nVersion: %s\n", Pkg.FullName().c_str(), Cache.GetCandidateVer(Pkg).VerStr()); } + else if (Cache[Pkg].Garbage == true) + { + fprintf(output, "Autoremove: %d\n", Pkg.CurrentVer()->ID); + if (Debug == true) + fprintf(output, "Package: %s\nVersion: %s\n", Pkg.FullName().c_str(), Pkg.CurrentVer().VerStr()); + fprintf(stderr, "Autoremove: %s\nVersion: %s\n", Pkg.FullName().c_str(), Pkg.CurrentVer().VerStr()); + } else continue; fprintf(output, "\n"); -- cgit v1.2.3 From 9221da7e1d5516494d17043a4d0b063a1d6b95c2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 2 May 2011 18:08:13 +0200 Subject: parse correctly the Hold: lines into Pkg->SelectedState = Hold --- apt-pkg/edsp/edsplistparser.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apt-pkg/edsp/edsplistparser.cc b/apt-pkg/edsp/edsplistparser.cc index 913455efa..3349e8cce 100644 --- a/apt-pkg/edsp/edsplistparser.cc +++ b/apt-pkg/edsp/edsplistparser.cc @@ -63,10 +63,13 @@ unsigned short edspListParser::VersionHash() bool edspListParser::ParseStatus(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver) { - if (Section.FindFlag("Hold",Pkg->Flags,pkgCache::State::Installed) == false) + unsigned long state = 0; + if (Section.FindFlag("Hold",state,pkgCache::State::Hold) == false) return false; + if (state != 0) + Pkg->SelectedState = pkgCache::State::Hold; - unsigned long state = 0; + state = 0; if (Section.FindFlag("Installed",state,pkgCache::State::Installed) == false) return false; if (state != 0) -- cgit v1.2.3 From 80699703b6015a8fe7707302f365020f9782cf2c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 3 May 2011 10:38:49 +0200 Subject: work on requests with the correct upgrade/dist-upgrade/else resolver --- cmdline/apt-internal-solver.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc index 0aa218d52..df6a6f569 100644 --- a/cmdline/apt-internal-solver.cc +++ b/cmdline/apt-internal-solver.cc @@ -156,7 +156,17 @@ int main(int argc,const char *argv[]) /*{{{*/ EDSP::WriteProgress(60, "Call problemresolver on current scenario…", output); - if (Fix.Resolve() == false) { + if (upgrade == true) { + if (pkgAllUpgrade(CacheFile) == false) { + EDSP::WriteError("An upgrade error occured", output); + return 0; + } + } else if (distUpgrade == true) { + if (pkgDistUpgrade(CacheFile) == false) { + EDSP::WriteError("An dist-upgrade error occured", output); + return 0; + } + } else if (Fix.Resolve() == false) { EDSP::WriteError("An error occured", output); return 0; } -- cgit v1.2.3 From 741b7da9de1d2ab470728f1e7f38b25e0d6a556c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 3 May 2011 10:50:25 +0200 Subject: implement external solver calling for upgrade and dist-upgrade, too --- apt-pkg/algorithms.cc | 40 ++++++++++++----------- apt-pkg/algorithms.h | 1 + apt-pkg/edsp.cc | 88 +++++++++++++++++++++++++++++++-------------------- apt-pkg/edsp.h | 3 ++ 4 files changed, 80 insertions(+), 52 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index fea9e92e1..5d9fefaa6 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -332,6 +332,10 @@ bool pkgFixBroken(pkgDepCache &Cache) */ bool pkgDistUpgrade(pkgDepCache &Cache) { + std::string const solver = _config->Find("APT::Solver::Name", "internal"); + if (solver != "internal") + return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false); + pkgDepCache::ActionGroup group(Cache); /* Upgrade all installed packages first without autoinst to help the resolver @@ -384,6 +388,10 @@ bool pkgDistUpgrade(pkgDepCache &Cache) to install packages not marked for install */ bool pkgAllUpgrade(pkgDepCache &Cache) { + std::string const solver = _config->Find("APT::Solver::Name", "internal"); + if (solver != "internal") + return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false); + pkgDepCache::ActionGroup group(Cache); pkgProblemResolver Fix(&Cache); @@ -740,25 +748,8 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) bool pkgProblemResolver::Resolve(bool BrokenFix) { std::string const solver = _config->Find("APT::Solver::Name", "internal"); - if (solver != "internal") - { - int solver_in, solver_out; - if (EDSP::ExecuteSolver(solver.c_str(), &solver_in, &solver_out) == false) - return false; - - FILE* output = fdopen(solver_in, "w"); - if (output == NULL) - return _error->Errno("Resolve", "fdopen on solver stdin failed"); - EDSP::WriteRequest(Cache, output); - EDSP::WriteScenario(Cache, output); - fclose(output); - - if (EDSP::ReadResponse(solver_out, Cache) == false) - return _error->Error("Reading solver response failed"); - - return true; - } + return EDSP::ResolveExternal(solver.c_str(), Cache, false, false, false); return ResolveInternal(BrokenFix); } /*}}}*/ @@ -1230,6 +1221,19 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) in that it does not install or remove any packages. It is assumed that the system was non-broken previously. */ bool pkgProblemResolver::ResolveByKeep() +{ + std::string const solver = _config->Find("APT::Solver::Name", "internal"); + if (solver != "internal") + return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false); + return ResolveByKeepInternal(); +} + /*}}}*/ +// ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/ +// --------------------------------------------------------------------- +/* This is the work horse of the soft upgrade routine. It is very gental + in that it does not install or remove any packages. It is assumed that the + system was non-broken previously. */ +bool pkgProblemResolver::ResolveByKeepInternal() { pkgDepCache::ActionGroup group(Cache); diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 0778ec722..582cbc527 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -107,6 +107,7 @@ class pkgProblemResolver /*{{{*/ bool DoUpgrade(pkgCache::PkgIterator Pkg); bool ResolveInternal(bool const BrokenFix = false); + bool ResolveByKeepInternal(); public: diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index f35570c12..d72370358 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -197,7 +197,7 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, continue; req->append(" ").append(Pkg.FullName()); } - fprintf(output, "Request: EDSP 0.2\n"); + fprintf(output, "Request: EDSP 0.4\n"); if (del.empty() == false) fprintf(output, "Remove: %s\n", del.c_str()+1); if (inst.empty() == false) @@ -460,42 +460,62 @@ bool EDSP::WriteError(std::string const &message, FILE* output) { return false; // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes {{{*/ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) { - std::vector const solverDirs = _config->FindVector("Dir::Bin::Solvers"); - std::string file; - for (std::vector::const_iterator dir = solverDirs.begin(); - dir != solverDirs.end(); ++dir) { - file = flCombine(*dir, solver); - if (RealFileExists(file.c_str()) == true) - break; - file.clear(); - } + std::vector const solverDirs = _config->FindVector("Dir::Bin::Solvers"); + std::string file; + for (std::vector::const_iterator dir = solverDirs.begin(); + dir != solverDirs.end(); ++dir) { + file = flCombine(*dir, solver); + if (RealFileExists(file.c_str()) == true) + break; + file.clear(); + } - if (file.empty() == true) - return _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver); - int external[4] = {-1, -1, -1, -1}; - if (pipe(external) != 0 || pipe(external + 2) != 0) - return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); - for (int i = 0; i < 4; ++i) - SetCloseExec(external[i], true); + if (file.empty() == true) + return _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver); + int external[4] = {-1, -1, -1, -1}; + if (pipe(external) != 0 || pipe(external + 2) != 0) + return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); + for (int i = 0; i < 4; ++i) + SetCloseExec(external[i], true); - pid_t Solver = ExecFork(); - if (Solver == 0) - { - dup2(external[0], STDIN_FILENO); - dup2(external[3], STDOUT_FILENO); - const char* calling[2] = { file.c_str(), 0 }; - execv(calling[0], (char**) calling); - std::cerr << "Failed to execute solver '" << solver << "'!" << std::endl; - _exit(100); - } - close(external[0]); - close(external[3]); + pid_t Solver = ExecFork(); + if (Solver == 0) { + dup2(external[0], STDIN_FILENO); + dup2(external[3], STDOUT_FILENO); + const char* calling[2] = { file.c_str(), 0 }; + execv(calling[0], (char**) calling); + std::cerr << "Failed to execute solver '" << solver << "'!" << std::endl; + _exit(100); + } + close(external[0]); + close(external[3]); - if (WaitFd(external[1], true, 5) == false) - return _error->Errno("Resolve", "Timed out while Waiting on availability of solver stdin"); + if (WaitFd(external[1], true, 5) == false) + return _error->Errno("Resolve", "Timed out while Waiting on availability of solver stdin"); - *solver_in = external[1]; - *solver_out = external[2]; - return true; + *solver_in = external[1]; + *solver_out = external[2]; + return true; +} + /*}}}*/ +// EDSP::ResolveExternal - resolve problems by asking external for help {{{*/ +bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache, + bool const upgrade, bool const distUpgrade, + bool const autoRemove) { + int solver_in, solver_out; + if (EDSP::ExecuteSolver(solver, &solver_in, &solver_out) == false) + return false; + + FILE* output = fdopen(solver_in, "w"); + if (output == NULL) + return _error->Errno("Resolve", "fdopen on solver stdin failed"); + EDSP::WriteRequest(Cache, output, upgrade, distUpgrade, autoRemove); + EDSP::WriteScenario(Cache, output); + fclose(output); + + if (EDSP::ReadResponse(solver_out, Cache) == false) + return _error->Error("Reading solver response failed"); + + return true; } /*}}}*/ diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index df6e1d21c..95132ebd0 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -53,6 +53,9 @@ public: bool static WriteError(std::string const &message, FILE* output); bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); + bool static ResolveExternal(const char* const solver, pkgDepCache &Cache, + bool const upgrade, bool const distUpgrade, + bool const autoRemove); }; /*}}}*/ #endif -- cgit v1.2.3 From cbc702ea5805ba63f6a032d38530879700f4d100 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 3 May 2011 10:51:55 +0200 Subject: tell the resolver a package is set on hold if it was set by the user to Keep which happens for example if a user decides to "remove" a not installed package to forbid that it's part of the solution --- apt-pkg/depcache.h | 1 + apt-pkg/edsp.cc | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index b15cd527d..f95ad9a14 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -232,6 +232,7 @@ class pkgDepCache : protected pkgCache::Namespace inline bool NewInstall() const {return Status == 2 && Mode == ModeInstall;}; inline bool Delete() const {return Mode == ModeDelete;}; inline bool Keep() const {return Mode == ModeKeep;}; + inline bool Protect() const {return (iFlags & Protected) == Protected;}; inline bool Upgrade() const {return Status > 0 && Mode == ModeInstall;}; inline bool Upgradable() const {return Status >= 1;}; inline bool Downgrade() const {return Status < 0 && Mode == ModeInstall;}; diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index d72370358..8bd0c14bb 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -61,7 +61,8 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI fprintf(output, "Version: %s\n", Ver.VerStr()); if (Pkg.CurrentVer() == Ver) fprintf(output, "Installed: yes\n"); - if (Pkg->SelectedState == pkgCache::State::Hold) + if (Pkg->SelectedState == pkgCache::State::Hold || + (Cache[Pkg].Keep() == true && Cache[Pkg].Protect() == true)) fprintf(output, "Hold: yes\n"); fprintf(output, "APT-ID: %d\n", Ver->ID); fprintf(output, "Priority: %s\n", PrioMap[Ver->Priority]); -- cgit v1.2.3 From 575e9b5c5c82087ebdbfe1d3660de8fe7e92d5e9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 3 May 2011 14:05:13 +0200 Subject: add a fair round of doxygen comments to the edsp header --- apt-pkg/edsp.h | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 3 deletions(-) diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 95132ebd0..98a70d7f6 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -1,7 +1,9 @@ // -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -/* ###################################################################### +/** Description \file edsp.h {{{ + ###################################################################### Set of methods to help writing and reading everything needed for EDSP + with the noteable exception of reading a scenario for conversion into + a Cache as this is handled by edsp interface for listparser and friends ##################################################################### */ /*}}}*/ #ifndef PKGLIB_EDSP_H @@ -32,27 +34,173 @@ class EDSP /*{{{*/ pkgCache::VerIterator const &Ver, APT::PackageSet const &pkgset); public: + /** \brief creates the EDSP request stanza + * + * In the EDSP protocol the first thing send to the resolver is a stanza + * encoding the request. This method will write this stanza by looking at + * the given Cache and requests the installation of all packages which were + * marked for installation in it (equally for remove). + * + * \param Cache in which the request is encoded + * \param output is written to this "file" + * \param upgrade is true if it is an request like apt-get upgrade + * \param distUpgrade is true if it is a request like apt-get dist-upgrade + * \param autoRemove is true if removal of unneeded packages should be performed + * + * \return true if request was composed successfully, otherwise false + */ bool static WriteRequest(pkgDepCache &Cache, FILE* output, bool const upgrade = false, bool const distUpgrade = false, bool const autoRemove = false); + + /** \brief creates the scenario representing the package universe + * + * After the request all known information about a package are send + * to the solver. The output looks similar to a Packages or status file + * + * All packages and version included in this Cache are send, even if + * it doesn't make sense from an APT resolver point of view like versions + * with a negative pin to enable the solver to propose even that as a + * solution or at least to be able to give a hint what can be done to + * statisfy a request. + * + * \param Cache is the known package universe + * \param output is written to this "file" + * + * \return true if universe was composed successfully, otherwise false + */ bool static WriteScenario(pkgDepCache &Cache, FILE* output); + + /** \brief creates a limited scenario representing the package universe + * + * This method works similar to #WriteScenario as it works in the same + * way but doesn't send the complete universe to the solver but only + * packages included in the pkgset which will have only dependencies + * on packages which are in the given set. All other dependencies will + * be removed, so that this method can be used to create testcases + * + * \param Cache is the known package universe + * \param output is written to this "file" + * \param pkgset is a set of packages the universe should be limited to + * + * \return true if universe was composed successfully, otherwise false + */ bool static WriteLimitedScenario(pkgDepCache &Cache, FILE* output, APT::PackageSet const &pkgset); + + /** \brief waits and acts on the information returned from the solver + * + * This method takes care of interpreting whatever the solver sends + * through the standard output like a solution, progress or an error. + * The main thread should handle his control over to this method to + * wait for the solver to finish the given task + * + * \param input file descriptor with the response from the solver + * \param Cache the solution should be applied on if any + * + * \return true if a solution is found and applied correctly, otherwise false + */ bool static ReadResponse(int const input, pkgDepCache &Cache); - // ReadScenario is provided by the listparser infrastructure + /** \brief search and read the request stanza for action later + * + * This method while ignore the input up to the point it finds the + * Request: line as an indicator for the Request stanza. + * The request is stored in the parameters install and remove then, + * as the cache isn't build yet as the scenario follows the request. + * + * \param input file descriptor with the edsp input for the solver + * \param[out] install is a list which gets populated with requested installs + * \param[out] remove is a list which gets populated with requested removals + * \param[out] upgrade is true if it is a request like apt-get upgrade + * \param[out] distUpgrade is true if it is a request like apt-get dist-upgrade + * \param[out] autoRemove is true if removal of uneeded packages should be performed + * + * \return true if the request could be found and worked on, otherwise false + */ bool static ReadRequest(int const input, std::list &install, std::list &remove, bool &upgrade, bool &distUpgrade, bool &autoRemove); + + /** \brief takes the request lists and applies it on the cache + * + * The lists as created by #ReadRequest will be used to find the + * packages in question and mark them for install/remove. + * No solving is done and no auto-install/-remove. + * + * \param install is a list of packages to mark for installation + * \param remove is a list of packages to mark for removal + * \param Cache is there the markers should be set + * + * \return false if the request couldn't be applied, true otherwise + */ bool static ApplyRequest(std::list const &install, std::list const &remove, pkgDepCache &Cache); + + /** \brief encodes the changes in the Cache as a EDSP solution + * + * The markers in the Cache are observed and send to given + * file. The solution isn't checked for consistency or alike, + * so even broken solutions can be written successfully, + * but the front-end revicing it will properly fail then. + * + * \param Cache which represents the solution + * \param output to write the stanzas forming the solution to + * + * \return true if solution could be written, otherwise false + */ bool static WriteSolution(pkgDepCache &Cache, FILE* output); + + /** \brief sends a progress report + * + * \param percent of the solving completed + * \param message the solver wants the user to see + * \param output the front-end listens for progress report + */ bool static WriteProgress(unsigned short const percent, const char* const message, FILE* output); + + /** \brief sends an error report + * + * Solvers are expected to execute successfully even if + * they were unable to calculate a solution for a given task. + * Obviously they can't send a solution through, so this + * methods deals with formatting an error message correctly + * so that the front-ends can recieve and display it. + * + * The first line of the message should be a short description + * of the error so it can be used for dialog titles or alike + */ bool static WriteError(std::string const &message, FILE* output); + /** \brief executes the given solver and returns the pipe ends + * + * The given solver is executed if it can be found in one of the + * configured directories and setup for it is performed. + * + * \param solver to execute + * \param[out] solver_in will be the stdin of the solver + * \param[out] solver_out will be the stdout of the solver + * + * \return true if the solver could be started and the pipes + * are set up correctly, otherwise false and the pipes are invalid + */ bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); + + /** \brief call an external resolver to handle the request + * + * This method wraps all the methods above to call an external solver + * + * \param solver to execute + * \param Cache with the problem and as universe to work in + * \param upgrade is true if it is a request like apt-get upgrade + * \param distUpgrade is true if it is a request like apt-get dist-upgrade + * \param autoRemove is true if unneeded packages should be removed + * + * \return true if the solver has successfully solved the problem, + * otherwise false + */ bool static ResolveExternal(const char* const solver, pkgDepCache &Cache, bool const upgrade, bool const distUpgrade, bool const autoRemove); -- cgit v1.2.3 From ff859c7f94e7ba2b698208d3db43a2b3bdbbb736 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 3 May 2011 14:15:52 +0200 Subject: ship the apt-internal-solver in apt-utils package and link it to /usr/lib/apt/solvers so we have it available for playing as 'apt' --- debian/apt-utils.links | 1 + debian/rules | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 debian/apt-utils.links diff --git a/debian/apt-utils.links b/debian/apt-utils.links new file mode 100644 index 000000000..5bf138c4a --- /dev/null +++ b/debian/apt-utils.links @@ -0,0 +1 @@ +usr/bin/apt-internal-solver usr/lib/apt/solvers/apt diff --git a/debian/rules b/debian/rules index 640900678..c8aefee63 100755 --- a/debian/rules +++ b/debian/rules @@ -62,7 +62,7 @@ configure.in: endif # APT Programs in apt-utils -APT_UTILS=ftparchive sortpkgs extracttemplates +APT_UTILS=ftparchive sortpkgs extracttemplates internal-solver # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 -- cgit v1.2.3 From df783e0aa69f70b7be2b7fb44cc593efd86f7730 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 3 May 2011 14:17:29 +0200 Subject: add a --solver option to apt-get --- cmdline/apt-get.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index a1264f54a..2312f5a10 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -3253,6 +3253,7 @@ int main(int argc,const char *argv[]) /*{{{*/ {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean}, {0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean}, {0,"fix-policy","APT::Get::Fix-Policy-Broken",0}, + {0,"solver","APT::Solver::Name",CommandLine::HasArg}, {'c',"config-file",0,CommandLine::ConfigFile}, {'o',"option",0,CommandLine::ArbItem}, {0,0,0,0}}; -- cgit v1.2.3 From ee8c790a660a817417267379bca1a26e7813dfde Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 3 May 2011 16:45:01 +0200 Subject: =?UTF-8?q?maybe=20Pre-Depends=20are=20checked=20if=20they=20write?= =?UTF-8?q?=20them=20as=20Pre-Depends=20and=20not=20as=20PreDepends=20(doh?= =?UTF-8?q?!)=20=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apt-pkg/edsp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 8bd0c14bb..ce9ad250c 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -21,7 +21,7 @@ // we could use pkgCache::DepType and ::Priority, but these would be localized strings… const char * const EDSP::PrioMap[] = {0, "important", "required", "standard", "optional", "extra"}; -const char * const EDSP::DepMap[] = {"", "Depends", "PreDepends", "Suggests", +const char * const EDSP::DepMap[] = {"", "Depends", "Pre-Depends", "Suggests", "Recommends" , "Conflicts", "Replaces", "Obsoletes", "Breaks", "Enhances"}; -- cgit v1.2.3 From 7f4713547665e12e032501228a98586e5add48f7 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 3 May 2011 17:27:11 +0200 Subject: add a tiny dump solver to quickly output a scenario --- cmdline/apt-dump-solver.cc | 50 ++++++++++++++++++++++++++++++++++++++++++++++ cmdline/makefile | 7 +++++++ debian/apt-utils.install | 1 + debian/apt.dirs | 1 + debian/rules | 2 +- 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 cmdline/apt-dump-solver.cc diff --git a/cmdline/apt-dump-solver.cc b/cmdline/apt-dump-solver.cc new file mode 100644 index 000000000..5bcfe4f06 --- /dev/null +++ b/cmdline/apt-dump-solver.cc @@ -0,0 +1,50 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ##################################################################### + + dummy solver to get quickly a scenario file out of APT + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include + +#include + +#include + /*}}}*/ + +// ShowHelp - Show a help screen /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool ShowHelp() { + + std::cout << + PACKAGE " " VERSION " for " COMMON_ARCH " compiled on " __DATE__ " " __TIME__ << std::endl << + "Usage: apt-dump-resolver\n" + "\n" + "apt-dump-resolver is a dummy solver who just dumps its input to the\n" + "file /tmp/dump.edsp and exists with a proper EDSP error.\n" + "\n" + " This dump has lost Super Cow Powers.\n"; + return true; +} + /*}}}*/ +int main(int argc,const char *argv[]) /*{{{*/ +{ + if (argc > 1 && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1],"-h") == 0 || + strcmp(argv[1],"-v") == 0 || strcmp(argv[1],"--version") == 0)) { + ShowHelp(); + return 0; + } + + FILE* input = fdopen(STDIN_FILENO, "r"); + FILE* output = fopen("/tmp/dump.edsp", "w"); + char buffer[400]; + while (fgets(buffer, sizeof(buffer), input) != NULL) + fputs(buffer, output); + fclose(output); + fclose(input); + + EDSP::WriteError("I am too dumb, i can just dump!", stdout); +} diff --git a/cmdline/makefile b/cmdline/makefile index 4462ccaf4..aea5d1db5 100644 --- a/cmdline/makefile +++ b/cmdline/makefile @@ -71,3 +71,10 @@ SLIBS = -lapt-pkg $(INTLLIBS) LIB_MAKES = apt-pkg/makefile SOURCE = apt-internal-solver.cc include $(PROGRAM_H) + +# The internal solver acting as an external +PROGRAM=apt-dump-solver +SLIBS = -lapt-pkg $(INTLLIBS) +LIB_MAKES = apt-pkg/makefile +SOURCE = apt-dump-solver.cc +include $(PROGRAM_H) diff --git a/debian/apt-utils.install b/debian/apt-utils.install index d947f26d4..0c72bfdc8 100644 --- a/debian/apt-utils.install +++ b/debian/apt-utils.install @@ -1 +1,2 @@ bin/libapt-inst*.so.* usr/lib/ +bin/apt-dump-solver usr/lib/apt/solvers/dump diff --git a/debian/apt.dirs b/debian/apt.dirs index 2770d79bb..f9c0b6c3e 100644 --- a/debian/apt.dirs +++ b/debian/apt.dirs @@ -1,5 +1,6 @@ usr/bin usr/lib/apt/methods +usr/lib/apt/solvers usr/lib/dpkg/methods/apt etc/apt etc/apt/apt.conf.d diff --git a/debian/rules b/debian/rules index c8aefee63..77a7b4fdb 100755 --- a/debian/rules +++ b/debian/rules @@ -182,7 +182,7 @@ apt: build build-doc dh_install -p$@ --sourcedir=$(BLD) # Remove the bits that are in apt-utils - rm $(addprefix debian/$@/usr/bin/apt-,$(APT_UTILS)) + rm $(addprefix debian/$@/usr/bin/apt-,$(APT_UTILS) dump-solver) # https has its own package rm debian/$@/usr/lib/apt/methods/https -- cgit v1.2.3 From bda94cb8432b3905f5757e92573fd16e73cb183f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 3 May 2011 19:59:45 +0200 Subject: fix arguments for MarkInstall so packages are really marked as automatic --- apt-pkg/edsp.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index ce9ad250c..5b59373bd 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -273,7 +273,7 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { pkgCache::VerIterator Ver(Cache.GetCache(), Cache.GetCache().VerP + VerIdx[id]); Cache.SetCandidateVersion(Ver); if (type == "Install") - Cache.MarkInstall(Ver.ParentPkg(), false, false); + Cache.MarkInstall(Ver.ParentPkg(), false, 0, false); else if (type == "Remove") Cache.MarkDelete(Ver.ParentPkg(), false); else if (type == "Autoremove") { @@ -450,10 +450,10 @@ bool EDSP::WriteSolution(pkgDepCache &Cache, FILE* output) /*}}}*/ // EDSP::WriteProgess - pulse to the given file descriptor /*{{{*/ bool EDSP::WriteProgress(unsigned short const percent, const char* const message, FILE* output) { - fprintf(output, "Progress: %s\n", TimeRFC1123(time(NULL)).c_str()); - fprintf(output, "Percentage: %d\n", percent); - fprintf(output, "Message: %s\n\n", message); - fflush(output); +// fprintf(output, "Progress: %s\n", TimeRFC1123(time(NULL)).c_str()); +// fprintf(output, "Percentage: %d\n", percent); +// fprintf(output, "Message: %s\n\n", message); +// fflush(output); return true; } /*}}}*/ -- cgit v1.2.3 From 3d17b9ffc7c5a417d69916c282f4756cc7e938d2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 6 May 2011 11:53:54 +0200 Subject: undo the temporary progress reporting disabling which slipped into last commit --- apt-pkg/edsp.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 5b59373bd..d604110ef 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -450,10 +450,10 @@ bool EDSP::WriteSolution(pkgDepCache &Cache, FILE* output) /*}}}*/ // EDSP::WriteProgess - pulse to the given file descriptor /*{{{*/ bool EDSP::WriteProgress(unsigned short const percent, const char* const message, FILE* output) { -// fprintf(output, "Progress: %s\n", TimeRFC1123(time(NULL)).c_str()); -// fprintf(output, "Percentage: %d\n", percent); -// fprintf(output, "Message: %s\n\n", message); -// fflush(output); + fprintf(output, "Progress: %s\n", TimeRFC1123(time(NULL)).c_str()); + fprintf(output, "Percentage: %d\n", percent); + fprintf(output, "Message: %s\n\n", message); + fflush(output); return true; } /*}}}*/ -- cgit v1.2.3 From ebfeeaedf5bc357170cae971c0f6a1458ff65f65 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 7 May 2011 15:49:51 +0200 Subject: implement correct error reporting --- apt-pkg/edsp.cc | 14 ++++++++++++-- apt-pkg/edsp.h | 7 ++++++- cmdline/apt-dump-solver.cc | 2 +- cmdline/apt-internal-solver.cc | 6 +++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index d604110ef..7ece92d2e 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -256,6 +256,11 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { else std::clog << msg << std::endl; continue; + } else if (section.Exists("Error") == true) { + std::cerr << "The solver encountered an error of type: " << section.FindS("Error") << std::endl; + std::cerr << "The following information might help you to understand what is wrong:" << std::endl; + std::cerr << SubstVar(SubstVar(section.FindS("Message"), "\n .\n", "\n\n"), "\n ", "\n") << std::endl << std::endl; + break; } else if (section.Exists("Autoremove") == true) type = "Autoremove"; else @@ -457,8 +462,13 @@ bool EDSP::WriteProgress(unsigned short const percent, const char* const message return true; } /*}}}*/ -bool EDSP::WriteError(std::string const &message, FILE* output) { return false; } - +// EDSP::WriteError - format an error message to be send to file descriptor /*{{{*/ +bool EDSP::WriteError(char const * const uuid, std::string const &message, FILE* output) { + fprintf(output, "Error: %s\n", uuid); + fprintf(output, "Message: %s\n\n", SubstVar(SubstVar(message, "\n\n", "\n.\n"), "\n", "\n ").c_str()); + return true; +} + /*}}}*/ // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes {{{*/ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) { std::vector const solverDirs = _config->FindVector("Dir::Bin::Solvers"); diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 98a70d7f6..210188d03 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -171,8 +171,13 @@ public: * * The first line of the message should be a short description * of the error so it can be used for dialog titles or alike + * + * \param uuid of this error message + * \param message is free form text to discribe the error + * \param output the front-end listens for error messages */ - bool static WriteError(std::string const &message, FILE* output); + bool static WriteError(char const * const uuid, std::string const &message, FILE* output); + /** \brief executes the given solver and returns the pipe ends * diff --git a/cmdline/apt-dump-solver.cc b/cmdline/apt-dump-solver.cc index 5bcfe4f06..dab0cc6fd 100644 --- a/cmdline/apt-dump-solver.cc +++ b/cmdline/apt-dump-solver.cc @@ -46,5 +46,5 @@ int main(int argc,const char *argv[]) /*{{{*/ fclose(output); fclose(input); - EDSP::WriteError("I am too dumb, i can just dump!", stdout); + EDSP::WriteError("ERR_JUST_DUMPING", "I am too dumb, i can just dump!\nPlease use one of my friends instead!", stdout); } diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc index df6a6f569..ad00a0e23 100644 --- a/cmdline/apt-internal-solver.cc +++ b/cmdline/apt-internal-solver.cc @@ -158,16 +158,16 @@ int main(int argc,const char *argv[]) /*{{{*/ if (upgrade == true) { if (pkgAllUpgrade(CacheFile) == false) { - EDSP::WriteError("An upgrade error occured", output); + EDSP::WriteError("ERR_UNSOLVABLE_UPGRADE", "An upgrade error occured", output); return 0; } } else if (distUpgrade == true) { if (pkgDistUpgrade(CacheFile) == false) { - EDSP::WriteError("An dist-upgrade error occured", output); + EDSP::WriteError("ERR_UNSOLVABLE_DIST_UPGRADE", "An dist-upgrade error occured", output); return 0; } } else if (Fix.Resolve() == false) { - EDSP::WriteError("An error occured", output); + EDSP::WriteError("ERR_UNSOLVABLE", "An error occured", output); return 0; } -- cgit v1.2.3 From b57c0e355d7f27a74c860ed73700cf9241cb4e61 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 9 May 2011 18:00:28 +0200 Subject: implement proper progress report with OpProgress --- apt-pkg/algorithms.cc | 24 ++++++++++++------- apt-pkg/edsp.cc | 64 ++++++++++++++++++++++++++++++++++++--------------- apt-pkg/edsp.h | 18 +++++++++++---- 3 files changed, 74 insertions(+), 32 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 5d9fefaa6..31c3e9c28 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -333,8 +333,10 @@ bool pkgFixBroken(pkgDepCache &Cache) bool pkgDistUpgrade(pkgDepCache &Cache) { std::string const solver = _config->Find("APT::Solver::Name", "internal"); - if (solver != "internal") - return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false); + if (solver != "internal") { + OpTextProgress Prog(*_config); + return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog); + } pkgDepCache::ActionGroup group(Cache); @@ -389,8 +391,10 @@ bool pkgDistUpgrade(pkgDepCache &Cache) bool pkgAllUpgrade(pkgDepCache &Cache) { std::string const solver = _config->Find("APT::Solver::Name", "internal"); - if (solver != "internal") - return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false); + if (solver != "internal") { + OpTextProgress Prog(*_config); + return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog); + } pkgDepCache::ActionGroup group(Cache); @@ -748,8 +752,10 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) bool pkgProblemResolver::Resolve(bool BrokenFix) { std::string const solver = _config->Find("APT::Solver::Name", "internal"); - if (solver != "internal") - return EDSP::ResolveExternal(solver.c_str(), Cache, false, false, false); + if (solver != "internal") { + OpTextProgress Prog(*_config); + return EDSP::ResolveExternal(solver.c_str(), Cache, false, false, false, &Prog); + } return ResolveInternal(BrokenFix); } /*}}}*/ @@ -1223,8 +1229,10 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) bool pkgProblemResolver::ResolveByKeep() { std::string const solver = _config->Find("APT::Solver::Name", "internal"); - if (solver != "internal") - return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false); + if (solver != "internal") { + OpTextProgress Prog(*_config); + return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog); + } return ResolveByKeepInternal(); } /*}}}*/ diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 7ece92d2e..489dd2933 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -26,29 +26,42 @@ const char * const EDSP::DepMap[] = {"", "Depends", "Pre-Depends", "Suggests", "Obsoletes", "Breaks", "Enhances"}; // EDSP::WriteScenario - to the given file descriptor /*{{{*/ -bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output) +bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress) { + if (Progress != NULL) + Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); + unsigned long p = 0; for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) - for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p) { WriteScenarioVersion(Cache, output, Pkg, Ver); WriteScenarioDependency(Cache, output, Pkg, Ver); fprintf(output, "\n"); + if (Progress != NULL && p % 100 == 0) + Progress->Progress(p); } return true; } /*}}}*/ // EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/ bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output, - APT::PackageSet const &pkgset) + APT::PackageSet const &pkgset, + OpProgress *Progress) { - for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) + if (Progress != NULL) + Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); + unsigned long p = 0; + for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg, ++p) for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) { WriteScenarioVersion(Cache, output, Pkg, Ver); WriteScenarioLimitedDependency(Cache, output, Pkg, Ver, pkgset); fprintf(output, "\n"); + if (Progress != NULL && p % 100 == 0) + Progress->Progress(p); } + if (Progress != NULL) + Progress->Done(); return true; } /*}}}*/ @@ -184,11 +197,17 @@ void EDSP::WriteScenarioLimitedDependency(pkgDepCache &Cache, FILE* output, /*}}}*/ // EDSP::WriteRequest - to the given file descriptor /*{{{*/ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, - bool const DistUpgrade, bool const AutoRemove) + bool const DistUpgrade, bool const AutoRemove, + OpProgress *Progress) { + if (Progress != NULL) + Progress->SubProgress(Cache.Head().PackageCount, _("Send request to solver")); + unsigned long p = 0; string del, inst; - for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg, ++p) { + if (Progress != NULL && p % 100 == 0) + Progress->Progress(p); string* req; if (Cache[Pkg].Delete() == true) req = &del; @@ -221,7 +240,7 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, } /*}}}*/ // EDSP::ReadResponse - from the given file descriptor /*{{{*/ -bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { +bool EDSP::ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress) { /* We build an map id to mmap offset here In theory we could use the offset as ID, but then VersionCount couldn't be used to create other versionmappings anymore and it @@ -247,14 +266,14 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) { else if (section.Exists("Remove") == true) type = "Remove"; else if (section.Exists("Progress") == true) { - std::clog << TimeRFC1123(time(NULL)) << " "; - ioprintf(std::clog, "[ %3d%% ] ", section.FindI("Percentage", 0)); - std::clog << section.FindS("Progress") << " - "; - string const msg = section.FindS("Message"); - if (msg.empty() == true) - std::clog << "Solver is still working on the solution" << std::endl; - else - std::clog << msg << std::endl; + if (Progress != NULL) { + string const msg = section.FindS("Message"); + if (msg.empty() == true) + Progress->SubProgress(100, _("Prepare for receiving solution")); + else + Progress->SubProgress(100, msg); + Progress->Progress(section.FindI("Percentage", 0)); + } continue; } else if (section.Exists("Error") == true) { std::cerr << "The solver encountered an error of type: " << section.FindS("Error") << std::endl; @@ -512,7 +531,7 @@ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_o // EDSP::ResolveExternal - resolve problems by asking external for help {{{*/ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache, bool const upgrade, bool const distUpgrade, - bool const autoRemove) { + bool const autoRemove, OpProgress *Progress) { int solver_in, solver_out; if (EDSP::ExecuteSolver(solver, &solver_in, &solver_out) == false) return false; @@ -520,11 +539,18 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache, FILE* output = fdopen(solver_in, "w"); if (output == NULL) return _error->Errno("Resolve", "fdopen on solver stdin failed"); - EDSP::WriteRequest(Cache, output, upgrade, distUpgrade, autoRemove); - EDSP::WriteScenario(Cache, output); + + if (Progress != NULL) + Progress->OverallProgress(0, 100, 5, _("Execute external solver")); + EDSP::WriteRequest(Cache, output, upgrade, distUpgrade, autoRemove, Progress); + if (Progress != NULL) + Progress->OverallProgress(5, 100, 20, _("Execute external solver")); + EDSP::WriteScenario(Cache, output, Progress); fclose(output); - if (EDSP::ReadResponse(solver_out, Cache) == false) + if (Progress != NULL) + Progress->OverallProgress(25, 100, 75, _("Execute external solver")); + if (EDSP::ReadResponse(solver_out, Cache, Progress) == false) return _error->Error("Reading solver response failed"); return true; diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 210188d03..743c3f5d1 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -11,6 +11,7 @@ #include #include +#include #include @@ -46,13 +47,15 @@ public: * \param upgrade is true if it is an request like apt-get upgrade * \param distUpgrade is true if it is a request like apt-get dist-upgrade * \param autoRemove is true if removal of unneeded packages should be performed + * \param Progress is an instance to report progress to * * \return true if request was composed successfully, otherwise false */ bool static WriteRequest(pkgDepCache &Cache, FILE* output, bool const upgrade = false, bool const distUpgrade = false, - bool const autoRemove = false); + bool const autoRemove = false, + OpProgress *Progress = NULL); /** \brief creates the scenario representing the package universe * @@ -67,10 +70,11 @@ public: * * \param Cache is the known package universe * \param output is written to this "file" + * \param Progress is an instance to report progress to * * \return true if universe was composed successfully, otherwise false */ - bool static WriteScenario(pkgDepCache &Cache, FILE* output); + bool static WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress = NULL); /** \brief creates a limited scenario representing the package universe * @@ -83,11 +87,13 @@ public: * \param Cache is the known package universe * \param output is written to this "file" * \param pkgset is a set of packages the universe should be limited to + * \param Progress is an instance to report progress to * * \return true if universe was composed successfully, otherwise false */ bool static WriteLimitedScenario(pkgDepCache &Cache, FILE* output, - APT::PackageSet const &pkgset); + APT::PackageSet const &pkgset, + OpProgress *Progress = NULL); /** \brief waits and acts on the information returned from the solver * @@ -98,10 +104,11 @@ public: * * \param input file descriptor with the response from the solver * \param Cache the solution should be applied on if any + * \param Progress is an instance to report progress to * * \return true if a solution is found and applied correctly, otherwise false */ - bool static ReadResponse(int const input, pkgDepCache &Cache); + bool static ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress = NULL); /** \brief search and read the request stanza for action later * @@ -202,13 +209,14 @@ public: * \param upgrade is true if it is a request like apt-get upgrade * \param distUpgrade is true if it is a request like apt-get dist-upgrade * \param autoRemove is true if unneeded packages should be removed + * \param Progress is an instance to report progress to * * \return true if the solver has successfully solved the problem, * otherwise false */ bool static ResolveExternal(const char* const solver, pkgDepCache &Cache, bool const upgrade, bool const distUpgrade, - bool const autoRemove); + bool const autoRemove, OpProgress *Progress = NULL); }; /*}}}*/ #endif -- cgit v1.2.3 From 66b6fe055a0604d2a8372e61032e492f88f49f86 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 9 May 2011 21:55:32 +0200 Subject: fix package building so 'dump' is a binary not a directory --- debian/apt-utils.dirs | 2 +- debian/apt-utils.install | 1 - debian/rules | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/apt-utils.dirs b/debian/apt-utils.dirs index 14f5b95d7..681e55192 100644 --- a/debian/apt-utils.dirs +++ b/debian/apt-utils.dirs @@ -1,2 +1,2 @@ -usr/lib +usr/lib/apt/solvers usr/bin diff --git a/debian/apt-utils.install b/debian/apt-utils.install index 0c72bfdc8..d947f26d4 100644 --- a/debian/apt-utils.install +++ b/debian/apt-utils.install @@ -1,2 +1 @@ bin/libapt-inst*.so.* usr/lib/ -bin/apt-dump-solver usr/lib/apt/solvers/dump diff --git a/debian/rules b/debian/rules index 77a7b4fdb..c83796e03 100755 --- a/debian/rules +++ b/debian/rules @@ -236,8 +236,10 @@ apt-utils: build dh_installdirs -p$@ cp $(addprefix $(BLD)/bin/apt-,$(APT_UTILS)) debian/$@/usr/bin/ + cp $(BLD)/bin/apt-dump-solver debian/$@/usr/lib/apt/solvers/dump dh_install -p$@ --sourcedir=$(BLD) + dh_link -p$@ dh_installdocs -p$@ dh_installexamples -p$@ -- cgit v1.2.3 From c6660a4ba95e2c8112ee5190a71bdfa6640eb35d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 10 May 2011 12:18:08 +0200 Subject: fix SubProgress to accept a Percent parameter to update the Current with the text as otherwise the update will be ignored --- apt-pkg/contrib/progress.cc | 27 +++++++++------------------ apt-pkg/contrib/progress.h | 3 +-- apt-pkg/edsp.cc | 8 +++----- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/apt-pkg/contrib/progress.cc b/apt-pkg/contrib/progress.cc index 45e81edcb..84ee4c124 100644 --- a/apt-pkg/contrib/progress.cc +++ b/apt-pkg/contrib/progress.cc @@ -65,27 +65,18 @@ void OpProgress::OverallProgress(unsigned long Current, unsigned long Total, // OpProgress::SubProgress - Set the sub progress state /*{{{*/ // --------------------------------------------------------------------- /* */ -void OpProgress::SubProgress(unsigned long SubTotal,const string &Op) +void OpProgress::SubProgress(unsigned long SubTotal,const string &Op, + float const Percent) { this->SubTotal = SubTotal; - SubOp = Op; - if (Total == 0) - Percent = 0; + if (Op.empty() == false) + SubOp = Op; + if (Total == 0 || Percent == 0) + this->Percent = 0; + else if (Percent != -1) + this->Percent = this->Current += (Size*Percent)/SubTotal; else - Percent = Current*100.0/Total; - Update(); -} - /*}}}*/ -// OpProgress::SubProgress - Set the sub progress state /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void OpProgress::SubProgress(unsigned long SubTotal) -{ - this->SubTotal = SubTotal; - if (Total == 0) - Percent = 0; - else - Percent = Current*100.0/Total; + this->Percent = Current*100.0/Total; Update(); } /*}}}*/ diff --git a/apt-pkg/contrib/progress.h b/apt-pkg/contrib/progress.h index 7dd004f7e..3a914d17f 100644 --- a/apt-pkg/contrib/progress.h +++ b/apt-pkg/contrib/progress.h @@ -55,8 +55,7 @@ class OpProgress public: void Progress(unsigned long Current); - void SubProgress(unsigned long SubTotal); - void SubProgress(unsigned long SubTotal,const string &Op); + void SubProgress(unsigned long SubTotal, const string &Op = "", float const Percent = -1); void OverallProgress(unsigned long Current,unsigned long Total, unsigned long Size,const string &Op); virtual void Done() {}; diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 489dd2933..0e229e1c0 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -267,12 +267,10 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progres type = "Remove"; else if (section.Exists("Progress") == true) { if (Progress != NULL) { - string const msg = section.FindS("Message"); + string msg = section.FindS("Message"); if (msg.empty() == true) - Progress->SubProgress(100, _("Prepare for receiving solution")); - else - Progress->SubProgress(100, msg); - Progress->Progress(section.FindI("Percentage", 0)); + msg = _("Prepare for receiving solution"); + Progress->SubProgress(100, msg, section.FindI("Percentage", 0)); } continue; } else if (section.Exists("Error") == true) { -- cgit v1.2.3 From 27c69dd0b36e3da7b6061e597d755f5a60a0d31b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 10 May 2011 13:00:56 +0200 Subject: send the first line of the error message to the error list and fail a bit more nicely and in order --- apt-pkg/edsp.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 0e229e1c0..218ce9f24 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -274,10 +274,18 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progres } continue; } else if (section.Exists("Error") == true) { + std::string msg = SubstVar(SubstVar(section.FindS("Message"), "\n .\n", "\n\n"), "\n ", "\n"); + if (msg.empty() == true) { + msg = _("External solver failed without a proper error message"); + _error->Error(msg.c_str()); + } else + _error->Error("External solver failed with: %s", msg.substr(0,msg.find('\n')).c_str()); + if (Progress != NULL) + Progress->Done(); std::cerr << "The solver encountered an error of type: " << section.FindS("Error") << std::endl; std::cerr << "The following information might help you to understand what is wrong:" << std::endl; - std::cerr << SubstVar(SubstVar(section.FindS("Message"), "\n .\n", "\n\n"), "\n ", "\n") << std::endl << std::endl; - break; + std::cerr << msg << std::endl << std::endl; + return false; } else if (section.Exists("Autoremove") == true) type = "Autoremove"; else @@ -549,7 +557,7 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache, if (Progress != NULL) Progress->OverallProgress(25, 100, 75, _("Execute external solver")); if (EDSP::ReadResponse(solver_out, Cache, Progress) == false) - return _error->Error("Reading solver response failed"); + return false; return true; } -- cgit v1.2.3