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