From 450af26202424bef33e0c58f3f99dfd0c21e7297 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 17 Jan 2020 13:18:03 +0100 Subject: 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 --- apt-pkg/policy.cc | 57 +++++++++++++++++++++++++++++++++++------------ doc/apt_preferences.5.xml | 21 +++++++++++++++++ 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. +Pinning by source package +APT supports pinning by source packages. To pin by a source package, +prepend "src:" to the package name. +For example, to pin all binaries produced by the apt source package +of this APT's version to 990, you can do: + +Package: src:apt +Pin: version &apt-product-version; +Pin-Priority: 990 + + +Source package pinning can be combined with regular expressions and +glob patterns, and can also take a binary architecture. +For example, let's pin all binaries for all architectures produced by +any source package containing apt in its name to 990: + +Package: src:*apt*:any +Pin: version * +Pin-Priority: 990 + + -- cgit v1.2.3