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

support lang= and target= sources.list options

We support arch= for a while, now we finally add lang= as well and as a
first simple way of controlling which targets to acquire also target=.

This asked for a redesign of the internal API of parsing and storing
information about 'deb' and 'deb-src' lines. As this API isn't visible
to the outside no damage done through.

Beside being a nice cleanup (= it actually does more in less lines) it
also provides us with a predictable order of architectures as provides
in the configuration rather than based on string sorting-order, so that
now the native architecture is parsed/displayed first. Observeable e.g.
in apt-get output.
David Kalnischkies лет назад: 11
Родитель
Сommit
463c8d8015

+ 3 - 3
apt-pkg/deb/debindexfile.cc

@@ -510,7 +510,7 @@ class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
    {
    {
       return new debDebFileRecordParser(File.FileName());
       return new debDebFileRecordParser(File.FileName());
    };
    };
-   debIFTypeDebPkgFile() {Label = "deb Package file";};
+   debIFTypeDebPkgFile() {Label = "Debian deb file";};
 };
 };
 class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
 class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
 {
 {
@@ -519,7 +519,7 @@ class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
    {
    {
       return new debDscRecordParser(DscFile, NULL);
       return new debDscRecordParser(DscFile, NULL);
    };
    };
-   debIFTypeDscFile() {Label = "dsc File Source Index";};
+   debIFTypeDscFile() {Label = "Debian dsc file";};
 };
 };
 class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
 class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
 {
 {
@@ -528,7 +528,7 @@ class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
    {
    {
       return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
       return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
    };
    };
-   debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";};
+   debIFTypeDebianSourceDir() {Label = "Debian control file";};
 };
 };
 
 
 APT_HIDDEN debIFTypeSrc _apt_Src;
 APT_HIDDEN debIFTypeSrc _apt_Src;

+ 186 - 244
apt-pkg/deb/debmetaindex.cc

@@ -29,11 +29,25 @@
 #include <unistd.h>
 #include <unistd.h>
 #include <string.h>
 #include <string.h>
 
 
-using namespace std;
-
-string debReleaseIndex::MetaIndexInfo(const char *Type) const
+class APT_HIDDEN debReleaseIndexPrivate					/*{{{*/
+{
+   public:
+   struct APT_HIDDEN debSectionEntry
+   {
+      std::string Name;
+      std::vector<std::string> Targets;
+      std::vector<std::string> Architectures;
+      std::vector<std::string> Languages;
+   };
+
+   std::vector<debSectionEntry> DebEntries;
+   std::vector<debSectionEntry> DebSrcEntries;
+};
+									/*}}}*/
+// ReleaseIndex::MetaIndex* - display helpers				/*{{{*/
+std::string debReleaseIndex::MetaIndexInfo(const char *Type) const
 {
 {
-   string Info = ::URI::ArchiveOnly(URI) + ' ';
+   std::string Info = ::URI::ArchiveOnly(URI) + ' ';
    if (Dist[Dist.size() - 1] == '/')
    if (Dist[Dist.size() - 1] == '/')
    {
    {
       if (Dist != "/")
       if (Dist != "/")
@@ -50,15 +64,15 @@ std::string debReleaseIndex::Describe() const
    return MetaIndexInfo("Release");
    return MetaIndexInfo("Release");
 }
 }
 
 
-string debReleaseIndex::MetaIndexFile(const char *Type) const
+std::string debReleaseIndex::MetaIndexFile(const char *Type) const
 {
 {
    return _config->FindDir("Dir::State::lists") +
    return _config->FindDir("Dir::State::lists") +
       URItoFileName(MetaIndexURI(Type));
       URItoFileName(MetaIndexURI(Type));
 }
 }
 
 
-string debReleaseIndex::MetaIndexURI(const char *Type) const
+std::string debReleaseIndex::MetaIndexURI(const char *Type) const
 {
 {
-   string Res;
+   std::string Res;
 
 
    if (Dist == "/")
    if (Dist == "/")
       Res = URI;
       Res = URI;
@@ -70,8 +84,8 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const
    Res += Type;
    Res += Type;
    return Res;
    return Res;
 }
 }
-
-std::string debReleaseIndex::LocalFileName() const
+									/*}}}*/
+std::string debReleaseIndex::LocalFileName() const			/*{{{*/
 {
 {
    // see if we have a InRelease file
    // see if we have a InRelease file
    std::string PathInRelease =  MetaIndexFile("InRelease");
    std::string PathInRelease =  MetaIndexFile("InRelease");
@@ -84,28 +98,24 @@ std::string debReleaseIndex::LocalFileName() const
 
 
    return "";
    return "";
 }
 }
-
-debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) :
-					metaIndex(URI, Dist, "deb"), d(NULL), Trusted(CHECK_TRUST)
+									/*}}}*/
+// ReleaseIndex Con- and Destructors					/*{{{*/
+debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist) :
+					metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()), Trusted(CHECK_TRUST)
 {}
 {}
-
-debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist, bool const Trusted) :
-					metaIndex(URI, Dist, "deb"), d(NULL) {
+debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted) :
+					metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()) {
 	SetTrusted(Trusted);
 	SetTrusted(Trusted);
 }
 }
-
 debReleaseIndex::~debReleaseIndex() {
 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;
+   if (d != NULL)
+      delete d;
 }
 }
