Browse Source

allow repositories to forbid arch:all for specific index targets

Debian has a Packages file for arch:all already, but the arch:any files
contain arch:all packages as well, so downloading it would be a total
waste of resources. Getting this solved is on the list of things to do,
but it is also the hardest part – for index targets like Contents the
situation is much easier and less server/client implementations are
involved so we might not want to stall them.

A repository can now declare via:
No-Support-for-Architecture-all: Packages
that even if an arch:all Packages exists, it shouldn't be downloaded, so
that support for Contents files can be added now.

See also 1dd20368486820efb6ef4476ad739e967174bec4 for the implementation
of downloading arch:all index targets, which this is limiting.

The field uses the name of the target from the apt configuration for
simplicity and is negative by design as this field is intended to be
supported/needed only for a "short" time (one or two Debian releases).

While this commit theoretically supports any target, its expected to
only see "Packages" as a value in reality.
David Kalnischkies 8 years ago
parent
commit
a628ca5256

+ 7 - 3
apt-pkg/acquire-item.cc

@@ -1042,9 +1042,13 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify)			/*{{{*/
       // download time, bandwidth and diskspace for nothing, BUT Debian doesn't feature all
       // in the set of supported architectures, so we can filter based on this property rather
       // than invent an entirely new flag we would need to carry for all of eternity.
-      if (Target->Option(IndexTarget::ARCHITECTURE) == "all" &&
-	    TransactionManager->MetaIndexParser->IsArchitectureSupported("all") == false)
-	 continue;
+      if (Target->Option(IndexTarget::ARCHITECTURE) == "all")
+      {
+	 if (TransactionManager->MetaIndexParser->IsArchitectureSupported("all") == false)
+	    continue;
+	 if (TransactionManager->MetaIndexParser->IsArchitectureAllSupportedFor(*Target) == false)
+	    continue;
+      }
 
       bool trypdiff = Target->OptionBool(IndexTarget::PDIFFS);
       if (verify == true)

+ 13 - 0
apt-pkg/deb/debmetaindex.cc

@@ -50,6 +50,7 @@ class APT_HIDDEN debReleaseIndexPrivate					/*{{{*/
    time_t ValidUntilMax;
 
    std::vector<std::string> Architectures;
+   std::vector<std::string> NoSupportForAll;
 
    debReleaseIndexPrivate() : CheckValidUntil(metaIndex::TRI_UNSET), ValidUntilMin(0), ValidUntilMax(0) {}
 };
@@ -346,6 +347,11 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro
       if (archs.empty() == false)
 	 d->Architectures = VectorizeString(archs, ' ');
    }
+   {
+      std::string const targets = Section.FindS("No-Support-for-Architecture-all");
+      if (targets.empty() == false)
+	 d->NoSupportForAll = VectorizeString(targets, ' ');
+   }
 
    bool FoundHashSum = false;
    bool FoundStrongHashSum = false;
@@ -624,6 +630,13 @@ bool debReleaseIndex::IsArchitectureSupported(std::string const &arch) const/*{{
    return std::find(d->Architectures.begin(), d->Architectures.end(), arch) != d->Architectures.end();
 }
 									/*}}}*/
+bool debReleaseIndex::IsArchitectureAllSupportedFor(IndexTarget const &target) const/*{{{*/
+{
+   if (d->NoSupportForAll.empty())
+      return true;
+   return std::find(d->NoSupportForAll.begin(), d->NoSupportForAll.end(), target.Option(IndexTarget::CREATED_BY)) == d->NoSupportForAll.end();
+}
+									/*}}}*/
 std::vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()		/*{{{*/
 {
    if (Indexes != NULL)

+ 1 - 0
apt-pkg/deb/debmetaindex.h

@@ -59,6 +59,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex
 
    virtual bool IsTrusted() const APT_OVERRIDE;
    bool IsArchitectureSupported(std::string const &arch) const;
+   bool IsArchitectureAllSupportedFor(IndexTarget const &target) const;
 
    void AddComponent(std::string const &sourcesEntry,
 	 bool const isSrc, std::string const &Name,

+ 8 - 0
apt-pkg/metaindex.cc

@@ -111,3 +111,11 @@ bool metaIndex::IsArchitectureSupported(std::string const &arch) const	/*{{{*/
    return true;
 }
 									/*}}}*/
+bool metaIndex::IsArchitectureAllSupportedFor(IndexTarget const &target) const/*{{{*/
+{
+   debReleaseIndex const * const deb = dynamic_cast<debReleaseIndex const *>(this);
+   if (deb != NULL)
+      return deb->IsArchitectureAllSupportedFor(target);
+   return true;
+}
+									/*}}}*/

+ 1 - 0
apt-pkg/metaindex.h

@@ -110,6 +110,7 @@ public:
 
    // FIXME: make virtual on next abi break
    bool IsArchitectureSupported(std::string const &arch) const;
+   bool IsArchitectureAllSupportedFor(IndexTarget const &target) const;
 };
 
 #endif

