libzypp  17.35.11
RepoStatus.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <sstream>
14 #include <fstream>
15 #include <optional>
16 #include <set>
17 #include <zypp/base/Logger.h>
18 #include <zypp/base/String.h>
19 #include <zypp/RepoStatus.h>
20 #include <zypp/RepoInfo.h>
21 #include <zypp/PathInfo.h>
22 
23 using std::endl;
24 
26 namespace zypp
27 {
29  namespace
30  {
32  void recursiveTimestamp( const Pathname & dir_r, time_t & max_r )
33  {
34  std::list<std::string> dircontent;
35  if ( filesystem::readdir( dircontent, dir_r, false/*no dots*/ ) != 0 )
36  return; // readdir logged the error
37 
38  for_( it, dircontent.begin(), dircontent.end() )
39  {
40  PathInfo pi( dir_r + *it, PathInfo::LSTAT );
41  if ( pi.isDir() )
42  {
43  if ( pi.mtime() > max_r )
44  max_r = pi.mtime();
45  recursiveTimestamp( pi.path(), max_r );
46  }
47  }
48  }
49  } // namespace
51 
53  //
54  // CLASS NAME : RepoStatus::Impl
55  //
58  {
59  using Checksums = std::set<std::string>;
60 
61  public:
69  void assignFromCtor( std::string && checksum_r, Date && timestamp_r )
70  {
71  if ( !checksum_r.empty() ) {
72  static const std::string magic( "43" );
73  checksum_r += magic;
74  _checksums.insert( std::move(checksum_r) );
75  }
76  _timestamp = std::move(timestamp_r);
77  }
78 
80  void inject( std::string && checksum_r, Date && timestamp_r )
81  {
82  if ( !checksum_r.empty() ) {
83  _checksums.insert( std::move(checksum_r) );
84  _cachedchecksum.reset();
85  }
86 
87  if ( timestamp_r > _timestamp )
88  _timestamp = std::move(timestamp_r);
89  }
90 
92  void injectFrom( const Impl & rhs )
93  {
94  if ( &rhs == this ) // no self insert
95  return;
96 
97  if ( !rhs._checksums.empty() ) {
98  _checksums.insert( rhs._checksums.begin(), rhs._checksums.end() );
99  _cachedchecksum.reset();
100  }
101 
102  if ( rhs._timestamp > _timestamp )
103  _timestamp = rhs._timestamp;
104  }
105 
106  bool empty() const
107  { return _checksums.empty(); }
108 
109  std::string checksum() const
110  {
111  std::string ret;
112  if ( _checksums.empty() )
113  return ret;
114 
115  if ( _checksums.size() == 1 )
116  ret = *_checksums.begin();
117  else {
118  if ( !_cachedchecksum ) {
119  std::stringstream ss;
120  for ( std::string_view c : _checksums )
121  ss << c;
123  }
124  ret = *_cachedchecksum;
125  }
126  return ret;
127  }
128 
129  Date timestamp() const
130  { return _timestamp; }
131 
133  std::ostream & dumpOn( std::ostream & str ) const
134  { return str << ( empty() ? "NO_REPOSTATUS" : checksum() ) << " " << time_t(_timestamp); }
135 
136  public:
137  void assignFromCookieFile( const Pathname & path_r, bool useMtime_r = false )
138  {
139  std::ifstream file( path_r.c_str() );
140  if ( not file ) {
141  WAR << "No cookie file " << path_r << endl;
142  return;
143  }
144  // line := "[checksum] time_t" !!! ALWAYS strip time from line
145  std::string line { str::getline( file ) };
146  const std::string & time { str::stripLastWord( line ) };
147 
148  Date stmp { useMtime_r ? PathInfo( path_r ).mtime() : str::strtonum<time_t>( time ) };
149  inject( std::move(line), std::move(stmp) ); // raw inject to avoid magic being added
150  }
151 
152  private:
155 
156  mutable std::optional<std::string> _cachedchecksum;
157 
158  private:
159  friend Impl * rwcowClone<Impl>( const Impl * rhs );
161  Impl * clone() const
162  { return new Impl( *this ); }
163  };
165 
167  //
168  // CLASS NAME : RepoStatus
169  //
171 
173  : _pimpl( new Impl() )
174  {}
175 
177  : _pimpl( new Impl() )
178  {
179  PathInfo info( path_r );
180  if ( info.isExist() )
181  {
182  if ( info.isFile() )
183  {
184  _pimpl->assignFromCtor( filesystem::sha1sum( path_r ), Date( info.mtime() ) );
185  }
186  else if ( info.isDir() )
187  {
188  time_t t = info.mtime();
189  recursiveTimestamp( path_r, t );
191  }
192  }
193  }
194 
196  : _pimpl( new Impl() )
197  {
199  }
200 
201  RepoStatus::RepoStatus( std::string checksum_r, Date timestamp_r )
202  : _pimpl( new Impl() )
203  {
204  _pimpl->assignFromCtor( std::move(checksum_r), std::move(timestamp_r) );
205  }
206 
208  {}
209 
211  {
212  RepoStatus ret;
213  ret._pimpl->assignFromCookieFile( path_r );
214  return ret;
215  }
216 
218  {
219  RepoStatus ret;
220  ret._pimpl->assignFromCookieFile( path_r, /*useMtime*/true );
221  return ret;
222  }
223 
224  void RepoStatus::saveToCookieFile( const Pathname & path_r ) const
225  {
226  std::ofstream file(path_r.c_str());
227  if (!file) {
228  ZYPP_THROW (Exception( "Can't open " + path_r.asString() ) );
229  }
230  file << _pimpl->checksum() << " " << time_t(_pimpl->timestamp()) << endl;
231  file.close();
232  }
233 
234  bool RepoStatus::empty() const
235  { return _pimpl->empty(); }
236 
238  { return _pimpl->timestamp(); }
239 
240  std::ostream & operator<<( std::ostream & str, const RepoStatus & obj )
241  { return obj._pimpl->dumpOn( str ); }
242 
243  RepoStatus operator&&( const RepoStatus & lhs, const RepoStatus & rhs )
244  {
245  RepoStatus result { lhs };
246  result._pimpl->injectFrom( *rhs._pimpl );
247  return result;
248  }
249 
250  bool operator==( const RepoStatus & lhs, const RepoStatus & rhs )
251  { return lhs._pimpl->checksum() == rhs._pimpl->checksum(); }
252 
254 } // namespace zypp
std::set< std::string > Checksums
Definition: RepoStatus.cc:59
bool empty() const
Whether the status is empty (empty checksum)
Definition: RepoStatus.cc:234
std::string getline(std::istream &str, const Trim trim_r)
Return stream content up to (but not returning) the next newline.
Definition: String.cc:479
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:424
std::string sha1sum(const Pathname &file)
Compute a files sha1sum.
Definition: PathInfo.cc:1046
void injectFrom(const Impl &rhs)
Inject the raw data from rhs.
Definition: RepoStatus.cc:92
std::string checksum() const
Definition: CheckSum.cc:170
void inject(std::string &&checksum_r, Date &&timestamp_r)
Inject raw data (no magic added).
Definition: RepoStatus.cc:80
std::ostream & dumpOn(std::ostream &str) const
Dump to log file (not to/from CookieFile).
Definition: RepoStatus.cc:133
void assignFromCookieFile(const Pathname &path_r, bool useMtime_r=false)
Definition: RepoStatus.cc:137
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
time_t mtime() const
Definition: PathInfo.h:377
const char * c_str() const
String representation.
Definition: Pathname.h:112
String related utilities and Regular expression matching.
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
Definition: SerialNumber.cc:52
What is known about a repository.
Definition: RepoInfo.h:71
bool operator==(const SetRelation::Enum &lhs, const SetCompare &rhs)
RepoStatus()
Default ctor.
Definition: RepoStatus.cc:172
static RepoStatus fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
Definition: RepoStatus.cc:210
Url url() const
Pars pro toto: The first repository url.
Definition: RepoInfo.h:136
void saveToCookieFile(const Pathname &path_r) const
Save the status information to a cookie file.
Definition: RepoStatus.cc:224
Store and operate on date (time_t).
Definition: Date.h:32
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:501
static RepoStatus fromCookieFileUseMtime(const Pathname &path)
Reads the status from a cookie file but uses the files mtime.
Definition: RepoStatus.cc:217
void assignFromCtor(std::string &&checksum_r, Date &&timestamp_r)
Assign data called from RepoStatus ctor (adds magic).
Definition: RepoStatus.cc:69
const std::string & asString() const
String representation.
Definition: Pathname.h:93
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:282
#define WAR
Definition: Logger.h:99
Date timestamp() const
Definition: RepoStatus.cc:129
std::string stripLastWord(std::string &line, const bool rtrim_first)
Definition: String.cc:297
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:610
std::string numstring(char n, int w=0)
Definition: String.h:289
std::optional< std::string > _cachedchecksum
Definition: RepoStatus.cc:156
RepoStatus implementation.
Definition: RepoStatus.cc:57
~RepoStatus()
Dtor.
Definition: RepoStatus.cc:207
Base class for Exception.
Definition: Exception.h:146
Date timestamp() const
The time the data were changed the last time.
Definition: RepoStatus.cc:237
std::string checksum(const Pathname &file, const std::string &algorithm)
Compute a files checksum.
Definition: PathInfo.cc:1056
RWCOW_pointer< Impl > _pimpl
Implementation.
Definition: RepoStatus.h:105
Impl * clone() const
clone for RWCOW_pointer
Definition: RepoStatus.cc:161
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
static CheckSum sha1(const std::string &checksum)
Definition: CheckSum.h:75
Track changing files or directories.
Definition: RepoStatus.h:40
RepoStatus operator &&(const RepoStatus &lhs, const RepoStatus &rhs)
Definition: RepoStatus.cc:243
std::string checksum() const
Definition: RepoStatus.cc:109
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
static CheckSum sha1FromString(const std::string &input_r)
Definition: CheckSum.h:105