Просмотр исходного кода

merge Goswin Brederlow "support download of index files for different archs"
patch which includes the following big changes:
- Declare the unused [vendor] field in sources.list as option field,
e.g. deb [arch=amd64,i386 lang=en_GB have=fun] http://example.org
- When fetching index files download them for all APT::Architectures
(overrideable with the options field above)
- Allow all architectures of APT::Architectures to be in the Cache
- Add the architecture to status and progress informations
- Add b= (Binary architecture) to policy

This commit doesn't incude the "pin-hack" as the Group structure will take
care of this (and does it already to some extend).

David Kalnischkies лет назад: 16
Родитель
Сommit
5dd4c8b811

+ 25 - 0
apt-pkg/aptconfiguration.cc

@@ -11,6 +11,7 @@
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/configuration.h>
+#include <system.h>
 
 #include <vector>
 #include <string>
@@ -223,4 +224,28 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 		return codes;
 }
 									/*}}}*/
+// getArchitectures - Return Vector of prefered Architectures		/*{{{*/
+std::vector<std::string> const Configuration::getArchitectures(bool const &Cached) {
+	using std::string;
+
+	std::vector<string> static archs;
+	if (likely(Cached == true) && archs.empty() == false)
+		return archs;
+
+	string const arch = _config->Find("APT::Architecture");
+	archs = _config->FindVector("APT::Architectures");
+	if (archs.empty() == true ||
+	    std::find(archs.begin(), archs.end(), arch) == archs.end())
+		archs.push_back(arch);
+	return archs;
+}
+									/*}}}*/
+// checkArchitecture - are we interested in the given Architecture?	/*{{{*/
+bool const Configuration::checkArchitecture(std::string const &Arch) {
+	if (Arch == "all")
+		return true;
+	std::vector<std::string> const archs = getArchitectures(true);
+	return (std::find(archs.begin(), archs.end(), Arch) != archs.end());
+}
+									/*}}}*/
 }

+ 16 - 0
apt-pkg/aptconfiguration.h

@@ -66,6 +66,22 @@ public:									/*{{{*/
 	std::vector<std::string> static const getLanguages(bool const &All = false,
 			bool const &Cached = true, char const * const Locale = 0);
 
+	/** \brief Returns a vector of Architectures we support
+	 *
+	 *  \param Cached saves the result so we need to calculated it only once
+	 *                this parameter should ony be used for testing purposes.
+	 *
+	 *  \return a vector of Architectures in prefered order
+	 */
+	std::vector<std::string> static const getArchitectures(bool const &Cached = true);
+
+	/** \brief Are we interested in the given Architecture?
+	 *
+	 *  \param Arch we want to check
+	 *  \return true if we are interested, false otherwise
+	 */
+	bool static const checkArchitecture(std::string const &Arch);
+
 									/*}}}*/
 };
 									/*}}}*/

+ 13 - 21
apt-pkg/cdrom.cc

@@ -6,6 +6,8 @@
 #include<apt-pkg/cdromutl.h>
 #include<apt-pkg/strutl.h>
 #include<apt-pkg/cdrom.h>
+#include<apt-pkg/aptconfiguration.h>
+
 #include<sstream>
 #include<fstream>
 #include<config.h>
