// at this point the real Items are loaded in the fetcher
ExpectedAdditionalItems = 0;
+ std::set<std::string> targetsSeen;
bool const metaBaseSupportsByHash = TransactionManager->MetaIndexParser->GetSupportsAcquireByHash();
- for (auto Target : TransactionManager->MetaIndexParser->GetIndexTargets())
+ for (auto &Target: TransactionManager->MetaIndexParser->GetIndexTargets())
{
+ // if we have seen a target which is created-by a target this one here is declared a
+ // fallback to, we skip acquiring the fallback (but we make sure we clean up)
+ if (targetsSeen.find(Target.Option(IndexTarget::FALLBACK_OF)) != targetsSeen.end())
+ {
+ targetsSeen.emplace(Target.Option(IndexTarget::CREATED_BY));
+ new CleanupItem(Owner, TransactionManager, Target);
+ continue;
+ }
// all is an implementation detail. Users shouldn't use this as arch
// We need this support trickery here as e.g. Debian has binary-all files already,
// but arch:all packages are still in the arch:any files, so we would waste precious
else if (hashes.FileSize() == 0)
{
new CleanupItem(Owner, TransactionManager, Target);
+ targetsSeen.emplace(Target.Option(IndexTarget::CREATED_BY));
continue;
}
}
std::string const idxfilename = GetFinalFileNameFromURI(GetDiffIndexURI(Target));
if (FileExists(idxfilename))
new NoActionItem(Owner, Target, idxfilename);
+ targetsSeen.emplace(Target.Option(IndexTarget::CREATED_BY));
continue;
}
}
// Queue the Index file (Packages, Sources, Translation-$foo, …)
+ targetsSeen.emplace(Target.Option(IndexTarget::CREATED_BY));
if (trypdiff)
new pkgAcqDiffIndex(Owner, TransactionManager, Target);
else
public:
struct APT_HIDDEN debSectionEntry
{
- std::string sourcesEntry;
- std::string Name;
- std::vector<std::string> Targets;
- std::vector<std::string> Architectures;
- std::vector<std::string> Languages;
- bool UsePDiffs;
- std::string UseByHash;
+ std::string const sourcesEntry;
+ std::string const Name;
+ std::vector<std::string> const Targets;
+ std::vector<std::string> const Architectures;
+ std::vector<std::string> const Languages;
+ bool const UsePDiffs;
+ std::string const UseByHash;
};
std::vector<debSectionEntry> DebEntries;
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())
Options.insert(std::make_pair("REPO_URI", URI));
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"));
// special case for --print-uris
if (GetAll)
for (auto const &Target: GetIndexTargets())
- new pkgAcqIndex(Owner, TransactionManager, Target);
+ if (Target.Option(IndexTarget::FALLBACK_OF).empty())
+ new pkgAcqIndex(Owner, TransactionManager, Target);
return true;
}
else if (optValue == false && tarItr != mytargets.end())
mytargets.erase(std::remove(mytargets.begin(), mytargets.end(), target), mytargets.end());
}
+ // if we can't order it in a 1000 steps we give up… probably a cycle
+ for (auto i = 0; i < 1000; ++i)
+ {
+ bool Changed = false;
+ for (auto t = mytargets.begin(); t != mytargets.end(); ++t)
+ {
+ std::string const fallback = _config->Find(std::string("Acquire::IndexTargets::") + Name + "::" + *t + "::Fallback-Of");
+ if (fallback.empty())
+ continue;
+ auto const faller = std::find(mytargets.begin(), mytargets.end(), fallback);
+ if (faller == mytargets.end() || faller < t)
+ continue;
+ Changed = true;
+ auto const tv = *t;
+ mytargets.erase(t);
+ mytargets.emplace_back(tv);
+ }
+ if (Changed == false)
+ break;
+ }
bool UsePDiffs = _config->FindB("Acquire::PDiffs", true);
{
APT_CASE(REPO_URI);
APT_CASE(TARGET_OF);
APT_CASE(CREATED_BY);
+ APT_CASE(FALLBACK_OF);
APT_CASE(PDIFFS);
APT_CASE(DEFAULTENABLED);
APT_CASE(COMPRESSIONTYPES);
SOURCESENTRY,
BY_HASH,
KEEPCOMPRESSEDAS,
+ FALLBACK_OF,
};
std::string Option(OptionKeys const Key) const;
bool OptionBool(OptionKeys const Key) const;
have to ensure your front-end can deal with all compressed fileformats
supported by apt (libapt users can e.g. use FileFd, others can use
the cat-file command of /usr/lib/apt/apt-helper).
+* Fallback-Of: Is by default not set. If it is set and specifies another
+ target name (see Created-By) which was found in the Release file the
+ download of this target will be skipped. This can be used to implement
+ fallback(chain)s to allow transitions like the rename of target files.
+ The behavior if cycles are formed with Fallback-Of is undefined!
* flat{MetaKey,Description}: APT supports two types of repositories:
dists-style repositories which are the default and by far the most
common which are named after the fact that the files are in an
To get all the filenames of all Translation-en files you can e.g. call:
apt-get indextargets --format '$(FILENAME)' "Created-By: Translations" "Language: en"
-The line-based filtering and the formating is rather crude and feature-
+The line-based filtering and the formatting is rather crude and feature-
less by design: The default format is Debians standard format deb822 (in
particular: Field names are case-insensitive and the order of fields in
the stanza is undefined), so instead of apt reimplementing powerful
-filters and formating for this command, it is recommend to use piping
+filters and formatting for this command, it is recommend to use piping
and dedicated tools like 'grep-dctrl' if you need more than the basics
provided.
testempty aptget indextargets --format '$(FILENAME)' 'Created-By: Contents'
runthistest
+msgmsg "Contents with 3 MetaKeys, first match"
+rm ./rootdir/var/lib/apt/lists/localhost:${APTHTTPPORT}_dists_unstable_main_Contents-amd64.gz
+rm ./rootdir/var/lib/apt/lists/localhost:${APTHTTPPORT}_dists_unstable_main_Contents-all.gz
+testempty aptget indextargets --format '$(FILENAME)' 'Created-By: Contents'
+cat > rootdir/etc/apt/apt.conf.d/content-target.conf <<EOF
+Acquire::IndexTargets::deb::Contents3 {
+ MetaKey "main/Contents-all";
+ ShortDescription "Contents3";
+ Description "\$(RELEASE) all Contents3";
+ Fallback-Of "Contents2";
+};
+Acquire::IndexTargets::deb::Contents {
+ MetaKey "\$(COMPONENT)/Contents-amd64";
+ ShortDescription "Contents";
+ Description "\$(RELEASE)/\$(COMPONENT) amd64 Contents";
+};
+Acquire::IndexTargets::deb::Contents2 {
+ MetaKey "Contents-all";
+ ShortDescription "Contents2";
+ Description "\$(RELEASE) all Contents2";
+ Fallback-Of "Contents";
+};
+EOF
+testequal "'http://localhost:${APTHTTPPORT}/dists/unstable/InRelease' localhost:${APTHTTPPORT}_dists_unstable_InRelease 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/source/Sources.xz' localhost:${APTHTTPPORT}_dists_unstable_main_source_Sources 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/binary-amd64/Packages.xz' localhost:${APTHTTPPORT}_dists_unstable_main_binary-amd64_Packages 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/binary-all/Packages.xz' localhost:${APTHTTPPORT}_dists_unstable_main_binary-all_Packages 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/i18n/Translation-en.xz' localhost:${APTHTTPPORT}_dists_unstable_main_i18n_Translation-en 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/Contents-amd64.xz' localhost:${APTHTTPPORT}_dists_unstable_main_Contents-amd64 0 " aptget update --print-uris
+testsuccessequal "Hit:1 http://localhost:${APTHTTPPORT} unstable InRelease
+Get:2 http://localhost:${APTHTTPPORT} unstable/main amd64 Contents [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B]
+Reading package lists..." aptget update
+testequal "rootdir/var/lib/apt/lists/localhost:${APTHTTPPORT}_dists_unstable_main_Contents-amd64" find rootdir/var/lib/apt/lists -name '*Contents*'
+testequal "$(readfile Contents-amd64)" aptget indextargets --format '$(FILENAME)' 'Created-By: Contents'
+testempty aptget indextargets --format '$(FILENAME)' 'Created-By: Contents2'
+testempty aptget indextargets --format '$(FILENAME)' 'Created-By: Contents3'
+testsuccess cmp "rootdir/var/lib/apt/lists/localhost:${APTHTTPPORT}_dists_unstable_main_Contents-amd64" 'aptarchive/dists/unstable/main/Contents-amd64'
+
+msgmsg "Contents with 3 MetaKeys, third match"
+rm ./rootdir/var/lib/apt/lists/localhost:${APTHTTPPORT}_dists_unstable_main_Contents-amd64
+testempty aptget indextargets --format '$(FILENAME)' 'Created-By: Contents'
+echo 'Acquire::IndexTargets::deb::Contents::MetaKey "$(COMPONENT)/Contents-i386";' >> rootdir/etc/apt/apt.conf.d/content-target.conf
+testequal "'http://localhost:${APTHTTPPORT}/dists/unstable/InRelease' localhost:${APTHTTPPORT}_dists_unstable_InRelease 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/source/Sources.xz' localhost:${APTHTTPPORT}_dists_unstable_main_source_Sources 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/binary-amd64/Packages.xz' localhost:${APTHTTPPORT}_dists_unstable_main_binary-amd64_Packages 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/binary-all/Packages.xz' localhost:${APTHTTPPORT}_dists_unstable_main_binary-all_Packages 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/i18n/Translation-en.xz' localhost:${APTHTTPPORT}_dists_unstable_main_i18n_Translation-en 0
+'http://localhost:${APTHTTPPORT}/dists/unstable/main/Contents-i386.xz' localhost:${APTHTTPPORT}_dists_unstable_main_Contents-i386 0 " aptget update --print-uris
+testsuccessequal "Hit:1 http://localhost:${APTHTTPPORT} unstable InRelease
+Get:2 http://localhost:${APTHTTPPORT} unstable all Contents3 [$(stat -c%s aptarchive/dists/unstable/main/Contents-all.gz) B]
+Reading package lists..." aptget update
+testequal "rootdir/var/lib/apt/lists/localhost:${APTHTTPPORT}_dists_unstable_main_Contents-all" find rootdir/var/lib/apt/lists -name '*Contents*'
+testequal "$(readfile Contents-all)" aptget indextargets --format '$(FILENAME)' 'Created-By: Contents3'
+testempty aptget indextargets --format '$(FILENAME)' 'Created-By: Contents'
+testempty aptget indextargets --format '$(FILENAME)' 'Created-By: Contents2'
+testsuccess cmp "rootdir/var/lib/apt/lists/localhost:${APTHTTPPORT}_dists_unstable_main_Contents-all" 'aptarchive/dists/unstable/main/Contents-all'
+
+rm ./rootdir/var/lib/apt/lists/localhost:${APTHTTPPORT}_dists_unstable_main_Contents-all
rm -f rootdir/etc/apt/apt.conf.d/content-target.conf
msgmsg "No Contents file"