-
-template<typename CallC>
-void foreachTarget(std::string const &URI, std::string const &Dist,
-      std::map<std::string, std::vector<debReleaseIndex::debSectionEntry const *> > const &ArchEntries,
-      CallC &Call)
+									/*}}}*/
+// ReleaseIndex::GetIndexTargets					/*{{{*/
+static void GetIndexTargetsFor(char const * const Type, std::string const &URI, std::string const &Dist,
+      std::vector<debReleaseIndexPrivate::debSectionEntry> const &entries,
+      std::vector<IndexTarget> &IndexTargets)
 {
 {
    bool const flatArchive = (Dist[Dist.length() - 1] == '/');
    bool const flatArchive = (Dist[Dist.length() - 1] == '/');
    std::string baseURI = URI;
    std::string baseURI = URI;
@@ -118,148 +128,101 @@ void foreachTarget(std::string const &URI, std::string const &Dist,
       baseURI += "dists/" + Dist + "/";
       baseURI += "dists/" + Dist + "/";
    std::string const Release = (Dist == "/") ? "" : Dist;
    std::string const Release = (Dist == "/") ? "" : Dist;
    std::string const Site = ::URI::ArchiveOnly(URI);
    std::string const Site = ::URI::ArchiveOnly(URI);
-   std::vector<std::string> lang = APT::Configuration::getLanguages(true);
-   if (lang.empty())
-      lang.push_back("none");
-   map<string, vector<debReleaseIndex::debSectionEntry const*> >::const_iterator const src = ArchEntries.find("source");
-   if (src != ArchEntries.end())
+
+   for (std::vector<debReleaseIndexPrivate::debSectionEntry>::const_iterator E = entries.begin(); E != entries.end(); ++E)
    {
    {
-      std::vector<std::string> const targets = _config->FindVector("APT::Acquire::Targets::deb-src", "", true);
-      for (std::vector<std::string>::const_iterator T = targets.begin(); T != targets.end(); ++T)
+      for (std::vector<std::string>::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T)
       {
       {
-#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb-src::") + *T + "::" + (X))
-	 std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey");
-	 std::string const ShortDesc = APT_T_CONFIG("ShortDescription");
-	 std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description");
+#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::") + Type  + "::" + *T + "::" + (X))
+	 std::string const tplMetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey");
+	 std::string const tplShortDesc = APT_T_CONFIG("ShortDescription");
+	 std::string const tplLongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description");
 	 bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true);
 	 bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true);
 #undef APT_T_CONFIG
 #undef APT_T_CONFIG
-	 if (MetaKey.empty())
+	 if (tplMetaKey.empty())
 	    continue;
 	    continue;
 
 
-	 vector<debReleaseIndex::debSectionEntry const*> const SectionEntries = src->second;
-	 for (vector<debReleaseIndex::debSectionEntry const*>::const_iterator I = SectionEntries.begin();
-	       I != SectionEntries.end(); ++I)
+	 for (std::vector<std::string>::const_iterator L = E->Languages.begin(); L != E->Languages.end(); ++L)
 	 {
 	 {
-	    for (vector<std::string>::const_iterator l = lang.begin(); l != lang.end(); ++l)
+	    if (*L == "none" && tplMetaKey.find("$(LANGUAGE)") != std::string::npos)
+	       continue;
+
+	    for (std::vector<std::string>::const_iterator A = E->Architectures.begin(); A != E->Architectures.end(); ++A)
 	    {
 	    {
-	       if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos)
-		  continue;
 
 
 	       std::map<std::string, std::string> Options;
 	       std::map<std::string, std::string> Options;
 	       Options.insert(std::make_pair("SITE", Site));
 	       Options.insert(std::make_pair("SITE", Site));
 	       Options.insert(std::make_pair("RELEASE", Release));
 	       Options.insert(std::make_pair("RELEASE", Release));
-	       if (MetaKey.find("$(COMPONENT)") != std::string::npos)
-		  Options.insert(std::make_pair("COMPONENT", (*I)->Section));
-	       if (MetaKey.find("$(LANGUAGE)") != std::string::npos)
-		  Options.insert(std::make_pair("LANGUAGE", *l));
-	       Options.insert(std::make_pair("ARCHITECTURE", "source"));
+	       if (tplMetaKey.find("$(COMPONENT)") != std::string::npos)
+		  Options.insert(std::make_pair("COMPONENT", E->Name));
+	       if (tplMetaKey.find("$(LANGUAGE)") != std::string::npos)
+		  Options.insert(std::make_pair("LANGUAGE", *L));
+	       if (tplMetaKey.find("$(ARCHITECTURE)") != std::string::npos)
+		  Options.insert(std::make_pair("ARCHITECTURE", *A));
 	       Options.insert(std::make_pair("BASE_URI", baseURI));
 	       Options.insert(std::make_pair("BASE_URI", baseURI));
 	       Options.insert(std::make_pair("REPO_URI", URI));
 	       Options.insert(std::make_pair("REPO_URI", URI));
 	       Options.insert(std::make_pair("TARGET_OF", "deb-src"));
 	       Options.insert(std::make_pair("TARGET_OF", "deb-src"));
 	       Options.insert(std::make_pair("CREATED_BY", *T));
 	       Options.insert(std::make_pair("CREATED_BY", *T));
-	       Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options);
 
 
-	       if (MetaKey.find("$(LANGUAGE)") == std::string::npos)
+	       std::string MetaKey = tplMetaKey;
+	       std::string ShortDesc = tplShortDesc;
+	       std::string LongDesc = tplLongDesc;
+	       for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
+	       {
+		  MetaKey = SubstVar(MetaKey, std::string("$(") + O->first + ")", O->second);
+		  ShortDesc = SubstVar(ShortDesc, std::string("$(") + O->first + ")", O->second);
+		  LongDesc = SubstVar(LongDesc, std::string("$(") + O->first + ")", O->second);
+	       }
+	       IndexTarget Target(
+		     MetaKey,
+		     ShortDesc,
+		     LongDesc,
+		     Options.find("BASE_URI")->second + MetaKey,
+		     IsOptional,
+		     Options
+		     );
+	       IndexTargets.push_back(Target);
+
+	       if (tplMetaKey.find("$(ARCHITECTURE)") == std::string::npos)
 		  break;
 		  break;
-	    }
-
-	    if (MetaKey.find("$(COMPONENT)") == std::string::npos)
-	       break;
-	 }
-      }
-   }
-
-   std::vector<std::string> const targets = _config->FindVector("APT::Acquire::Targets::deb", "", true);
-   for (std::vector<std::string>::const_iterator T = targets.begin(); T != targets.end(); ++T)
-   {
-#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb::") + *T + "::" + (X))
-      std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey");
-      std::string const ShortDesc = APT_T_CONFIG("ShortDescription");
-      std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description");
-      bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb::") + *T + "::Optional", true);
-#undef APT_T_CONFIG
-      if (MetaKey.empty())
-	 continue;
-
-      for (map<string, vector<debReleaseIndex::debSectionEntry const*> >::const_iterator a = ArchEntries.begin();
-	    a != ArchEntries.end(); ++a)
-      {
-	 if (a->first == "source")
-	    continue;
-
-	 for (vector <const debReleaseIndex::debSectionEntry *>::const_iterator I = a->second.begin();
-	       I != a->second.end(); ++I) {
-
-	    for (vector<std::string>::const_iterator l = lang.begin(); l != lang.end(); ++l)
-	    {
-	       if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos)
-		  continue;
-
-	       std::map<std::string, std::string> Options;
-	       Options.insert(std::make_pair("SITE", Site));
-	       Options.insert(std::make_pair("RELEASE", Release));
-	       if (MetaKey.find("$(COMPONENT)") != std::string::npos)
-		  Options.insert(std::make_pair("COMPONENT", (*I)->Section));
-	       if (MetaKey.find("$(LANGUAGE)") != std::string::npos)
-		  Options.insert(std::make_pair("LANGUAGE", *l));
-	       if (MetaKey.find("$(ARCHITECTURE)") != std::string::npos)
-		  Options.insert(std::make_pair("ARCHITECTURE", a->first));
-	       Options.insert(std::make_pair("BASE_URI", baseURI));
-	       Options.insert(std::make_pair("REPO_URI", URI));
-	       Options.insert(std::make_pair("TARGET_OF", "deb"));
-	       Options.insert(std::make_pair("CREATED_BY", *T));
-	       Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options);
 
 
-	       if (MetaKey.find("$(LANGUAGE)") == std::string::npos)
-		  break;
 	    }
 	    }
 
 
-	    if (MetaKey.find("$(COMPONENT)") == std::string::npos)
+	    if (tplMetaKey.find("$(LANGUAGE)") == std::string::npos)
 	       break;
 	       break;
+
 	 }
 	 }
 
 
-	 if (MetaKey.find("$(ARCHITECTURE)") == std::string::npos)
-	    break;
       }
       }
    }
    }
 }
 }