@@ -216,33 +218,23 @@ int pkgCdrom::Score(string Path)
 /* Here we drop everything that is not this machines arch */
 bool pkgCdrom::DropBinaryArch(vector<string> &List)
 {
-   char S[300];
-   snprintf(S,sizeof(S),"/binary-%s/",
-	    _config->Find("Apt::Architecture").c_str());
-   
+
    for (unsigned int I = 0; I < List.size(); I++)
    {
       const char *Str = List[I].c_str();
-      
-      const char *Res;
-      if ((Res = strstr(Str,"/binary-")) == 0)
+      const char *Start, *End;
+      if ((Start = strstr(Str,"/binary-")) == 0)
 	 continue;
 
-      // Weird, remove it.
-      if (strlen(Res) < strlen(S))
-      {
-	 List.erase(List.begin() + I);
-	 I--;
-	 continue;
-      }
-	  
-      // See if it is our arch
-      if (stringcmp(Res,Res + strlen(S),S) == 0)
-	 continue;
-      
-      // Erase it
+      // Between Start and End is the architecture
+      Start += 8;
+      if ((End = strstr(Start,"/")) != 0 && Start != End &&
+          APT::Configuration::checkArchitecture(string(Start, --End)) == true)
+	 continue; // okay, architecture is accepted
+
+      // not accepted -> Erase it
       List.erase(List.begin() + I);
-      I--;
+      --I; // the next entry is at the same index after the erase
    }
    
    return true;

+ 3 - 3
apt-pkg/clean.cc

@@ -12,6 +12,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
 
 #include <apti18n.h>    
 
@@ -26,7 +27,6 @@
 bool pkgArchiveCleaner::Go(string Dir,pkgCache &Cache)
 {
    bool CleanInstalled = _config->FindB("APT::Clean-Installed",true);
-   string MyArch = _config->Find("APT::Architecture");
       
    DIR *D = opendir(Dir.c_str());
    if (D == 0)
@@ -75,9 +75,9 @@ bool pkgArchiveCleaner::Go(string Dir,pkgCache &Cache)
       for (I = Start; *I != 0 && *I != '.' ;I++);
       if (*I != '.')
 	 continue;
-      string Arch = DeQuoteString(string(Start,I-Start));
+      string const Arch = DeQuoteString(string(Start,I-Start));
       
-      if (Arch != "all" && Arch != MyArch)
+      if (APT::Configuration::checkArchitecture(Arch) == false)
 	 continue;
       
       // Lookup the package

+ 17 - 0
apt-pkg/contrib/strutl.cc

@@ -983,6 +983,23 @@ bool TokSplitString(char Tok,char *Input,char **List,
    return true;
 }
 									/*}}}*/
+// ExplodeString - Split a string up into a vector			/*{{{*/
+// ---------------------------------------------------------------------
+/* This can be used to split a given string up into a vector, so the
+   propose is the same as in the method above and this one is a bit slower
+   also, but the advantage is that we an iteratable vector */
+vector<string> ExplodeString(string const &haystack, char const &split) {
+	string::const_iterator start = haystack.begin();
+	string::const_iterator end = start;
+	vector<string> exploded;
+	do {
+		for (; end != haystack.end() && *end != split; ++end);
+		exploded.push_back(string(start, end));
+		start = end;
+	} while (end != haystack.end() && (++end) != haystack.end());
+	return exploded;
+}
+									/*}}}*/
 // RegexChoice - Simple regex list/list matcher				/*{{{*/
 // ---------------------------------------------------------------------
 /* */

+ 1 - 0
apt-pkg/contrib/strutl.h

@@ -59,6 +59,7 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0)
 bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length);
 bool TokSplitString(char Tok,char *Input,char **List,
 		    unsigned long ListMax);
+vector<string> ExplodeString(string const &haystack, char const &split=',');
 void ioprintf(ostream &out,const char *format,...) APT_FORMAT2;
 void strprintf(string &out,const char *format,...) APT_FORMAT2;
 char *safe_snprintf(char *Buffer,char *End,const char *Format,...) APT_FORMAT3;

+ 11 - 4
apt-pkg/deb/debindexfile.cc

@@ -149,9 +149,12 @@ unsigned long debSourcesIndex::Size() const
 // PackagesIndex::debPackagesIndex - Contructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-debPackagesIndex::debPackagesIndex(string URI,string Dist,string Section,bool Trusted) : 
-                  pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section)
+debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string const &Section,
+					bool const &Trusted, string const &Arch) :
+                  pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section), Architecture(Arch)
 {
+	if (Architecture == "native")
+		Architecture = _config->Find("APT::Architecture");
 }
 									/*}}}*/
 // PackagesIndex::ArchiveInfo - Short version of the archive url	/*{{{*/
@@ -171,6 +174,8 @@ string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
    Res += " ";
    Res += Ver.ParentPkg().Name();
    Res += " ";
+   Res += Ver.Arch();
+   Res += " ";
    Res += Ver.VerStr();
    return Res;
 }
@@ -204,6 +209,8 @@ string debPackagesIndex::Info(const char *Type) const
    else
       Info += Dist + '/' + Section;   
    Info += " ";
+   Info += Architecture;
+   Info += " ";
    Info += Type;
    return Info;
 }
@@ -227,7 +234,7 @@ string debPackagesIndex::IndexURI(const char *Type) const
    }
    else
       Res = URI + "dists/" + Dist + '/' + Section +
-      "/binary-" + _config->Find("APT::Architecture") + '/';
+      "/binary-" + Architecture + '/';
    
    Res += Type;
    return Res;
@@ -259,7 +266,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
 {
    string PackageFile = IndexFile("Packages");
    FileFd Pkg(PackageFile,FileFd::ReadOnly);
-   debListParser Parser(&Pkg);
+   debListParser Parser(&Pkg, Architecture);
    if (_error->PendingError() == true)
       return _error->Error("Problem opening %s",PackageFile.c_str());
    

+ 3 - 1
apt-pkg/deb/debindexfile.h

@@ -46,6 +46,7 @@ class debPackagesIndex : public pkgIndexFile
    string URI;
    string Dist;
    string Section;
+   string Architecture;
 
    string Info(const char *Type) const;
    string IndexFile(const char *Type) const;
@@ -69,7 +70,8 @@ class debPackagesIndex : public pkgIndexFile
    virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
-   debPackagesIndex(string URI,string Dist,string Section,bool Trusted);
+   debPackagesIndex(string const &URI, string const &Dist, string const &Section,
+			bool const &Trusted, string const &Arch = "native");
 };
 
 class debTranslationsIndex : public pkgIndexFile

+ 38 - 19
apt-pkg/deb/deblistparser.cc

