#include "zypp/base/UserRequestException.h"
#include "zypp/ZConfig.h"
+#include "zypp/ZYppFactory.h"
#include "zypp/PoolItem.h"
#include "zypp/ResObjects.h"
createAnonymousId();
-
MIL << "Initialized target on " << _root << endl;
}
MIL << "Targets closed" << endl;
}
+ ///////////////////////////////////////////////////////////////////
+ //
+ // solv file handling
+ //
+ ///////////////////////////////////////////////////////////////////
+
+ Pathname TargetImpl::defaultSolvfilesPath() const
+ {
+ return Pathname::assertprefix( _root, ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoAlias() );
+ }
+
void TargetImpl::clearCache()
{
- Pathname base = Pathname::assertprefix( _root,
- ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoAlias() );
+ Pathname base = solvfilesPath();
filesystem::recursive_rmdir( base );
}
void TargetImpl::buildCache()
{
- Pathname base = Pathname::assertprefix( _root,
- ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoAlias() );
+ Pathname base = solvfilesPath();
Pathname rpmsolv = base/"solv";
Pathname rpmsolvcookie = base/"cookie";
if ( build_rpm_solv )
{
- // Take care we unlink the solvfile on exception
- ManagedFile guard( base, filesystem::recursive_rmdir );
-
- // if it does not exist yet, we better create it
+ // if the solvfile dir does not exist yet, we better create it
filesystem::assert_dir( base );
+ Pathname oldSolvFile( solvexisted ? rpmsolv : Pathname() ); // to speedup rpmdb2solv
+
filesystem::TmpFile tmpsolv( filesystem::TmpFile::makeSibling( rpmsolv ) );
- if (!tmpsolv)
+ if ( !tmpsolv )
{
+ // Can't create temporary solv file, usually due to insufficient permission
+ // (user query while @System solv needs refresh). If so, try switching
+ // to a location within zypps temp. space (will be cleaned at application end).
+
+ bool switchingToTmpSolvfile = false;
Exception ex("Failed to cache rpm database.");
- ex.remember(str::form(
- "Cannot create temporary file under %s.", base.c_str()));
- ZYPP_THROW(ex);
+ ex.remember(str::form("Cannot create temporary file under %s.", base.c_str()));
+
+ if ( ! solvfilesPathIsTemp() )
+ {
+ base = getZYpp()->tmpPath() / sat::Pool::instance().systemRepoAlias();
+ rpmsolv = base/"solv";
+ rpmsolvcookie = base/"cookie";
+
+ filesystem::assert_dir( base );
+ tmpsolv = filesystem::TmpFile::makeSibling( rpmsolv );
+
+ if ( tmpsolv )
+ {
+ WAR << "Using a temporary solv file at " << base << endl;
+ switchingToTmpSolvfile = true;
+ _tmpSolvfilesPath = base;
+ }
+ else
+ {
+ ex.remember(str::form("Cannot create temporary file under %s.", base.c_str()));
+ }
+ }
+
+ if ( ! switchingToTmpSolvfile )
+ {
+ ZYPP_THROW(ex);
+ }
}
+ // Take care we unlink the solvfile on exception
+ ManagedFile guard( base, filesystem::recursive_rmdir );
+
std::ostringstream cmd;
cmd << "rpmdb2solv";
if ( ! _root.empty() )
cmd << " -p '" << Pathname::assertprefix( _root, "/etc/products.d" ) << "'";
- if ( solvexisted )
- cmd << " '" << rpmsolv << "'";
+ if ( ! oldSolvFile.empty() )
+ cmd << " '" << oldSolvFile << "'";
cmd << " > '" << tmpsolv.path() << "'";
// now add the repos to the pool
sat::Pool satpool( sat::Pool::instance() );
- Pathname rpmsolv( Pathname::assertprefix( _root,
- ZConfig::instance().repoSolvfilesPath() / satpool.systemRepoAlias() / "solv" ) );
+ Pathname rpmsolv( solvfilesPath() / "solv" );
MIL << "adding " << rpmsolv << " to pool(" << satpool.systemRepoAlias() << ")" << endl;
// Providing an empty system repo, unload any old content
/** Null implementation */
static TargetImpl_Ptr nullimpl();
- /**
+ /**
* generates the unique anonymous id which is called
* when creating the target
*/
*/
void createLastDistributionFlavorCache() const;
+ /** \name Solv file handling.
+ * If target solv file is outdated, but (non-root-)user has
+ * no permission to create it at the default location, we
+ * use a temporary one.
+ */
+ //@{
+ private:
+ /** The systems default solv file location. */
+ Pathname defaultSolvfilesPath() const;
+
+ /** The solv file location actually in use (default or temp). */
+ Pathname solvfilesPath() const
+ { return solvfilesPathIsTemp() ? _tmpSolvfilesPath : defaultSolvfilesPath(); }
+
+ /** Whether we're using a temp. solvfile. */
+ bool solvfilesPathIsTemp() const
+ { return ! _tmpSolvfilesPath.empty(); }
+
+ Pathname _tmpSolvfilesPath;
+
+ public:
void load();
void unload();
void clearCache();
void buildCache();
+ //@}
std::string anonymousUniqueId() const;