-
-
-struct ComputeIndexTargetsClass
-{
-   vector <IndexTarget> IndexTargets;
-
-   void operator()(std::string MetaKey, std::string ShortDesc, std::string LongDesc,
-	 bool const IsOptional, std::map<std::string, std::string> Options)
-   {
-      for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
-      {
-	 MetaKey = SubstVar(MetaKey, std::string("$(") + O->first + ")", O->second);
-	 ShortDesc = SubstVar(ShortDesc, std::string("$(") + O->first + ")", O->second);
-	 LongDesc = SubstVar(LongDesc, std::string("$(") + O->first + ")", O->second);
-      }
-      IndexTarget Target(
-	    MetaKey,
-	    ShortDesc,
-	    LongDesc,
-	    Options.find("BASE_URI")->second + MetaKey,
-	    IsOptional,
-	    Options
-	    );
-      IndexTargets.push_back(Target);
-   }
-};
-
 std::vector<IndexTarget> debReleaseIndex::GetIndexTargets() const
 std::vector<IndexTarget> debReleaseIndex::GetIndexTargets() const
 {
 {
-   ComputeIndexTargetsClass comp;
-   foreachTarget(URI, Dist, ArchEntries, comp);
-   return comp.IndexTargets;
+   std::vector<IndexTarget> IndexTargets;
+   GetIndexTargetsFor("deb-src", URI, Dist, d->DebSrcEntries, IndexTargets);
+   GetIndexTargetsFor("deb", URI, Dist, d->DebEntries, IndexTargets);
+   return IndexTargets;
 }
 }
+									/*}}}*/
+void debReleaseIndex::AddComponent(bool const isSrc, std::string const &Name,/*{{{*/
+	 std::vector<std::string> const &Targets,
+	 std::vector<std::string> const &Architectures,
+	 std::vector<std::string> Languages)
+{
+   if (Languages.empty() == true)
+      Languages.push_back("none");
+   debReleaseIndexPrivate::debSectionEntry const entry = {
+      Name, Targets, Architectures, Languages
+   };
+   if (isSrc)
+      d->DebSrcEntries.push_back(entry);
+   else
+      d->DebEntries.push_back(entry);
+}
+									/*}}}*/
 
 
 
 
-									/*}}}*/
-bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
+bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const/*{{{*/
 {
 {
    indexRecords * const iR = new indexRecords(Dist);
    indexRecords * const iR = new indexRecords(Dist);
    if (Trusted == ALWAYS_TRUSTED)
    if (Trusted == ALWAYS_TRUSTED)
@@ -282,7 +245,8 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
 
 
    return true;
    return true;
 }
 }
-
+									/*}}}*/
+// ReleaseIndex::*Trusted setters and checkers				/*{{{*/
 void debReleaseIndex::SetTrusted(bool const Trusted)
 void debReleaseIndex::SetTrusted(bool const Trusted)
 {
 {
 	if (Trusted == true)
 	if (Trusted == true)
@@ -290,7 +254,6 @@ void debReleaseIndex::SetTrusted(bool const Trusted)
 	else
 	else
 		this->Trusted = NEVER_TRUSTED;
 		this->Trusted = NEVER_TRUSTED;
 }
 }
-
 bool debReleaseIndex::IsTrusted() const
 bool debReleaseIndex::IsTrusted() const
 {
 {
    if (Trusted == ALWAYS_TRUSTED)
    if (Trusted == ALWAYS_TRUSTED)
@@ -303,19 +266,13 @@ bool debReleaseIndex::IsTrusted() const
       if(URI.substr(0,strlen("cdrom:")) == "cdrom:")
       if(URI.substr(0,strlen("cdrom:")) == "cdrom:")
 	 return true;
 	 return true;
 
 
-   string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
-      URItoFileName(MetaIndexURI("Release")) + ".gpg";
-
-   if (FileExists(VerifiedSigFile))
+   if (FileExists(MetaIndexFile("Release.gpg")))
       return true;
       return true;
 
 
-   VerifiedSigFile = _config->FindDir("Dir::State::lists") +
-      URItoFileName(MetaIndexURI("InRelease"));
-
-   return FileExists(VerifiedSigFile);
+   return FileExists(MetaIndexFile("InRelease"));
 }
 }
-
-std::vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
+									/*}}}*/
+std::vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()		/*{{{*/
 {
 {
    if (Indexes != NULL)
    if (Indexes != NULL)
       return Indexes;
       return Indexes;
@@ -335,23 +292,9 @@ std::vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
    }
    }
    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(string const &Arch, const debSectionEntry *Entry) {
-	ArchEntries[Arch].push_back(Entry);
-}
-
-debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section,
-		bool const &IsSrc): Section(Section), IsSrc(IsSrc)
-{}
-
-static bool ReleaseFileName(debReleaseIndex const * const That, std::string &ReleaseFile)
+static bool ReleaseFileName(debReleaseIndex const * const That, std::string &ReleaseFile)/*{{{*/
 {
 {
    ReleaseFile = That->MetaIndexFile("InRelease");
    ReleaseFile = That->MetaIndexFile("InRelease");
    bool releaseExists = false;
    bool releaseExists = false;
@@ -365,7 +308,7 @@ static bool ReleaseFileName(debReleaseIndex const * const That, std::string &Rel
    }
    }
    return releaseExists;
    return releaseExists;
 }
 }