@@ -32,10 +32,13 @@ static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Impor
 
 // ListParser::debListParser - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
-/* */
-debListParser::debListParser(FileFd *File) : Tags(File)
-{
-   Arch = _config->Find("APT::architecture");
+/* Provide an architecture and only this one and "all" will be accepted
+   in Step(), if no Architecture is given we will accept every arch
+   we would accept in general with checkArchitecture() */
+debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File),
+				Arch(Arch) {
+	if (Arch == "native")
+		this->Arch = _config->Find("APT::Architecture");
 }
 									/*}}}*/
 // ListParser::UniqFindTagWrite - Find the tag and write a unq string	/*{{{*/
@@ -64,13 +67,19 @@ string debListParser::Package() {
 // ---------------------------------------------------------------------
 /* This will return the Architecture of the package this section describes
    Note that architecture "all" packages will get the architecture of the
-   Packages file parsed here */
+   Packages file parsed here. */
 string debListParser::Architecture() {
 	string const Result = Section.FindS("Architecture");
-	if (Result.empty() == true)
-		return Arch;
-	if (Result == "all")
-		return Arch;
+	if (Result.empty() == true || Result == "all") {
+		if (Arch.empty() == true)
+			/* FIXME: this is a problem for installed arch all
+			   packages as we don't know from which arch this
+			   package was installed - and therefore which
+			   dependency this package resolves. */
+			return _config->Find("APT::Architecture");
+		else
+			return Arch;
+	}
 	return Result;
 }
 									/*}}}*/
@@ -199,8 +208,12 @@ bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
 {
    if (Pkg->Section == 0)
       Pkg->Section = UniqFindTagWrite("Section");
-   if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
-      return false;
+
+   // Packages which are not from "our" arch doesn't get the essential flag
+   string const static myArch = _config->Find("APT::Architecture");
+   if (Pkg->Arch != 0 && myArch == Pkg.Arch())
+      if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
+	 return false;
    if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
       return false;
 
@@ -630,17 +643,23 @@ bool debListParser::Step()
       /* See if this is the correct Architecture, if it isn't then we
          drop the whole section. A missing arch tag only happens (in theory)
          inside the Status file, so that is a positive return */
-      const char *Start;
-      const char *Stop;
-      if (Section.Find("Architecture",Start,Stop) == false)
+      string const Architecture = Section.FindS("Architecture");
+      if (Architecture.empty() == true)
 	 return true;
 
-      //FIXME: Accept different Architectures here
-      if (stringcmp(Arch,Start,Stop) == 0)
-	 return true;
+      if (Arch.empty() == true)
+      {
+	 if (APT::Configuration::checkArchitecture(Architecture) == true)
+	    return true;
+      }
+      else
+      {
+	 if (Architecture == Arch)
+	    return true;
 
-      if (stringcmp(Start,Stop,"all") == 0)
-	 return true;
+	 if (Architecture == "all")
+	    return true;
+      }
 
       iOffset = Tags.Offset();
    }   

+ 1 - 1
apt-pkg/deb/deblistparser.h

@@ -69,7 +69,7 @@ class debListParser : public pkgCacheGenerator::ListParser
 			    bool const &StripMultiArch = false);
    static const char *ConvertRelation(const char *I,unsigned int &Op);
 
-   debListParser(FileFd *File);
+   debListParser(FileFd *File, string const &Arch = "");
 };
 
 #endif

+ 183 - 109
apt-pkg/deb/debmetaindex.cc

@@ -8,9 +8,11 @@
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/error.h>
 
+#include <set>
+
 using namespace std;
 
-string debReleaseIndex::Info(const char *Type, const string Section) const
+string debReleaseIndex::Info(const char *Type, string const &Section, string const &Arch) const
 {
    string Info = ::URI::SiteOnly(URI) + ' ';
    if (Dist[Dist.size() - 1] == '/')
@@ -19,7 +21,11 @@ string debReleaseIndex::Info(const char *Type, const string Section) const
          Info += Dist;
    }
    else
-      Info += Dist + '/' + Section;   
+   {
+      Info += Dist + '/' + Section;
+      if (Arch.empty() == true)
+	 Info += " " + Arch;
+   }
    Info += " ";
    Info += Type;
    return Info;
@@ -61,16 +67,21 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const
    return Res;
 }
 
-string debReleaseIndex::IndexURISuffix(const char *Type, const string Section) const
+string debReleaseIndex::IndexURISuffix(const char *Type, string const &Section, string const &Arch) const
 {
    string Res ="";
    if (Dist[Dist.size() - 1] != '/')
-      Res += Section + "/binary-" + _config->Find("APT::Architecture") + '/';
+   {
+      if (Arch == "native")
+	 Res += Section + "/binary-" + _config->Find("APT::Architecture") + '/';
+      else
+	 Res += Section + "/binary-" + Arch + '/';
+   }
    return Res + Type;
 }
    
 
