1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/RepoStatus.cc
15 #include <zypp/base/Logger.h>
16 #include <zypp/base/String.h>
17 #include <zypp/RepoStatus.h>
18 #include <zypp/PathInfo.h>
22 ///////////////////////////////////////////////////////////////////
24 { /////////////////////////////////////////////////////////////////
26 ///////////////////////////////////////////////////////////////////
28 // CLASS NAME : RepoStatus::Impl
30 /** RepoStatus implementation. */
31 struct RepoStatus::Impl
34 std::string _checksum;
37 // NOTE: Changing magic will at once invalidate all solv file caches.
38 // Helpfull if solv file content must be refreshed (e.g. due to different
39 // repo2* arguments) even if raw metadata are unchanged.
40 // Only values set from a RepoStatus ctor need magic to be added.
41 void assignFromCtor( std::string && checksum_r, Date && timestamp_r )
43 _checksum = std::move(checksum_r);
44 _timestamp = std::move(timestamp_r);
45 if ( !_checksum.empty() )
47 static const std::string magic( "43" );
52 /** Recursive computation of max dir timestamp. */
53 static void recursive_timestamp( const Pathname & dir_r, time_t & max_r )
55 std::list<std::string> dircontent;
56 if ( filesystem::readdir( dircontent, dir_r, false/*no dots*/ ) != 0 )
57 return; // readdir logged the error
59 for_( it, dircontent.begin(), dircontent.end() )
61 PathInfo pi( dir_r + *it, PathInfo::LSTAT );
64 if ( pi.mtime() > max_r )
66 recursive_timestamp( pi.path(), max_r );
72 friend Impl * rwcowClone<Impl>( const Impl * rhs );
73 /** clone for RWCOW_pointer */
75 { return new Impl( *this ); }
77 ///////////////////////////////////////////////////////////////////
79 /** \relates RepoStatus::Impl Stream output */
80 inline std::ostream & operator<<( std::ostream & str, const RepoStatus::Impl & obj )
81 { return str << obj._checksum << " " << (time_t)obj._timestamp; }
83 ///////////////////////////////////////////////////////////////////
85 // CLASS NAME : RepoStatus
87 ///////////////////////////////////////////////////////////////////
89 RepoStatus::RepoStatus()
90 : _pimpl( new Impl() )
93 RepoStatus::RepoStatus( const Pathname & path_r )
94 : _pimpl( new Impl() )
96 PathInfo info( path_r );
101 _pimpl->assignFromCtor( filesystem::sha1sum( path_r ), Date( info.mtime() ) );
103 else if ( info.isDir() )
105 time_t t = info.mtime();
106 Impl::recursive_timestamp( path_r, t );
107 _pimpl->assignFromCtor( CheckSum::sha1FromString( str::numstring( t ) ).checksum(), Date( t ) );
112 RepoStatus::RepoStatus( std::string checksum_r, Date timestamp_r )
113 : _pimpl( new Impl() )
115 _pimpl->assignFromCtor( std::move(checksum_r), std::move(timestamp_r) );
118 RepoStatus::~RepoStatus()
121 RepoStatus RepoStatus::fromCookieFile( const Pathname & path_r )
124 std::ifstream file( path_r.c_str() );
127 WAR << "No cookie file " << path_r << endl;
131 // line := "[checksum] time_t"
132 std::string line( str::getline( file ) );
133 ret._pimpl->_timestamp = Date( str::strtonum<time_t>( str::stripLastWord( line ) ) );
134 ret._pimpl->_checksum = line;
139 void RepoStatus::saveToCookieFile( const Pathname & path_r ) const
141 std::ofstream file(path_r.c_str());
143 ZYPP_THROW (Exception( "Can't open " + path_r.asString() ) );
145 file << _pimpl->_checksum << " " << (time_t)_pimpl->_timestamp << endl;
149 bool RepoStatus::empty() const
150 { return _pimpl->_checksum.empty(); }
152 Date RepoStatus::timestamp() const
153 { return _pimpl->_timestamp; }
155 std::ostream & operator<<( std::ostream & str, const RepoStatus & obj )
156 { return str << *obj._pimpl; }
158 RepoStatus operator&&( const RepoStatus & lhs, const RepoStatus & rhs )
164 else if ( rhs.empty() )
168 // order strings to assert && is kommutativ
169 std::string lchk( lhs._pimpl->_checksum );
170 std::string rchk( rhs._pimpl->_checksum );
171 std::stringstream ss( lchk < rchk ? lchk+rchk : rchk+lchk );
173 result._pimpl->_checksum = CheckSum::sha1(ss).checksum();
174 result._pimpl->_timestamp = std::max( lhs._pimpl->_timestamp, rhs._pimpl->_timestamp );
179 bool operator==( const RepoStatus & lhs, const RepoStatus & rhs )
180 { return lhs._pimpl->_checksum == rhs._pimpl->_checksum; }
182 /////////////////////////////////////////////////////////////////
184 ///////////////////////////////////////////////////////////////////