libzypp  16.20.4
TargetImpl.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <fstream>
14 #include <sstream>
15 #include <string>
16 #include <list>
17 #include <set>
18 
19 #include <sys/types.h>
20 #include <dirent.h>
21 
22 #include "zypp/base/LogTools.h"
23 #include "zypp/base/Exception.h"
24 #include "zypp/base/Iterator.h"
25 #include "zypp/base/Gettext.h"
26 #include "zypp/base/IOStream.h"
27 #include "zypp/base/Functional.h"
29 #include "zypp/base/Json.h"
30 
31 #include "zypp/ZConfig.h"
32 #include "zypp/ZYppFactory.h"
33 
34 #include "zypp/PoolItem.h"
35 #include "zypp/ResObjects.h"
36 #include "zypp/Url.h"
37 #include "zypp/TmpPath.h"
38 #include "zypp/RepoStatus.h"
39 #include "zypp/ExternalProgram.h"
40 #include "zypp/Repository.h"
41 
42 #include "zypp/ResFilters.h"
43 #include "zypp/HistoryLog.h"
44 #include "zypp/target/TargetImpl.h"
49 
52 
53 #include "zypp/sat/Pool.h"
55 #include "zypp/sat/Transaction.h"
56 
57 #include "zypp/PluginExecutor.h"
58 
59 using namespace std;
60 
62 namespace zypp
63 {
65  namespace
66  {
67  // HACK for bnc#906096: let pool re-evaluate multiversion spec
68  // if target root changes. ZConfig returns data sensitive to
69  // current target root.
70  inline void sigMultiversionSpecChanged()
71  {
72  sat::detail::PoolMember::myPool().multiversionSpecChanged();
73  }
74  } //namespace
76 
78  namespace json
79  {
80  // Lazy via template specialisation / should switch to overloading
81 
82  template<>
83  inline std::string toJSON( const ZYppCommitResult::TransactionStepList & steps_r )
84  {
85  using sat::Transaction;
86  json::Array ret;
87 
88  for ( const Transaction::Step & step : steps_r )
89  // ignore implicit deletes due to obsoletes and non-package actions
90  if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
91  ret.add( step );
92 
93  return ret.asJSON();
94  }
95 
97  template<>
98  inline std::string toJSON( const sat::Transaction::Step & step_r )
99  {
100  static const std::string strType( "type" );
101  static const std::string strStage( "stage" );
102  static const std::string strSolvable( "solvable" );
103 
104  static const std::string strTypeDel( "-" );
105  static const std::string strTypeIns( "+" );
106  static const std::string strTypeMul( "M" );
107 
108  static const std::string strStageDone( "ok" );
109  static const std::string strStageFailed( "err" );
110 
111  static const std::string strSolvableN( "n" );
112  static const std::string strSolvableE( "e" );
113  static const std::string strSolvableV( "v" );
114  static const std::string strSolvableR( "r" );
115  static const std::string strSolvableA( "a" );
116 
117  using sat::Transaction;
118  json::Object ret;
119 
120  switch ( step_r.stepType() )
121  {
122  case Transaction::TRANSACTION_IGNORE: /*empty*/ break;
123  case Transaction::TRANSACTION_ERASE: ret.add( strType, strTypeDel ); break;
124  case Transaction::TRANSACTION_INSTALL: ret.add( strType, strTypeIns ); break;
125  case Transaction::TRANSACTION_MULTIINSTALL: ret.add( strType, strTypeMul ); break;
126  }
127 
128  switch ( step_r.stepStage() )
129  {
130  case Transaction::STEP_TODO: /*empty*/ break;
131  case Transaction::STEP_DONE: ret.add( strStage, strStageDone ); break;
132  case Transaction::STEP_ERROR: ret.add( strStage, strStageFailed ); break;
133  }
134 
135  {
136  IdString ident;
137  Edition ed;
138  Arch arch;
139  if ( sat::Solvable solv = step_r.satSolvable() )
140  {
141  ident = solv.ident();
142  ed = solv.edition();
143  arch = solv.arch();
144  }
145  else
146  {
147  // deleted package; post mortem data stored in Transaction::Step
148  ident = step_r.ident();
149  ed = step_r.edition();
150  arch = step_r.arch();
151  }
152 
153  json::Object s {
154  { strSolvableN, ident.asString() },
155  { strSolvableV, ed.version() },
156  { strSolvableR, ed.release() },
157  { strSolvableA, arch.asString() }
158  };
159  if ( Edition::epoch_t epoch = ed.epoch() )
160  s.add( strSolvableE, epoch );
161 
162  ret.add( strSolvable, s );
163  }
164 
165  return ret.asJSON();
166  }
167  } // namespace json
169 
171  namespace target
172  {
174  namespace
175  {
176  SolvIdentFile::Data getUserInstalledFromHistory( const Pathname & historyFile_r )
177  {
178  SolvIdentFile::Data onSystemByUserList;
179  // go and parse it: 'who' must constain an '@', then it was installed by user request.
180  // 2009-09-29 07:25:19|install|lirc-remotes|0.8.5-3.2|x86_64|root@opensuse|InstallationImage|a204211eb0...
181  std::ifstream infile( historyFile_r.c_str() );
182  for( iostr::EachLine in( infile ); in; in.next() )
183  {
184  const char * ch( (*in).c_str() );
185  // start with year
186  if ( *ch < '1' || '9' < *ch )
187  continue;
188  const char * sep1 = ::strchr( ch, '|' ); // | after date
189  if ( !sep1 )
190  continue;
191  ++sep1;
192  // if logs an install or delete
193  bool installs = true;
194  if ( ::strncmp( sep1, "install|", 8 ) )
195  {
196  if ( ::strncmp( sep1, "remove |", 8 ) )
197  continue; // no install and no remove
198  else
199  installs = false; // remove
200  }
201  sep1 += 8; // | after what
202  // get the package name
203  const char * sep2 = ::strchr( sep1, '|' ); // | after name
204  if ( !sep2 || sep1 == sep2 )
205  continue;
206  (*in)[sep2-ch] = '\0';
207  IdString pkg( sep1 );
208  // we're done, if a delete
209  if ( !installs )
210  {
211  onSystemByUserList.erase( pkg );
212  continue;
213  }
214  // now guess whether user installed or not (3rd next field contains 'user@host')
215  if ( (sep1 = ::strchr( sep2+1, '|' )) // | after version
216  && (sep1 = ::strchr( sep1+1, '|' )) // | after arch
217  && (sep2 = ::strchr( sep1+1, '|' )) ) // | after who
218  {
219  (*in)[sep2-ch] = '\0';
220  if ( ::strchr( sep1+1, '@' ) )
221  {
222  // by user
223  onSystemByUserList.insert( pkg );
224  continue;
225  }
226  }
227  }
228  MIL << "onSystemByUserList found: " << onSystemByUserList.size() << endl;
229  return onSystemByUserList;
230  }
231  } // namespace
233 
235  namespace
236  {
237  inline PluginFrame transactionPluginFrame( const std::string & command_r, ZYppCommitResult::TransactionStepList & steps_r )
238  {
239  return PluginFrame( command_r, json::Object {
240  { "TransactionStepList", steps_r }
241  }.asJSON() );
242  }
243  } // namespace
245 
248  {
249  unsigned toKeep( ZConfig::instance().solver_upgradeTestcasesToKeep() );
250  MIL << "Testcases to keep: " << toKeep << endl;
251  if ( !toKeep )
252  return;
253  Target_Ptr target( getZYpp()->getTarget() );
254  if ( ! target )
255  {
256  WAR << "No Target no Testcase!" << endl;
257  return;
258  }
259 
260  std::string stem( "updateTestcase" );
261  Pathname dir( target->assertRootPrefix("/var/log/") );
262  Pathname next( dir / Date::now().form( stem+"-%Y-%m-%d-%H-%M-%S" ) );
263 
264  {
265  std::list<std::string> content;
266  filesystem::readdir( content, dir, /*dots*/false );
267  std::set<std::string> cases;
268  for_( c, content.begin(), content.end() )
269  {
270  if ( str::startsWith( *c, stem ) )
271  cases.insert( *c );
272  }
273  if ( cases.size() >= toKeep )
274  {
275  unsigned toDel = cases.size() - toKeep + 1; // +1 for the new one
276  for_( c, cases.begin(), cases.end() )
277  {
278  filesystem::recursive_rmdir( dir/(*c) );
279  if ( ! --toDel )
280  break;
281  }
282  }
283  }
284 
285  MIL << "Write new testcase " << next << endl;
286  getZYpp()->resolver()->createSolverTestcase( next.asString(), false/*no solving*/ );
287  }
288 
290  namespace
291  {
292 
303  std::pair<bool,PatchScriptReport::Action> doExecuteScript( const Pathname & root_r,
304  const Pathname & script_r,
306  {
307  MIL << "Execute script " << PathInfo(Pathname::assertprefix( root_r,script_r)) << endl;
308 
309  HistoryLog historylog;
310  historylog.comment(script_r.asString() + _(" executed"), /*timestamp*/true);
311  ExternalProgram prog( script_r.asString(), ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r );
312 
313  for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
314  {
315  historylog.comment(output);
316  if ( ! report_r->progress( PatchScriptReport::OUTPUT, output ) )
317  {
318  WAR << "User request to abort script " << script_r << endl;
319  prog.kill();
320  // the rest is handled by exit code evaluation
321  // in case the script has meanwhile finished.
322  }
323  }
324 
325  std::pair<bool,PatchScriptReport::Action> ret( std::make_pair( false, PatchScriptReport::ABORT ) );
326 
327  if ( prog.close() != 0 )
328  {
329  ret.second = report_r->problem( prog.execError() );
330  WAR << "ACTION" << ret.second << "(" << prog.execError() << ")" << endl;
331  std::ostringstream sstr;
332  sstr << script_r << _(" execution failed") << " (" << prog.execError() << ")" << endl;
333  historylog.comment(sstr.str(), /*timestamp*/true);
334  return ret;
335  }
336 
337  report_r->finish();
338  ret.first = true;
339  return ret;
340  }
341 
345  bool executeScript( const Pathname & root_r,
346  const Pathname & script_r,
347  callback::SendReport<PatchScriptReport> & report_r )
348  {
349  std::pair<bool,PatchScriptReport::Action> action( std::make_pair( false, PatchScriptReport::ABORT ) );
350 
351  do {
352  action = doExecuteScript( root_r, script_r, report_r );
353  if ( action.first )
354  return true; // success
355 
356  switch ( action.second )
357  {
358  case PatchScriptReport::ABORT:
359  WAR << "User request to abort at script " << script_r << endl;
360  return false; // requested abort.
361  break;
362 
363  case PatchScriptReport::IGNORE:
364  WAR << "User request to skip script " << script_r << endl;
365  return true; // requested skip.
366  break;
367 
368  case PatchScriptReport::RETRY:
369  break; // again
370  }
371  } while ( action.second == PatchScriptReport::RETRY );
372 
373  // THIS is not intended to be reached:
374  INT << "Abort on unknown ACTION request " << action.second << " returned" << endl;
375  return false; // abort.
376  }
377 
383  bool RunUpdateScripts( const Pathname & root_r,
384  const Pathname & scriptsPath_r,
385  const std::vector<sat::Solvable> & checkPackages_r,
386  bool aborting_r )
387  {
388  if ( checkPackages_r.empty() )
389  return true; // no installed packages to check
390 
391  MIL << "Looking for new update scripts in (" << root_r << ")" << scriptsPath_r << endl;
392  Pathname scriptsDir( Pathname::assertprefix( root_r, scriptsPath_r ) );
393  if ( ! PathInfo( scriptsDir ).isDir() )
394  return true; // no script dir
395 
396  std::list<std::string> scripts;
397  filesystem::readdir( scripts, scriptsDir, /*dots*/false );
398  if ( scripts.empty() )
399  return true; // no scripts in script dir
400 
401  // Now collect and execute all matching scripts.
402  // On ABORT: at least log all outstanding scripts.
403  // - "name-version-release"
404  // - "name-version-release-*"
405  bool abort = false;
406  std::map<std::string, Pathname> unify; // scripts <md5,path>
407  for_( it, checkPackages_r.begin(), checkPackages_r.end() )
408  {
409  std::string prefix( str::form( "%s-%s", it->name().c_str(), it->edition().c_str() ) );
410  for_( sit, scripts.begin(), scripts.end() )
411  {
412  if ( ! str::hasPrefix( *sit, prefix ) )
413  continue;
414 
415  if ( (*sit)[prefix.size()] != '\0' && (*sit)[prefix.size()] != '-' )
416  continue; // if not exact match it had to continue with '-'
417 
418  PathInfo script( scriptsDir / *sit );
419  Pathname localPath( scriptsPath_r/(*sit) ); // without root prefix
420  std::string unifytag; // must not stay empty
421 
422  if ( script.isFile() )
423  {
424  // Assert it's set executable, unify by md5sum.
425  filesystem::addmod( script.path(), 0500 );
426  unifytag = filesystem::md5sum( script.path() );
427  }
428  else if ( ! script.isExist() )
429  {
430  // Might be a dangling symlink, might be ok if we are in
431  // instsys (absolute symlink within the system below /mnt).
432  // readlink will tell....
433  unifytag = filesystem::readlink( script.path() ).asString();
434  }
435 
436  if ( unifytag.empty() )
437  continue;
438 
439  // Unify scripts
440  if ( unify[unifytag].empty() )
441  {
442  unify[unifytag] = localPath;
443  }
444  else
445  {
446  // translators: We may find the same script content in files with different names.
447  // Only the first occurence is executed, subsequent ones are skipped. It's a one-line
448  // message for a log file. Preferably start translation with "%s"
449  std::string msg( str::form(_("%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
450  MIL << "Skip update script: " << msg << endl;
451  HistoryLog().comment( msg, /*timestamp*/true );
452  continue;
453  }
454 
455  if ( abort || aborting_r )
456  {
457  WAR << "Aborting: Skip update script " << *sit << endl;
458  HistoryLog().comment(
459  localPath.asString() + _(" execution skipped while aborting"),
460  /*timestamp*/true);
461  }
462  else
463  {
464  MIL << "Found update script " << *sit << endl;
465  callback::SendReport<PatchScriptReport> report;
466  report->start( make<Package>( *it ), script.path() );
467 
468  if ( ! executeScript( root_r, localPath, report ) ) // script path without root prefix!
469  abort = true; // requested abort.
470  }
471  }
472  }
473  return !abort;
474  }
475 
477  //
479 
480  inline void copyTo( std::ostream & out_r, const Pathname & file_r )
481  {
482  std::ifstream infile( file_r.c_str() );
483  for( iostr::EachLine in( infile ); in; in.next() )
484  {
485  out_r << *in << endl;
486  }
487  }
488 
489  inline std::string notificationCmdSubst( const std::string & cmd_r, const UpdateNotificationFile & notification_r )
490  {
491  std::string ret( cmd_r );
492 #define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
493  SUBST_IF( "%p", notification_r.solvable().asString() );
494  SUBST_IF( "%P", notification_r.file().asString() );
495 #undef SUBST_IF
496  return ret;
497  }
498 
499  void sendNotification( const Pathname & root_r,
500  const UpdateNotifications & notifications_r )
501  {
502  if ( notifications_r.empty() )
503  return;
504 
505  std::string cmdspec( ZConfig::instance().updateMessagesNotify() );
506  MIL << "Notification command is '" << cmdspec << "'" << endl;
507  if ( cmdspec.empty() )
508  return;
509 
510  std::string::size_type pos( cmdspec.find( '|' ) );
511  if ( pos == std::string::npos )
512  {
513  ERR << "Can't send Notification: Missing 'format |' in command spec." << endl;
514  HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
515  return;
516  }
517 
518  std::string formatStr( str::toLower( str::trim( cmdspec.substr( 0, pos ) ) ) );
519  std::string commandStr( str::trim( cmdspec.substr( pos + 1 ) ) );
520 
521  enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
522  Format format = UNKNOWN;
523  if ( formatStr == "none" )
524  format = NONE;
525  else if ( formatStr == "single" )
526  format = SINGLE;
527  else if ( formatStr == "digest" )
528  format = DIGEST;
529  else if ( formatStr == "bulk" )
530  format = BULK;
531  else
532  {
533  ERR << "Can't send Notification: Unknown format '" << formatStr << " |' in command spec." << endl;
534  HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
535  return;
536  }
537 
538  // Take care: commands are ececuted chroot(root_r). The message file
539  // pathnames in notifications_r are local to root_r. For physical access
540  // to the file they need to be prefixed.
541 
542  if ( format == NONE || format == SINGLE )
543  {
544  for_( it, notifications_r.begin(), notifications_r.end() )
545  {
546  std::vector<std::string> command;
547  if ( format == SINGLE )
548  command.push_back( "<"+Pathname::assertprefix( root_r, it->file() ).asString() );
549  str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
550 
551  ExternalProgram prog( command, ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r );
552  if ( true ) // Wait for feedback
553  {
554  for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
555  {
556  DBG << line;
557  }
558  int ret = prog.close();
559  if ( ret != 0 )
560  {
561  ERR << "Notification command returned with error (" << ret << ")." << endl;
562  HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
563  return;
564  }
565  }
566  }
567  }
568  else if ( format == DIGEST || format == BULK )
569  {
570  filesystem::TmpFile tmpfile;
571  ofstream out( tmpfile.path().c_str() );
572  for_( it, notifications_r.begin(), notifications_r.end() )
573  {
574  if ( format == DIGEST )
575  {
576  out << it->file() << endl;
577  }
578  else if ( format == BULK )
579  {
580  copyTo( out << '\f', Pathname::assertprefix( root_r, it->file() ) );
581  }
582  }
583 
584  std::vector<std::string> command;
585  command.push_back( "<"+tmpfile.path().asString() ); // redirect input
586  str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
587 
588  ExternalProgram prog( command, ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r );
589  if ( true ) // Wait for feedback otherwise the TmpFile goes out of scope.
590  {
591  for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
592  {
593  DBG << line;
594  }
595  int ret = prog.close();
596  if ( ret != 0 )
597  {
598  ERR << "Notification command returned with error (" << ret << ")." << endl;
599  HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
600  return;
601  }
602  }
603  }
604  else
605  {
606  INT << "Can't send Notification: Missing handler for 'format |' in command spec." << endl;
607  HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
608  return;
609  }
610  }
611 
612 
618  void RunUpdateMessages( const Pathname & root_r,
619  const Pathname & messagesPath_r,
620  const std::vector<sat::Solvable> & checkPackages_r,
621  ZYppCommitResult & result_r )
622  {
623  if ( checkPackages_r.empty() )
624  return; // no installed packages to check
625 
626  MIL << "Looking for new update messages in (" << root_r << ")" << messagesPath_r << endl;
627  Pathname messagesDir( Pathname::assertprefix( root_r, messagesPath_r ) );
628  if ( ! PathInfo( messagesDir ).isDir() )
629  return; // no messages dir
630 
631  std::list<std::string> messages;
632  filesystem::readdir( messages, messagesDir, /*dots*/false );
633  if ( messages.empty() )
634  return; // no messages in message dir
635 
636  // Now collect all matching messages in result and send them
637  // - "name-version-release"
638  // - "name-version-release-*"
639  HistoryLog historylog;
640  for_( it, checkPackages_r.begin(), checkPackages_r.end() )
641  {
642  std::string prefix( str::form( "%s-%s", it->name().c_str(), it->edition().c_str() ) );
643  for_( sit, messages.begin(), messages.end() )
644  {
645  if ( ! str::hasPrefix( *sit, prefix ) )
646  continue;
647 
648  if ( (*sit)[prefix.size()] != '\0' && (*sit)[prefix.size()] != '-' )
649  continue; // if not exact match it had to continue with '-'
650 
651  PathInfo message( messagesDir / *sit );
652  if ( ! message.isFile() || message.size() == 0 )
653  continue;
654 
655  MIL << "Found update message " << *sit << endl;
656  Pathname localPath( messagesPath_r/(*sit) ); // without root prefix
657  result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
658  historylog.comment( str::Str() << _("New update message") << " " << localPath, /*timestamp*/true );
659  }
660  }
661  sendNotification( root_r, result_r.updateMessages() );
662  }
663 
665  } // namespace
667 
668  void XRunUpdateMessages( const Pathname & root_r,
669  const Pathname & messagesPath_r,
670  const std::vector<sat::Solvable> & checkPackages_r,
671  ZYppCommitResult & result_r )
672  { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
673 
675 
677 
679  //
680  // METHOD NAME : TargetImpl::TargetImpl
681  // METHOD TYPE : Ctor
682  //
683  TargetImpl::TargetImpl( const Pathname & root_r, bool doRebuild_r )
684  : _root( root_r )
685  , _requestedLocalesFile( home() / "RequestedLocales" )
686  , _autoInstalledFile( home() / "AutoInstalled" )
687  , _hardLocksFile( Pathname::assertprefix( _root, ZConfig::instance().locksFile() ) )
688  {
689  _rpm.initDatabase( root_r, Pathname(), doRebuild_r );
690 
692 
694  sigMultiversionSpecChanged(); // HACK: see sigMultiversionSpecChanged
695  MIL << "Initialized target on " << _root << endl;
696  }
697 
701  static std::string generateRandomId()
702  {
703  std::ifstream uuidprovider( "/proc/sys/kernel/random/uuid" );
704  return iostr::getline( uuidprovider );
705  }
706 
712  void updateFileContent( const Pathname &filename,
713  boost::function<bool ()> condition,
714  boost::function<string ()> value )
715  {
716  string val = value();
717  // if the value is empty, then just dont
718  // do anything, regardless of the condition
719  if ( val.empty() )
720  return;
721 
722  if ( condition() )
723  {
724  MIL << "updating '" << filename << "' content." << endl;
725 
726  // if the file does not exist we need to generate the uuid file
727 
728  std::ofstream filestr;
729  // make sure the path exists
730  filesystem::assert_dir( filename.dirname() );
731  filestr.open( filename.c_str() );
732 
733  if ( filestr.good() )
734  {
735  filestr << val;
736  filestr.close();
737  }
738  else
739  {
740  // FIXME, should we ignore the error?
741  ZYPP_THROW(Exception("Can't openfile '" + filename.asString() + "' for writing"));
742  }
743  }
744  }
745 
747  static bool fileMissing( const Pathname &pathname )
748  {
749  return ! PathInfo(pathname).isExist();
750  }
751 
753  {
754  // bsc#1024741: Omit creating a new uid for chrooted systems (if it already has one, fine)
755  if ( root() != "/" )
756  return;
757 
758  // Create the anonymous unique id, used for download statistics
759  Pathname idpath( home() / "AnonymousUniqueId");
760 
761  try
762  {
763  updateFileContent( idpath,
764  boost::bind(fileMissing, idpath),
766  }
767  catch ( const Exception &e )
768  {
769  WAR << "Can't create anonymous id file" << endl;
770  }
771 
772  }
773 
775  {
776  // create the anonymous unique id
777  // this value is used for statistics
778  Pathname flavorpath( home() / "LastDistributionFlavor");
779 
780  // is there a product
782  if ( ! p )
783  {
784  WAR << "No base product, I won't create flavor cache" << endl;
785  return;
786  }
787 
788  string flavor = p->flavor();
789 
790  try
791  {
792 
793  updateFileContent( flavorpath,
794  // only if flavor is not empty
795  functor::Constant<bool>( ! flavor.empty() ),
796  functor::Constant<string>(flavor) );
797  }
798  catch ( const Exception &e )
799  {
800  WAR << "Can't create flavor cache" << endl;
801  return;
802  }
803  }
804 
806  //
807  // METHOD NAME : TargetImpl::~TargetImpl
808  // METHOD TYPE : Dtor
809  //
811  {
813  sigMultiversionSpecChanged(); // HACK: see sigMultiversionSpecChanged
814  MIL << "Targets closed" << endl;
815  }
816 
818  //
819  // solv file handling
820  //
822 
824  {
825  return Pathname::assertprefix( _root, ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoAlias() );
826  }
827 
829  {
830  Pathname base = solvfilesPath();
832  }
833 
835  {
836  Pathname base = solvfilesPath();
837  Pathname rpmsolv = base/"solv";
838  Pathname rpmsolvcookie = base/"cookie";
839 
840  bool build_rpm_solv = true;
841  // lets see if the rpm solv cache exists
842 
843  RepoStatus rpmstatus( RepoStatus(_root/"var/lib/rpm/Name") && RepoStatus(_root/"etc/products.d") );
844 
845  bool solvexisted = PathInfo(rpmsolv).isExist();
846  if ( solvexisted )
847  {
848  // see the status of the cache
849  PathInfo cookie( rpmsolvcookie );
850  MIL << "Read cookie: " << cookie << endl;
851  if ( cookie.isExist() )
852  {
853  RepoStatus status = RepoStatus::fromCookieFile(rpmsolvcookie);
854  // now compare it with the rpm database
855  if ( status == rpmstatus )
856  build_rpm_solv = false;
857  MIL << "Read cookie: " << rpmsolvcookie << " says: "
858  << (build_rpm_solv ? "outdated" : "uptodate") << endl;
859  }
860  }
861 
862  if ( build_rpm_solv )
863  {
864  // if the solvfile dir does not exist yet, we better create it
865  filesystem::assert_dir( base );
866 
867  Pathname oldSolvFile( solvexisted ? rpmsolv : Pathname() ); // to speedup rpmdb2solv
868 
870  if ( !tmpsolv )
871  {
872  // Can't create temporary solv file, usually due to insufficient permission
873  // (user query while @System solv needs refresh). If so, try switching
874  // to a location within zypps temp. space (will be cleaned at application end).
875 
876  bool switchingToTmpSolvfile = false;
877  Exception ex("Failed to cache rpm database.");
878  ex.remember(str::form("Cannot create temporary file under %s.", base.c_str()));
879 
880  if ( ! solvfilesPathIsTemp() )
881  {
882  base = getZYpp()->tmpPath() / sat::Pool::instance().systemRepoAlias();
883  rpmsolv = base/"solv";
884  rpmsolvcookie = base/"cookie";
885 
886  filesystem::assert_dir( base );
887  tmpsolv = filesystem::TmpFile::makeSibling( rpmsolv );
888 
889  if ( tmpsolv )
890  {
891  WAR << "Using a temporary solv file at " << base << endl;
892  switchingToTmpSolvfile = true;
893  _tmpSolvfilesPath = base;
894  }
895  else
896  {
897  ex.remember(str::form("Cannot create temporary file under %s.", base.c_str()));
898  }
899  }
900 
901  if ( ! switchingToTmpSolvfile )
902  {
903  ZYPP_THROW(ex);
904  }
905  }
906 
907  // Take care we unlink the solvfile on exception
909 
911  cmd.push_back( "/usr/lib/zypp/tools/rpmdb2solv" );
912  if ( ! _root.empty() ) {
913  cmd.push_back( "-r" );
914  cmd.push_back( _root.asString() );
915  }
916  cmd.push_back( "-X" ); // autogenerate pattern/product/... from -package
917  //cmd.push_back( "-A" ); // autogenerate application pseudo packages
918  cmd.push_back( "-p" );
919  cmd.push_back( Pathname::assertprefix( _root, "/etc/products.d" ).asString() );
920 
921  if ( ! oldSolvFile.empty() )
922  cmd.push_back( oldSolvFile.asString() );
923 
924  cmd.push_back( "-o" );
925  cmd.push_back( tmpsolv.path().asString() );
926 
928  std::string errdetail;
929 
930  for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
931  WAR << " " << output;
932  if ( errdetail.empty() ) {
933  errdetail = prog.command();
934  errdetail += '\n';
935  }
936  errdetail += output;
937  }
938 
939  int ret = prog.close();
940  if ( ret != 0 )
941  {
942  Exception ex(str::form("Failed to cache rpm database (%d).", ret));
943  ex.remember( errdetail );
944  ZYPP_THROW(ex);
945  }
946 
947  ret = filesystem::rename( tmpsolv, rpmsolv );
948  if ( ret != 0 )
949  ZYPP_THROW(Exception("Failed to move cache to final destination"));
950  // if this fails, don't bother throwing exceptions
951  filesystem::chmod( rpmsolv, 0644 );
952 
953  rpmstatus.saveToCookieFile(rpmsolvcookie);
954 
955  // We keep it.
956  guard.resetDispose();
957  sat::updateSolvFileIndex( rpmsolv ); // content digest for zypper bash completion
958 
959  // system-hook: Finally send notification to plugins
960  if ( root() == "/" )
961  {
962  PluginExecutor plugins;
963  plugins.load( ZConfig::instance().pluginsPath()/"system" );
964  if ( plugins )
965  plugins.send( PluginFrame( "PACKAGESETCHANGED" ) );
966  }
967  }
968  else
969  {
970  // On the fly add missing solv.idx files for bash completion.
971  if ( ! PathInfo(base/"solv.idx").isExist() )
972  sat::updateSolvFileIndex( rpmsolv );
973  }
974  return build_rpm_solv;
975  }
976 
978  {
979  load( false );
980  }
981 
983  {
984  Repository system( sat::Pool::instance().findSystemRepo() );
985  if ( system )
986  system.eraseFromPool();
987  }
988 
989  void TargetImpl::load( bool force )
990  {
991  bool newCache = buildCache();
992  MIL << "New cache built: " << (newCache?"true":"false") <<
993  ", force loading: " << (force?"true":"false") << endl;
994 
995  // now add the repos to the pool
996  sat::Pool satpool( sat::Pool::instance() );
997  Pathname rpmsolv( solvfilesPath() / "solv" );
998  MIL << "adding " << rpmsolv << " to pool(" << satpool.systemRepoAlias() << ")" << endl;
999 
1000  // Providing an empty system repo, unload any old content
1001  Repository system( sat::Pool::instance().findSystemRepo() );
1002 
1003  if ( system && ! system.solvablesEmpty() )
1004  {
1005  if ( newCache || force )
1006  {
1007  system.eraseFromPool(); // invalidates system
1008  }
1009  else
1010  {
1011  return; // nothing to do
1012  }
1013  }
1014 
1015  if ( ! system )
1016  {
1017  system = satpool.systemRepo();
1018  }
1019 
1020  try
1021  {
1022  MIL << "adding " << rpmsolv << " to system" << endl;
1023  system.addSolv( rpmsolv );
1024  }
1025  catch ( const Exception & exp )
1026  {
1027  ZYPP_CAUGHT( exp );
1028  MIL << "Try to handle exception by rebuilding the solv-file" << endl;
1029  clearCache();
1030  buildCache();
1031 
1032  system.addSolv( rpmsolv );
1033  }
1034  satpool.rootDir( _root );
1035 
1036  // (Re)Load the requested locales et al.
1037  // If the requested locales are empty, we leave the pool untouched
1038  // to avoid undoing changes the application applied. We expect this
1039  // to happen on a bare metal installation only. An already existing
1040  // target should be loaded before its settings are changed.
1041  {
1043  if ( ! requestedLocales.empty() )
1044  {
1046  }
1047  }
1048  {
1049  if ( ! PathInfo( _autoInstalledFile.file() ).isExist() )
1050  {
1051  // Initialize from history, if it does not exist
1052  Pathname historyFile( Pathname::assertprefix( _root, ZConfig::instance().historyLogFile() ) );
1053  if ( PathInfo( historyFile ).isExist() )
1054  {
1055  SolvIdentFile::Data onSystemByUser( getUserInstalledFromHistory( historyFile ) );
1056  SolvIdentFile::Data onSystemByAuto;
1057  for_( it, system.solvablesBegin(), system.solvablesEnd() )
1058  {
1059  IdString ident( (*it).ident() );
1060  if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1061  onSystemByAuto.insert( ident );
1062  }
1063  _autoInstalledFile.setData( onSystemByAuto );
1064  }
1065  // on the fly removed any obsolete SoftLocks file
1066  filesystem::unlink( home() / "SoftLocks" );
1067  }
1068  // read from AutoInstalled file
1069  sat::StringQueue q;
1070  for ( const auto & idstr : _autoInstalledFile.data() )
1071  q.push( idstr.id() );
1072  satpool.setAutoInstalled( q );
1073  }
1074  if ( ZConfig::instance().apply_locks_file() )
1075  {
1076  const HardLocksFile::Data & hardLocks( _hardLocksFile.data() );
1077  if ( ! hardLocks.empty() )
1078  {
1079  ResPool::instance().setHardLockQueries( hardLocks );
1080  }
1081  }
1082 
1083  // now that the target is loaded, we can cache the flavor
1085 
1086  MIL << "Target loaded: " << system.solvablesSize() << " resolvables" << endl;
1087  }
1088 
1090  //
1091  // COMMIT
1092  //
1095  {
1096  // ----------------------------------------------------------------- //
1097  ZYppCommitPolicy policy_r( policy_rX );
1098  bool explicitDryRun = policy_r.dryRun(); // explicit dry run will trigger a fileconflict check, implicit (download-only) not.
1099 
1100  // Fake outstanding YCP fix: Honour restriction to media 1
1101  // at installation, but install all remaining packages if post-boot.
1102  if ( policy_r.restrictToMedia() > 1 )
1103  policy_r.allMedia();
1104 
1105  if ( policy_r.downloadMode() == DownloadDefault ) {
1106  if ( root() == "/" )
1107  policy_r.downloadMode(DownloadInHeaps);
1108  else
1109  policy_r.downloadMode(DownloadAsNeeded);
1110  }
1111  // DownloadOnly implies dry-run.
1112  else if ( policy_r.downloadMode() == DownloadOnly )
1113  policy_r.dryRun( true );
1114  // ----------------------------------------------------------------- //
1115 
1116  MIL << "TargetImpl::commit(<pool>, " << policy_r << ")" << endl;
1117 
1119  // Compute transaction:
1121  ZYppCommitResult result( root() );
1122  result.rTransaction() = pool_r.resolver().getTransaction();
1123  result.rTransaction().order();
1124  // steps: this is our todo-list
1126  if ( policy_r.restrictToMedia() )
1127  {
1128  // Collect until the 1st package from an unwanted media occurs.
1129  // Further collection could violate install order.
1130  MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl;
1131  for_( it, result.transaction().begin(), result.transaction().end() )
1132  {
1133  if ( makeResObject( *it )->mediaNr() > 1 )
1134  break;
1135  steps.push_back( *it );
1136  }
1137  }
1138  else
1139  {
1140  result.rTransactionStepList().insert( steps.end(), result.transaction().begin(), result.transaction().end() );
1141  }
1142  MIL << "Todo: " << result << endl;
1143 
1145  // Prepare execution of commit plugins:
1147  PluginExecutor commitPlugins;
1148  if ( root() == "/" && ! policy_r.dryRun() )
1149  {
1150  commitPlugins.load( ZConfig::instance().pluginsPath()/"commit" );
1151  }
1152  if ( commitPlugins )
1153  commitPlugins.send( transactionPluginFrame( "COMMITBEGIN", steps ) );
1154 
1156  // Write out a testcase if we're in dist upgrade mode.
1158  if ( pool_r.resolver().upgradeMode() || pool_r.resolver().upgradingRepos() )
1159  {
1160  if ( ! policy_r.dryRun() )
1161  {
1163  }
1164  else
1165  {
1166  DBG << "dryRun: Not writing upgrade testcase." << endl;
1167  }
1168  }
1169 
1171  // Store non-package data:
1173  if ( ! policy_r.dryRun() )
1174  {
1176  // requested locales
1178  // autoinstalled
1179  {
1180  SolvIdentFile::Data newdata;
1181  for ( sat::Queue::value_type id : result.rTransaction().autoInstalled() )
1182  newdata.insert( IdString(id) );
1183  _autoInstalledFile.setData( newdata );
1184  }
1185  // hard locks
1186  if ( ZConfig::instance().apply_locks_file() )
1187  {
1188  HardLocksFile::Data newdata;
1189  pool_r.getHardLockQueries( newdata );
1190  _hardLocksFile.setData( newdata );
1191  }
1192  }
1193  else
1194  {
1195  DBG << "dryRun: Not stroring non-package data." << endl;
1196  }
1197 
1199  // First collect and display all messages
1200  // associated with patches to be installed.
1202  if ( ! policy_r.dryRun() )
1203  {
1204  for_( it, steps.begin(), steps.end() )
1205  {
1206  if ( ! it->satSolvable().isKind<Patch>() )
1207  continue;
1208 
1209  PoolItem pi( *it );
1210  if ( ! pi.status().isToBeInstalled() )
1211  continue;
1212 
1213  Patch::constPtr patch( asKind<Patch>(pi.resolvable()) );
1214  if ( ! patch ||patch->message().empty() )
1215  continue;
1216 
1217  MIL << "Show message for " << patch << endl;
1219  if ( ! report->show( patch ) )
1220  {
1221  WAR << "commit aborted by the user" << endl;
1222  ZYPP_THROW( TargetAbortedException( N_("Installation has been aborted as directed.") ) );
1223  }
1224  }
1225  }
1226  else
1227  {
1228  DBG << "dryRun: Not checking patch messages." << endl;
1229  }
1230 
1232  // Remove/install packages.
1234  DBG << "commit log file is set to: " << HistoryLog::fname() << endl;
1235  if ( ! policy_r.dryRun() || policy_r.downloadMode() == DownloadOnly )
1236  {
1237  // Prepare the package cache. Pass all items requiring download.
1238  CommitPackageCache packageCache;
1239  packageCache.setCommitList( steps.begin(), steps.end() );
1240 
1241  bool miss = false;
1242  if ( policy_r.downloadMode() != DownloadAsNeeded )
1243  {
1244  // Preload the cache. Until now this means pre-loading all packages.
1245  // Once DownloadInHeaps is fully implemented, this will change and
1246  // we may actually have more than one heap.
1247  for_( it, steps.begin(), steps.end() )
1248  {
1249  switch ( it->stepType() )
1250  {
1253  // proceed: only install actionas may require download.
1254  break;
1255 
1256  default:
1257  // next: no download for or non-packages and delete actions.
1258  continue;
1259  break;
1260  }
1261 
1262  PoolItem pi( *it );
1263  if ( pi->isKind<Package>() || pi->isKind<SrcPackage>() )
1264  {
1265  ManagedFile localfile;
1266  try
1267  {
1268  localfile = packageCache.get( pi );
1269  localfile.resetDispose(); // keep the package file in the cache
1270  }
1271  catch ( const AbortRequestException & exp )
1272  {
1273  it->stepStage( sat::Transaction::STEP_ERROR );
1274  miss = true;
1275  WAR << "commit cache preload aborted by the user" << endl;
1276  ZYPP_THROW( TargetAbortedException( N_("Installation has been aborted as directed.") ) );
1277  break;
1278  }
1279  catch ( const SkipRequestException & exp )
1280  {
1281  ZYPP_CAUGHT( exp );
1282  it->stepStage( sat::Transaction::STEP_ERROR );
1283  miss = true;
1284  WAR << "Skipping cache preload package " << pi->asKind<Package>() << " in commit" << endl;
1285  continue;
1286  }
1287  catch ( const Exception & exp )
1288  {
1289  // bnc #395704: missing catch causes abort.
1290  // TODO see if packageCache fails to handle errors correctly.
1291  ZYPP_CAUGHT( exp );
1292  it->stepStage( sat::Transaction::STEP_ERROR );
1293  miss = true;
1294  INT << "Unexpected Error: Skipping cache preload package " << pi->asKind<Package>() << " in commit" << endl;
1295  continue;
1296  }
1297  }
1298  }
1299  packageCache.preloaded( true ); // try to avoid duplicate infoInCache CBs in commit
1300  }
1301 
1302  if ( miss )
1303  {
1304  ERR << "Some packages could not be provided. Aborting commit."<< endl;
1305  }
1306  else
1307  {
1308  if ( ! policy_r.dryRun() )
1309  {
1310  // if cache is preloaded, check for file conflicts
1311  commitFindFileConflicts( policy_r, result );
1312  commit( policy_r, packageCache, result );
1313  }
1314  else
1315  {
1316  DBG << "dryRun/downloadOnly: Not installing/deleting anything." << endl;
1317  if ( explicitDryRun ) {
1318  // if cache is preloaded, check for file conflicts
1319  commitFindFileConflicts( policy_r, result );
1320  }
1321  }
1322  }
1323  }
1324  else
1325  {
1326  DBG << "dryRun: Not downloading/installing/deleting anything." << endl;
1327  if ( explicitDryRun ) {
1328  // if cache is preloaded, check for file conflicts
1329  commitFindFileConflicts( policy_r, result );
1330  }
1331  }
1332 
1334  // Send result to commit plugins:
1336  if ( commitPlugins )
1337  commitPlugins.send( transactionPluginFrame( "COMMITEND", steps ) );
1338 
1340  // Try to rebuild solv file while rpm database is still in cache
1342  if ( ! policy_r.dryRun() )
1343  {
1344  buildCache();
1345  }
1346 
1347  MIL << "TargetImpl::commit(<pool>, " << policy_r << ") returns: " << result << endl;
1348  return result;
1349  }
1350 
1352  //
1353  // COMMIT internal
1354  //
1356  namespace
1357  {
1358  struct NotifyAttemptToModify
1359  {
1360  NotifyAttemptToModify( ZYppCommitResult & result_r ) : _result( result_r ) {}
1361 
1362  void operator()()
1363  { if ( _guard ) { _result.attemptToModify( true ); _guard = false; } }
1364 
1365  TrueBool _guard;
1366  ZYppCommitResult & _result;
1367  };
1368  } // namespace
1369 
1370  void TargetImpl::commit( const ZYppCommitPolicy & policy_r,
1371  CommitPackageCache & packageCache_r,
1372  ZYppCommitResult & result_r )
1373  {
1374  // steps: this is our todo-list
1376  MIL << "TargetImpl::commit(<list>" << policy_r << ")" << steps.size() << endl;
1377 
1379 
1380  // Send notification once upon 1st call to rpm
1381  NotifyAttemptToModify attemptToModify( result_r );
1382 
1383  bool abort = false;
1384 
1385  RpmPostTransCollector postTransCollector( _root );
1386  std::vector<sat::Solvable> successfullyInstalledPackages;
1387  TargetImpl::PoolItemList remaining;
1388 
1389  for_( step, steps.begin(), steps.end() )
1390  {
1391  PoolItem citem( *step );
1392  if ( step->stepType() == sat::Transaction::TRANSACTION_IGNORE )
1393  {
1394  if ( citem->isKind<Package>() )
1395  {
1396  // for packages this means being obsoleted (by rpm)
1397  // thius no additional action is needed.
1398  step->stepStage( sat::Transaction::STEP_DONE );
1399  continue;
1400  }
1401  }
1402 
1403  if ( citem->isKind<Package>() )
1404  {
1405  Package::constPtr p = citem->asKind<Package>();
1406  if ( citem.status().isToBeInstalled() )
1407  {
1408  ManagedFile localfile;
1409  try
1410  {
1411  localfile = packageCache_r.get( citem );
1412  }
1413  catch ( const AbortRequestException &e )
1414  {
1415  WAR << "commit aborted by the user" << endl;
1416  abort = true;
1417  step->stepStage( sat::Transaction::STEP_ERROR );
1418  break;
1419  }
1420  catch ( const SkipRequestException &e )
1421  {
1422  ZYPP_CAUGHT( e );
1423  WAR << "Skipping package " << p << " in commit" << endl;
1424  step->stepStage( sat::Transaction::STEP_ERROR );
1425  continue;
1426  }
1427  catch ( const Exception &e )
1428  {
1429  // bnc #395704: missing catch causes abort.
1430  // TODO see if packageCache fails to handle errors correctly.
1431  ZYPP_CAUGHT( e );
1432  INT << "Unexpected Error: Skipping package " << p << " in commit" << endl;
1433  step->stepStage( sat::Transaction::STEP_ERROR );
1434  continue;
1435  }
1436 
1437 #warning Exception handling
1438  // create a installation progress report proxy
1439  RpmInstallPackageReceiver progress( citem.resolvable() );
1440  progress.connect(); // disconnected on destruction.
1441 
1442  bool success = false;
1443  rpm::RpmInstFlags flags( policy_r.rpmInstFlags() & rpm::RPMINST_JUSTDB );
1444  // Why force and nodeps?
1445  //
1446  // Because zypp builds the transaction and the resolver asserts that
1447  // everything is fine.
1448  // We use rpm just to unpack and register the package in the database.
1449  // We do this step by step, so rpm is not aware of the bigger context.
1450  // So we turn off rpms internal checks, because we do it inside zypp.
1451  flags |= rpm::RPMINST_NODEPS;
1452  flags |= rpm::RPMINST_FORCE;
1453  //
1454  if (p->multiversionInstall()) flags |= rpm::RPMINST_NOUPGRADE;
1455  if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST;
1456  if (policy_r.rpmExcludeDocs()) flags |= rpm::RPMINST_EXCLUDEDOCS;
1457  if (policy_r.rpmNoSignature()) flags |= rpm::RPMINST_NOSIGNATURE;
1458 
1459  attemptToModify();
1460  try
1461  {
1463  if ( postTransCollector.collectScriptFromPackage( localfile ) )
1464  flags |= rpm::RPMINST_NOPOSTTRANS;
1465  rpm().installPackage( localfile, flags );
1466  HistoryLog().install(citem);
1467 
1468  if ( progress.aborted() )
1469  {
1470  WAR << "commit aborted by the user" << endl;
1471  localfile.resetDispose(); // keep the package file in the cache
1472  abort = true;
1473  step->stepStage( sat::Transaction::STEP_ERROR );
1474  break;
1475  }
1476  else
1477  {
1478  success = true;
1479  step->stepStage( sat::Transaction::STEP_DONE );
1480  }
1481  }
1482  catch ( Exception & excpt_r )
1483  {
1484  ZYPP_CAUGHT(excpt_r);
1485  localfile.resetDispose(); // keep the package file in the cache
1486 
1487  if ( policy_r.dryRun() )
1488  {
1489  WAR << "dry run failed" << endl;
1490  step->stepStage( sat::Transaction::STEP_ERROR );
1491  break;
1492  }
1493  // else
1494  if ( progress.aborted() )
1495  {
1496  WAR << "commit aborted by the user" << endl;
1497  abort = true;
1498  }
1499  else
1500  {
1501  WAR << "Install failed" << endl;
1502  }
1503  step->stepStage( sat::Transaction::STEP_ERROR );
1504  break; // stop
1505  }
1506 
1507  if ( success && !policy_r.dryRun() )
1508  {
1510  successfullyInstalledPackages.push_back( citem.satSolvable() );
1511  step->stepStage( sat::Transaction::STEP_DONE );
1512  }
1513  }
1514  else
1515  {
1516  RpmRemovePackageReceiver progress( citem.resolvable() );
1517  progress.connect(); // disconnected on destruction.
1518 
1519  bool success = false;
1520  rpm::RpmInstFlags flags( policy_r.rpmInstFlags() & rpm::RPMINST_JUSTDB );
1521  flags |= rpm::RPMINST_NODEPS;
1522  if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST;
1523 
1524  attemptToModify();
1525  try
1526  {
1527  rpm().removePackage( p, flags );
1528  HistoryLog().remove(citem);
1529 
1530  if ( progress.aborted() )
1531  {
1532  WAR << "commit aborted by the user" << endl;
1533  abort = true;
1534  step->stepStage( sat::Transaction::STEP_ERROR );
1535  break;
1536  }
1537  else
1538  {
1539  success = true;
1540  step->stepStage( sat::Transaction::STEP_DONE );
1541  }
1542  }
1543  catch (Exception & excpt_r)
1544  {
1545  ZYPP_CAUGHT( excpt_r );
1546  if ( progress.aborted() )
1547  {
1548  WAR << "commit aborted by the user" << endl;
1549  abort = true;
1550  step->stepStage( sat::Transaction::STEP_ERROR );
1551  break;
1552  }
1553  // else
1554  WAR << "removal of " << p << " failed";
1555  step->stepStage( sat::Transaction::STEP_ERROR );
1556  }
1557  if ( success && !policy_r.dryRun() )
1558  {
1560  step->stepStage( sat::Transaction::STEP_DONE );
1561  }
1562  }
1563  }
1564  else if ( ! policy_r.dryRun() ) // other resolvables (non-Package)
1565  {
1566  // Status is changed as the buddy package buddy
1567  // gets installed/deleted. Handle non-buddies only.
1568  if ( ! citem.buddy() )
1569  {
1570  if ( citem->isKind<Product>() )
1571  {
1572  Product::constPtr p = citem->asKind<Product>();
1573  if ( citem.status().isToBeInstalled() )
1574  {
1575  ERR << "Can't install orphan product without release-package! " << citem << endl;
1576  }
1577  else
1578  {
1579  // Deleting the corresponding product entry is all we con do.
1580  // So the product will no longer be visible as installed.
1581  std::string referenceFilename( p->referenceFilename() );
1582  if ( referenceFilename.empty() )
1583  {
1584  ERR << "Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1585  }
1586  else
1587  {
1588  PathInfo referenceFile( Pathname::assertprefix( _root, Pathname( "/etc/products.d" ) ) / referenceFilename );
1589  if ( ! referenceFile.isFile() || filesystem::unlink( referenceFile.path() ) != 0 )
1590  {
1591  ERR << "Delete orphan product failed: " << referenceFile << endl;
1592  }
1593  }
1594  }
1595  }
1596  else if ( citem->isKind<SrcPackage>() && citem.status().isToBeInstalled() )
1597  {
1598  // SrcPackage is install-only
1599  SrcPackage::constPtr p = citem->asKind<SrcPackage>();
1600  installSrcPackage( p );
1601  }
1602 
1604  step->stepStage( sat::Transaction::STEP_DONE );
1605  }
1606 
1607  } // other resolvables
1608 
1609  } // for
1610 
1611  // process all remembered posttrans scripts.
1612  if ( !abort )
1613  postTransCollector.executeScripts();
1614  else
1615  postTransCollector.discardScripts();
1616 
1617  // Check presence of update scripts/messages. If aborting,
1618  // at least log omitted scripts.
1619  if ( ! successfullyInstalledPackages.empty() )
1620  {
1621  if ( ! RunUpdateScripts( _root, ZConfig::instance().update_scriptsPath(),
1622  successfullyInstalledPackages, abort ) )
1623  {
1624  WAR << "Commit aborted by the user" << endl;
1625  abort = true;
1626  }
1627  // send messages after scripts in case some script generates output,
1628  // that should be kept in t %ghost message file.
1629  RunUpdateMessages( _root, ZConfig::instance().update_messagesPath(),
1630  successfullyInstalledPackages,
1631  result_r );
1632  }
1633 
1634  if ( abort )
1635  {
1636  ZYPP_THROW( TargetAbortedException( N_("Installation has been aborted as directed.") ) );
1637  }
1638  }
1639 
1641 
1643  {
1644  return _rpm;
1645  }
1646 
1647  bool TargetImpl::providesFile (const std::string & path_str, const std::string & name_str) const
1648  {
1649  return _rpm.hasFile(path_str, name_str);
1650  }
1651 
1652 
1654  {
1655  return _rpm.timestamp();
1656  }
1657 
1659  namespace
1660  {
1661  parser::ProductFileData baseproductdata( const Pathname & root_r )
1662  {
1664  PathInfo baseproduct( Pathname::assertprefix( root_r, "/etc/products.d/baseproduct" ) );
1665 
1666  if ( baseproduct.isFile() )
1667  {
1668  try
1669  {
1670  ret = parser::ProductFileReader::scanFile( baseproduct.path() );
1671  }
1672  catch ( const Exception & excpt )
1673  {
1674  ZYPP_CAUGHT( excpt );
1675  }
1676  }
1677  else if ( PathInfo( Pathname::assertprefix( root_r, "/etc/products.d" ) ).isDir() )
1678  {
1679  ERR << "baseproduct symlink is dangling or missing: " << baseproduct << endl;
1680  }
1681  return ret;
1682  }
1683 
1684  inline Pathname staticGuessRoot( const Pathname & root_r )
1685  {
1686  if ( root_r.empty() )
1687  {
1688  // empty root: use existing Target or assume "/"
1689  Pathname ret ( ZConfig::instance().systemRoot() );
1690  if ( ret.empty() )
1691  return Pathname("/");
1692  return ret;
1693  }
1694  return root_r;
1695  }
1696 
1697  inline std::string firstNonEmptyLineIn( const Pathname & file_r )
1698  {
1699  std::ifstream idfile( file_r.c_str() );
1700  for( iostr::EachLine in( idfile ); in; in.next() )
1701  {
1702  std::string line( str::trim( *in ) );
1703  if ( ! line.empty() )
1704  return line;
1705  }
1706  return std::string();
1707  }
1708  } // namespace
1710 
1712  {
1713  ResPool pool(ResPool::instance());
1714  for_( it, pool.byKindBegin<Product>(), pool.byKindEnd<Product>() )
1715  {
1716  Product::constPtr p = (*it)->asKind<Product>();
1717  if ( p->isTargetDistribution() )
1718  return p;
1719  }
1720  return nullptr;
1721  }
1722 
1724  {
1725  const Pathname needroot( staticGuessRoot(root_r) );
1726  const Target_constPtr target( getZYpp()->getTarget() );
1727  if ( target && target->root() == needroot )
1728  return target->requestedLocales();
1729  return RequestedLocalesFile( home(needroot) / "RequestedLocales" ).locales();
1730  }
1731 
1733  {
1734  MIL << "updateAutoInstalled if changed..." << endl;
1735  SolvIdentFile::Data newdata;
1736  for ( auto id : sat::Pool::instance().autoInstalled() )
1737  newdata.insert( IdString(id) ); // explicit ctor!
1738  _autoInstalledFile.setData( std::move(newdata) );
1739  }
1740 
1742  { return baseproductdata( _root ).registerTarget(); }
1743  // static version:
1744  std::string TargetImpl::targetDistribution( const Pathname & root_r )
1745  { return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
1746 
1748  { return baseproductdata( _root ).registerRelease(); }
1749  // static version:
1750  std::string TargetImpl::targetDistributionRelease( const Pathname & root_r )
1751  { return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
1752 
1754  { return baseproductdata( _root ).registerFlavor(); }
1755  // static version:
1756  std::string TargetImpl::targetDistributionFlavor( const Pathname & root_r )
1757  { return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
1758 
1760  {
1762  parser::ProductFileData pdata( baseproductdata( _root ) );
1763  ret.shortName = pdata.shortName();
1764  ret.summary = pdata.summary();
1765  return ret;
1766  }
1767  // static version:
1769  {
1771  parser::ProductFileData pdata( baseproductdata( staticGuessRoot(root_r) ) );
1772  ret.shortName = pdata.shortName();
1773  ret.summary = pdata.summary();
1774  return ret;
1775  }
1776 
1778  {
1779  if ( _distributionVersion.empty() )
1780  {
1782  if ( !_distributionVersion.empty() )
1783  MIL << "Remember distributionVersion = '" << _distributionVersion << "'" << endl;
1784  }
1785  return _distributionVersion;
1786  }
1787  // static version
1788  std::string TargetImpl::distributionVersion( const Pathname & root_r )
1789  {
1790  std::string distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version();
1791  if ( distributionVersion.empty() )
1792  {
1793  // ...But the baseproduct method is not expected to work on RedHat derivatives.
1794  // On RHEL, Fedora and others the "product version" is determined by the first package
1795  // providing 'redhat-release'. This value is not hardcoded in YUM and can be configured
1796  // with the $distroverpkg variable.
1797  scoped_ptr<rpm::RpmDb> tmprpmdb;
1798  if ( ZConfig::instance().systemRoot() == Pathname() )
1799  {
1800  try
1801  {
1802  tmprpmdb.reset( new rpm::RpmDb );
1803  tmprpmdb->initDatabase( /*default ctor uses / but no additional keyring exports */ );
1804  }
1805  catch( ... )
1806  {
1807  return "";
1808  }
1809  }
1812  distributionVersion = it->tag_version();
1813  }
1814  return distributionVersion;
1815  }
1816 
1817 
1819  {
1820  return firstNonEmptyLineIn( home() / "LastDistributionFlavor" );
1821  }
1822  // static version:
1823  std::string TargetImpl::distributionFlavor( const Pathname & root_r )
1824  {
1825  return firstNonEmptyLineIn( staticGuessRoot(root_r) / "/var/lib/zypp/LastDistributionFlavor" );
1826  }
1827 
1829  namespace
1830  {
1831  std::string guessAnonymousUniqueId( const Pathname & root_r )
1832  {
1833  // bsc#1024741: Omit creating a new uid for chrooted systems (if it already has one, fine)
1834  std::string ret( firstNonEmptyLineIn( root_r / "/var/lib/zypp/AnonymousUniqueId" ) );
1835  if ( ret.empty() && root_r != "/" )
1836  {
1837  // if it has nonoe, use the outer systems one
1838  ret = firstNonEmptyLineIn( "/var/lib/zypp/AnonymousUniqueId" );
1839  }
1840  return ret;
1841  }
1842  }
1843 
1844  std::string TargetImpl::anonymousUniqueId() const
1845  {
1846  return guessAnonymousUniqueId( root() );
1847  }
1848  // static version:
1849  std::string TargetImpl::anonymousUniqueId( const Pathname & root_r )
1850  {
1851  return guessAnonymousUniqueId( staticGuessRoot(root_r) );
1852  }
1853 
1855 
1856  void TargetImpl::installSrcPackage( const SrcPackage_constPtr & srcPackage_r )
1857  {
1858  // provide on local disk
1859  ManagedFile localfile = provideSrcPackage(srcPackage_r);
1860  // create a installation progress report proxy
1861  RpmInstallPackageReceiver progress( srcPackage_r );
1862  progress.connect(); // disconnected on destruction.
1863  // install it
1864  rpm().installPackage ( localfile );
1865  }
1866 
1867  ManagedFile TargetImpl::provideSrcPackage( const SrcPackage_constPtr & srcPackage_r )
1868  {
1869  // provide on local disk
1870  repo::RepoMediaAccess access_r;
1871  repo::SrcPackageProvider prov( access_r );
1872  return prov.provideSrcPackage( srcPackage_r );
1873  }
1875  } // namespace target
1878 } // namespace zypp
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:354
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:350
Interface to gettext.
#define N_(MSG)
Just tag text for translation.
Definition: Gettext.h:18
#define _(MSG)
Definition: Gettext.h:29
#define DBG
Definition: Logger.h:63
#define MIL
Definition: Logger.h:64
#define ERR
Definition: Logger.h:66
#define WAR
Definition: Logger.h:65
#define INT
Definition: Logger.h:68
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:203
#define idstr(V)
#define IMPL_PTR_TYPE(NAME)
const Pathname & _root
Definition: RepoManager.cc:143
#define SUBST_IF(PAT, VAL)
ZYppCommitResult & _result
Definition: TargetImpl.cc:1366
TrueBool _guard
Definition: TargetImpl.cc:1365
Architecture.
Definition: Arch.h:37
const std::string & asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: Arch.cc:481
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:93
void resetDispose()
Set no dispose function.
Definition: AutoDispose.h:162
Store and operate on date (time_t).
Definition: Date.h:33
Edition represents [epoch:]version[-release]
Definition: Edition.h:61
unsigned epoch_t
Type of an epoch.
Definition: Edition.h:64
std::string version() const
Version.
Definition: Edition.cc:94
std::string release() const
Release.
Definition: Edition.cc:110
epoch_t epoch() const
Epoch.
Definition: Edition.cc:82
Base class for Exception.
Definition: Exception.h:144
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:105
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
std::vector< std::string > Arguments
int close()
Wait for the progamm to complete.
const std::string & command() const
The command we're executing.
Writing the zypp history file.
Definition: HistoryLog.h:56
void stampCommand()
Log info about the current process.
Definition: HistoryLog.cc:220
static void setRoot(const Pathname &root)
Set new root directory to the default history log file path.
Definition: HistoryLog.cc:163
void remove(const PoolItem &pi)
Log removal of a package.
Definition: HistoryLog.cc:261
static const Pathname & fname()
Get the current log file path.
Definition: HistoryLog.cc:179
void install(const PoolItem &pi)
Log installation (or update) of a package.
Definition: HistoryLog.cc:232
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Definition: HistoryLog.cc:188
Access to the sat-pools string space.
Definition: IdString.h:42
std::string asString() const
Conversion to std::string
Definition: IdString.h:91
Package interface.
Definition: Package.h:33
TraitsType::constPtrType constPtr
Definition: Package.h:38
Class representing a patch.
Definition: Patch.h:37
TraitsType::constPtrType constPtr
Definition: Patch.h:42
Parallel execution of stateful PluginScripts.
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
Command frame for communication with PluginScript.
Definition: PluginFrame.h:41
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:51
ResObject::constPtr resolvable() const
Returns the ResObject::constPtr.
Definition: PoolItem.cc:217
ResStatus & status() const
Returns the current status.
Definition: PoolItem.cc:204
sat::Solvable buddy() const
Return the buddy we share our status object with.
Definition: PoolItem.cc:206
Product interface.
Definition: Product.h:33
TraitsType::constPtrType constPtr
Definition: Product.h:38
Track changing files or directories.
Definition: RepoStatus.h:39
static RepoStatus fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
Definition: RepoStatus.cc:108
void saveToCookieFile(const Pathname &path_r) const
Save the status information to a cookie file.
Definition: RepoStatus.cc:126
bool solvablesEmpty() const
Whether Repository contains solvables.
Definition: Repository.cc:219
SolvableIterator solvablesEnd() const
Iterator behind the last Solvable.
Definition: Repository.cc:241
SolvableIterator solvablesBegin() const
Iterator to the first Solvable.
Definition: Repository.cc:231
size_type solvablesSize() const
Number of solvables in Repository.
Definition: Repository.cc:225
void addSolv(const Pathname &file_r)
Load Solvables from a solv-file.
Definition: Repository.cc:320
void eraseFromPool()
Remove this Repository from it's Pool.
Definition: Repository.cc:297
Global ResObject pool.
Definition: ResPool.h:61
static ResPool instance()
Singleton ctor.
Definition: ResPool.cc:33
void setHardLockQueries(const HardLockQueries &newLocks_r)
Set a new set of queries.
Definition: ResPool.cc:98
Resolver & resolver() const
The Resolver.
Definition: ResPool.cc:57
const LocaleSet & getRequestedLocales() const
Return the requested locales.
Definition: ResPool.cc:125
byKind_iterator byKindEnd(const ResKind &kind_r) const
Definition: ResPool.h:268
byKind_iterator byKindBegin(const ResKind &kind_r) const
Definition: ResPool.h:261
void getHardLockQueries(HardLockQueries &activeLocks_r)
Suggest a new set of queries based on the current selection.
Definition: ResPool.cc:101
bool isToBeInstalled() const
Definition: ResStatus.h:244
bool resetTransact(TransactByValue causer_r)
Not the same as setTransact( false ).
Definition: ResStatus.h:476
sat::Transaction getTransaction()
Return the Transaction computed by the last solver run.
Definition: Resolver.cc:74
bool upgradeMode() const
Definition: Resolver.cc:94
bool upgradingRepos() const
Whether there is at least one UpgradeRepo request pending.
Definition: Resolver.cc:133
SrcPackage interface.
Definition: SrcPackage.h:30
TraitsType::constPtrType constPtr
Definition: SrcPackage.h:36
Interim helper class to collect global options and settings.
Definition: ZConfig.h:60
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:125
std::string distroverpkg() const
Package telling the "product version" on systems not using /etc/product.d/baseproduct.
Definition: ZConfig.cc:1127
Options and policies for ZYpp::commit.
ZYppCommitPolicy & rpmInstFlags(target::rpm::RpmInstFlags newFlags_r)
The default target::rpm::RpmInstFlags.
ZYppCommitPolicy & rpmExcludeDocs(bool yesNo_r)
Use rpm option –excludedocs (default: false)
ZYppCommitPolicy & dryRun(bool yesNo_r)
Set dry run (default: false).
ZYppCommitPolicy & restrictToMedia(unsigned mediaNr_r)
Restrict commit to media 1.
ZYppCommitPolicy & allMedia()
Process all media (default)
ZYppCommitPolicy & downloadMode(DownloadMode val_r)
Commit download policy to use.
ZYppCommitPolicy & rpmNoSignature(bool yesNo_r)
Use rpm option –nosignature (default: false)
Result returned from ZYpp::commit.
TransactionStepList & rTransactionStepList()
Manipulate transactionStepList.
std::vector< sat::Transaction::Step > TransactionStepList
const sat::Transaction & transaction() const
The full transaction list.
sat::Transaction & rTransaction()
Manipulate transaction.
std::string receiveLine()
Read one line from the input stream.
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:246
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:123
const std::string & asString() const
String representation.
Definition: Pathname.h:90
bool empty() const
Test for an empty path.
Definition: Pathname.h:113
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Definition: Pathname.cc:235
const char * c_str() const
String representation.
Definition: Pathname.h:109
Provide a new empty temporary file and delete it when no longer needed.
Definition: TmpPath.h:127
static TmpFile makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:218
Pathname path() const
Definition: TmpPath.cc:146
Data returned by ProductFileReader.
bool empty() const
Whether this is an empty object without valid data.
static ProductFileData scanFile(const Pathname &file_r)
Parse one file (or symlink) and return the ProductFileData parsed.
Provides files from different repos.
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r) const
Provide SrcPackage in a local file.
Global sat-pool.
Definition: Pool.h:45
void setAutoInstalled(const Queue &autoInstalled_r)
Set ident list of all autoinstalled solvables.
Definition: Pool.cc:244
Pathname rootDir() const
Get rootdir (for file conflicts check)
Definition: Pool.cc:64
static Pool instance()
Singleton ctor.
Definition: Pool.h:53
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
Definition: Pool.cc:46
Repository systemRepo()
Return the system repository, create it if missing.
Definition: Pool.cc:157
void initRequestedLocales(const LocaleSet &locales_r)
Start tracking changes based on this locales_r.
Definition: Pool.cc:230
Libsolv Id queue wrapper.
Definition: Queue.h:35
detail::IdType value_type
Definition: Queue.h:38
void push(value_type val_r)
Push a value to the end off the Queue.
Definition: Queue.cc:103
A Solvable object within the sat Pool.
Definition: Solvable.h:54
A single step within a Transaction.
Definition: Transaction.h:217
StepType stepType() const
Type of action to perform in this step.
Definition: Transaction.cc:386
StepStage stepStage() const
Step action result.
Definition: Transaction.cc:389
Solvable satSolvable() const
Return the corresponding Solvable.
Definition: Transaction.h:241
Libsolv transaction wrapper.
Definition: Transaction.h:52
const_iterator end() const
Iterator behind the last TransactionStep.
Definition: Transaction.cc:341
StringQueue autoInstalled() const
Return the ident strings of all packages that would be auto-installed after the transaction is run.
Definition: Transaction.cc:356
const_iterator begin() const
Iterator to the first TransactionStep.
Definition: Transaction.cc:335
bool order()
Order transaction steps for commit.
Definition: Transaction.cc:326
@ TRANSACTION_MULTIINSTALL
[M] Install(multiversion) item (
Definition: Transaction.h:67
@ TRANSACTION_INSTALL
[+] Install(update) item
Definition: Transaction.h:66
@ TRANSACTION_IGNORE
[ ] Nothing (includes implicit deletes due to obsoletes and non-package actions)
Definition: Transaction.h:64
@ STEP_DONE
[OK] success
Definition: Transaction.h:74
@ STEP_ERROR
[**] error
Definition: Transaction.h:75
Target::commit helper optimizing package provision.
void setCommitList(std::vector< sat::Solvable > commitList_r)
Download(commit) sequence of solvables to compute read ahead.
bool preloaded() const
Whether preloaded hint is set.
ManagedFile get(const PoolItem &citem_r)
Provide a package.
void setData(const Data &data_r)
Store new Data.
Definition: HardLocksFile.h:73
const Data & data() const
Return the data.
Definition: HardLocksFile.h:57
pool::PoolTraits::HardLockQueries Data
Definition: HardLocksFile.h:41
Save and restore locale set from file.
void setLocales(const LocaleSet &locales_r)
Store a new locale set.
const LocaleSet & locales() const
Return the loacale set.
void tryLevel(target::rpm::InstallResolvableReport::RpmLevel level_r)
Extract and remember posttrans scripts for later execution.
bool collectScriptFromPackage(ManagedFile rpmPackage_r)
Extract and remember a packages posttrans script for later execution.
void executeScripts()
Execute te remembered scripts.
void discardScripts()
Discard all remembered scrips.
bool aborted() const
Returns true if removing is aborted during progress.
const Pathname & file() const
Return the file path.
Definition: SolvIdentFile.h:46
std::unordered_set< IdString > Data
Definition: SolvIdentFile.h:37
const Data & data() const
Return the data.
Definition: SolvIdentFile.h:53
void setData(const Data &data_r)
Store new Data.
Definition: SolvIdentFile.h:69
Base class for concrete Target implementations.
Definition: TargetImpl.h:54
std::string targetDistributionRelease() const
This is register.release attribute of the installed base product.
Definition: TargetImpl.cc:1747
std::string targetDistribution() const
This is register.target attribute of the installed base product.
Definition: TargetImpl.cc:1741
LocaleSet requestedLocales() const
Languages to be supported by the system.
Definition: TargetImpl.h:160
void updateAutoInstalled()
Update the database of autoinstalled packages.
Definition: TargetImpl.cc:1732
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Provides a source package on the Target.
Definition: TargetImpl.cc:1867
Pathname _root
Path to the target.
Definition: TargetImpl.h:213
RequestedLocalesFile _requestedLocalesFile
Requested Locales database.
Definition: TargetImpl.h:217
void createLastDistributionFlavorCache() const
generates a cache of the last product flavor
Definition: TargetImpl.cc:774
Date timestamp() const
return the last modification date of the target
Definition: TargetImpl.cc:1653
std::string _distributionVersion
Cache distributionVersion.
Definition: TargetImpl.h:223
std::list< PoolItem > PoolItemList
list of pool items
Definition: TargetImpl.h:59
rpm::RpmDb _rpm
RPM database.
Definition: TargetImpl.h:215
rpm::RpmDb & rpm()
The RPM database.
Definition: TargetImpl.cc:1642
Pathname solvfilesPath() const
The solv file location actually in use (default or temp).
Definition: TargetImpl.h:92
std::string distributionVersion() const
This is version attribute of the installed base product.
Definition: TargetImpl.cc:1777
void createAnonymousId() const
generates the unique anonymous id which is called when creating the target
Definition: TargetImpl.cc:752
SolvIdentFile _autoInstalledFile
user/auto installed database
Definition: TargetImpl.h:219
Product::constPtr baseProduct() const
returns the target base installed product, also known as the distribution or platform.
Definition: TargetImpl.cc:1711
Target::DistributionLabel distributionLabel() const
This is shortName and summary attribute of the installed base product.
Definition: TargetImpl.cc:1759
virtual ~TargetImpl()
Dtor.
Definition: TargetImpl.cc:810
bool providesFile(const std::string &path_str, const std::string &name_str) const
If the package is installed and provides the file Needed to evaluate split provides during Resolver::...
Definition: TargetImpl.cc:1647
HardLocksFile _hardLocksFile
Hard-Locks database.
Definition: TargetImpl.h:221
Pathname root() const
The root set for this target.
Definition: TargetImpl.h:116
void load(bool force=true)
Definition: TargetImpl.cc:989
std::string distributionFlavor() const
This is flavor attribute of the installed base product but does not require the target to be loaded a...
Definition: TargetImpl.cc:1818
void installSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
Definition: TargetImpl.cc:1856
ZYppCommitResult commit(ResPool pool_r, const ZYppCommitPolicy &policy_r)
Commit changes in the pool.
Definition: TargetImpl.cc:1094
Pathname home() const
The directory to store things.
Definition: TargetImpl.h:120
void commitFindFileConflicts(const ZYppCommitPolicy &policy_r, ZYppCommitResult &result_r)
Commit helper checking for file conflicts after download.
Pathname defaultSolvfilesPath() const
The systems default solv file location.
Definition: TargetImpl.cc:823
std::string anonymousUniqueId() const
anonymous unique id
Definition: TargetImpl.cc:1844
bool solvfilesPathIsTemp() const
Whether we're using a temp.
Definition: TargetImpl.h:96
std::string targetDistributionFlavor() const
This is register.flavor attribute of the installed base product.
Definition: TargetImpl.cc:1753
Interface to the rpm program.
Definition: RpmDb.h:48
Date timestamp() const
timestamp of the rpm database (last modification)
Definition: RpmDb.cc:261
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
Definition: RpmDb.cc:1916
void initDatabase(Pathname root_r=Pathname(), Pathname dbPath_r=Pathname(), bool doRebuild_r=false)
Prepare access to the rpm database.
Definition: RpmDb.cc:315
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
Definition: RpmDb.cc:2103
void closeDatabase()
Block further access to the rpm database and go back to uninitialized state.
Definition: RpmDb.cc:713
bool hasFile(const std::string &file_r, const std::string &name_r="") const
Return true if at least one package owns a certain file (name_r empty) Return true if package name_r ...
Definition: RpmDb.cc:1298
Subclass to retrieve database content.
Definition: librpmDb.h:491
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
Definition: librpmDb.cc:826
Definition: Arch.h:345
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
Definition: PathInfo.cc:1045
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:589
int unlink(const Pathname &path)
Like 'unlink'.
Definition: PathInfo.cc:653
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
Definition: PathInfo.cc:695
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
Definition: PathInfo.cc:413
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
Definition: PathInfo.cc:1054
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
Definition: PathInfo.cc:877
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:320
std::string md5sum(const Pathname &file)
Compute a files md5sum.
Definition: PathInfo.cc:977
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
std::string toJSON(const sat::Transaction::Step &step_r)
See COMMITBEGIN (added in v1) on page Commit plugin for the specs.
Definition: TargetImpl.cc:98
SolvableIdType size_type
Definition: PoolMember.h:152
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
Definition: Pool.cc:263
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1037
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
Definition: String.h:1095
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition: String.cc:175
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t", bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
Definition: String.h:578
std::string trim(const std::string &s, const Trim trim_r)
Definition: String.cc:221
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
Definition: TargetImpl.cc:668
void updateFileContent(const Pathname &filename, boost::function< bool()> condition, boost::function< string()> value)
updates the content of filename if condition is true, setting the content the the value returned by v...
Definition: TargetImpl.cc:712
void writeUpgradeTestcase()
Definition: TargetImpl.cc:247
static bool fileMissing(const Pathname &pathname)
helper functor
Definition: TargetImpl.cc:747
static std::string generateRandomId()
generates a random id using uuidgen
Definition: TargetImpl.cc:701
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
std::unordered_set< Locale > LocaleSet
Definition: Locale.h:27
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
Definition: ResObject.cc:44
std::list< UpdateNotificationFile > UpdateNotifications
@ DownloadInHeaps
Similar to DownloadInAdvance, but try to split the transaction into heaps, where at the end of each h...
Definition: DownloadMode.h:29
@ DownloadOnly
Just download all packages to the local cache.
Definition: DownloadMode.h:25
@ DownloadAsNeeded
Alternating download and install.
Definition: DownloadMode.h:32
@ DownloadDefault
libzypp will decide what to do.
Definition: DownloadMode.h:24
JSON array.
Definition: Json.h:257
std::string asJSON() const
JSON representation.
Definition: Json.h:279
void add(const Value &val_r)
Push JSON Value to Array.
Definition: Json.h:271
JSON object.
Definition: Json.h:322
void add(const String &key_r, const Value &val_r)
Add key/value pair.
Definition: Json.h:336
std::string asJSON() const
JSON representation.
Definition: Json.h:344
bool isKind(const ResKind &kind_r) const
Definition: SolvableType.h:64
Solvable satSolvable() const
Return the corresponding sat::Solvable.
Definition: SolvableType.h:57