[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: