00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <set>
00011 #include <fstream>
00012 #include <boost/function.hpp>
00013
00014 #include <zypp/base/Regex.h>
00015 #include <zypp/base/String.h>
00016 #include "zypp/base/Logger.h"
00017 #include "zypp/base/IOStream.h"
00018 #include "zypp/PoolItem.h"
00019 #include "zypp/CapFactory.h"
00020 #include "zypp/CapMatchHelper.h"
00021 #include "zypp/capability/Capabilities.h"
00022
00023 #undef ZYPP_BASE_LOGGER_LOGGROUP
00024 #define ZYPP_BASE_LOGGER_LOGGROUP "locks"
00025
00026 #include "zypp/Locks.h"
00027 #include "zypp/PathInfo.h"
00028
00029 using namespace std;
00030 using namespace zypp;
00031 using namespace zypp::str;
00032
00033 namespace zypp
00034 {
00035 namespace locks
00036 {
00037
00038
00039
00040
00041
00042
00043
00044 struct NameMatchCollectorFunc
00045 {
00046 set<string> matches;
00047
00048 bool operator()( const PoolItem &item )
00049 {
00050 matches.insert( item.resolvable()->name() );
00051 return true;
00052 }
00053 };
00054
00055
00056
00057 struct Match
00058 {
00059 const regex * _regex;
00060
00061 Match(const regex & regex ) :
00062 _regex(®ex)
00063 {}
00064
00065 bool operator()(const zypp::PoolItem & pi) const
00066 {
00067 return
00068
00069 regex_match(pi.resolvable()->name(), *_regex);
00070 }
00071 };
00072
00073
00074 string
00075 wildcards2regex(const string & str)
00076 {
00077 string regexed;
00078
00079 string all("*");
00080 string one("?");
00081 string r_all(".*");
00082 string r_one(".");
00083
00084
00085 regexed = str::gsub( str, all, r_all );
00086 MIL << "wildcards2regex: " << str << " -> " << regexed;
00087
00088
00089 regexed = str::gsub(regexed, one, r_one);
00090 MIL << " -> " << regexed << endl;
00091
00092 return regexed;
00093 }
00094
00095
00096
00097
00098
00099
00100 struct ItemLockerFunc
00101 {
00102 ItemLockerFunc( const string lock_str )
00103 : _lock_str(lock_str)
00104 {}
00105
00106 bool operator()( const CapAndItem &cai_r )
00107 {
00108 PoolItem_Ref item(cai_r.item);
00109 MIL << "Locking " << cai_r.item << "(matched by " << _lock_str << ")" << endl;
00110 item.status().setLock( true, ResStatus::USER);
00111 return true;
00112 }
00113
00114 string _lock_str;
00115 };
00116
00117 struct AddLockToPool
00118 {
00119 AddLockToPool( const ResPool &pool )
00120 : _pool(pool)
00121 , _count(0)
00122 {
00123
00124 }
00125
00126 bool operator()( const std::string & str_r )
00127 {
00128 CapFactory cap_factory;
00129
00130 std::string line( str::trim( str_r ) );
00131
00132 if ( line.empty() || line[0] == '#')
00133 return true;
00134
00135 MIL << "Applying locks from pattern '" << str_r << "'" << endl;
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 Rel rel;
00146 Edition edition;
00147 string name;
00148
00149 try
00150 {
00151 Capability capability = cap_factory.parse( ResTraits<zypp::Package>::kind, line );
00152
00153 capability::NamedCap::constPtr named = capability::asKind<capability::NamedCap>(capability);
00154 if ( named )
00155 {
00156 rel = named->op();
00157 edition = named->edition();
00158 name = named->index();
00159 }
00160 else
00161 {
00162 ERR << "Not a named capability in: '" << line << "' skipping" << std::endl;
00163 return true;
00164 }
00165 }
00166 catch ( const Exception &e )
00167 {
00168 ERR << "Can't parse capability in: '" << line << "' (" << e.msg() << ") skipping" << std::endl;
00169 return true;
00170 }
00171
00172
00173 if (rel == Rel::NONE) rel = Rel::ANY;
00174
00175 NameMatchCollectorFunc nameMatchFunc;
00176
00177
00178 unsigned int flags = regex::normal;
00179 flags |= regex::icase;
00180 regex reg;
00181
00182
00183 string regstr( wildcards2regex( name ) );
00184 MIL << "regstr '" << regstr << "'" << endl;
00185 try
00186 {
00187 reg.assign( regstr, flags );
00188 }
00189 catch (regex_error & e)
00190 {
00191 ERR << "locks: " << regstr << " is not a valid regular expression: \"" << e.msg() << "\"" << endl;
00192 ERR << "This is a bug, please file a bug report against libzypp" << endl;
00193
00194 return true;;
00195 }
00196
00197 invokeOnEach( _pool.begin(), _pool.end(), Match(reg), functor::functorRef<bool, const PoolItem &>(nameMatchFunc) );
00198
00199 MIL << "Found " << nameMatchFunc.matches.size() << " matches." << endl;
00200
00201
00202
00203
00204
00205 ItemLockerFunc lockItemFunc( line );
00206
00207 for ( set<string>::const_iterator it = nameMatchFunc.matches.begin(); it != nameMatchFunc.matches.end(); ++it )
00208 {
00209 string matched_name = *it;
00210
00211 try
00212 {
00213 Capability capability = cap_factory.parse( ResTraits<zypp::Package>::kind, matched_name, rel, edition );
00214 MIL << "Locking capability " << capability << endl;
00215 forEachMatchIn( _pool, Dep::PROVIDES, capability, functor::functorRef<bool, const CapAndItem &>(lockItemFunc) );
00216 }
00217 catch ( const Exception &e )
00218 {
00219 ERR << "Invalid lock: " << e.msg() << std::endl;
00220 }
00221 ++_count;
00222 }
00223 return true;
00224 }
00225
00226 ResPool _pool;
00227 int _count;
00228 };
00229
00230
00231
00232
00233 int
00234 readLocks(const ResPool & pool, const Pathname &file )
00235 {
00236 PathInfo lockrc( file );
00237 if ( lockrc.isFile() )
00238 {
00239 MIL << "Reading " << lockrc << endl;
00240 ifstream inp( file.c_str() );
00241 AddLockToPool addlock(pool);
00242 iostr::forEachLine( inp, addlock);
00243 MIL << addlock._count << " locks." << endl;
00244 return addlock._count;
00245 }
00246 return 0;
00247 }
00248
00249 }
00250 }