-string debReleaseIndex::IndexURI(const char *Type, const string Section) const
+string debReleaseIndex::IndexURI(const char *Type, string const &Section, string const &Arch) const
 {
    if (Dist[Dist.size() - 1] == '/')
    {
@@ -82,10 +93,10 @@ string debReleaseIndex::IndexURI(const char *Type, const string Section) const
       return Res + Type;
    }
    else
-      return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section);
+      return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section, Arch);
  }
 
-string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string Section) const
+string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string &Section) const
 {
    string Res ="";
    if (Dist[Dist.size() - 1] != '/')
@@ -93,7 +104,7 @@ string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string Sect
    return Res + Type;
 }
 
-string debReleaseIndex::SourceIndexURI(const char *Type, const string Section) const
+string debReleaseIndex::SourceIndexURI(const char *Type, const string &Section) const
 {
    string Res;
    if (Dist[Dist.size() - 1] == '/')
@@ -108,44 +119,61 @@ string debReleaseIndex::SourceIndexURI(const char *Type, const string Section) c
       return URI + "dists/" + Dist + "/" + SourceIndexURISuffix(Type, Section);
 }
 
-debReleaseIndex::debReleaseIndex(string URI,string Dist)
-{
-   this->URI = URI;
-   this->Dist = Dist;
-   this->Indexes = NULL;
-   this->Type = "deb";
+debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) {
+	this->URI = URI;
+	this->Dist = Dist;
+	this->Indexes = NULL;
+	this->Type = "deb";
 }
 
-debReleaseIndex::~debReleaseIndex()
-{
-   for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin();
-	I != SectionEntries.end(); I++)
-      delete *I;
+debReleaseIndex::~debReleaseIndex() {
+	for (map<string, vector<debSectionEntry const*> >::const_iterator A = ArchEntries.begin();
+	     A != ArchEntries.end(); ++A)
+		for (vector<const debSectionEntry *>::const_iterator S = A->second.begin();
+		     S != A->second.end(); ++S)
+			delete *S;
 }
 
-vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const
-{
-   vector <struct IndexTarget *>* IndexTargets = new vector <IndexTarget *>;
-   for (vector <const debSectionEntry *>::const_iterator I = SectionEntries.begin();
-	I != SectionEntries.end();
-	I++)
-   {
-      IndexTarget * Target = new IndexTarget();
-      Target->ShortDesc = (*I)->IsSrc ? "Sources" : "Packages";
-      Target->MetaKey
-	= (*I)->IsSrc ? SourceIndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section)
-	              : IndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section);
-      Target->URI 
-	= (*I)->IsSrc ? SourceIndexURI(Target->ShortDesc.c_str(), (*I)->Section)
-	              : IndexURI(Target->ShortDesc.c_str(), (*I)->Section);
-      
-      Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section);
-      IndexTargets->push_back (Target);
-   }
-   return IndexTargets;
+vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const {
+	vector <struct IndexTarget *>* IndexTargets = new vector <IndexTarget *>;
+
+	map<string, vector<debSectionEntry const*> >::const_iterator const src = ArchEntries.find("source");
+	if (src != ArchEntries.end()) {
+		vector<debSectionEntry const*> const SectionEntries = src->second;
+		for (vector<debSectionEntry const*>::const_iterator I = SectionEntries.begin();
+		     I != SectionEntries.end(); ++I) {
+			IndexTarget * Target = new IndexTarget();
+			Target->ShortDesc = "Sources";
+			Target->MetaKey = SourceIndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section);
+			Target->URI = SourceIndexURI(Target->ShortDesc.c_str(), (*I)->Section);
+			Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section);
+			IndexTargets->push_back (Target);
+		}
+	}
+
+	// Only source release
+	if (IndexTargets->empty() == false && ArchEntries.size() == 1)
+		return IndexTargets;
+
+	for (map<string, vector<debSectionEntry const*> >::const_iterator a = ArchEntries.begin();
+	     a != ArchEntries.end(); ++a) {
+		if (a->first == "source")
+			continue;
+		for (vector <const debSectionEntry *>::const_iterator I = a->second.begin();
+		     I != a->second.end(); ++I) {
+			IndexTarget * Target = new IndexTarget();
+			Target->ShortDesc = "Packages";
+			Target->MetaKey = IndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section, a->first);
+			Target->URI = IndexURI(Target->ShortDesc.c_str(), (*I)->Section, a->first);
+			Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section, a->first);
+			IndexTargets->push_back (Target);
+		}
+	}
+
+	return IndexTargets;
 }
 									/*}}}*/
-bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const
+bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
 {
    // special case for --print-uris
    if (GetAll) {
@@ -170,23 +198,27 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const
 		     ComputeIndexTargets(),
 		     new indexRecords (Dist));
 
-   // Queue the translations
-   std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
-   for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin(); 
-	I != SectionEntries.end(); I++) {
-
-      if((*I)->IsSrc)
-	 continue;
-
-      for (vector<string>::const_iterator l = lang.begin();
-		l != lang.end(); l++)
-      {
-	debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str());
-	i.GetIndexes(Owner);
-      }
-   }
-
-   return true;
+	// Queue the translations
+	std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
+	map<string, set<string> > sections;
+	for (map<string, vector<debSectionEntry const*> >::const_iterator a = ArchEntries.begin();
+	     a != ArchEntries.end(); ++a) {
+		if (a->first == "source")
+			continue;
+		for (vector<debSectionEntry const*>::const_iterator I = a->second.begin();
+		     I != a->second.end(); I++)
+			sections[(*I)->Section].insert(lang.begin(), lang.end());
+	}
+
+	for (map<string, set<string> >::const_iterator s = sections.begin();
+	     s != sections.end(); ++s)
+		for (set<string>::const_iterator l = s->second.begin();
+		     l != s->second.end(); l++) {
+			debTranslationsIndex i = debTranslationsIndex(URI,Dist,s->first,(*l).c_str());
+			i.GetIndexes(Owner);
+		}
+
+	return true;
 }
 
 bool debReleaseIndex::IsTrusted() const
@@ -203,71 +235,111 @@ bool debReleaseIndex::IsTrusted() const
    return false;
 }
 
-vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
-{
-   if (Indexes != NULL)
-      return Indexes;
-
-   Indexes = new vector <pkgIndexFile*>;
-   std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
-   for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin(); 
-	I != SectionEntries.end(); I++) {
-      if ((*I)->IsSrc)
-         Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted()));
-      else 
-      {
-         Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted()));
-
-	 for (vector<string>::const_iterator l = lang.begin();
-		l != lang.end(); l++)
-	    Indexes->push_back(new debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str()));
-      }
-   }
+vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() {
+	if (Indexes != NULL)
+		return Indexes;
+
+	Indexes = new vector <pkgIndexFile*>;
+	map<string, vector<debSectionEntry const*> >::const_iterator const src = ArchEntries.find("source");
+	if (src != ArchEntries.end()) {
+		vector<debSectionEntry const*> const SectionEntries = src->second;
+		for (vector<debSectionEntry const*>::const_iterator I = SectionEntries.begin();
+		     I != SectionEntries.end(); I++)
+			Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted()));
+	}
+
+	// Only source release
+	if (Indexes->empty() == false && ArchEntries.size() == 1)
+		return Indexes;
+
+	std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
+	map<string, set<string> > sections;
+	for (map<string, vector<debSectionEntry const*> >::const_iterator a = ArchEntries.begin();
+	     a != ArchEntries.end(); ++a) {
+		if (a->first == "source")
+			continue;
+		for (vector<debSectionEntry const*>::const_iterator I = a->second.begin();
+		     I != a->second.end(); I++) {
+			Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted(), a->first));
+			sections[(*I)->Section].insert(lang.begin(), lang.end());
+		}
+	}
+
+	for (map<string, set<string> >::const_iterator s = sections.begin();
+	     s != sections.end(); ++s)
+		for (set<string>::const_iterator l = s->second.begin();
+		     l != s->second.end(); l++)
+			Indexes->push_back(new debTranslationsIndex(URI,Dist,s->first,(*l).c_str()));
+
+	return Indexes;
+}
 
-   return Indexes;
+void debReleaseIndex::PushSectionEntry(vector<string> const &Archs, const debSectionEntry *Entry) {
+	for (vector<string>::const_iterator a = Archs.begin();
+	     a != Archs.end(); ++a)
+		ArchEntries[*a].push_back(new debSectionEntry(Entry->Section, Entry->IsSrc));
+	delete Entry;
 }
 
