--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/target/SolvIdentFile.cc
+ *
+*/
+#include <iostream>
+#include <fstream>
+
+#include "zypp/base/LogTools.h"
+#include "zypp/base/IOStream.h"
+#include "zypp/base/String.h"
+
+#include "zypp/PathInfo.h"
+#include "zypp/TmpPath.h"
+#include "zypp/Date.h"
+
+#include "zypp/target/SolvIdentFile.h"
+
+using std::endl;
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{ /////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+ namespace target
+ { /////////////////////////////////////////////////////////////////
+
+ void SolvIdentFile::load( const Pathname & file_r, Data & data_r )
+ {
+ PathInfo pi( file_r );
+ if ( ! pi.isFile() )
+ {
+ WAR << "Can't read " << pi << endl;
+ return;
+ }
+ std::ifstream infile( file_r.c_str() );
+ for( iostr::EachLine in( infile ); in; in.next() )
+ {
+ std::string l( str::trim(*in) );
+ if ( ! l.empty() && l[0] != '#' )
+ {
+ data_r.insert( IdString(l) );
+ }
+ }
+ MIL << "Read " << pi << endl;
+ }
+
+ void SolvIdentFile::store( const Pathname & file_r, const Data & data_r )
+ {
+ filesystem::TmpFile tmp( filesystem::TmpFile::makeSibling( file_r ) );
+ filesystem::chmod( tmp.path(), 0644 );
+
+ std::ofstream outs( tmp.path().c_str() );
+ outs << "# " << file_r.basename() << " generated " << Date::now() << endl;
+ dumpRange( outs, data_r.begin(), data_r.end(), "#", "\n", "\n", "\n", "#\n" );
+ outs.close();
+
+ if ( outs.good() )
+ {
+ filesystem::rename( tmp.path(), file_r );
+ MIL << "Wrote " << PathInfo(file_r) << endl;
+ }
+ else
+ {
+ ERR << "Can't write " << PathInfo(tmp.path()) << endl;
+ }
+ }
+
+ /******************************************************************
+ **
+ ** FUNCTION NAME : operator<<
+ ** FUNCTION TYPE : std::ostream &
+ */
+ std::ostream & operator<<( std::ostream & str, const SolvIdentFile & obj )
+ {
+ str << obj.file() << ' ';
+ if ( obj._dataPtr )
+ str << obj.data();
+ else
+ str << "(unloaded)";
+ return str;
+ }
+
+ /////////////////////////////////////////////////////////////////
+ } // namespace target
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/target/SolvIdentFile.h
+ *
+*/
+#ifndef ZYPP_TARGET_SOLVIDENTFILE_H
+#define ZYPP_TARGET_SOLVIDENTFILE_H
+
+#include <iosfwd>
+
+#include "zypp/base/PtrTypes.h"
+
+#include "zypp/IdString.h"
+#include "zypp/Pathname.h"
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{ /////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+ namespace target
+ { /////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ /// \class SolvIdentFile
+ /// \short Save and restore a list of solvable names (ident IdString)
+ ///////////////////////////////////////////////////////////////////
+ class SolvIdentFile
+ {
+ friend std::ostream & operator<<( std::ostream & str, const SolvIdentFile & obj );
+ public:
+ typedef std::tr1::unordered_set<IdString> Data;
+
+ public:
+ /** Ctor taking the file to read/write. */
+ SolvIdentFile( const Pathname & file_r )
+ : _file( file_r )
+ {}
+
+ /** Return the file path. */
+ const Pathname & file() const
+ { return _file; }
+
+ /** Return the data.
+ * The file is read once on demand. Returns empty \ref Data if
+ * the file does not exist or is not readable.
+ */
+ const Data & data() const
+ {
+ if ( !_dataPtr )
+ {
+ _dataPtr.reset( new Data );
+ Data & mydata( *_dataPtr );
+ load( _file, mydata );
+ }
+ return *_dataPtr;
+ }
+
+ /** Store new \ref Data.
+ * Write the new \ref Data to file, unless we know it
+ * did not change. The directory containing file must
+ * exist.
+ */
+ void setData( const Data & data_r )
+ {
+ if ( !_dataPtr )
+ _dataPtr.reset( new Data );
+
+ if ( differs( *_dataPtr, data_r ) )
+ {
+ store( _file, data_r );
+ *_dataPtr = data_r;
+ }
+ }
+
+ private:
+ /** Helper testing whether two \ref Data differ. */
+ bool differs( const Data & lhs, const Data & rhs ) const
+ {
+
+ if ( lhs.size() != rhs.size() )
+ return true;
+ for_( it, lhs.begin(), lhs.end() )
+ {
+ if ( rhs.find( *it ) == rhs.end() )
+ return true;
+ }
+ return false;
+ }
+ /** Read \ref Data from \c file_r. */
+ static void load( const Pathname & file_r, Data & data_r );
+ /** Write \ref Data to \c file_r. */
+ static void store( const Pathname & file_r, const Data & data_r );
+
+ private:
+ Pathname _file;
+ mutable scoped_ptr<Data> _dataPtr;
+ };
+ ///////////////////////////////////////////////////////////////////
+
+ /** \relates SolvIdentFile Stream output */
+ std::ostream & operator<<( std::ostream & str, const SolvIdentFile & obj );
+
+ /////////////////////////////////////////////////////////////////
+ } // namespace target
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP_TARGET_SOLVIDENTFILE_H