-
+									/*}}}*/
 bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/*{{{*/
 bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/*{{{*/
 {
 {
    std::string ReleaseFile;
    std::string ReleaseFile;
@@ -459,46 +402,46 @@ pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool con
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 
-debDebFileMetaIndex::~debDebFileMetaIndex() {}
-
-class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type
+static std::vector<std::string> parsePlusMinusOptions(std::string const &Name, /*{{{*/
+      std::map<std::string, std::string> const &Options, std::vector<std::string> const &defaultValues)
 {
 {
-   protected:
+   std::map<std::string, std::string>::const_iterator val = Options.find(Name);
+   std::vector<std::string> Values;
+   if (val != Options.end())
+      Values = VectorizeString(val->second, ',');
+   else
+      Values = defaultValues;
 
 
-   bool CreateItemInternal(vector<metaIndex *> &List, string const &URI,
-			   string const &Dist, string const &Section,
-			   bool const &IsSrc, map<string, string> const &Options) const
+   if ((val = Options.find(Name + "+")) != Options.end())
    {
    {
-      // parse arch=, arch+= and arch-= settings
-      map<string, string>::const_iterator arch = Options.find("arch");
-      vector<string> Archs;
-      if (arch != Options.end())
-	 Archs = VectorizeString(arch->second, ',');
-      else
-	 Archs = APT::Configuration::getArchitectures();
-
-      if ((arch = Options.find("arch+")) != Options.end())
-      {
-	 std::vector<std::string> const plusArch = VectorizeString(arch->second, ',');
-	 for (std::vector<std::string>::const_iterator plus = plusArch.begin(); plus != plusArch.end(); ++plus)
-	    if (std::find(Archs.begin(), Archs.end(), *plus) == Archs.end())
-	       Archs.push_back(*plus);
-      }
-      if ((arch = Options.find("arch-")) != Options.end())
+      std::vector<std::string> const plusArch = VectorizeString(val->second, ',');
+      for (std::vector<std::string>::const_iterator plus = plusArch.begin(); plus != plusArch.end(); ++plus)
+	 if (std::find(Values.begin(), Values.end(), *plus) == Values.end())
+	    Values.push_back(*plus);
+   }
+   if ((val = Options.find(Name + "-")) != Options.end())
+   {
+      std::vector<std::string> const minusArch = VectorizeString(val->second, ',');
+      for (std::vector<std::string>::const_iterator minus = minusArch.begin(); minus != minusArch.end(); ++minus)
       {
       {
-	 std::vector<std::string> const minusArch = VectorizeString(arch->second, ',');
-	 for (std::vector<std::string>::const_iterator minus = minusArch.begin(); minus != minusArch.end(); ++minus)
-	 {
-	    std::vector<std::string>::iterator kill = std::find(Archs.begin(), Archs.end(), *minus);
-	    if (kill != Archs.end())
-	       Archs.erase(kill);
-	 }
+	 std::vector<std::string>::iterator kill = std::find(Values.begin(), Values.end(), *minus);
+	 if (kill != Values.end())
+	    Values.erase(kill);
       }
       }
+   }
+   return Values;
+}
+									/*}}}*/
+class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type		/*{{{*/
+{
+   protected:
 
 
-      map<string, string>::const_iterator const trusted = Options.find("trusted");
-
+   bool CreateItemInternal(std::vector<metaIndex *> &List, std::string const &URI,
+			   std::string const &Dist, std::string const &Section,
+			   bool const &IsSrc, std::map<std::string, std::string> const &Options) const
+   {
       debReleaseIndex *Deb = NULL;
       debReleaseIndex *Deb = NULL;
-      for (vector<metaIndex *>::const_iterator I = List.begin();
+      for (std::vector<metaIndex *>::const_iterator I = List.begin();
 	   I != List.end(); ++I)
 	   I != List.end(); ++I)
       {
       {
 	 // We only worry about debian entries here
 	 // We only worry about debian entries here
@@ -523,87 +466,86 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type
 	 List.push_back(Deb);
 	 List.push_back(Deb);
       }
       }
 
 
-      if (IsSrc == true)
-	 Deb->PushSectionEntry ("source", new debReleaseIndex::debSectionEntry(Section, IsSrc));
-      else
-      {
-	 if (Dist[Dist.size() - 1] == '/')
-	    Deb->PushSectionEntry ("any", new debReleaseIndex::debSectionEntry(Section, IsSrc));
-	 else
-	    Deb->PushSectionEntry (Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc));
-      }
+      Deb->AddComponent(
+	    IsSrc,
+	    Section,
+	    parsePlusMinusOptions("target", Options, _config->FindVector(std::string("APT::Acquire::Targets::") + Name, "", true)),
+	    parsePlusMinusOptions("arch", Options, APT::Configuration::getArchitectures()),
+	    parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true))
+	    );
 
 
+      std::map<std::string, std::string>::const_iterator const trusted = Options.find("trusted");
       if (trusted != Options.end())
       if (trusted != Options.end())
 	 Deb->SetTrusted(StringToBool(trusted->second, false));
 	 Deb->SetTrusted(StringToBool(trusted->second, false));
 
 
       return true;
       return true;
    }
    }
-};
-
-debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile)
-   : metaIndex(DebFile, "local-uri", "deb-dist"), d(NULL), DebFile(DebFile)
-{
-   DebIndex = new debDebPkgFileIndex(DebFile);
-   Indexes = new vector<pkgIndexFile *>();
-   Indexes->push_back(DebIndex);
-}
 
 
-
-class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian
+   debSLTypeDebian(char const * const Name, char const * const Label) : Type(Name, Label)
+   {
+   }
+};
+									/*}}}*/
+class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian			/*{{{*/
 {
 {
    public:
    public:
 
 
-   bool CreateItem(vector<metaIndex *> &List, string const &URI,
-		   string const &Dist, string const &Section,
-		   std::map<string, string> const &Options) const
+   bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
+		   std::string const &Dist, std::string const &Section,
+		   std::map<std::string, std::string> const &Options) const
    {
    {
       return CreateItemInternal(List, URI, Dist, Section, false, Options);
       return CreateItemInternal(List, URI, Dist, Section, false, Options);
    }
    }
 
 
-   debSLTypeDeb()
+   debSLTypeDeb() : debSLTypeDebian("deb", "Debian binary tree")
    {
    {
-      Name = "deb";
-      Label = "Standard Debian binary tree";
-   }   
+   }
 };
 };
-
-class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian
+									/*}}}*/
+class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian		/*{{{*/
 {
 {
    public:
    public:
 
 
-   bool CreateItem(vector<metaIndex *> &List, string const &URI,
-		   string const &Dist, string const &Section,
-		   std::map<string, string> const &Options) const
+   bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
+		   std::string const &Dist, std::string const &Section,
+		   std::map<std::string, std::string> const &Options) const
    {
    {
       return CreateItemInternal(List, URI, Dist, Section, true, Options);
       return CreateItemInternal(List, URI, Dist, Section, true, Options);
    }
    }
-   
-   debSLTypeDebSrc()
+
+   debSLTypeDebSrc() : debSLTypeDebian("deb-src", "Debian source tree")
    {
    {
-      Name = "deb-src";
-      Label = "Standard Debian source tree";
-   }   
+   }
 };
 };
+									/*}}}*/
 
 
-class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type
+debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile)	/*{{{*/
+   : metaIndex(DebFile, "local-uri", "deb-dist"), d(NULL), DebFile(DebFile)
+{
+   DebIndex = new debDebPkgFileIndex(DebFile);
+   Indexes = new std::vector<pkgIndexFile *>();
+   Indexes->push_back(DebIndex);
+}
+debDebFileMetaIndex::~debDebFileMetaIndex() {}
+									/*}}}*/
+class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type		/*{{{*/
 {
 {
    public:
    public:
 
 
-   bool CreateItem(vector<metaIndex *> &List, string const &URI,
-		   string const &/*Dist*/, string const &/*Section*/,
-		   std::map<string, string> const &/*Options*/) const
+   bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
+		   std::string const &/*Dist*/, std::string const &/*Section*/,
+		   std::map<std::string, std::string> const &/*Options*/) const
    {
    {
       metaIndex *mi = new debDebFileMetaIndex(URI);
       metaIndex *mi = new debDebFileMetaIndex(URI);
       List.push_back(mi);
       List.push_back(mi);
       return true;
       return true;
    }
    }
-   
-   debSLTypeDebFile()
+
+   debSLTypeDebFile() : Type("deb-file", "Debian local deb file")
    {
    {
-      Name = "deb-file";
-      Label = "Debian Deb File";
-   }   
+   }
 };
 };
+									/*}}}*/
 
 
 APT_HIDDEN debSLTypeDeb _apt_DebType;
 APT_HIDDEN debSLTypeDeb _apt_DebType;
 APT_HIDDEN debSLTypeDebSrc _apt_DebSrcType;
 APT_HIDDEN debSLTypeDebSrc _apt_DebSrcType;

+ 13 - 25
apt-pkg/deb/debmetaindex.h

