+ bool const flatArchive = (Dist[Dist.length() - 1] == '/');
+ std::string const baseURI = constructMetaIndexURI(URI, Dist, "");
+ std::string const Release = (Dist == "/") ? "" : Dist;
+ std::string const Site = ::URI::ArchiveOnly(URI);
+
+ std::string DefCompressionTypes;
+ {
+ std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+ if (types.empty() == false)
+ {
+ std::ostringstream os;
+ std::copy(types.begin(), types.end()-1, std::ostream_iterator<std::string>(os, " "));
+ os << *types.rbegin();
+ DefCompressionTypes = os.str();
+ }
+ }
+ std::string DefKeepCompressedAs;
+ {
+ std::vector<APT::Configuration::Compressor> comps = APT::Configuration::getCompressors();
+ if (comps.empty() == false)
+ {
+ std::sort(comps.begin(), comps.end(),
+ [](APT::Configuration::Compressor const &a, APT::Configuration::Compressor const &b) { return a.Cost < b.Cost; });
+ std::ostringstream os;
+ for (auto const &c : comps)
+ if (c.Cost != 0)
+ os << c.Extension.substr(1) << ' ';
+ DefKeepCompressedAs = os.str();
+ }
+ DefKeepCompressedAs += "uncompressed";
+ }
+
+ std::vector<std::string> const NativeArchs = { _config->Find("APT::Architecture"), "implicit:all" };
+ bool const GzipIndex = _config->FindB("Acquire::GzipIndexes", false);
+ for (std::vector<debReleaseIndexPrivate::debSectionEntry>::const_iterator E = entries.begin(); E != entries.end(); ++E)
+ {
+ for (std::vector<std::string>::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T)
+ {
+#define APT_T_CONFIG_STR(X, Y) _config->Find(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X), (Y))
+#define APT_T_CONFIG_BOOL(X, Y) _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X), (Y))
+ std::string const tplMetaKey = APT_T_CONFIG_STR(flatArchive ? "flatMetaKey" : "MetaKey", "");
+ std::string const tplShortDesc = APT_T_CONFIG_STR("ShortDescription", "");
+ std::string const tplLongDesc = "$(SITE) " + APT_T_CONFIG_STR(flatArchive ? "flatDescription" : "Description", "");
+ std::string const tplIdentifier = APT_T_CONFIG_STR("Identifier", *T);
+ bool const IsOptional = APT_T_CONFIG_BOOL("Optional", true);
+ bool const KeepCompressed = APT_T_CONFIG_BOOL("KeepCompressed", GzipIndex);
+ bool const DefaultEnabled = APT_T_CONFIG_BOOL("DefaultEnabled", true);
+ bool const UsePDiffs = APT_T_CONFIG_BOOL("PDiffs", E->UsePDiffs);
+ std::string const UseByHash = APT_T_CONFIG_STR("By-Hash", E->UseByHash);
+ std::string const CompressionTypes = APT_T_CONFIG_STR("CompressionTypes", DefCompressionTypes);
+ std::string KeepCompressedAs = APT_T_CONFIG_STR("KeepCompressedAs", "");
+ std::string const FallbackOf = APT_T_CONFIG_STR("Fallback-Of", "");
+#undef APT_T_CONFIG_BOOL
+#undef APT_T_CONFIG_STR
+ if (tplMetaKey.empty())
+ continue;
+
+ if (KeepCompressedAs.empty())
+ KeepCompressedAs = DefKeepCompressedAs;
+ else
+ {
+ std::vector<std::string> const defKeep = VectorizeString(DefKeepCompressedAs, ' ');
+ std::vector<std::string> const valKeep = VectorizeString(KeepCompressedAs, ' ');
+ std::vector<std::string> keep;
+ for (auto const &val : valKeep)
+ {
+ if (val.empty())
+ continue;
+ if (std::find(defKeep.begin(), defKeep.end(), val) == defKeep.end())
+ continue;
+ keep.push_back(val);
+ }
+ if (std::find(keep.begin(), keep.end(), "uncompressed") == keep.end())
+ keep.push_back("uncompressed");
+ std::ostringstream os;
+ std::copy(keep.begin(), keep.end()-1, std::ostream_iterator<std::string>(os, " "));
+ os << *keep.rbegin();
+ KeepCompressedAs = os.str();
+ }
+
+ for (std::vector<std::string>::const_iterator L = E->Languages.begin(); L != E->Languages.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)
+ {
+ for (auto const &NativeArch: NativeArchs)
+ {
+ constexpr static auto BreakPoint = "$(NATIVE_ARCHITECTURE)";
+ // available in templates
+ std::map<std::string, std::string> Options;
+ Options.insert(std::make_pair("SITE", Site));
+ Options.insert(std::make_pair("RELEASE", Release));
+ if (tplMetaKey.find("$(COMPONENT)") != std::string::npos)
+ Options.emplace("COMPONENT", E->Name);
+ if (tplMetaKey.find("$(LANGUAGE)") != std::string::npos)
+ Options.emplace("LANGUAGE", *L);
+ if (tplMetaKey.find("$(ARCHITECTURE)") != std::string::npos)
+ Options.emplace("ARCHITECTURE", (*A == "implicit:all") ? "all" : *A);
+ else if (tplMetaKey.find("$(NATIVE_ARCHITECTURE)") != std::string::npos)
+ Options.emplace("ARCHITECTURE", (NativeArch == "implicit:all") ? "all" : NativeArch);
+ if (tplMetaKey.find("$(NATIVE_ARCHITECTURE)") != std::string::npos)
+ Options.emplace("NATIVE_ARCHITECTURE", (NativeArch == "implicit:all") ? "all" : NativeArch);
+
+ std::string MetaKey = tplMetaKey;
+ std::string ShortDesc = tplShortDesc;
+ std::string LongDesc = tplLongDesc;
+ std::string Identifier = tplIdentifier;
+ for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
+ {
+ std::string const varname = "$(" + O->first + ")";
+ MetaKey = SubstVar(MetaKey, varname, O->second);
+ ShortDesc = SubstVar(ShortDesc, varname, O->second);
+ LongDesc = SubstVar(LongDesc, varname, O->second);
+ Identifier = SubstVar(Identifier, varname, O->second);
+ }
+
+ {
+ auto const dup = std::find_if(IndexTargets.begin(), IndexTargets.end(), [&](IndexTarget const &IT) {
+ return MetaKey == IT.MetaKey && baseURI == IT.Option(IndexTarget::BASE_URI) &&
+ E->sourcesEntry == IT.Option(IndexTarget::SOURCESENTRY) && *T == IT.Option(IndexTarget::CREATED_BY);
+ });
+ if (dup != IndexTargets.end())
+ {
+ if (tplMetaKey.find(BreakPoint) == std::string::npos)
+ break;
+ continue;
+ }
+ }
+
+ {
+ auto const dup = std::find_if(IndexTargets.begin(), IndexTargets.end(), [&](IndexTarget const &IT) {
+ return MetaKey == IT.MetaKey && baseURI == IT.Option(IndexTarget::BASE_URI) &&
+ E->sourcesEntry == IT.Option(IndexTarget::SOURCESENTRY) && *T != IT.Option(IndexTarget::CREATED_BY);
+ });
+ if (dup != IndexTargets.end())
+ {
+ std::string const dupT = dup->Option(IndexTarget::CREATED_BY);
+ std::string const dupEntry = dup->Option(IndexTarget::SOURCESENTRY);
+ //TRANSLATOR: an identifier like Packages; Releasefile key indicating
+ // a file like main/binary-amd64/Packages; another identifier like Contents;
+ // filename and linenumber of the sources.list entry currently parsed
+ _error->Warning(_("Target %s wants to acquire the same file (%s) as %s from source %s"),
+ T->c_str(), MetaKey.c_str(), dupT.c_str(), dupEntry.c_str());
+ if (tplMetaKey.find(BreakPoint) == std::string::npos)
+ break;
+ continue;
+ }
+ }
+
+ {
+ auto const dup = std::find_if(IndexTargets.begin(), IndexTargets.end(), [&](IndexTarget const &T) {
+ return MetaKey == T.MetaKey && baseURI == T.Option(IndexTarget::BASE_URI) &&
+ E->sourcesEntry != T.Option(IndexTarget::SOURCESENTRY);
+ });
+ if (dup != IndexTargets.end())
+ {
+ std::string const dupEntry = dup->Option(IndexTarget::SOURCESENTRY);
+ //TRANSLATOR: an identifier like Packages; Releasefile key indicating
+ // a file like main/binary-amd64/Packages; filename and linenumber of
+ // two sources.list entries
+ _error->Warning(_("Target %s (%s) is configured multiple times in %s and %s"),
+ T->c_str(), MetaKey.c_str(), dupEntry.c_str(), E->sourcesEntry.c_str());
+ if (tplMetaKey.find(BreakPoint) == std::string::npos)
+ break;
+ continue;
+ }
+ }
+
+ // not available in templates, but in the indextarget
+ Options.insert(ReleaseOptions.begin(), ReleaseOptions.end());
+ Options.insert(std::make_pair("IDENTIFIER", Identifier));
+ Options.insert(std::make_pair("TARGET_OF", Type));
+ Options.insert(std::make_pair("CREATED_BY", *T));
+ Options.insert(std::make_pair("FALLBACK_OF", FallbackOf));
+ Options.insert(std::make_pair("PDIFFS", UsePDiffs ? "yes" : "no"));
+ Options.insert(std::make_pair("BY_HASH", UseByHash));
+ Options.insert(std::make_pair("DEFAULTENABLED", DefaultEnabled ? "yes" : "no"));
+ Options.insert(std::make_pair("COMPRESSIONTYPES", CompressionTypes));
+ Options.insert(std::make_pair("KEEPCOMPRESSEDAS", KeepCompressedAs));
+ Options.insert(std::make_pair("SOURCESENTRY", E->sourcesEntry));
+
+ bool IsOpt = IsOptional;
+ {
+ auto const arch = Options.find("ARCHITECTURE");
+ if (arch != Options.end() && arch->second == "all")
+ {
+ // one of them must be implicit:all then
+ if (*A != "all" && NativeArch != "all")
+ IsOpt = true;
+ else // user used arch=all explicitly
+ Options.emplace("Force-Support-For-All", "yes");
+ }
+ }
+
+ IndexTarget Target(
+ MetaKey,
+ ShortDesc,
+ LongDesc,
+ baseURI + MetaKey,
+ IsOpt,
+ KeepCompressed,
+ Options
+ );
+ IndexTargets.push_back(Target);
+
+ if (tplMetaKey.find(BreakPoint) == std::string::npos)
+ break;
+ }
+
+ if (tplMetaKey.find("$(ARCHITECTURE)") == std::string::npos)
+ break;