Bug#121132: [patch] Proposed regex pinning feature
Hi
The attached patch adds a very basic and crufty extension to apt policy
such that pinnings can use regex matching. If the name given on the
"Package:" line in the apt preference file begins and ends with '/', it
is interpreted as a regular expression (with ^ and $ pre- and post-fixed
for a semblance of safety).
So you can write, for example:
Package: /.*openoffice\.org.*/
Pin: release a=unstable
Pin-Priority: 900
and get approximately the behaviour you might expect.
This is potentially dangerous, potentially expensive, and not the glob
feature more intuitively suggested by the original reporter of bug
#121132. There is no error reporting and no documentation. And it's
been written by someone with no prior knowledge of the apt internals,
and who does not speak C++.
If people are interested, I'll try to find time to fix some of those
issues ;-)
As it stands this applies to the Lenny and the Experimental source.
Tested only briefly, only on Lenny/amd64.
Cheers
Duncan
--
Duncan Gibb - Technical Director
Sirius Corporation plc - control through freedom
http://www.siriusit.co.uk/ || t: +44 870 608 0063
diff -rub apt-0.7.20.2/apt-pkg/policy.cc apt-0.7.20.2/apt-pkg/policy.cc
--- apt-0.7.20.2/apt-pkg/policy.cc 2009-02-07 15:09:35.000000000 +0000
+++ apt-0.7.20.2/apt-pkg/policy.cc 2009-03-28 17:08:34.000000000 +0000
@@ -34,6 +34,7 @@
#include <iostream>
#include <sstream>
+#include <regex.h>
/*}}}*/
using namespace std;
@@ -181,8 +182,14 @@
Pin *P = 0;
if (Name.empty() == true)
+ {
P = &*Defaults.insert(Defaults.end(),PkgPin());
- else
+ // Set..
+ P->Type = Type;
+ P->Priority = Priority;
+ P->Data = Data;
+ }
+ else if (Name[0] != '/')
{
// Get a spot to put the pin
pkgCache::PkgIterator Pkg = Cache->FindPkg(Name);
@@ -201,12 +208,34 @@
{
P = Pins + Pkg->ID;
}
+ // Set..
+ P->Type = Type;
+ P->Priority = Priority;
+ P->Data = Data;
}
+ else // Do a regex pin
+ {
+ if (Name[(Name.length()-1)] != '/')
+ return; // Regex pins must begin and end with '/'.
- // Set..
+ regex_t Pattern;
+ string mypat = "^" + Name.substr(1,(Name.length()-2)) + "$";
+ if (regcomp(&Pattern, mypat.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
+ return; // Regex does not compile.
+
+ for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); !Pkg.end(); ++Pkg)
+ {
+ if (regexec(&Pattern,Pkg.Name(),0,0,0) == 0)
+ {
+ P = Pins + Pkg->ID;
P->Type = Type;
P->Priority = Priority;
P->Data = Data;
+ }
+ } // end package iteration loop
+
+ regfree(&Pattern);
+ }
}
/*}}}*/
// Policy::GetMatch - Get the matching version for a package pin /*{{{*/
Reply to: