summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2020-01-17 13:18:03 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2020-01-17 13:24:39 +0100
commit450af26202424bef33e0c58f3f99dfd0c21e7297 (patch)
tree633055b6cd785a0211d64767ca90dce50faa6fd9
parent8ebabf3d9026d1a738a4e8988e168902af7446e3 (diff)
policy: Implement pinning by source package
This implements the src: syntax inside policy, allowing you to pin by source package. This by default only pins the native architecuture, use src:pkg:any to pin for all architectures in your cache. Closes: #166032
-rw-r--r--apt-pkg/policy.cc57
-rw-r--r--doc/apt_preferences.5.xml21
2 files changed, 64 insertions, 14 deletions
diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc
index b9bdfd20f..618e17e0b 100644
--- a/apt-pkg/policy.cc
+++ b/apt-pkg/policy.cc
@@ -175,6 +175,11 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name,
return;
}
+ bool IsSourcePin = APT::String::Startswith(Name, "src:");
+ if (IsSourcePin) {
+ Name = Name.substr(sizeof("src:") - 1);
+ }
+
size_t found = Name.rfind(':');
string Arch;
if (found != string::npos) {
@@ -190,10 +195,11 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name,
for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() != true; ++G)
if (Name != G.Name() && match.ExpressionMatches(Name, G.Name()))
{
+ auto NameToPinFor = IsSourcePin ? string("src:").append(G.Name()) : string(G.Name());
if (Arch.empty() == false)
- CreatePin(Type, string(G.Name()).append(":").append(Arch), Data, Priority);
+ CreatePin(Type, NameToPinFor.append(":").append(Arch), Data, Priority);
else
- CreatePin(Type, G.Name(), Data, Priority);
+ CreatePin(Type, NameToPinFor, Data, Priority);
}
return;
}
@@ -209,20 +215,19 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name,
else
MatchingArch = Arch;
APT::CacheFilter::PackageArchitectureMatchesSpecification pams(MatchingArch);
- for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() != true; Pkg = Grp.NextPkg(Pkg))
- {
- if (pams(Pkg.Arch()) == false)
- continue;
-
- PkgPin P(Pkg.FullName());
- P.Type = Type;
- P.Priority = Priority;
- P.Data = Data;
- // Find matching version(s) and copy the pin into it
- pkgVersionMatch Match(P.Data,P.Type);
- for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() != true; ++Ver)
+ if (IsSourcePin) {
+ for (pkgCache::VerIterator Ver = Grp.VersionsInSource(); not Ver.end(); Ver = Ver.NextInSource())
{
+ if (pams(Ver.ParentPkg().Arch()) == false)
+ continue;
+
+ PkgPin P(Ver.ParentPkg().FullName());
+ P.Type = Type;
+ P.Priority = Priority;
+ P.Data = Data;
+ // Find matching version(s) and copy the pin into it
+ pkgVersionMatch Match(P.Data,P.Type);
if (Match.VersionMatches(Ver)) {
Pin *VP = VerPins + Ver->ID;
if (VP->Type == pkgVersionMatch::None) {
@@ -231,6 +236,30 @@ void pkgPolicy::CreatePin(pkgVersionMatch::MatchType Type,string Name,
}
}
}
+ } else {
+ for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() != true; Pkg = Grp.NextPkg(Pkg))
+ {
+ if (pams(Pkg.Arch()) == false)
+ continue;
+
+ PkgPin P(Pkg.FullName());
+ P.Type = Type;
+ P.Priority = Priority;
+ P.Data = Data;
+
+ // Find matching version(s) and copy the pin into it
+ pkgVersionMatch Match(P.Data,P.Type);
+ for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() != true; ++Ver)
+ {
+ if (Match.VersionMatches(Ver)) {
+ Pin *VP = VerPins + Ver->ID;
+ if (VP->Type == pkgVersionMatch::None) {
+ *VP = P;
+ matched = true;
+ }
+ }
+ }
+ }
}
}
diff --git a/doc/apt_preferences.5.xml b/doc/apt_preferences.5.xml
index cac9a96e1..dacf3dc21 100644
--- a/doc/apt_preferences.5.xml
+++ b/doc/apt_preferences.5.xml
@@ -303,7 +303,28 @@ a &glob; expression in itself.
</para>
</refsect2>
+<refsect2><title>Pinning by source package</title>
+<para>APT supports pinning by source packages. To pin by a source package,
+prepend "src:" to the package name.</para>
+<para>For example, to pin all binaries produced by the apt source package
+of this APT's version to 990, you can do:</para>
+<programlisting>
+Package: src:apt
+Pin: version &apt-product-version;
+Pin-Priority: 990
+</programlisting>
+
+<para>Source package pinning can be combined with regular expressions and
+glob patterns, and can also take a binary architecture.</para>
+<para>For example, let's pin all binaries for all architectures produced by
+any source package containing apt in its name to 990:</para>
+<programlisting>
+Package: src:*apt*:any
+Pin: version *
+Pin-Priority: 990
+</programlisting>
+</refsect2>