+ 40 - 0
test/integration/test-acquire-binary-all

@@ -10,15 +10,26 @@ buildsimplenativepackage 'foo-1' 'all' '2' 'unstable'
 buildsimplenativepackage 'foo-2' 'amd64' '2' 'unstable'
 setupaptarchive --no-update
 
+cat >rootdir/etc/apt/apt.conf.d/get-contents <<EOF
+Acquire::IndexTargets::deb::Contents {
+	MetaKey "\$(COMPONENT)/Contents-\$(ARCHITECTURE)";
+	ShortDescription "Contents";
+	Description "\$(RELEASE)/\$(COMPONENT) \$(ARCHITECTURE) Contents";
+	KeepCompressed "true";
+};
+EOF
+
 msgmsg 'Releasefile with Architectures field and all included'
 testsuccess apt update
 cp rootdir/tmp/testsuccess.output aptupdate.output
 testsuccess grep '^Get.* all Packages ' aptupdate.output
+testsuccess grep '^Get.* all Contents ' aptupdate.output
 testequal 'foo-1
 foo-2' aptcache pkgnames foo-
 
 listcurrentlistsdirectory > lists.before
 testsuccess grep '_binary-all_Packages' lists.before
+testsuccess grep '_Contents-all\.' lists.before
 
 configarchitecture 'amd64' 'i386'
 testsuccessequal "All packages are up to date.
@@ -27,20 +38,35 @@ testfileequal lists.before "$(listcurrentlistsdirectory)"
 testequal 'foo-1
 foo-2' aptcache pkgnames foo-
 
+rm -rf rootdir/var/lib/apt/lists
+msgmsg 'Releasefile has all, but forbids its usage'
+configarchitecture 'amd64'
+sed -i '/^Architectures: / a\
+No-Support-for-Architecture-all: Packages' $(find ./aptarchive -name 'Release')
+signreleasefiles
+testsuccess apt update
+cp rootdir/tmp/testsuccess.output aptupdate.output
+testfailure grep '^Get.* all Packages ' aptupdate.output
+testsuccess grep '^Get.* all Contents ' aptupdate.output
+sed -i '/^No-Support-for-Architecture-all: / d' $(find ./aptarchive -name 'Release')
+
 rm -rf rootdir/var/lib/apt/lists
 msgmsg 'Releasefile with Architectures field but without all'
+configarchitecture 'amd64' 'i386'
 getarchitecturesfromreleasefile() { echo "$(getarchitectures)"; }
 generatereleasefiles
 signreleasefiles
 testsuccessequal 'All packages are up to date.' apt update -o quiet::NoProgress=1
 cp rootdir/tmp/testsuccess.output aptupdate.output
 testfailure grep '^Get.* all Packages ' aptupdate.output
+testfailure grep '^Get.* all Contents ' aptupdate.output
 testequal 'foo-2' aptcache pkgnames foo-
 
 configarchitecture 'amd64'
 testsuccess apt update
 cp rootdir/tmp/testsuccess.output aptupdate.output
 testfailure grep '^Get.* all Packages ' aptupdate.output
+testfailure grep '^Get.* all Contents ' aptupdate.output
 testequal 'foo-2' aptcache pkgnames foo-
 
 rm -rf rootdir/var/lib/apt/lists
@@ -48,9 +74,11 @@ msgmsg 'Releasefile without Architectures field'
 getarchitecturesfromreleasefile() { echo -n ''; }
 generatereleasefiles
 signreleasefiles
+testfailure grep '^Architectures: ' $(find ./aptarchive -name 'Release')
 testsuccess apt update
 cp rootdir/tmp/testsuccess.output aptupdate.output
 testsuccess grep '^Get.* all Packages ' aptupdate.output
+testsuccess grep '^Get.* all Contents ' aptupdate.output
 testequal 'foo-1
 foo-2' aptcache pkgnames foo-
 
@@ -60,6 +88,18 @@ testfailure apt update
 testequal 'foo-1
 foo-2' aptcache pkgnames foo-
 
+rm -rf rootdir/var/lib/apt/lists
+msgmsg 'Releasefile no Architectures all, but forbids its usage'
+configarchitecture 'amd64'
+sed -i '/^Date: / a\
+No-Support-for-Architecture-all: Packages' $(find ./aptarchive -name 'Release')
+signreleasefiles
+testsuccess apt update
+cp rootdir/tmp/testsuccess.output aptupdate.output
+testfailure grep '^Get.* all Packages ' aptupdate.output
+testsuccess grep '^Get.* all Contents ' aptupdate.output
+sed -i '/^No-Support-for-Architecture-all: / d' $(find ./aptarchive -name 'Release')
+
 msgmsg 'No Releasefile'
 rm -rf rootdir/var/lib/apt/lists
 find aptarchive -name '*Release*' -delete