Imported Upstream version 16.7.0
[platform/upstream/libzypp.git] / tools / zypp-NameReqPrv.cc
1 #define INCLUDE_TESTSETUP_WITHOUT_BOOST
2 #include "zypp/../tests/lib/TestSetup.h"
3 #undef  INCLUDE_TESTSETUP_WITHOUT_BOOST
4
5 #include <algorithm>
6 #include <zypp/PoolQuery.h>
7 #include <zypp/ResObjects.h>
8
9 static std::string appname( "NameReqPrv" );
10
11 #define message cout
12 using std::flush;
13
14 int errexit( const std::string & msg_r = std::string(), int exit_r = 100 )
15 {
16   if ( ! msg_r.empty() )
17   {
18     cerr << endl << msg_r << endl << endl;
19   }
20   return exit_r;
21 }
22
23 int usage( const std::string & msg_r = std::string(), int exit_r = 100 )
24 {
25   if ( ! msg_r.empty() )
26   {
27     cerr << endl << msg_r << endl << endl;
28   }
29   cerr << "Usage: " << appname << " [--root ROOTDIR] [OPTIONS] NAME... [[OPTIONS] NAME...]..." << endl;
30   cerr << "  Load all enabled repositories (no refresh) and search for" << endl;
31   cerr << "  occurrences of NAME (regex or -x) in package names or dependencies" << endl;
32   cerr << "  --root   Load repos from the system located below ROOTDIR. If ROOTDIR" << endl;
33   cerr << "           denotes a sover testcase, the testcase is loaded." << endl;
34   cerr << "  --installed Process installed packages only." << endl;
35   cerr << "  -i/-I    turn on/off case insensitive search (default on)" << endl;
36   cerr << "  -n/-N    turn on/off looking for names       (default on)" << endl;
37   cerr << "  -p/-P    turn on/off looking for provides    (default off)" << endl;
38   cerr << "  -r/-R    turn on/off looking for requires    (default off)" << endl;
39   cerr << "  -c/-C    turn on/off looking for conflicts   (default off)" << endl;
40   cerr << "  -o/-O    turn on/off looking for obsoletes   (default off)" << endl;
41   cerr << "  -m/-M    turn on/off looking for recommends  (default off)" << endl;
42   cerr << "  -s/-S    turn on/off looking for supplements (default off)" << endl;
43   cerr << "  -e/-E    turn on/off looking for enhan./sugg.(default off)" << endl;
44   cerr << "  -a       short for -n -p -r" << endl;
45   cerr << "  -A       short for -n -P -R" << endl;
46   cerr << "  -x       do exact matching (glob) rather than regex (substring)" << endl;
47   cerr << "  -D <pkg> dump dependencies of <pkg>" << endl;
48   cerr << "" << endl;
49   return exit_r;
50 }
51
52 void tableOut( const std::string & s1 = std::string(),
53                const std::string & s2 = std::string(),
54                const std::string & s3 = std::string(),
55                const std::string & s4 = std::string(),
56                const std::string & s5 = std::string() )
57 {
58   message << "  ";
59 #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() )
60 #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() )
61   TABER( 1 ); TABEL( 2 ); TABEL( 3 ); TABEL( 4 ); TABEL( 5 );
62 #undef TABEL
63   message << endl;
64 }
65
66
67 ///////////////////////////////////////////////////////////////////
68
69 void dDump( const std::string & spec_r )
70 {
71   message << "DUMP " << spec_r << " {";
72
73   sat::WhatProvides q( Capability::guessPackageSpec( spec_r ) );
74   if ( q.empty() )
75   {
76     message << "}" << endl;
77     return;
78   }
79
80   for ( const auto & el : q )
81   {
82     message << endl << "==============================" << endl << dump(el);
83     if ( isKind<Product>(el) )
84     {
85       message << endl << "REPLACES: " << make<Product>(el)->replacedProducts();
86     }
87     else if ( isKind<Pattern>(el) )
88     {
89       message << endl << "CONTENT: " << make<Pattern>(el)->contents();
90     }
91   }
92   message << endl << "}" << endl;
93 }
94
95 /******************************************************************
96 **
97 **      FUNCTION NAME : main
98 **      FUNCTION TYPE : int
99 */
100 int main( int argc, char * argv[] )
101 {
102   INT << "===[START]==========================================" << endl;
103   appname = Pathname::basename( argv[0] );
104   --argc,++argv;
105
106   if ( ! argc )
107   {
108     return usage();
109   }
110
111   ///////////////////////////////////////////////////////////////////
112
113   ZConfig::instance();
114   Pathname sysRoot("/");
115   sat::Pool satpool( sat::Pool::instance() );
116
117   if ( argc && (*argv) == std::string("--root") )
118   {
119     --argc,++argv;
120     if ( ! argc )
121       return errexit("--root requires an argument.");
122
123     if ( ! PathInfo( *argv ).isDir() )
124       return errexit("--root requires a directory.");
125
126     sysRoot = *argv;
127     --argc,++argv;
128   }
129
130   bool onlyInstalled( false );
131   if ( argc && (*argv) == std::string("--installed") )
132   {
133     --argc,++argv;
134     onlyInstalled = true;
135   }
136
137   if ( TestSetup::isTestcase( sysRoot ) )
138   {
139     message << str::form( "*** Load Testcase from '%s'", sysRoot.c_str() ) << endl;
140     TestSetup test;
141     test.loadTestcaseRepos( sysRoot );
142     dumpRange( message, satpool.reposBegin(), satpool.reposEnd() ) << endl;
143   }
144   else if ( TestSetup::isTestSetup( sysRoot ) )
145   {
146     message << str::form( "*** Load TestSetup from '%s'", sysRoot.c_str() ) << endl;
147     const char * astr = getenv( "ZYPP_TESTSUITE_FAKE_ARCH" );
148     if ( !astr || !*astr )
149       astr = getenv( "ZYPP_ARCH" );
150     if ( !astr || !*astr )
151       astr = "x86_64";
152     TestSetup test( sysRoot, Arch( astr ) );
153     test.loadRepos();
154     dumpRange( message, satpool.reposBegin(), satpool.reposEnd() ) << endl;
155   }
156   else
157   {
158     // a system
159     message << str::form( "*** Load system at '%s'", sysRoot.c_str() ) << endl;
160     if ( true )
161     {
162       message << "*** load target '" << Repository::systemRepoAlias() << "'\t" << endl;
163       getZYpp()->initializeTarget( sysRoot );
164       getZYpp()->target()->load();
165       message << satpool.systemRepo() << endl;
166     }
167
168     if ( !onlyInstalled )
169     {
170       RepoManager repoManager( sysRoot );
171       RepoInfoList repos = repoManager.knownRepositories();
172       for_( it, repos.begin(), repos.end() )
173       {
174         RepoInfo & nrepo( *it );
175
176         if ( ! nrepo.enabled() )
177           continue;
178
179         if ( ! repoManager.isCached( nrepo ) )
180         {
181           message << str::form( "*** omit uncached repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl;
182           continue;
183         }
184
185         message << str::form( "*** load repo '%s'\t", nrepo.name().c_str() ) << flush;
186         try
187         {
188           repoManager.loadFromCache( nrepo );
189           message << satpool.reposFind( nrepo.alias() ) << endl;
190         }
191         catch ( const Exception & exp )
192         {
193           message << exp.asString() + "\n" + exp.historyAsString() << endl;
194           message << str::form( "*** omit broken repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl;
195           continue;
196         }
197       }
198     }
199   }
200
201   ///////////////////////////////////////////////////////////////////
202
203   bool ignorecase       ( true );
204   bool matechexact      ( false );
205   bool names            ( true );
206   bool provides         ( false );
207   bool requires         ( false );
208   bool conflicts        ( false );
209   bool obsoletes        ( false );
210   bool recommends       ( false );
211   bool supplements      ( false );
212   bool enhacements      ( false );
213
214
215   for ( ; argc; --argc,++argv )
216   {
217     if ( (*argv)[0] == '-' )
218     {
219       switch ( (*argv)[1] )
220       {
221         case 'a': names =       true,   requires = provides =   true;   break;
222         case 'A': names =       true,   requires = provides =   false;  break;
223         case 'D':
224           if ( argc > 1 )
225           {
226             --argc,++argv;
227             dDump( *argv );
228           }
229           else
230             return errexit("-D <pkgspec> requires an argument.");
231           break;
232         case 'i': ignorecase =  true;   break;
233         case 'I': ignorecase =  false;  break;
234         case 'x': matechexact = true;   break;
235         case 'n': names =       true;   break;
236         case 'N': names =       false;  break;
237         case 'r': requires =    true;   break;
238         case 'R': requires =    false;  break;
239         case 'p': provides =    true;   break;
240         case 'P': provides =    false;  break;
241         case 'c': conflicts =   true;   break;
242         case 'C': conflicts =   false;  break;
243         case 'o': obsoletes =   true;   break;
244         case 'O': obsoletes =   false;  break;
245         case 'm': recommends =  true;   break;
246         case 'M': recommends =  false;  break;
247         case 's': supplements = true;   break;
248         case 'S': supplements = false;  break;
249         case 'e': enhacements = true;   break;
250         case 'E': enhacements = false;  break;
251       }
252       continue;
253     }
254
255     PoolQuery q;
256     if ( onlyInstalled )
257       q.setInstalledOnly();
258     std::string qstr( *argv );
259
260     if ( *argv == ResKind::product )
261     {
262       q.addKind( ResKind::product );
263     }
264     else if ( *argv == ResKind::patch )
265     {
266       q.addKind( ResKind::patch );
267     }
268     else if ( *argv == ResKind::pattern )
269     {
270       q.addKind( ResKind::pattern );
271     }
272     else
273     {
274       sat::Solvable::SplitIdent ident( qstr );
275       if ( ident.kind() != ResKind::package )
276       {
277         q.addKind( ident.kind() );
278         q.addString( ident.name().asString() );
279       }
280       else
281         q.addString( qstr );
282
283       if ( matechexact )
284         q.setMatchGlob();
285       else
286         q.setMatchRegex();
287       q.setCaseSensitive( ! ignorecase );
288
289       if ( names )
290         q.addAttribute( sat::SolvAttr::name );
291       if ( provides )
292         q.addDependency( sat::SolvAttr::provides );
293       if ( requires )
294         q.addDependency( sat::SolvAttr::requires );
295       if ( conflicts )
296         q.addDependency( sat::SolvAttr::conflicts );
297       if ( obsoletes )
298         q.addDependency( sat::SolvAttr::obsoletes );
299       if ( recommends )
300         q.addDependency( sat::SolvAttr::recommends );
301       if ( supplements )
302         q.addDependency( sat::SolvAttr::supplements );
303       if ( enhacements )
304       {
305         q.addDependency( sat::SolvAttr::enhances );
306         q.addDependency( sat::SolvAttr::suggests );
307       }
308     }
309
310     message << *argv << " [" << (ignorecase?'i':'_') << (names?'n':'_') << (requires?'r':'_') << (provides?'p':'_')
311     << (conflicts?'c':'_') << (obsoletes?'o':'_') << (recommends?'m':'_') << (supplements?'s':'_') << (enhacements?'e':'_')
312     << "] {" << endl;
313
314     for_( it, q.begin(), q.end() )
315     {
316       tableOut( str::numstring( it->id() ), it->asString(),
317                 str::form( "(%d)%s", it->repository().info().priority(), it->repository().name().c_str() ),
318                 str::numstring( PoolItem(*it)->buildtime() ) );
319       tableOut( "", "",
320                 it->vendor().asString() );
321       if ( ! it.matchesEmpty() )
322       {
323         for_( match, it.matchesBegin(), it.matchesEnd() )
324         {
325           tableOut( "", "", match->inSolvAttr().asString().substr( 9, 3 )+": " +match->asString() );
326         }
327       }
328     }
329
330     message << "}" << endl;
331   }
332
333   INT << "===[END]============================================" << endl << endl;
334   return 0;
335 }