summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/deb/debmetaindex.cc56
-rw-r--r--apt-pkg/deb/debmetaindex.h15
-rw-r--r--apt-pkg/indexfile.cc7
-rw-r--r--apt-pkg/indexfile.h1
-rw-r--r--apt-pkg/pkgcachegen.cc26
-rw-r--r--apt-pkg/pkgcachegen.h5
-rw-r--r--apt-pkg/sourcelist.cc2
-rw-r--r--doc/sources.list.5.xml9
-rwxr-xr-xtest/integration/test-sourceslist-include-exclude63
9 files changed, 159 insertions, 25 deletions
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index c53b00881..c040b76b9 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -111,6 +111,8 @@ class APT_HIDDEN debReleaseIndexPrivate /*{{{*/
std::vector<std::string> const Languages;
bool const UsePDiffs;
std::string const UseByHash;
+ std::optional<std::vector<std::string>> const include;
+ std::optional<std::vector<std::string>> const exclude;
};
std::vector<debSectionEntry> DebEntries;
@@ -375,6 +377,10 @@ static void GetIndexTargetsFor(char const * const Type, std::string const &URI,
Options.insert(std::make_pair("COMPRESSIONTYPES", CompressionTypes));
Options.insert(std::make_pair("KEEPCOMPRESSEDAS", KeepCompressedAs));
Options.insert(std::make_pair("SOURCESENTRY", E->sourcesEntry));
+ if (auto include = E->include)
+ Options.insert(std::make_pair("INCLUDE", APT::String::Join(*include, " ")));
+ if (auto exclude = E->exclude)
+ Options.insert(std::make_pair("EXCLUDE", APT::String::Join(*exclude, " ")));
bool IsOpt = IsOptional;
{
@@ -425,22 +431,36 @@ std::vector<IndexTarget> debReleaseIndex::GetIndexTargets() const
return IndexTargets;
}
/*}}}*/
-void debReleaseIndex::AddComponent(std::string const &sourcesEntry, /*{{{*/
- bool const isSrc, std::string const &Name,
- std::vector<std::string> const &Targets,
- std::vector<std::string> const &Architectures,
- std::vector<std::string> Languages,
- bool const usePDiffs, std::string const &useByHash)
+bool debReleaseIndex::AddComponent(std::string const &sourcesEntry, /*{{{*/
+ bool const isSrc, std::string const &Name,
+ std::vector<std::string> const &Targets,
+ std::vector<std::string> const &Architectures,
+ std::vector<std::string> Languages,
+ bool const usePDiffs, std::string const &useByHash,
+ std::optional<std::vector<std::string>> const &include,
+ std::optional<std::vector<std::string>> const &exclude)
{
+ if (include && exclude)
+ return _error->Error("Both 'Include' and 'Exclude' specified in %s", sourcesEntry.c_str());
if (Languages.empty() == true)
Languages.push_back("none");
debReleaseIndexPrivate::debSectionEntry const entry = {
- sourcesEntry, Name, Targets, Architectures, Languages, usePDiffs, useByHash
+ sourcesEntry,
+ Name,
+ Targets,
+ Architectures,
+ Languages,
+ usePDiffs,
+ useByHash,
+ include,
+ exclude,
};
if (isSrc)
d->DebSrcEntries.push_back(entry);
else
d->DebEntries.push_back(entry);
+
+ return true;
}
/*}}}*/
std::string debReleaseIndex::ArchiveURI(std::string const &File) const /*{{{*/
@@ -1403,16 +1423,18 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/
}
auto const entry = Options.find("sourceslist-entry");
- Deb->AddComponent(
- entry->second,
- IsSrc,
- Section,
- parsePlusMinusTargetOptions(Name, Options),
- parsePlusMinusArchOptions("arch", Options),
- parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)),
- UsePDiffs,
- UseByHash
- );
+ if (not Deb->AddComponent(
+ entry->second,
+ IsSrc,
+ Section,
+ parsePlusMinusTargetOptions(Name, Options),
+ parsePlusMinusArchOptions("arch", Options),
+ parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)),
+ UsePDiffs,
+ UseByHash,
+ getDefaultSetOf("include", Options),
+ getDefaultSetOf("exclude", Options)))
+ return false;
if (Deb->SetTrusted(GetTriStateOption(Options, "trusted")) == false ||
Deb->SetCheckValidUntil(GetTriStateOption(Options, "check-valid-until")) == false ||
diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h
index 7a6f1fbb4..712b4ec7f 100644
--- a/apt-pkg/deb/debmetaindex.h
+++ b/apt-pkg/deb/debmetaindex.h
@@ -5,6 +5,7 @@
#include <apt-pkg/metaindex.h>
#include <map>
+#include <optional>
#include <string>
#include <vector>
@@ -63,12 +64,14 @@ class APT_HIDDEN debReleaseIndex : public metaIndex
[[nodiscard]] time_t GetNotBefore() const override APT_PURE;
- void AddComponent(std::string const &sourcesEntry,
- bool const isSrc, std::string const &Name,
- std::vector<std::string> const &Targets,
- std::vector<std::string> const &Architectures,
- std::vector<std::string> Languages,
- bool const usePDiffs, std::string const &useByHash);
+ bool AddComponent(std::string const &sourcesEntry,
+ bool const isSrc, std::string const &Name,
+ std::vector<std::string> const &Targets,
+ std::vector<std::string> const &Architectures,
+ std::vector<std::string> Languages,
+ bool const usePDiffs, std::string const &useByHash,
+ std::optional<std::vector<std::string>> const &include,
+ std::optional<std::vector<std::string>> const &exclude);
};
#endif
diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc
index 1176903f4..a6da06029 100644
--- a/apt-pkg/indexfile.cc
+++ b/apt-pkg/indexfile.cc
@@ -324,7 +324,9 @@ pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg)
bool pkgDebianIndexFile::Merge(pkgCacheGenerator &Gen,OpProgress * const Prog)
{
std::string const PackageFile = IndexFileName();
+ const IndexTarget *Target = nullptr;
FileFd Pkg;
+
if (OpenListFile(Pkg, PackageFile) == false)
return false;
_error->PushToStack();
@@ -339,7 +341,10 @@ bool pkgDebianIndexFile::Merge(pkgCacheGenerator &Gen,OpProgress * const Prog)
if (Prog != NULL)
Prog->SubProgress(0, GetProgressDescription());
- if (Gen.SelectFile(PackageFile, *this, GetArchitecture(), GetComponent(), GetIndexFlags()) == false)
+ if (auto tmp = dynamic_cast<pkgDebianIndexTargetFile *>(this))
+ Target = &tmp->Target;
+
+ if (Gen.SelectFile(PackageFile, *this, GetArchitecture(), GetComponent(), Target, GetIndexFlags()) == false)
return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
// Store the IMS information
diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h
index ce57745ea..887e9ff74 100644
--- a/apt-pkg/indexfile.h
+++ b/apt-pkg/indexfile.h
@@ -172,6 +172,7 @@ public:
class APT_PUBLIC pkgDebianIndexTargetFile : public pkgDebianIndexFile
{
+ friend class pkgDebianIndexFile;
void * const d;
protected:
IndexTarget const Target;
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index 7d93db4b4..3358441ee 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -251,6 +251,15 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
if (PackageName.empty() == true)
return false;
+ // Package is excluded
+ if (exclude.find(PackageName) != exclude.end())
+ continue;
+
+ // Includes are specified, this is the total set of packages to include,
+ // so we need to skip the package if it is not in the include list.
+ if (not include.empty() && include.find(PackageName) == include.end())
+ continue;
+
Counter++;
if (Counter % 100 == 0 && Progress != 0)
Progress->Progress(List.Offset());
@@ -1332,6 +1341,7 @@ bool pkgCacheGenerator::SelectFile(std::string const &File,
pkgIndexFile const &Index,
std::string const &Architecture,
std::string const &Component,
+ const IndexTarget *Target,
unsigned long const Flags)
{
CurrentFile = nullptr;
@@ -1374,6 +1384,22 @@ bool pkgCacheGenerator::SelectFile(std::string const &File,
Cache.HeaderP->FileList = map_pointer<pkgCache::PackageFile>{NarrowOffset(CurrentFile - Cache.PkgFileP)};
Cache.HeaderP->PackageFileCount++;
+ include.clear();
+ exclude.clear();
+ if (Target)
+ {
+ if (auto inc = Target->Options.find("INCLUDE"); inc != Target->Options.end())
+ {
+ auto v = VectorizeString(inc->second, ' ');
+ include.insert(v.begin(), v.end());
+ }
+ if (auto exc = Target->Options.find("EXCLUDE"); exc != Target->Options.end())
+ {
+ auto v = VectorizeString(exc->second, ' ');
+ exclude.insert(v.begin(), v.end());
+ }
+ }
+
if (Progress != 0)
Progress->SubProgress(Index.Size());
return true;
diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h
index b67b37559..c481e1b96 100644
--- a/apt-pkg/pkgcachegen.h
+++ b/apt-pkg/pkgcachegen.h
@@ -35,6 +35,7 @@
class FileFd;
class pkgSourceList;
+class IndexTarget;
class OpProgress;
class pkgIndexFile;
class pkgCacheListParser;
@@ -114,6 +115,8 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/
pkgCache::ReleaseFile *CurrentRlsFile;
std::string PkgFileName;
pkgCache::PackageFile *CurrentFile;
+ std::unordered_set<std::string> include;
+ std::unordered_set<std::string> exclude;
bool NewGroup(pkgCache::GrpIterator &Grp, std::string_view Name);
bool NewPackage(pkgCache::PkgIterator &Pkg, std::string_view Name, std::string_view Arch);
@@ -137,7 +140,7 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/
inline map_stringitem_t StoreString(enum StringType const type, std::string_view S) {return StoreString(type, S.data(),S.length());};
void DropProgress() {Progress = 0;};
- bool SelectFile(const std::string &File,pkgIndexFile const &Index, std::string const &Architecture, std::string const &Component, unsigned long Flags = 0);
+ bool SelectFile(const std::string &File, pkgIndexFile const &Index, std::string const &Architecture, std::string const &Component, const IndexTarget *target, unsigned long Flags = 0);
bool SelectReleaseFile(const std::string &File, const std::string &Site, unsigned long Flags = 0);
bool MergeList(ListParser &List,pkgCache::VerIterator *Ver = 0);
inline pkgCache &GetCache() {return Cache;};
diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc
index b744da23a..687ac39ca 100644
--- a/apt-pkg/sourcelist.cc
+++ b/apt-pkg/sourcelist.cc
@@ -125,6 +125,8 @@ bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List, /*{{{*/
mapping.insert(std::make_pair("Signed-By", std::make_pair("signed-by", false)));
mapping.insert(std::make_pair("PDiffs", std::make_pair("pdiffs", false)));
mapping.insert(std::make_pair("By-Hash", std::make_pair("by-hash", false)));
+ mapping.insert(std::make_pair("Include", std::make_pair("include", false)));
+ mapping.insert(std::make_pair("Exclude", std::make_pair("exclude", false)));
for (std::map<char const * const, std::pair<char const * const, bool> >::const_iterator m = mapping.begin(); m != mapping.end(); ++m)
if (Tags.Exists(m->first))
diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml
index 3d0e40bd7..63bede827 100644
--- a/doc/sources.list.5.xml
+++ b/doc/sources.list.5.xml
@@ -219,6 +219,15 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [.
APT versions.
<itemizedlist>
+ <listitem><para><option>Include</option>
+ (<option>include</option>) is a multivalue option defining
+ which packages should be used from this repository. Others are not parsed.
+ </para></listitem>
+ <listitem><para><option>Exclude</option>
+ (<option>exclude</option>) is a multivalue option defining
+ which packages should not be used from this repository. They will not be parsed.
+ This option is mutually exclusive with <option>Include</option>.
+ </para></listitem>
<listitem><para><option>Architectures</option>
(<option>arch</option>) is a multivalue option defining for
which architectures information should be downloaded. If this
diff --git a/test/integration/test-sourceslist-include-exclude b/test/integration/test-sourceslist-include-exclude
new file mode 100755
index 000000000..7188b978f
--- /dev/null
+++ b/test/integration/test-sourceslist-include-exclude
@@ -0,0 +1,63 @@
+#!/bin/sh
+set -e
+
+TESTDIR="$(readlink -f "$(dirname "$0")")"
+. "$TESTDIR/framework"
+
+setupenvironment
+configarchitecture 'i386' 'armel'
+
+insertpackage 'unstable' 'foo' 'all' '1.0'
+insertpackage 'unstable' 'bar' 'all' '1.0'
+insertpackage 'unstable' 'baz' 'all' '1.0'
+
+setupaptarchive
+
+rm rootdir/etc/apt/sources.list.d/apt-test-unstable-deb.list
+
+cat > rootdir/etc/apt/sources.list.d/apt-test-unstable-deb.sources << EOF
+Types: deb
+URIs: file://${TMPWORKINGDIRECTORY}/aptarchive
+Suites: unstable
+Components: main
+Include: foo
+EOF
+
+testsuccess apt update
+testsuccessequal "foo/unstable 1.0 all" apt list -qq
+
+cat > rootdir/etc/apt/sources.list.d/apt-test-unstable-deb.sources << EOF
+Types: deb
+URIs: file://${TMPWORKINGDIRECTORY}/aptarchive
+Suites: unstable
+Components: main
+Exclude: foo bar
+EOF
+
+testsuccess apt update
+testsuccessequal "baz/unstable 1.0 all" apt list -qq
+
+
+cat > rootdir/etc/apt/sources.list.d/apt-test-unstable-deb.sources << EOF
+Types: deb
+URIs: file://${TMPWORKINGDIRECTORY}/aptarchive
+Suites: unstable
+Components: main
+Exclude: foo , baz
+EOF
+
+testsuccess apt update
+testsuccessequal "bar/unstable 1.0 all" apt list -qq
+
+cat > rootdir/etc/apt/sources.list.d/apt-test-unstable-deb.sources << EOF
+Types: deb
+URIs: file://${TMPWORKINGDIRECTORY}/aptarchive
+Suites: unstable
+Components: main
+Include: foo
+Exclude: foo , baz
+EOF
+
+testfailureequal "E: Both 'Include' and 'Exclude' specified in ${TMPWORKINGDIRECTORY}/rootdir/etc/apt/sources.list.d/apt-test-unstable-deb.sources:1
+E: The list of sources could not be read." apt update
+