-void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry)
-{
-   SectionEntries.push_back(Entry);
+void debReleaseIndex::PushSectionEntry(string const &Arch, const debSectionEntry *Entry) {
+	ArchEntries[Arch].push_back(Entry);
 }
 
-debReleaseIndex::debSectionEntry::debSectionEntry (string Section, bool IsSrc): Section(Section)
-{
-   this->IsSrc = IsSrc;
+void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry) {
+	if (Entry->IsSrc == true)
+		PushSectionEntry("source", Entry);
+	else {
+		for (map<string, vector<const debSectionEntry *> >::iterator a = ArchEntries.begin();
+		     a != ArchEntries.end(); ++a) {
+			a->second.push_back(Entry);
+		}
+	}
 }
 
+debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section,
+		bool const &IsSrc): Section(Section), IsSrc(IsSrc)
+{}
+
 class debSLTypeDebian : public pkgSourceList::Type
 {
    protected:
 
-   bool CreateItemInternal(vector<metaIndex *> &List,string URI,
-			   string Dist,string Section,
-			   bool IsSrc) const
+   bool CreateItemInternal(vector<metaIndex *> &List, string const &URI,
+			   string const &Dist, string const &Section,
+			   bool const &IsSrc, map<string, string> const &Options) const
    {
-      for (vector<metaIndex *>::const_iterator I = List.begin(); 
+      map<string, string>::const_iterator const arch = Options.find("arch");
+      vector<string> const Archs =
+		(arch != Options.end()) ? ExplodeString(arch->second) :
+				APT::Configuration::getArchitectures();
+
+      for (vector<metaIndex *>::const_iterator I = List.begin();
 	   I != List.end(); I++)
       {
-	 // This check insures that there will be only one Release file
-	 // queued for all the Packages files and Sources files it
-	 // corresponds to.
-		if (strcmp((*I)->GetType(), "deb") == 0)
+	 // We only worry about debian entries here
+	 if (strcmp((*I)->GetType(), "deb") != 0)
+	    continue;
+
+	 debReleaseIndex *Deb = (debReleaseIndex *) (*I);
+	 /* This check insures that there will be only one Release file
+	    queued for all the Packages files and Sources files it
+	    corresponds to. */
+	 if (Deb->GetURI() == URI && Deb->GetDist() == Dist)
 	 {
-	    debReleaseIndex *Deb = (debReleaseIndex *) (*I);
-	    // This check insures that there will be only one Release file
-	    // queued for all the Packages files and Sources files it
-	    // corresponds to.
-	    if (Deb->GetURI() == URI && Deb->GetDist() == Dist)
-	    {
-	       Deb->PushSectionEntry(new debReleaseIndex::debSectionEntry(Section, IsSrc));
-	       return true;
-	    }
+	    if (IsSrc == true)
+	       Deb->PushSectionEntry("source", new debReleaseIndex::debSectionEntry(Section, IsSrc));
+	    else
+	       Deb->PushSectionEntry(Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc));
+	    return true;
 	 }
       }
       // No currently created Release file indexes this entry, so we create a new one.
       // XXX determine whether this release is trusted or not
-      debReleaseIndex *Deb = new debReleaseIndex(URI,Dist);
-      Deb->PushSectionEntry (new debReleaseIndex::debSectionEntry(Section, IsSrc));
+      debReleaseIndex *Deb = new debReleaseIndex(URI, Dist);
+      if (IsSrc == true)
+	 Deb->PushSectionEntry ("source", new debReleaseIndex::debSectionEntry(Section, IsSrc));
+      else
+	 Deb->PushSectionEntry (Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc));
       List.push_back(Deb);
       return true;
    }
@@ -277,10 +349,11 @@ class debSLTypeDeb : public debSLTypeDebian
 {
    public:
 
-   bool CreateItem(vector<metaIndex *> &List,string URI,
-		   string Dist,string Section) const
+   bool CreateItem(vector<metaIndex *> &List, string const &URI,
+		   string const &Dist, string const &Section,
+		   std::map<string, string> const &Options) const
    {
-      return CreateItemInternal(List, URI, Dist, Section, false);
+      return CreateItemInternal(List, URI, Dist, Section, false, Options);
    }
 
    debSLTypeDeb()
@@ -294,10 +367,11 @@ class debSLTypeDebSrc : public debSLTypeDebian
 {
    public:
 
-   bool CreateItem(vector<metaIndex *> &List,string URI,
-		   string Dist,string Section) const 
+   bool CreateItem(vector<metaIndex *> &List, string const &URI,
+		   string const &Dist, string const &Section,
+		   std::map<string, string> const &Options) const
    {
-      return CreateItemInternal(List, URI, Dist, Section, true);
+      return CreateItemInternal(List, URI, Dist, Section, true, Options);
    }
    
    debSLTypeDebSrc()

+ 16 - 12
apt-pkg/deb/debmetaindex.h

@@ -5,40 +5,44 @@
 #include <apt-pkg/metaindex.h>
 #include <apt-pkg/sourcelist.h>
 
+#include <map>
+
 class debReleaseIndex : public metaIndex {
    public:
 
    class debSectionEntry
    {
       public:
-      debSectionEntry (string Section, bool IsSrc);
-      bool IsSrc;
-      string Section;
+      debSectionEntry (string const &Section, bool const &IsSrc);
+      string const Section;
+      bool const IsSrc;
    };
 
    private:
-   vector <const debSectionEntry *> SectionEntries;
+   std::map<string, vector<debSectionEntry const*> > ArchEntries;
 
    public:
 
-   debReleaseIndex(string URI, string Dist);
+   debReleaseIndex(string const &URI, string const &Dist);
    ~debReleaseIndex();
 
-   virtual string ArchiveURI(string File) const {return URI + File;};
-   virtual bool GetIndexes(pkgAcquire *Owner, bool GetAll=false) const;
+   virtual string ArchiveURI(string const &File) const {return URI + File;};
+   virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const;
    vector <struct IndexTarget *>* ComputeIndexTargets() const;
-   string Info(const char *Type, const string Section) const;
+   string Info(const char *Type, string const &Section, string const &Arch="") const;
    string MetaIndexInfo(const char *Type) const;
    string MetaIndexFile(const char *Types) const;
    string MetaIndexURI(const char *Type) const;
-   string IndexURI(const char *Type, const string Section) const;
-   string IndexURISuffix(const char *Type, const string Section) const;
-   string SourceIndexURI(const char *Type, const string Section) const;
-   string SourceIndexURISuffix(const char *Type, const string Section) const;
+   string IndexURI(const char *Type, string const &Section, string const &Arch="native") const;
+   string IndexURISuffix(const char *Type, string const &Section, string const &Arch="native") const;
+   string SourceIndexURI(const char *Type, const string &Section) const;
+   string SourceIndexURISuffix(const char *Type, const string &Section) const;
    virtual vector <pkgIndexFile *> *GetIndexFiles();
 
    virtual bool IsTrusted() const;
 
+   void PushSectionEntry(vector<string> const &Archs, const debSectionEntry *Entry);
+   void PushSectionEntry(string const &Arch, const debSectionEntry *Entry);
    void PushSectionEntry(const debSectionEntry *Entry);
 };
 

+ 2 - 2
apt-pkg/metaindex.h

@@ -33,8 +33,8 @@ class metaIndex
    virtual const char* GetType() const {return Type;}
 
    // Interface for acquire
-   virtual string ArchiveURI(string /*File*/) const = 0;
-   virtual bool GetIndexes(pkgAcquire *Owner, bool GetAll=false) const = 0;
+   virtual string ArchiveURI(string const& /*File*/) const = 0;
+   virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0;
    
    virtual vector<pkgIndexFile *> *GetIndexFiles() = 0; 
    virtual bool IsTrusted() const = 0;

+ 6 - 2
apt-pkg/pkgcache.cc

@@ -406,7 +406,7 @@ operator<<(ostream& out, pkgCache::PkgIterator Pkg)
    string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion());
    string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr());
 