@@ -1,4 +1,3 @@
-// ijones, walters
 #ifndef PKGLIB_DEBMETAINDEX_H
 #ifndef PKGLIB_DEBMETAINDEX_H
 #define PKGLIB_DEBMETAINDEX_H
 #define PKGLIB_DEBMETAINDEX_H
 
 
@@ -22,26 +21,20 @@ class debDebPkgFileIndex;
 class IndexTarget;
 class IndexTarget;
 class pkgCacheGenerator;
 class pkgCacheGenerator;
 class OpProgress;
 class OpProgress;
+class debReleaseIndexPrivate;
 
 
-class APT_HIDDEN debReleaseIndex : public metaIndex {
-   public:
+class APT_HIDDEN debReleaseIndex : public metaIndex
+{
+   debReleaseIndexPrivate * const d;
 
 
-   class debSectionEntry
-   {
-      public:
-      debSectionEntry (std::string const &Section, bool const &IsSrc);
-      std::string const Section;
-      bool const IsSrc;
-   };
-
-   private:
-   /** \brief dpointer placeholder (for later in case we need it) */
-   void * const d;
-   std::map<std::string, std::vector<debSectionEntry const*> > ArchEntries;
    enum APT_HIDDEN { ALWAYS_TRUSTED, NEVER_TRUSTED, CHECK_TRUST } Trusted;
    enum APT_HIDDEN { ALWAYS_TRUSTED, NEVER_TRUSTED, CHECK_TRUST } Trusted;
 
 
    public:
    public:
 
 
+   APT_HIDDEN std::string MetaIndexInfo(const char *Type) const;
+   APT_HIDDEN std::string MetaIndexFile(const char *Types) const;
+   APT_HIDDEN std::string MetaIndexURI(const char *Type) const;
+
    debReleaseIndex(std::string const &URI, std::string const &Dist);
    debReleaseIndex(std::string const &URI, std::string const &Dist);
    debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted);
    debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted);
    virtual ~debReleaseIndex();
    virtual ~debReleaseIndex();
@@ -54,22 +47,17 @@ class APT_HIDDEN debReleaseIndex : public metaIndex {
    virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const;
    virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const;
    virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
    virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
 
 
-   std::string MetaIndexInfo(const char *Type) const;
-   std::string MetaIndexFile(const char *Types) const;
-   std::string MetaIndexURI(const char *Type) const;
-
-#if APT_PKG_ABI >= 413
-   virtual
-#endif
-   std::string LocalFileName() const;
+   virtual std::string LocalFileName() const;
 
 
    virtual std::vector <pkgIndexFile *> *GetIndexFiles();
    virtual std::vector <pkgIndexFile *> *GetIndexFiles();
 
 
    void SetTrusted(bool const Trusted);
    void SetTrusted(bool const Trusted);
    virtual bool IsTrusted() const;
    virtual bool IsTrusted() const;
 
 
-   void PushSectionEntry(std::vector<std::string> const &Archs, const debSectionEntry *Entry);
-   void PushSectionEntry(std::string const &Arch, const debSectionEntry *Entry);
+   void AddComponent(bool const isSrc, std::string const &Name,
+	 std::vector<std::string> const &Targets,
+	 std::vector<std::string> const &Architectures,
+	 std::vector<std::string> Languages);
 };
 };
 
 
 class APT_HIDDEN debDebFileMetaIndex : public metaIndex
 class APT_HIDDEN debDebFileMetaIndex : public metaIndex

+ 22 - 18
apt-pkg/sourcelist.cc

@@ -37,25 +37,26 @@
 using namespace std;
 using namespace std;
 
 
 // Global list of Items supported
 // Global list of Items supported
-static  pkgSourceList::Type *ItmList[10];
+static pkgSourceList::Type *ItmList[10];
 pkgSourceList::Type **pkgSourceList::Type::GlobalList = ItmList;
 pkgSourceList::Type **pkgSourceList::Type::GlobalList = ItmList;
 unsigned long pkgSourceList::Type::GlobalListLen = 0;
 unsigned long pkgSourceList::Type::GlobalListLen = 0;
 
 
 // Type::Type - Constructor						/*{{{*/
 // Type::Type - Constructor						/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Link this to the global list of items*/
 /* Link this to the global list of items*/
-pkgSourceList::Type::Type() : Name(NULL), Label(NULL)
+pkgSourceList::Type::Type(char const * const pName, char const * const pLabel) : Name(pName), Label(pLabel)
 {
 {
    ItmList[GlobalListLen] = this;
    ItmList[GlobalListLen] = this;
-   GlobalListLen++;
+   ++GlobalListLen;
 }
 }
