1 #define INCLUDE_TESTSETUP_WITHOUT_BOOST
2 #include "zypp/../tests/lib/TestSetup.h"
3 #undef INCLUDE_TESTSETUP_WITHOUT_BOOST
6 #include <zypp/PoolQuery.h>
7 #include <zypp/ResObjects.h>
8 #include <zypp/ui/SelectableTraits.h>
10 static std::string appname( "NameReqPrv" );
15 int errexit( const std::string & msg_r = std::string(), int exit_r = 100 )
17 if ( ! msg_r.empty() )
19 cerr << endl << msg_r << endl << endl;
24 int usage( const std::string & msg_r = std::string(), int exit_r = 100 )
26 if ( ! msg_r.empty() )
28 cerr << endl << msg_r << endl << endl;
30 cerr << "Usage: " << appname << " [--root ROOTDIR] [OPTIONS] NAME... [[OPTIONS] NAME...]..." << endl;
31 cerr << " Load all enabled repositories (no refresh) and search for" << endl;
32 cerr << " occurrences of NAME (regex or -x) in package names or dependencies" << endl;
33 cerr << " --root Load repos from the system located below ROOTDIR. If ROOTDIR" << endl;
34 cerr << " denotes a sover testcase, the testcase is loaded." << endl;
35 cerr << " --installed Process installed packages only." << endl;
36 cerr << " -i/-I turn on/off case insensitive search (default on)" << endl;
37 cerr << " -n/-N turn on/off looking for names (default on)" << endl;
38 cerr << " -p/-P turn on/off looking for provides (default off)" << endl;
39 cerr << " -r/-R turn on/off looking for requires (default off)" << endl;
40 cerr << " -c/-C turn on/off looking for conflicts (default off)" << endl;
41 cerr << " -o/-O turn on/off looking for obsoletes (default off)" << endl;
42 cerr << " -m/-M turn on/off looking for recommends (default off)" << endl;
43 cerr << " -s/-S turn on/off looking for supplements (default off)" << endl;
44 cerr << " -e/-E turn on/off looking for enhan./sugg.(default off)" << endl;
45 cerr << " -a short for -n -p -r" << endl;
46 cerr << " -A short for -n -P -R" << endl;
47 cerr << " -x do exact matching (glob) rather than regex (substring)" << endl;
48 cerr << " -D <pkg> dump dependencies of <pkg>" << endl;
53 #define COL_R "\033[0;31m"
54 #define COL_G "\033[0;32m"
55 #define COL_B "\033[0;34m"
56 #define COL_C "\033[0;36m"
57 #define COL_M "\033[0;35m"
58 #define COL_Y "\033[0;33m"
59 #define COL_BL "\033[0;30m"
60 #define COL_WH "\033[1;37m"
61 #define COL_OFF "\033[0m"
63 std::string colorId( sat::Solvable solv_r )
65 // return solv_r.asString();
69 static str::Format fmt { COL_B "%s" COL_OFF "-" COL_G "%s" COL_OFF ".%s" };
70 ret = fmt % solv_r.name() % solv_r.edition() % solv_r.arch();
74 ret = ( solv_r.id() == sat::detail::systemSolvableId ? "systemSolvable" : "noSolvable" );
79 void tableOut( const std::string & s1 = std::string(),
80 const std::string & s2 = std::string(),
81 const std::string & s3 = std::string(),
82 const std::string & s4 = std::string(),
83 const std::string & s5 = std::string() )
86 #define TABEL(N) static unsigned w##N = 0; if ( ! s##N.empty() ) w##N = std::max( w##N, unsigned(s##N.size()) ); message << str::form( " %-*s ", w##N, s##N.c_str() )
87 #define TABER(N) static unsigned w##N = 0; if ( ! s##N.empty() ) w##N = std::max( w##N, unsigned(s##N.size()) ); message << str::form( " %*s ", w##N, s##N.c_str() )
88 TABER( 1 ); TABEL( 2 ); TABEL( 3 ); TABEL( 4 ); TABEL( 5 );
96 bool operator()( const PoolQuery::const_iterator & lhs, const PoolQuery::const_iterator & rhs ) const
99 bool l = lhs->isSystem();
100 bool r = rhs->isSystem();
105 std::string l( lhs->ident().asString() );
106 std::string r( rhs->ident().asString() );
110 return avo( PoolItem(*lhs), PoolItem(*rhs) );
111 return lhs->id() > rhs->id();
114 ui::SelectableTraits::AVOrder avo;
117 ///////////////////////////////////////////////////////////////////
119 void dDump( const std::string & spec_r )
121 message << "DUMP " << spec_r << " {";
123 sat::WhatProvides q( Capability::guessPackageSpec( spec_r ) );
126 message << "}" << endl;
130 for ( const auto & el : q )
132 message << endl << "==============================" << endl << dump(el);
133 if ( isKind<Product>(el) )
135 message << endl << "REPLACES: " << make<Product>(el)->replacedProducts();
137 else if ( isKind<Pattern>(el) )
139 message << endl << "CONTENT: " << make<Pattern>(el)->contents();
142 message << endl << "}" << endl;
145 /******************************************************************
147 ** FUNCTION NAME : main
148 ** FUNCTION TYPE : int
150 int main( int argc, char * argv[] )
152 INT << "===[START]==========================================" << endl;
153 appname = Pathname::basename( argv[0] );
161 ///////////////////////////////////////////////////////////////////
164 Pathname sysRoot("/");
165 sat::Pool satpool( sat::Pool::instance() );
167 if ( argc && (*argv) == std::string("--root") )
171 return errexit("--root requires an argument.");
173 if ( ! PathInfo( *argv ).isDir() )
174 return errexit("--root requires a directory.");
180 bool onlyInstalled( false );
181 if ( argc && (*argv) == std::string("--installed") )
184 onlyInstalled = true;
187 if ( TestSetup::isTestcase( sysRoot ) )
189 message << str::form( "*** Load Testcase from '%s'", sysRoot.c_str() ) << endl;
191 test.loadTestcaseRepos( sysRoot );
192 dumpRange( message, satpool.reposBegin(), satpool.reposEnd() ) << endl;
194 else if ( TestSetup::isTestSetup( sysRoot ) )
196 message << str::form( "*** Load TestSetup from '%s'", sysRoot.c_str() ) << endl;
197 const char * astr = getenv( "ZYPP_TESTSUITE_FAKE_ARCH" );
198 if ( !astr || !*astr )
199 astr = getenv( "ZYPP_ARCH" );
200 if ( !astr || !*astr )
202 TestSetup test( sysRoot, Arch( astr ) );
204 dumpRange( message, satpool.reposBegin(), satpool.reposEnd() ) << endl;
209 message << str::form( "*** Load system at '%s'", sysRoot.c_str() ) << endl;
212 message << "*** load target '" << Repository::systemRepoAlias() << "'\t" << endl;
213 getZYpp()->initializeTarget( sysRoot );
214 getZYpp()->target()->load();
215 message << satpool.systemRepo() << endl;
218 if ( !onlyInstalled )
220 RepoManager repoManager( sysRoot );
221 RepoInfoList repos = repoManager.knownRepositories();
222 for_( it, repos.begin(), repos.end() )
224 RepoInfo & nrepo( *it );
226 if ( ! nrepo.enabled() )
229 if ( ! repoManager.isCached( nrepo ) )
231 message << str::form( "*** omit uncached repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl;
235 message << str::form( "*** load repo '%s'\t", nrepo.name().c_str() ) << flush;
238 repoManager.loadFromCache( nrepo );
239 message << satpool.reposFind( nrepo.alias() ) << endl;
241 catch ( const Exception & exp )
243 message << exp.asString() + "\n" + exp.historyAsString() << endl;
244 message << str::form( "*** omit broken repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl;
251 ///////////////////////////////////////////////////////////////////
253 bool ignorecase ( true );
254 bool matechexact ( false );
255 bool withSrcPackages ( false );
257 bool provides ( false );
258 bool requires ( false );
259 bool conflicts ( false );
260 bool obsoletes ( false );
261 bool recommends ( false );
262 bool supplements ( false );
263 bool enhacements ( false );
266 for ( ; argc; --argc,++argv )
268 if ( (*argv)[0] == '-' )
270 for ( const char * arg = (*argv)+1; *arg != '\0'; ++arg ) // -pr for -p -r
274 case 'a': names = true, requires = provides = true; break;
275 case 'A': names = true, requires = provides = false; break;
283 return errexit("-D <pkgspec> requires an argument.");
285 case 'i': ignorecase = true; break;
286 case 'I': ignorecase = false; break;
287 case 'x': matechexact = true; break;
288 case 'n': names = true; break;
289 case 'N': names = false; break;
290 case 'r': requires = true; break;
291 case 'R': requires = false; break;
292 case 'p': provides = true; break;
293 case 'P': provides = false; break;
294 case 'c': conflicts = true; break;
295 case 'C': conflicts = false; break;
296 case 'o': obsoletes = true; break;
297 case 'O': obsoletes = false; break;
298 case 'm': recommends = true; break;
299 case 'M': recommends = false; break;
300 case 's': supplements = true; break;
301 case 'S': supplements = false; break;
302 case 'e': enhacements = true; break;
303 case 'E': enhacements = false; break;
311 q.setInstalledOnly();
312 std::string qstr( *argv );
314 if ( *argv == ResKind::product )
316 q.addKind( ResKind::product );
318 else if ( *argv == ResKind::patch )
320 q.addKind( ResKind::patch );
322 else if ( *argv == ResKind::pattern )
324 q.addKind( ResKind::pattern );
328 sat::Solvable::SplitIdent ident( qstr );
329 if ( ident.kind() != ResKind::package )
331 q.addKind( ident.kind() );
332 q.addString( ident.name().asString() );
341 q.setCaseSensitive( ! ignorecase );
344 q.addAttribute( sat::SolvAttr::name );
347 q.addDependency( sat::SolvAttr::provides );
348 q.addDependency( sat::SolvAttr::provides, Capability(qstr) );
352 q.addDependency( sat::SolvAttr::requires );
353 q.addDependency( sat::SolvAttr::requires, Capability(qstr) );
357 q.addDependency( sat::SolvAttr::conflicts );
358 q.addDependency( sat::SolvAttr::conflicts, Capability(qstr) );
362 q.addDependency( sat::SolvAttr::obsoletes );
363 q.addDependency( sat::SolvAttr::obsoletes, Capability(qstr) );
367 q.addDependency( sat::SolvAttr::recommends );
368 q.addDependency( sat::SolvAttr::recommends, Capability(qstr) );
372 q.addDependency( sat::SolvAttr::supplements );
373 q.addDependency( sat::SolvAttr::supplements, Capability(qstr) );
377 q.addDependency( sat::SolvAttr::enhances );
378 q.addDependency( sat::SolvAttr::enhances, Capability(qstr) );
379 q.addDependency( sat::SolvAttr::suggests );
380 q.addDependency( sat::SolvAttr::suggests, Capability(qstr) );
384 message << *argv << " [" << (ignorecase?'i':'_') << (names?'n':'_') << (requires?'r':'_') << (provides?'p':'_')
385 << (conflicts?'c':'_') << (obsoletes?'o':'_') << (recommends?'m':'_') << (supplements?'s':'_') << (enhacements?'e':'_')
388 std::set<PoolQuery::const_iterator,PQSort> qsorted;
389 for_( it, q.begin(), q.end() )
390 qsorted.insert( it );
392 for ( auto && it : qsorted )
394 if ( it->isKind( ResKind::srcpackage ) && !withSrcPackages )
397 tableOut( str::numstring( it->id() ), colorId(*it),
398 str::form( "(%d)%s", it->repository().info().priority(), it->repository().name().c_str() ),
399 str::numstring( PoolItem(*it)->buildtime() ) );
401 it->vendor().asString() );
402 if ( ! it.matchesEmpty() )
404 for_( match, it.matchesBegin(), it.matchesEnd() )
406 tableOut( "", "", match->inSolvAttr().asString().substr( 9, 3 )+": " +match->asString() );
411 message << "}" << endl;
414 INT << "===[END]============================================" << endl << endl;