-   out << Pkg.Name() << " < " << current;
+   out << Pkg.Name() << " [ " << Pkg.Arch() << " ] < " << current;
    if (current != candidate)
       out << " -> " << candidate;
    if ( newest != "none" && candidate != newest)
@@ -699,7 +699,9 @@ string pkgCache::VerIterator::RelStr()
 	 else
 	    Res += File.Site();
       }      
-   }   
+   }
+   if (S->Arch != 0)
+      Res.append(" [").append(Arch()).append("]");
    return Res;
 }
 									/*}}}*/
@@ -738,6 +740,8 @@ string pkgCache::PkgFileIterator::RelStr()
       Res = Res + (Res.empty() == true?"l=":",l=")  + Label();
    if (Component() != 0)
       Res = Res + (Res.empty() == true?"c=":",c=")  + Component();
+   if (Architecture() != 0)
+      Res = Res + (Res.empty() == true?"b=":",b=")  + Architecture();
    return Res;
 }
 									/*}}}*/

+ 45 - 36
apt-pkg/sourcelist.cc

@@ -79,13 +79,51 @@ bool pkgSourceList::Type::FixupURI(string &URI) const
    Weird types may override this. */
 bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
 				    const char *Buffer,
-				    unsigned long CurLine,
-				    string File) const
+				    unsigned long const &CurLine,
+				    string const &File) const
 {
+   for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces
+
+   // Parse option field if it exists
+   // e.g.: [ option1=value1 option2=value2 ]
+   map<string, string> Options;
+   if (Buffer != 0 && Buffer[0] == '[')
+   {
+      ++Buffer; // ignore the [
+      for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces
+      while (*Buffer != ']')
+      {
+	 // get one option, e.g. option1=value1
+	 string option;
+	 if (ParseQuoteWord(Buffer,option) == false)
+	    return _error->Error(_("Malformed line %lu in source list %s ([option] unparseable)"),CurLine,File.c_str());
+
+	 if (option.length() < 3)
+	    return _error->Error(_("Malformed line %lu in source list %s ([option] too short)"),CurLine,File.c_str());
+
+	 size_t const needle = option.find('=');
+	 if (needle == string::npos)
+	    return _error->Error(_("Malformed line %lu in source list %s ([%s] is not an assignment)"),CurLine,File.c_str(), option.c_str());
+
+	 string const key = string(option, 0, needle);
+	 string const value = string(option, needle + 1, option.length());
+
+	 if (key.empty() == true)
+	    return _error->Error(_("Malformed line %lu in source list %s ([%s] has no key)"),CurLine,File.c_str(), option.c_str());
+
+	 if (value.empty() == true)
+	    return _error->Error(_("Malformed line %lu in source list %s ([%s] key %s has no value)"),CurLine,File.c_str(),option.c_str(),key.c_str());
+
+	 Options[key] = value;
+      }
+      ++Buffer; // ignore the ]
+      for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces
+   }
+
    string URI;
    string Dist;
-   string Section;   
-   
+   string Section;
+
    if (ParseQuoteWord(Buffer,URI) == false)
       return _error->Error(_("Malformed line %lu in source list %s (URI)"),CurLine,File.c_str());
    if (ParseQuoteWord(Buffer,Dist) == false)
@@ -100,7 +138,7 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
       if (ParseQuoteWord(Buffer,Section) == true)
 	 return _error->Error(_("Malformed line %lu in source list %s (absolute dist)"),CurLine,File.c_str());
       Dist = SubstVar(Dist,"$(ARCH)",_config->Find("APT::Architecture"));
-      return CreateItem(List,URI,Dist,Section);
+      return CreateItem(List, URI, Dist, Section, Options);
    }
    
    // Grab the rest of the dists
