libzypp  17.37.10
ZYppCommitPolicy.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <iostream>
14 
15 #include <zypp-core/base/String.h>
16 #include <zypp-core/base/StringV.h>
17 
18 #include <zypp/ZConfig.h>
19 #include <zypp-core/APIConfig.h>
20 #include <zypp/ZYppCommitPolicy.h>
22 #include <zypp-core/TriBool.h>
23 #include <zypp/PathInfo.h>
24 #include <zypp/ZYppCallbacks.h>
25 #include <zypp/ZYppFactory.h>
26 
28 namespace zypp
29 {
30 
32 #ifdef SUSE
33 
34 #if APIConfig(LIBZYPP_CONFIG_USE_CLASSIC_RPMTRANS_BY_DEFAULT)
35  // In old codebases it can be explicitly enabled for zypper only via ZYPP_SINGLE_RPMTRANS.
36  inline bool ImZYPPER()
37  {
38  static bool ret = filesystem::readlink( "/proc/self/exe" ).basename() == "zypper";
39  return ret;
40  }
41  inline bool singleTransInEnv()
42  {
43  const char *val = ::getenv("ZYPP_SINGLE_RPMTRANS");
44  return ( val && str::strToFalse( val ) );
45  }
46  inline bool singleTransEnabled()
47  { return ImZYPPER() && singleTransInEnv(); }
48 #else
49  // SUSE using singletrans as default may allow to explicitly disable it via ZYPP_SINGLE_RPMTRANS.
50  // NOTE: singleTransInEnv() here is no real enablement because it defaults to false
51  // if ZYPP_SINGLE_RPMTRANS is undefined. By now it just allows using singletrans
52  // with all applications, not just zypper. In case it actually becomes the
53  // default on SUSE, we may just want a method to explicitly disable it.
54  inline bool singleTransInEnv()
55  {
56  const char *val = ::getenv("ZYPP_SINGLE_RPMTRANS");
57  return ( val && str::strToFalse( val ) );
58  }
59  inline bool singleTransEnabled()
60  { return singleTransInEnv(); }
61 #endif
62 
63 #else // not SUSE
64  inline bool singleTransEnabled()
65  { return true; }
66 #endif
67 
69  inline bool isPreUsrmerge( const Pathname & root_r )
70  {
71  // If systems /lib is a directory and not a symlink.
72  return PathInfo( root_r / "lib", PathInfo::LSTAT ).isDir();
73  }
74 
76  {
77  // A package providing "may-perform-usrmerge" is going to be installed.
78  const sat::WhatProvides q { Capability("may-perform-usrmerge") };
79  for ( const auto & pi : q.poolItem() ) {
80  if ( pi.status().isToBeInstalled() )
81  return true;
82  }
83  return false;
84  }
85 
86  inline bool pendingUsrmerge()
87  {
88 #if 1
89  // introduced solely for the use in QA test for Code16
90  const char *val = ::getenv("ZYPP_NO_USRMERGE_PROTECT");
91  if ( val && str::strToTrue( val ) )
92  return false;
93 #endif
94 
95  // NOTE: Bug 1189788 - UsrMerge: filesystem package breaks system when
96  // upgraded in a single rpm transaction. Target::Commit must amend this
97  // request depending on whether a UsrMerge may be performed by the
98  // transaction.
99  Target_Ptr target { getZYpp()->getTarget() };
100  bool ret = target && isPreUsrmerge( target->root() ) && transactionWillUsrmerge();
101  return ret;
102  }
103 
105  //
106  // CLASS NAME : ZYppCommitPolicy::Impl
107  //
109 
111  {
112  public:
114  : _restrictToMedia ( 0 )
115  , _downloadMode ( ZConfig::instance().commit_downloadMode() )
116  , _rpmInstFlags ( ZConfig::instance().rpmInstallFlags() )
117  , _syncPoolAfterCommit ( true )
119  {}
120 
121  public:
124  target::rpm::RpmInstFlags _rpmInstFlags;
127 
128  mutable bool _notifyBSC1189788 = true; // mutable: send notification just once
129 
130  private:
131  friend Impl * rwcowClone<Impl>( const Impl * rhs );
133  Impl * clone() const { return new Impl( *this ); }
134  };
135 
137  //
138  // CLASS NAME : ZYppCommitPolicy
139  //
141 
143  : _pimpl( new Impl )
144  {}
145 
146 
148  { _pimpl->_restrictToMedia = ( mediaNr_r == 1 ) ? 1 : 0; return *this; }
149 
151  { return _pimpl->_restrictToMedia; }
152 
153 
155  { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_TEST, yesNo_r ); return *this; }
156 
158  { return _pimpl->_rpmInstFlags.testFlag( target::rpm::RPMINST_TEST );}
159 
161  { _pimpl->_downloadMode = val_r; return *this; }
162 
164  { return _pimpl->_downloadMode; }
165 
166  ZYppCommitPolicy & ZYppCommitPolicy::rpmInstFlags( target::rpm::RpmInstFlags newFlags_r )
167  { _pimpl->_rpmInstFlags = newFlags_r; return *this; }
168 
170  { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_NOSIGNATURE, yesNo_r ); return *this; }
171 
173  { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_EXCLUDEDOCS, yesNo_r ); return *this; }
174 
175  target::rpm::RpmInstFlags ZYppCommitPolicy::rpmInstFlags() const
176  { return _pimpl->_rpmInstFlags; }
177 
179  { return _pimpl->_rpmInstFlags.testFlag( target::rpm::RPMINST_NOSIGNATURE ); }
180 
182  { return _pimpl->_rpmInstFlags.testFlag( target::rpm::RPMINST_EXCLUDEDOCS ); }
183 
185  { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_ALLOWDOWNGRADE, yesNo_r ); return *this; }
186 
189 
191  { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_REPLACEFILES, yesNo_r ); return *this; }
192 
195 
197  { _pimpl->_syncPoolAfterCommit = yesNo_r; return *this; }
198 
200  { return _pimpl->_syncPoolAfterCommit; }
201 
203  {
204  if ( _pimpl->_singleTransMode ) {
205  // Explicitly selecting DownloadAsNeeded also selects the classic_rpmtrans backend.
206  // NOTE: This behavior was negotiated with YAST/Agama and is required for
207  // certain install scenarios. Don't change it without checking with the teams.
209  MIL << "DownloadAsNeeded enforces the classic_rpmtrans backend!" << std::endl;
210  return false;
211  }
212 
213  if ( pendingUsrmerge() ) {
214  WAR << "Ignore $ZYPP_SINGLE_RPMTRANS=1: Bug 1189788 - UsrMerge: filesystem package breaks system when upgraded in a single rpm transaction" << std::endl;
215  if ( _pimpl->_notifyBSC1189788 ) {
216  _pimpl->_notifyBSC1189788 = false;
218  "[bsc#1189788] The filesystem package seems to be unable to perform the pending\n"
219  " UsrMerge reliably in a single transaction. The single_rpmtrans\n"
220  " backend will therefore be IGNORED and the transaction is performed\n"
221  " by the classic_rpmtrans backend."
222  , JobReport::UserData( "cmdout", "[bsc#1189788]" ) );
223  }
224  return false;
225  }
226  }
227  return _pimpl->_singleTransMode;
228  }
229 
230  std::ostream & operator<<( std::ostream & str, const ZYppCommitPolicy & obj )
231  {
232  str << "CommitPolicy(";
233  if ( obj.restrictToMedia() )
234  str << " restrictToMedia:" << obj.restrictToMedia();
235  if ( obj.dryRun() )
236  str << " dryRun";
237  str << " " << obj.downloadMode();
238  if ( obj.syncPoolAfterCommit() )
239  str << " syncPoolAfterCommit";
240  if ( obj.rpmInstFlags() )
241  str << " rpmInstFlags{" << str::hexstring(obj.rpmInstFlags()) << "}";
242  return str << " )";
243  }
244 
246 } // namespace zypp
bool strToFalse(const C_Str &str)
Return false if str is 0, false, no, off, never.
Definition: String.cc:84
#define MIL
Definition: Logger.h:100
DownloadMode downloadMode() const
Container of Solvable providing a Capability (read only).
Definition: WhatProvides.h:87
Alternating download and install.
Definition: DownloadMode.h:34
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like &#39;readlink&#39;.
Definition: PathInfo.cc:929
ZYppCommitPolicy & rpmInstFlags(target::rpm::RpmInstFlags newFlags_r)
The default target::rpm::RpmInstFlags.
ZYppCommitPolicy & dryRun(bool yesNo_r)
Set dry run (default: false).
String related utilities and Regular expression matching.
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
Definition: SerialNumber.cc:52
bool singleTransEnabled()
target::rpm::RpmInstFlags rpmInstFlags() const
bool transactionWillUsrmerge()
Options and policies for ZYpp::commit.
ZYppCommitPolicy & downloadMode(DownloadMode val_r)
Commit download policy to use.
Interim helper class to collect global options and settings.
Definition: ZConfig.h:68
#define WAR
Definition: Logger.h:101
ZYppCommitPolicy & syncPoolAfterCommit(bool yesNo_r)
Kepp pool in sync with the Target databases after commit (default: true)
bool pendingUsrmerge()
ZYppCommitPolicy & restrictToMedia(unsigned mediaNr_r)
Restrict commit to media 1.
Impl * clone() const
clone for RWCOW_pointer
RWCOW_pointer< Impl > _pimpl
Pointer to data.
A sat capability.
Definition: Capability.h:62
bool isPreUsrmerge(const Pathname &root_r)
Typesafe passing of user data via callbacks.
Definition: UserData.h:39
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:225
bool singleTransModeEnabled() const
Whether the single_rpmtrans backend is enabled (or the classic_rpmtrans)
static bool info(const std::string &msg_r, const UserData &userData_r=UserData())
send message text
bool syncPoolAfterCommit() const
target::rpm::RpmInstFlags _rpmInstFlags
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
std::string hexstring(char n, int w=4)
Definition: String.h:325
unsigned restrictToMedia() const
DownloadMode
Supported commit download policies.
Definition: DownloadMode.h:24
bool strToTrue(const C_Str &str)
Parsing boolean from string.
Definition: String.cc:66