Imported Upstream version 17.17.0
[platform/upstream/libzypp.git] / tools / zypp-install.cc
1 //
2 // g++ -Wall zypp-install.cc -l zypp -o zypp-install
3 //
4 // A small (and simple) demo which walks through zypp, initializing
5 // and refreshing the repos, selecting packages ('zypper dup'),
6 // resolving dependencies and finally comitting/installing the
7 // result (in dry-run mode).
8 //
9 // No callbacks, questions or fancy output during commit, but it will
10 // do a 'zypper dup' if you'd remove the DryRun and DownloadOnly flag.
11 //
12 // So be careful if running it as root.
13 //
14 #include <iostream>
15
16 #define TEST_DEBUGLOG 0
17
18 #if ( TEST_DEBUGLOG )
19 #include <zypp/base/LogControl.h>
20 #endif
21 #include <zypp/ZYppFactory.h>
22 #include <zypp/RepoManager.h>
23 #include <zypp/ResPool.h>
24
25 using std::cin;
26 using std::cout;
27 using std::cerr;
28 using std::endl;
29 using namespace zypp;
30
31 ////////////////////////////////////////////////////////////////////////////////
32 int main( int argc, char * argv[] )
33 try {
34   --argc;
35   ++argv;
36 #if ( TEST_DEBUGLOG )
37 #warning debug log is on
38   base::LogControl::instance().logfile( "/tmp/zypp-install.log" );
39 #endif
40
41   Pathname sysRoot( "/" );
42   ZYpp::Ptr zypp = getZYpp();           // acquire initial zypp lock
43
44   ////////////////////////////////////////////////////////////////////////////////
45   // init Target:
46   {
47     cout << "Initialize target at " << sysRoot << endl;
48     zypp->initializeTarget( sysRoot );  // initialize target
49     cout << "Loading target resolvables" << endl;
50     zypp->getTarget()->load();          // load installed packages to pool
51   }
52
53   ////////////////////////////////////////////////////////////////////////////////
54   // init Repos:
55   {
56     RepoManager repoManager( sysRoot );
57
58     // sync the current repo set
59     for ( RepoInfo & nrepo : repoManager.knownRepositories() )
60     {
61       if ( ! nrepo.enabled() )
62         continue;
63
64       // Often volatile media are sipped in automated environments
65       // to avoid media chagne requests:
66       if ( nrepo.url().schemeIsVolatile() )
67         continue;
68
69       bool refreshNeeded = false;
70       if ( nrepo.autorefresh() )        // test whether to autorefresh repo metadata
71       {
72         for ( const Url & url : nrepo.baseUrls() )
73         {
74           try
75           {
76             if ( repoManager.checkIfToRefreshMetadata( nrepo, url ) == RepoManager::REFRESH_NEEDED )
77             {
78               cout << "Need to autorefresh repo " << nrepo.alias() << endl;
79               refreshNeeded = true;
80             }
81             break;      // exit after first successful checkIfToRefreshMetadata
82           }
83           catch ( const Exception & exp )
84           {}    // Url failed, try next one...
85         }
86         // If all urls failed we can leave it to the code below to
87         // fail if access is actually needed and still failing.
88         // (missing metadata, package download, ...)
89       }
90
91       // initial metadata download or cache refresh
92       if ( ! repoManager.isCached( nrepo ) || refreshNeeded )
93       {
94         cout << "Refreshing repo " << nrepo << endl;
95         if ( repoManager.isCached( nrepo ) )
96         {
97           repoManager.cleanCache( nrepo );
98         }
99         repoManager.refreshMetadata( nrepo );
100         repoManager.buildCache( nrepo );
101       }
102
103       // load cache
104       try
105       {
106         cout << "Loading resolvables from " << nrepo.alias() << endl;
107         repoManager.loadFromCache( nrepo );// load available packages to pool
108       }
109       catch ( const Exception & exp )
110       {
111         // cachefile has old fomat (or is corrupted): try yo rebuild it
112         repoManager.cleanCache( nrepo );
113         repoManager.buildCache( nrepo );
114         repoManager.loadFromCache( nrepo );
115       }
116     }
117   }
118
119   cout << zypp->pool() << endl;
120   cout << "=====[pool ready]==============================" << endl;
121
122   ////////////////////////////////////////////////////////////////////////////////
123   // GO...
124   ////////////////////////////////////////////////////////////////////////////////
125
126   ////////////////////////////////////////////////////////////////////////////////
127   // Select package to install...
128   // For demo purpose do 'zypper dup'
129   // otherwise select manually whatever you need...
130   zypp->resolver()->doUpgrade();
131
132
133   ////////////////////////////////////////////////////////////////////////////////
134   // solve selection...
135   {
136     cout << "Solving dependencies..." << endl;
137
138     unsigned attempt = 0;
139     while ( ! zypp->resolver()->resolvePool() )
140     {
141       ++attempt;
142       cout << "Solving dependencies: " << attempt << ". attempt failed" << endl;
143       const ResolverProblemList & problems( zypp->resolver()->problems() );
144       cout << problems.size() << " problems found..." << endl;
145       // Problem:
146       // ==============================
147       // kdepim3-3.5.10-29.1.4.x86_64 requires libsasl2.so.2()(64bit), but this requirement
148       // cannot be provided deleted providers: cyrus-sasl-2.1.25-28.1.2.x86_64
149       // ------------------------------
150       // Solution:
151       // keep obsolete cyrus-sasl-2.1.25-28.1.2.x86_64
152       // Solution:
153       // remove lock to allow removal of kdepim3-3.5.10-29.1.4.x86_64
154       // Solution:
155       // remove lock to allow removal of kdepim3-3.5.10-29.1.4.x86_64
156       // Solution:
157       // break kdepim3-3.5.10-29.1.4.x86_64 by ignoring some of its dependencies
158
159       ProblemSolutionList totry;        // only needed if you (interactively) resolve problems...
160
161       unsigned probNo = 0;
162       for ( const auto & probPtr : problems )
163       {
164         cout << "Problem " << ++probNo << ": " << probPtr->description() << endl;
165
166         const ProblemSolutionList & solutions = probPtr->solutions();
167         unsigned solNo = 0;
168         for ( const auto & solPtr : solutions )
169         {
170           cout << "  Solution " << ++solNo << ": " << solPtr->description() << endl;
171         }
172
173         // if you (interactively) resolve problems pick 1 solution per problem
174         // and store it int the totry list. After having applied the selected
175         // start a new attempt.
176         //
177         // It's not necessary to process all problems. You can pick a solution
178         // for the first problem and retry immediately. Often one solution actually
179         // resolves more than one reported problem.
180         //
181         // totry.push_back( solPtr );
182       }
183
184
185       if ( ! totry.empty() )
186       {
187         cout << "Apply selected solutions..." << endl;
188         zypp->resolver()->applySolutions( totry );
189         cout << "Solving dependencies..." << endl;
190         continue;
191       }
192       // otherwise give up
193       throw "Solving dependencies failed: Giving up!";
194     }
195     cout << "Dependencies solved" << endl;
196   }
197
198   ////////////////////////////////////////////////////////////////////////////////
199   // printing some stats...
200   if ( false )
201   {
202     cout << "PoolItem summary (individual packages):" << endl;
203     for ( const PoolItem & pi : zypp->pool() )
204     {
205       if ( pi.status().transacts() )
206         cout << "  " << pi << endl;
207     }
208   }
209   else
210   {
211     cout << "Selectable summary (grouped by name):" << endl;
212     for ( const ui::Selectable_Ptr & sel : zypp->pool().proxy() )
213     {
214       if ( sel->toModify() )
215         cout << "  " << sel << endl;
216     }
217   }
218
219   ////////////////////////////////////////////////////////////////////////////////
220   // finally commit..
221   {
222     cout << "Going to commit..." << endl;
223     // dryRun and DownloadOnly will cause commit to skip
224     // transaction steps, so you want to check for 'noError'
225     // rather than 'allDone'.
226     bool dryRunEtc = false;
227
228     ZYppCommitPolicy policy;
229     if ( true )
230     {
231       policy.dryRun( true );
232       dryRunEtc = true;
233     }
234     if ( true  )
235     {
236       policy.downloadMode( DownloadOnly );
237       dryRunEtc = true;
238     }
239
240     try
241     {
242       ZYppCommitResult result = zypp->commit( policy ); // go....
243       if ( ! ( result.allDone() || ( dryRunEtc && result.noError() ) ) )
244       {
245         throw "Incomplete commit!";
246         // ZYppCommitResult offers access to the TransactionStepList
247         // where you can see which packages have been processed and
248         // which not.
249       }
250       cout << "Commit succeeded" << endl;
251     }
252     catch ( const Exception & exp )
253     {
254       cout << "Commit aborted with exception:" << endl;
255       throw;
256     }
257   }
258   cout << "[bye]: " << endl;
259   return 0;
260 }
261 catch ( const Exception & exp )
262 { cerr << exp << endl << exp.historyAsString(); exit( 91 ); }
263 catch ( const std::exception & exp )
264 { cerr << exp.what() << endl;                   exit( 92 ); }
265 catch ( const char * exp )
266 { cerr << (exp?exp:"Oops!") << endl;            exit( 93 ); }
267 catch (...)
268 { cerr << "Oops!" << endl;                      exit( 94 ); }
269
270