@@ -109,7 +147,7 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
    
    do
    {
-      if (CreateItem(List,URI,Dist,Section) == false)
+      if (CreateItem(List, URI, Dist, Section, Options) == false)
 	 return false;
    }
    while (ParseQuoteWord(Buffer,Section) == true);
@@ -246,36 +284,7 @@ bool pkgSourceList::ReadAppend(string File)
       if (Parse == 0)
 	 return _error->Error(_("Type '%s' is not known on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str());
       
-      // Vendor name specified
-      if (C[0] == '[')
-      {
-	 string VendorID;
-	 
-	 if (ParseQuoteWord(C,VendorID) == false)
-	     return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
-
-	 if (VendorID.length() < 2 || VendorID.end()[-1] != ']')
-	     return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
-	 VendorID = string(VendorID,1,VendorID.size()-2);
-	 
-// 	 for (vector<const Vendor *>::const_iterator iter = VendorList.begin();
-// 	      iter != VendorList.end(); iter++) 
-// 	 {
-// 	    if ((*iter)->GetVendorID() == VendorID)
-// 	    {
-// 	      if (_config->FindB("Debug::sourceList", false)) 
-// 		std::cerr << "Comparing VendorID \"" << VendorID << "\" with \"" << (*iter)->GetVendorID() << '"' << std::endl;
-// 	       Verifier = *iter;
-// 	       break;
-// 	    }
-// 	 }
-
-// 	 if (Verifier == 0)
-// 	    return _error->Error(_("Unknown vendor ID '%s' in line %u of source list %s"),
-// 				 VendorID.c_str(),CurLine,File.c_str());
-      }
-
-      if (Parse->ParseLine(SrcList,C,CurLine,File) == false)
+      if (Parse->ParseLine(SrcList, C, CurLine, File) == false)
 	 return false;
    }
    return true;

+ 5 - 3
apt-pkg/sourcelist.h

@@ -29,6 +29,7 @@
 
 #include <string>
 #include <vector>
+#include <map>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/metaindex.h>
 
@@ -57,9 +58,10 @@ class pkgSourceList
       bool FixupURI(string &URI) const;
       virtual bool ParseLine(vector<metaIndex *> &List,
 			     const char *Buffer,
-			     unsigned long CurLine,string File) const;
-      virtual bool CreateItem(vector<metaIndex *> &List,string URI,
-			      string Dist,string Section) const = 0;
+			     unsigned long const &CurLine,string const &File) const;
+      virtual bool CreateItem(vector<metaIndex *> &List,string const &URI,
+			      string const &Dist,string const &Section,
+			      std::map<string, string> const &Options) const = 0;
       Type();
       virtual ~Type() {};
    };

+ 7 - 1
apt-pkg/versionmatch.cc

@@ -100,6 +100,8 @@ pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type)
 	    RelLabel = Fragments[J]+2;
 	 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"c=") == 0)
 	    RelComponent = Fragments[J]+2;
+	 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"b=") == 0)
+	    RelArchitecture = Fragments[J]+2;
       }
 
       if (RelVerStr.end()[-1] == '*')
@@ -178,7 +180,7 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File)
       if (RelVerStr.empty() == true && RelOrigin.empty() == true &&
 	  RelArchive.empty() == true && RelLabel.empty() == true &&
 	  RelRelease.empty() == true && RelCodename.empty() == true &&
-	  RelComponent.empty() == true)
+	  RelComponent.empty() == true && RelArchitecture.empty() == true)
 	 return false;
 
       if (RelVerStr.empty() == false)
@@ -211,6 +213,10 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File)
 	 if (File->Component == 0 ||
 	     stringcasecmp(RelComponent,File.Component()) != 0)
 	    return false;
+      if (RelArchitecture.empty() == false)
+	 if (File->Architecture == 0 ||
+	     stringcasecmp(RelArchitecture,File.Architecture()) != 0)
+	    return false;
       return true;
    }
 

+ 2 - 0
apt-pkg/versionmatch.h

@@ -23,6 +23,7 @@
       Codename (n=) e.g. etch, lenny, squeeze, sid
       Label (l=)
       Component (c=)
+      Binary Architecture (b=)
    If there are no equals signs in the string then it is scanned in short
    form - if it starts with a number it is Version otherwise it is an
    Archive or a Codename.
@@ -55,6 +56,7 @@ class pkgVersionMatch
    string RelArchive;
    string RelLabel;
    string RelComponent;
+   string RelArchitecture;
    bool MatchAll;
    
    // Origin Matching