summaryrefslogtreecommitdiff
path: root/apt-pkg/edsp
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2011-03-30 17:23:43 +0200
committerDavid Kalnischkies <kalnischkies@gmail.com>2011-03-30 17:23:43 +0200
commit6d38011bb93451dd9da3294614d821c77ac91687 (patch)
tree4fd5c4c679ce39ff9599ed5e81c82c19c96185f4 /apt-pkg/edsp
parent92d956ea4d68789fa6d15702a4c2336039dcdb0f (diff)
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.
Diffstat (limited to 'apt-pkg/edsp')
-rw-r--r--apt-pkg/edsp/edspindexfile.cc74
-rw-r--r--apt-pkg/edsp/edspindexfile.h25
-rw-r--r--apt-pkg/edsp/edsplistparser.cc109
-rw-r--r--apt-pkg/edsp/edsplistparser.h38
-rw-r--r--apt-pkg/edsp/edspsystem.cc117
-rw-r--r--apt-pkg/edsp/edspsystem.h38
-rw-r--r--apt-pkg/edsp/edspwriter.cc130
-rw-r--r--apt-pkg/edsp/edspwriter.h19
8 files changed, 550 insertions, 0 deletions
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 <apt-pkg/edspindexfile.h>
+#include <apt-pkg/edsplistparser.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/progress.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/acquire-item.h>
+
+#include <sys/stat.h>
+ /*}}}*/
+
+// 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 <apt-pkg/indexfile.h>
+#include <apt-pkg/debindexfile.h>
+
+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 <apt-pkg/edsplistparser.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/md5.h>
+#include <apt-pkg/macros.h>
+ /*}}}*/
+
+// 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 <apt-pkg/deblistparser.h>
+#include <apt-pkg/pkgcachegen.h>
+#include <apt-pkg/indexfile.h>
+#include <apt-pkg/tagfile.h>
+
+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 <apt-pkg/edspsystem.h>
+#include <apt-pkg/debversion.h>
+#include <apt-pkg/edspindexfile.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/fileutl.h>
+#include <apti18n.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+ /*}}}*/
+
+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<pkgIndexFile *> &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 <apt-pkg/pkgsystem.h>
+
+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<pkgIndexFile *> &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 <apt-pkg/edspwriter.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/policy.h>
+
+#include <apti18n.h>
+#include <limits>
+
+#include <stdio.h>
+ /*}}}*/
+
+// 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<signed short>::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 <apt-pkg/depcache.h>
+
+class edspWriter /*{{{*/
+{
+public:
+ bool static WriteUniverse(pkgDepCache &Cache, FILE* output);
+ bool static WriteRequest(pkgDepCache &Cache, FILE* output);
+};
+ /*}}}*/
+#endif