+pkgSourceList::Type::~Type() {}
 									/*}}}*/
 									/*}}}*/
 // Type::GetType - Get a specific meta for a given type			/*{{{*/
 // Type::GetType - Get a specific meta for a given type			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 pkgSourceList::Type *pkgSourceList::Type::GetType(const char *Type)
 pkgSourceList::Type *pkgSourceList::Type::GetType(const char *Type)
 {
 {
-   for (unsigned I = 0; I != GlobalListLen; I++)
+   for (unsigned I = 0; I != GlobalListLen; ++I)
       if (strcmp(GlobalList[I]->Name,Type) == 0)
       if (strcmp(GlobalList[I]->Name,Type) == 0)
 	 return GlobalList[I];
 	 return GlobalList[I];
    return 0;
    return 0;
@@ -91,23 +92,26 @@ bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List,
    string Enabled = Tags.FindS("Enabled");
    string Enabled = Tags.FindS("Enabled");
    if (Enabled.size() > 0 && StringToBool(Enabled) == false)
    if (Enabled.size() > 0 && StringToBool(Enabled) == false)
       return true;
       return true;
-   
-   // Define external/internal options
-   const char* option_deb822[] = { 
-      "Architectures", "Architectures-Add", "Architectures-Remove", "Trusted",
-   };
-   const char* option_internal[] = { 
-      "arch", "arch+", "arch-", "trusted",
-   };
-   for (unsigned int j=0; j < sizeof(option_deb822)/sizeof(char*); j++)
-      if (Tags.Exists(option_deb822[j]))
+
+   std::map<char const * const, char const * const> mapping;
+#define APT_PLUSMINUS(X, Y) \
+   mapping.insert(std::make_pair(X, Y)); \
+   mapping.insert(std::make_pair(X "Add", Y "+")); \
+   mapping.insert(std::make_pair(X "Remove", Y "-"))
+   APT_PLUSMINUS("Architectures", "arch");
+   APT_PLUSMINUS("Languages", "lang");
+   APT_PLUSMINUS("Targets", "target");
+#undef APT_PLUSMINUS
+   mapping.insert(std::make_pair("Trusted", "trusted"));
+   for (std::map<char const * const, char const * const>::const_iterator m = mapping.begin(); m != mapping.end(); ++m)
+      if (Tags.Exists(m->first))
       {
       {
          // for deb822 the " " is the delimiter, but the backend expects ","
          // for deb822 the " " is the delimiter, but the backend expects ","
-         std::string option = Tags.FindS(option_deb822[j]);
+         std::string option = Tags.FindS(m->first);
          std::replace(option.begin(), option.end(), ' ', ',');
          std::replace(option.begin(), option.end(), ' ', ',');
-         Options[option_internal[j]] = option;
+         Options[m->second] = option;
       }
       }
-   
+
    // now create one item per suite/section
    // now create one item per suite/section
    string Suite = Tags.FindS("Suites");
    string Suite = Tags.FindS("Suites");
    Suite = SubstVar(Suite,"$(ARCH)",_config->Find("APT::Architecture"));
    Suite = SubstVar(Suite,"$(ARCH)",_config->Find("APT::Architecture"));
@@ -209,7 +213,7 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
       
       
    if (FixupURI(URI) == false)
    if (FixupURI(URI) == false)
       return _error->Error(_("Malformed line %lu in source list %s (URI parse)"),CurLine,File.c_str());
       return _error->Error(_("Malformed line %lu in source list %s (URI parse)"),CurLine,File.c_str());
-   
+
    // Check for an absolute dists specification.
    // Check for an absolute dists specification.
    if (Dist.empty() == false && Dist[Dist.size() - 1] == '/')
    if (Dist.empty() == false && Dist[Dist.size() - 1] == '/')
    {
    {

+ 4 - 4
apt-pkg/sourcelist.h

@@ -66,8 +66,8 @@ class pkgSourceList
       static unsigned long GlobalListLen;
       static unsigned long GlobalListLen;
       static Type *GetType(const char *Type) APT_PURE;
       static Type *GetType(const char *Type) APT_PURE;
 
 
-      const char *Name;
-      const char *Label;
+      char const * const Name;
+      char const * const Label;
 
 
       bool FixupURI(std::string &URI) const;
       bool FixupURI(std::string &URI) const;
       virtual bool ParseStanza(std::vector<metaIndex *> &List,
       virtual bool ParseStanza(std::vector<metaIndex *> &List,
@@ -80,8 +80,8 @@ class pkgSourceList
       virtual bool CreateItem(std::vector<metaIndex *> &List,std::string const &URI,
       virtual bool CreateItem(std::vector<metaIndex *> &List,std::string const &URI,
 			      std::string const &Dist,std::string const &Section,
 			      std::string const &Dist,std::string const &Section,
 			      std::map<std::string, std::string> const &Options) const = 0;
 			      std::map<std::string, std::string> const &Options) const = 0;
-      Type();
-      virtual ~Type() {};
+      Type(char const * const Name, char const * const Label);
+      virtual ~Type();
    };
    };
 
 
    typedef std::vector<metaIndex *>::const_iterator const_iterator;
    typedef std::vector<metaIndex *>::const_iterator const_iterator;

+ 2 - 2
cmdline/apt-get.cc

@@ -1045,7 +1045,7 @@ static bool DoBuildDep(CommandLine &CmdL)
       {
       {
          ioprintf(c1out, _("Note, using directory '%s' to get the build dependencies\n"), *I);
          ioprintf(c1out, _("Note, using directory '%s' to get the build dependencies\n"), *I);
          // FIXME: how can we make this more elegant?
          // FIXME: how can we make this more elegant?
-         std::string TypeName = "debian/control File Source Index";
+         std::string TypeName = "Debian control file";
          pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str());
          pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str());
          if(Type != NULL)
          if(Type != NULL)
             LastOwner = Last = Type->CreateSrcPkgParser(*I);
             LastOwner = Last = Type->CreateSrcPkgParser(*I);
@@ -1056,7 +1056,7 @@ static bool DoBuildDep(CommandLine &CmdL)
          ioprintf(c1out, _("Note, using file '%s' to get the build dependencies\n"), *I);
          ioprintf(c1out, _("Note, using file '%s' to get the build dependencies\n"), *I);
 
 
          // see if we can get a parser for this pkgIndexFile type
          // see if we can get a parser for this pkgIndexFile type
-         string TypeName = flExtension(*I) + " File Source Index";
+         string TypeName = "Debian " + flExtension(*I) + " file";
          pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str());
          pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str());
          if(Type != NULL)
          if(Type != NULL)
             LastOwner = Last = Type->CreateSrcPkgParser(*I);
             LastOwner = Last = Type->CreateSrcPkgParser(*I);

+ 16 - 0
doc/sources.list.5.xml

@@ -137,9 +137,25 @@
    can be used to specify for which architectures information should
    can be used to specify for which architectures information should
    be downloaded. If this option is not set all architectures defined by the
    be downloaded. If this option is not set all architectures defined by the
    <literal>APT::Architectures</literal> option will be downloaded.</para></listitem>
    <literal>APT::Architectures</literal> option will be downloaded.</para></listitem>
+
    <listitem><para><literal>arch+=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
    <listitem><para><literal>arch+=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
    and <literal>arch-=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
    and <literal>arch-=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
    which can be used to add/remove architectures from the set which will be downloaded.</para></listitem>
    which can be used to add/remove architectures from the set which will be downloaded.</para></listitem>
+
+   <listitem><para><literal>lang=<replaceable>lang1</replaceable>,<replaceable>lang2</replaceable>,…</literal>,
+   <literal>lang+=<replaceable>lang1</replaceable>,<replaceable>lang2</replaceable>,…</literal> and
+   <literal>lang-=<replaceable>lang1</replaceable>,<replaceable>lang2</replaceable>,…</literal> functioning in
+   the same way as the <literal>arch</literal>-options described before. They can be used to specify for
+   which languages apt will acquire metadata, like translated package descriptions, for. If not specified, the
+   default set is defined by the <literal>Acquire::Languages</literal> config option.</para></listitem>
+
+   <listitem><para><literal>target=<replaceable>target1</replaceable>,<replaceable>target2</replaceable>,…</literal>,
+   <literal>target+=<replaceable>target1</replaceable>,<replaceable>target2</replaceable>,…</literal> and
+   <literal>target-=<replaceable>target1</replaceable>,<replaceable>target2</replaceable>,…</literal> again functioning in
+   the same way as the <literal>arch</literal>-options described before. They can be used to specify which
+   targets apt will try to acquire from this source. If not specified, the default set is defined by
+   the <literal>APT::Acquire::Targets</literal> configuration scope.</para></listitem>
+
    <listitem><para><literal>trusted=yes</literal> can be set to indicate that packages
    <listitem><para><literal>trusted=yes</literal> can be set to indicate that packages
    from this source are always authenticated even if the <filename>Release</filename> file
    from this source are always authenticated even if the <filename>Release</filename> file
    is not signed or the signature can't be checked. This disables parts of &apt-secure;
    is not signed or the signature can't be checked. This disables parts of &apt-secure;

+ 11 - 11
test/integration/test-bug-632221-cross-dependency-satisfaction

@@ -167,17 +167,17 @@ Conf libfwibble-dev (1.0 unstable [armel])' aptget build-dep apt -s
 testsuccessequal 'Reading package lists...
 testsuccessequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
 The following NEW packages will be installed:
 The following NEW packages will be installed:
-  amdboot:amd64 cool doxygen foreigner libc6:amd64 libc6 libc6-dev:amd64
-  libc6-dev libfwibble-dev:amd64 libfwibble1:amd64 linux-stuff:amd64
+  amdboot:amd64 cool doxygen foreigner libc6 libc6:amd64 libc6-dev
+  libc6-dev:amd64 libfwibble-dev:amd64 libfwibble1:amd64 linux-stuff:amd64
 0 upgraded, 11 newly installed, 0 to remove and 0 not upgraded.
 0 upgraded, 11 newly installed, 0 to remove and 0 not upgraded.
 Inst amdboot:amd64 (1.0 unstable [amd64])
 Inst amdboot:amd64 (1.0 unstable [amd64])
 Inst cool (1.0 unstable [armel])
 Inst cool (1.0 unstable [armel])
 Inst doxygen (1.0 unstable [armel])
 Inst doxygen (1.0 unstable [armel])
 Inst foreigner (1.0 unstable [armel])
 Inst foreigner (1.0 unstable [armel])
-Inst libc6:amd64 (1.0 unstable [amd64])
 Inst libc6 (1.0 unstable [armel])
 Inst libc6 (1.0 unstable [armel])
-Inst libc6-dev:amd64 (1.0 unstable [amd64])
+Inst libc6:amd64 (1.0 unstable [amd64])
 Inst libc6-dev (1.0 unstable [armel])
 Inst libc6-dev (1.0 unstable [armel])
+Inst libc6-dev:amd64 (1.0 unstable [amd64])
 Inst libfwibble1:amd64 (1.0 unstable [amd64])
 Inst libfwibble1:amd64 (1.0 unstable [amd64])
 Inst libfwibble-dev:amd64 (1.0 unstable [amd64])
 Inst libfwibble-dev:amd64 (1.0 unstable [amd64])
 Inst linux-stuff:amd64 (1.0 unstable [amd64])
 Inst linux-stuff:amd64 (1.0 unstable [amd64])
@@ -185,10 +185,10 @@ Conf amdboot:amd64 (1.0 unstable [amd64])
 Conf cool (1.0 unstable [armel])
 Conf cool (1.0 unstable [armel])
 Conf doxygen (1.0 unstable [armel])
 Conf doxygen (1.0 unstable [armel])
 Conf foreigner (1.0 unstable [armel])
 Conf foreigner (1.0 unstable [armel])
-Conf libc6:amd64 (1.0 unstable [amd64])
 Conf libc6 (1.0 unstable [armel])
 Conf libc6 (1.0 unstable [armel])
-Conf libc6-dev:amd64 (1.0 unstable [amd64])
+Conf libc6:amd64 (1.0 unstable [amd64])
 Conf libc6-dev (1.0 unstable [armel])
 Conf libc6-dev (1.0 unstable [armel])
+Conf libc6-dev:amd64 (1.0 unstable [amd64])
 Conf libfwibble1:amd64 (1.0 unstable [amd64])
 Conf libfwibble1:amd64 (1.0 unstable [amd64])
 Conf libfwibble-dev:amd64 (1.0 unstable [amd64])
 Conf libfwibble-dev:amd64 (1.0 unstable [amd64])
 Conf linux-stuff:amd64 (1.0 unstable [amd64])' aptget build-dep apt -s -a amd64
 Conf linux-stuff:amd64 (1.0 unstable [amd64])' aptget build-dep apt -s -a amd64
@@ -275,24 +275,24 @@ Conf libfwibble-dev (1.0 unstable [armel])' aptget build-dep apt -s
 testsuccessequal 'Reading package lists...
 testsuccessequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
 The following NEW packages will be installed:
 The following NEW packages will be installed:
-  amdboot:amd64 doxygen libc6:amd64 libc6 libc6-dev:amd64 libc6-dev
+  amdboot:amd64 doxygen libc6 libc6:amd64 libc6-dev libc6-dev:amd64
   libfwibble-dev:amd64 libfwibble1:amd64 linux-stuff:amd64
   libfwibble-dev:amd64 libfwibble1:amd64 linux-stuff:amd64
 0 upgraded, 9 newly installed, 0 to remove and 2 not upgraded.
 0 upgraded, 9 newly installed, 0 to remove and 2 not upgraded.
 Inst amdboot:amd64 (1.0 unstable [amd64])
 Inst amdboot:amd64 (1.0 unstable [amd64])
 Inst doxygen (1.0 unstable [armel])
 Inst doxygen (1.0 unstable [armel])
-Inst libc6:amd64 (1.0 unstable [amd64])
 Inst libc6 (1.0 unstable [armel])
 Inst libc6 (1.0 unstable [armel])
-Inst libc6-dev:amd64 (1.0 unstable [amd64])
+Inst libc6:amd64 (1.0 unstable [amd64])
 Inst libc6-dev (1.0 unstable [armel])
 Inst libc6-dev (1.0 unstable [armel])
+Inst libc6-dev:amd64 (1.0 unstable [amd64])
 Inst libfwibble1:amd64 (1.0 unstable [amd64])
 Inst libfwibble1:amd64 (1.0 unstable [amd64])
 Inst libfwibble-dev:amd64 (1.0 unstable [amd64])
 Inst libfwibble-dev:amd64 (1.0 unstable [amd64])
 Inst linux-stuff:amd64 (1.0 unstable [amd64])
 Inst linux-stuff:amd64 (1.0 unstable [amd64])
 Conf amdboot:amd64 (1.0 unstable [amd64])
 Conf amdboot:amd64 (1.0 unstable [amd64])
 Conf doxygen (1.0 unstable [armel])
 Conf doxygen (1.0 unstable [armel])
-Conf libc6:amd64 (1.0 unstable [amd64])
 Conf libc6 (1.0 unstable [armel])
 Conf libc6 (1.0 unstable [armel])
-Conf libc6-dev:amd64 (1.0 unstable [amd64])
+Conf libc6:amd64 (1.0 unstable [amd64])
 Conf libc6-dev (1.0 unstable [armel])
 Conf libc6-dev (1.0 unstable [armel])
+Conf libc6-dev:amd64 (1.0 unstable [amd64])
 Conf libfwibble1:amd64 (1.0 unstable [amd64])
 Conf libfwibble1:amd64 (1.0 unstable [amd64])
 Conf libfwibble-dev:amd64 (1.0 unstable [amd64])
 Conf libfwibble-dev:amd64 (1.0 unstable [amd64])
 Conf linux-stuff:amd64 (1.0 unstable [amd64])' aptget build-dep apt -s -a amd64
 Conf linux-stuff:amd64 (1.0 unstable [amd64])' aptget build-dep apt -s -a amd64

+ 5 - 5
test/integration/test-ignore-provides-if-versioned-breaks

@@ -134,17 +134,17 @@ Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider f
 testsuccessequal 'Reading package lists...
 testsuccessequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
 The following extra packages will be installed:
 The following extra packages will be installed:
-  foo-same:amd64 foo-same
+  foo-same foo-same:amd64
 The following NEW packages will be installed:
 The following NEW packages will be installed:
   foo-same-breaker-3 foo-same-provider
   foo-same-breaker-3 foo-same-provider
 The following packages will be upgraded:
 The following packages will be upgraded:
-  foo-same:amd64 foo-same
+  foo-same foo-same:amd64
 2 upgraded, 2 newly installed, 0 to remove and 2 not upgraded.
 2 upgraded, 2 newly installed, 0 to remove and 2 not upgraded.
-Inst foo-same:amd64 [2.0] (4.0 unstable [amd64]) [foo-same:amd64 on foo-same:i386] [foo-same:i386 on foo-same:amd64] [foo-same:i386 ]
-Inst foo-same [2.0] (4.0 unstable [i386])
+Inst foo-same [2.0] (4.0 unstable [i386]) [foo-same:i386 on foo-same:amd64] [foo-same:amd64 on foo-same:i386] [foo-same:amd64 ]
+Inst foo-same:amd64 [2.0] (4.0 unstable [amd64])
 Inst foo-same-breaker-3 (1.0 unstable [i386])
 Inst foo-same-breaker-3 (1.0 unstable [i386])
 Inst foo-same-provider (1.0 unstable [i386])
 Inst foo-same-provider (1.0 unstable [i386])
-Conf foo-same (4.0 unstable [i386])
 Conf foo-same:amd64 (4.0 unstable [amd64])
 Conf foo-same:amd64 (4.0 unstable [amd64])
+Conf foo-same (4.0 unstable [i386])
 Conf foo-same-breaker-3 (1.0 unstable [i386])
 Conf foo-same-breaker-3 (1.0 unstable [i386])
 Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider foo-same-breaker-3 -s
 Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider foo-same-breaker-3 -s

+ 5 - 5
test/integration/test-ignore-provides-if-versioned-conflicts

@@ -134,17 +134,17 @@ Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider f
 testsuccessequal 'Reading package lists...
 testsuccessequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
 The following extra packages will be installed:
 The following extra packages will be installed:
-  foo-same:amd64 foo-same
+  foo-same foo-same:amd64
 The following NEW packages will be installed:
 The following NEW packages will be installed:
   foo-same-breaker-3 foo-same-provider
   foo-same-breaker-3 foo-same-provider
 The following packages will be upgraded:
 The following packages will be upgraded:
-  foo-same:amd64 foo-same
+  foo-same foo-same:amd64
 2 upgraded, 2 newly installed, 0 to remove and 2 not upgraded.
 2 upgraded, 2 newly installed, 0 to remove and 2 not upgraded.
-Inst foo-same:amd64 [2.0] (4.0 unstable [amd64]) [foo-same:amd64 on foo-same:i386] [foo-same:i386 on foo-same:amd64] [foo-same:i386 ]
-Inst foo-same [2.0] (4.0 unstable [i386])
+Inst foo-same [2.0] (4.0 unstable [i386]) [foo-same:i386 on foo-same:amd64] [foo-same:amd64 on foo-same:i386] [foo-same:amd64 ]
+Inst foo-same:amd64 [2.0] (4.0 unstable [amd64])
 Inst foo-same-breaker-3 (1.0 unstable [i386])
 Inst foo-same-breaker-3 (1.0 unstable [i386])
 Inst foo-same-provider (1.0 unstable [i386])
 Inst foo-same-provider (1.0 unstable [i386])
-Conf foo-same (4.0 unstable [i386])
 Conf foo-same:amd64 (4.0 unstable [amd64])
 Conf foo-same:amd64 (4.0 unstable [amd64])
+Conf foo-same (4.0 unstable [i386])
 Conf foo-same-breaker-3 (1.0 unstable [i386])
 Conf foo-same-breaker-3 (1.0 unstable [i386])
 Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider foo-same-breaker-3 -s
 Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider foo-same-breaker-3 -s

+ 87 - 0
test/integration/test-sourceslist-lang-plusminus-options

@@ -0,0 +1,87 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'native'
+
+testlangs() {
+	msgtest 'Test acquired languages for' "$1"
+	local LANGS="$2"
+	shift 2
+	rm -f gotlangs.list
+	aptget files --no-release-info 'Created-By: Translations' "$@" --format '$(LANGUAGE)' | sort -u > gotlangs.list
+	if [ -z "$LANGS" ]; then
+		echo -n | tr ',' '\n' | sort | checkdiff - gotlangs.list && msgpass || msgfail
+	else
+		echo -n "$LANGS" | tr ',' '\n' | sort | checkdiff - gotlangs.list && msgpass || msgfail
+	fi
+}
+echo 'deb http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'default' 'en'
+
+echo 'Acquire::Languages "environment,en";' > rootdir/etc/apt/apt.conf.d/langs.conf
+testlangs 'default config' 'en'
+
+echo 'Acquire::Languages "en,en,en";' > rootdir/etc/apt/apt.conf.d/langs.conf
+testlangs 'duplicated config' 'en'
+
+echo 'Acquire::Languages "none";' > rootdir/etc/apt/apt.conf.d/langs.conf
+testlangs 'none config' ''
+
+echo 'Acquire::Languages "en,none,de,de_DE";' > rootdir/etc/apt/apt.conf.d/langs.conf
+testlangs 'english + german config' 'en,de,de_DE'
+
+echo 'deb [lang=pt] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang=pt' 'pt'
+
+echo 'deb [lang=en] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang=en' 'en'
+
+echo 'deb [lang=de_DE] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang=de_DE' 'de_DE'
+
+echo 'deb [lang=none] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang=none' ''
+testequal 'amd64' aptget files --no-release-info 'Created-By: Packages' --format '$(ARCHITECTURE)'
+
+echo 'deb [lang+=pt] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang+=pt' 'en,de,de_DE,pt'
+
+echo 'deb [lang+=en] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang+=en' 'en,de,de_DE'
+
+echo 'deb [lang+=de_DE] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang+=de_DE' 'en,de,de_DE'
+
+echo 'deb [lang-=pt] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang-=pt' 'en,de,de_DE'
+
+echo 'deb [lang-=en] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang-=en' 'de,de_DE'
+
+echo 'deb [lang-=de_DE] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list
+testlangs 'lang-=de_DE' 'en,de'
+
+echo 'deb http://example.org/debian stable rocks
+deb http://example.org/debian stable solid' > rootdir/etc/apt/sources.list
+testlangs 'english + german config multicomponent' 'en,de,de_DE'
+
+echo 'deb http://example.org/debian stable rocks
+deb [lang=pt] http://example.org/debian stable solid' > rootdir/etc/apt/sources.list
+testlangs 'multicomponent one lang= combined' 'en,de,de_DE,pt'
+testlangs 'multicomponent one lang= rocks' 'en,de,de_DE' 'Component: rocks'
+testlangs 'multicomponent one lang= solid' 'pt' 'Component: solid'
+
+echo 'deb [lang=pt] http://example.org/debian stable rocks
+deb [lang=de] http://example.org/debian stable solid' > rootdir/etc/apt/sources.list
+testlangs 'multicomponent different lang= combined' 'de,pt'
+testlangs 'multicomponent different lang= rocks' 'pt' 'Component: rocks'
+testlangs 'multicomponent different lang= solid' 'de' 'Component: solid'
+
+echo 'deb [lang+=pt] http://example.org/debian stable rocks
+deb [lang-=de] http://example.org/debian stable solid' > rootdir/etc/apt/sources.list
+testlangs 'multicomponent different lang+-= combined' 'en,de,de_DE,pt'
+testlangs 'multicomponent different lang+-= rocks' 'en,de,de_DE,pt' 'Component: rocks'
+testlangs 'multicomponent different lang+-= solid' 'en,de_DE' 'Component: solid'