Author: mlandres
Date: Thu Jun 19 17:50:58 2008
New Revision: 10410
URL: http://svn.opensuse.org/viewcvs/zypp?rev=10410&view=rev
Log:
Handle new patch messages and scripts in commit (bnc #401220)
Modified:
branches/SuSE-Linux-11_0-Branch/libzypp/devel/devel.ma/NewPool.cc
branches/SuSE-Linux-11_0-Branch/libzypp/package/libzypp.changes
branches/SuSE-Linux-11_0-Branch/libzypp/zypp/target/TargetImpl.cc
Modified: branches/SuSE-Linux-11_0-Branch/libzypp/devel/devel.ma/NewPool.cc
URL: http://svn.opensuse.org/viewcvs/zypp/branches/SuSE-Linux-11_0-Branch/libzypp/devel/devel.ma/NewPool.cc?rev=10410&r1=10409&r2=10410&view=diff
==============================================================================
--- branches/SuSE-Linux-11_0-Branch/libzypp/devel/devel.ma/NewPool.cc (original)
+++ branches/SuSE-Linux-11_0-Branch/libzypp/devel/devel.ma/NewPool.cc Thu Jun 19 17:50:58 2008
@@ -255,6 +255,7 @@
if ( ! rres )
{
ERR << "resolve " << rres << endl;
+ getZYpp()->resolver()->problems();
return false;
}
MIL << "resolve " << rres << endl;
@@ -369,6 +370,19 @@
}
};
+ struct PatchMessageReceive : public callback::ReceiveReporttarget::PatchMessageReport
+{
+ PatchMessageReceive()
+ { connect(); }
+
+ virtual bool show( Patch::constPtr patch )
+ {
+ DBG << patch->message() << endl;
+ //return patch->name() != "libsatsolver";
+ return callback::ReceiveReporttarget::PatchMessageReport::show( patch );
+ }
+};
+
///////////////////////////////////////////////////////////////////
namespace container
@@ -471,6 +485,7 @@
++argv;
zypp::base::LogControl::instance().logToStdErr();
INT << "===[START]==========================================" << endl;
+ PatchMessageReceive r;
ZConfig::instance();
ResPool pool( ResPool::instance() );
@@ -534,7 +549,7 @@
}
}
- if ( 0 )
+ if ( 1 )
{
Measure x( "INIT TARGET" );
{
@@ -560,17 +575,33 @@
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
- for_( it, pool.byKindBegin<Pattern>(), pool.byKindEnd<Pattern>() )
+ for_( it, pool.byKindBegin<Patch>(), pool.byKindEnd<Patch>() )
{
MIL << *it << endl;
- //it->status().setTransact( true, ResStatus::USER );
+ Patch::constPtr patch( asKind<Patch>(it->resolvable()) );
+ if ( ! patch->message().empty() )
+ DBG << patch->message() << endl;
+ it->status().setTransact( true, ResStatus::USER );
}
+ PoolItem pix ( getPi<Package>("amarok",Edition("1.4.9.1-4"),Arch("i586")) );
+ MIL << pix << endl;
+ if ( pix )
+ {
+ pix.status().setTransact( true, ResStatus::USER );
+ }
+
+ solve();
+ vdumpPoolStats( USR << "Transacting:"<< endl,
+ make_filter_beginresfilter::ByTransact(pool),
+ make_filter_endresfilter::ByTransact(pool) ) << endl;
+ install();
///////////////////////////////////////////////////////////////////
INT << "===[END]============================================" << endl << endl;
zypp::base::LogControl::instance().logNothing();
return 0;
+
SEC << zypp::getZYpp()->diskUsage() << endl;
// for_( it, pool.byKindBegin<SrcPackage>(), pool.byKindEnd<SrcPackage>() )
Modified: branches/SuSE-Linux-11_0-Branch/libzypp/package/libzypp.changes
URL: http://svn.opensuse.org/viewcvs/zypp/branches/SuSE-Linux-11_0-Branch/libzypp/package/libzypp.changes?rev=10410&r1=10409&r2=10410&view=diff
==============================================================================
--- branches/SuSE-Linux-11_0-Branch/libzypp/package/libzypp.changes (original)
+++ branches/SuSE-Linux-11_0-Branch/libzypp/package/libzypp.changes Thu Jun 19 17:50:58 2008
@@ -1,4 +1,12 @@
-------------------------------------------------------------------
+Thu Jun 19 17:46:04 CEST 2008 - ma@suse.de
+
+- Handle new patch messages and scripts in commit. Provide callbacks
+ to display the patch messages and give visual feedback on script
+ execution. (bnc #401220)
+- revision 10410
+
+-------------------------------------------------------------------
Tue Jun 10 15:55:31 CEST 2008 - ma@suse.de
- Allow to abort commit during package deletion. (bnc #389238)
Modified: branches/SuSE-Linux-11_0-Branch/libzypp/zypp/target/TargetImpl.cc
URL: http://svn.opensuse.org/viewcvs/zypp/branches/SuSE-Linux-11_0-Branch/libzypp/zypp/target/TargetImpl.cc?rev=10410&r1=10409&r2=10410&view=diff
==============================================================================
--- branches/SuSE-Linux-11_0-Branch/libzypp/zypp/target/TargetImpl.cc (original)
+++ branches/SuSE-Linux-11_0-Branch/libzypp/zypp/target/TargetImpl.cc Thu Jun 19 17:50:58 2008
@@ -19,7 +19,7 @@
#include
#include
-#include "zypp/base/Logger.h"
+#include "zypp/base/LogTools.h"
#include "zypp/base/Exception.h"
#include "zypp/base/Iterator.h"
#include "zypp/base/Gettext.h"
@@ -53,10 +53,7 @@
#include "zypp/sat/Pool.h"
-using namespace std;
-using namespace zypp;
-using namespace zypp::resfilter;
-using zypp::solver::detail::Helper;
+using std::endl;
///////////////////////////////////////////////////////////////////
namespace zypp
@@ -69,138 +66,144 @@
namespace
{ /////////////////////////////////////////////////////////////////
- // Execute file (passed as pi_t) as script
- // report against report_r
- //
- void ExecuteScript( const Pathname & pn_r,
- callback::SendReport<ScriptResolvableReport> * report)
- {
- PathInfo pi( pn_r );
- if ( ! pi.isFile() )
- {
- std::ostringstream err;
- err << "Script is not a file: " << pi.fileType() << " " << pn_r;
- if (report)
- (*report)->problem( err.str() );
- ZYPP_THROW(Exception(err.str()));
- }
-
- filesystem::chmod( pn_r, S_IRUSR|S_IWUSR|S_IXUSR ); // "rwx------"
- ExternalProgram prog( pn_r.asString(), ExternalProgram::Stderr_To_Stdout, false, -1, true );
+ /** Execute script and report against report_r.
+ * Return \c std::pair to indicate if
+ * execution was successfull (<tt>first = true</tt>), or the desired
+ * \c PatchScriptReport::Action in case execution failed
+ * (<tt>first = false</tt>).
+ *
+ * \note The packager is responsible for setting the correct permissions
+ * of the script. If the script is not executable it is reported as an
+ * error. We must not modify the permessions.
+ */
+ std::pair doExecuteScript( const Pathname & root_r,
+ const Pathname & script_r,
+ callback::SendReport<PatchScriptReport> & report_r )
+ {
+ MIL << "Execute script " << PathInfo(script_r) << endl;
+
+ CommitLog progresslog;
+ progresslog(/*timestamp*/true) << script_r << _(" executed") << endl;
+ ExternalProgram prog( script_r.asString(), ExternalProgram::Stderr_To_Stdout, false, -1, true /*, root_r*/ );
for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
{
- // hmm, this depends on a ScriptResolvableReport :-(
- if ( report
- && ! (*report)->progress( ScriptResolvableReport::OUTPUT, output ) )
- {
- WAR << "User request to abort script." << endl;
- prog.kill(); // the rest is handled by exit code evaluation.
- }
+ progresslog() << output;
+ if ( ! report_r->progress( PatchScriptReport::OUTPUT, output ) )
+ {
+ WAR << "User request to abort script " << script_r << endl;
+ prog.kill();
+ // the rest is handled by exit code evaluation
+ // in case the script has meanwhile finished.
+ }
}
- int exitCode = prog.close();
- if ( exitCode != 0 )
+ std::pair ret( std::make_pair( false, PatchScriptReport::ABORT ) );
+
+ if ( prog.close() != 0 )
{
- std::ostringstream err;
- err << "Script failed with exit code " << exitCode;
- if (report)
- (*report)->problem( err.str() );
- ZYPP_THROW(Exception(err.str()));
+ ret.second = report_r->problem( prog.execError() );
+ WAR << "ACTION" << ret.second << "(" << prog.execError() << ")" << endl;
+ progresslog(/*timestamp*/true)<< script_r << _(" execution failed") << " (" << prog.execError() << ")" << endl;
+ return ret;
}
- return;
+
+ report_r->finish();
+ ret.first = true;
+ return ret;
}
- // Check for (and run) update script
- // path: directory where to look
- // name,version,release: Script name must match 'name-version.release-' prefix
- //
-#warning needs to be reimplemented exception safe
-#warning needs to take root prefix into account and execute chroot
- void RunUpdateScript(Pathname path, std::string name, std::string version, std::string release)
+ /** Execute script and report against report_r.
+ * Return \c false if user requested \c ABORT.
+ */
+ bool executeScript( const Pathname & root_r,
+ const Pathname & script_r,
+ callback::SendReport<PatchScriptReport> & report_r )
{
- // open the scripts directory
-
- DIR *dir = opendir(path.asString().c_str());
- if (!dir)
- {
- WAR << "Cannot access directory " << path << endl;
- return;
- }
+ std::pair action( std::make_pair( false, PatchScriptReport::ABORT ) );
- // compute the name-version.release- prefix
- std::string prefix = name + "-" + version + "-" + release + "-";
- size_t pfx_size = prefix.length();
- if (pfx_size > 255)
- {
- ERR << "Prefix size (" << pfx_size << ") larger than supported (255)" << endl;
- pfx_size = 255;
- }
+ do {
+ action = doExecuteScript( root_r, script_r, report_r );
+ if ( action.first )
+ return true; // success
- // scan directory for match
- const char *found = NULL;
- struct dirent *dentry;
- while ((dentry = readdir(dir)))
- {
- if (strncmp( dentry->d_name, prefix.c_str(), pfx_size) == 0) {
- found = dentry->d_name;
- break;
- }
- }
- if (found)
- {
- ExecuteScript( Pathname(path / found), NULL );
- }
- closedir(dir);
- return;
- }
+ switch ( action.second )
+ {
+ case PatchScriptReport::ABORT:
+ WAR << "User request to abort at script " << script_r << endl;
+ return false; // requested abort.
+ break;
- // Fetch and execute remote script
- // access_r: remote access handle
- // script_r: script (resolvable) handle
- // do_r: true for 'do', false for 'undo'
- //
- void ExecuteScriptHelper( repo::RepoMediaAccess & access_r,
- Script::constPtr script_r,
- bool do_r )
- {
- MIL << "Execute script " << script_r << endl;
- if ( ! script_r )
- {
- INT << "NULL Script passed." << endl;
- return;
- }
+ case PatchScriptReport::IGNORE:
+ WAR << "User request to skip script " << script_r << endl;
+ return true; // requested skip.
+ break;
- repo::ScriptProvider prov( access_r );
- ManagedFile localfile = prov.provideScript( script_r, do_r );
+ case PatchScriptReport::RETRY:
+ break; // again
+ }
+ } while ( action.second == PatchScriptReport::RETRY );
- if ( localfile->empty() )
+ // THIS is not intended to be reached:
+ INT << "Abort on unknown ACTION request " << action.second << " returned" << endl;
+ return false; // abort.
+ }
+
+ /** Look for patch scripts named 'name-version-release-*' and
+ * execute them. Return \c false if \c ABORT was requested.
+ */
+ bool RunUpdateScripts( const Pathname & root_r,
+ const Pathname & scriptsPath_r,
+ const std::vectorsat::Solvable & checkPackages_r,
+ bool aborting_r )
+ {
+ if ( checkPackages_r.empty() )
+ return true; // no installed packages to check
+
+ MIL << "Looking for new patch scripts in (" << root_r << ")" << scriptsPath_r << endl;
+ Pathname scriptsDir( Pathname::assertprefix( root_r, scriptsPath_r ) );
+ if ( ! PathInfo( scriptsDir ).isDir() )
+ return true; // no script dir
+
+ std::liststd::string scripts;
+ filesystem::readdir( scripts, scriptsDir, /*dots*/false );
+ if ( scripts.empty() )
+ return true; // no scripts in script dir
+
+ // Now collect and execute all matching scripts.
+ // On ABORT: at least log all outstanding scripts.
+ bool abort = false;
+ for_( it, checkPackages_r.begin(), checkPackages_r.end() )
{
- DBG << "No " << (do_r?"do":"undo") << " script for " << script_r << endl;
- return; // success
- }
-
- // Go...
- callback::SendReport<ScriptResolvableReport> report;
- report->start( script_r, localfile,
- (do_r ? ScriptResolvableReport::DO
- : ScriptResolvableReport::UNDO ) );
+ std::string prefix( str::form( "%s-%s-", it->name().c_str(), it->edition().c_str() ) );
+ for_( sit, scripts.begin(), scripts.end() )
+ {
+ if ( ! str::hasPrefix( *sit, prefix ) )
+ continue;
- ExecuteScript( localfile, &report );
- report->finish();
+ PathInfo script( scriptsDir / *sit );
+ if ( ! script.isFile() )
+ continue;
- return;
- }
+ if ( abort || aborting_r )
+ {
+ WAR << "Aborting: Skip patch script " << *sit << endl;
+ CommitLog()(/*timestamp*/true) << script.path() << _(" execution skipped while aborting") << endl;
+ }
+ else
+ {
+ MIL << "Found patch script " << *sit << endl;
+ callback::SendReport<PatchScriptReport> report;
+ report->start( make<Package>( *it ), script.path() );
- inline void ExecuteDoScript( repo::RepoMediaAccess & access_r, const Script::constPtr & script_r )
- {
- ExecuteScriptHelper( access_r, script_r, true );
+ if ( ! executeScript( root_r, script.path(), report ) )
+ abort = true; // requested abort.
+ }
+ }
+ }
+ return !abort;
}
- inline void ExecuteUndoScript( repo::RepoMediaAccess & access_r, const Script::constPtr & script_r )
- {
- ExecuteScriptHelper( access_r, script_r, false );
- }
/////////////////////////////////////////////////////////////////
} // namespace
///////////////////////////////////////////////////////////////////
@@ -302,14 +305,14 @@
void TargetImpl::clearCache()
{
Pathname base = Pathname::assertprefix( _root,
- ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoName() );
+ ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoAlias() );
filesystem::recursive_rmdir( base );
}
void TargetImpl::buildCache()
{
Pathname base = Pathname::assertprefix( _root,
- ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoName() );
+ ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoAlias() );
Pathname rpmsolv = base/"solv";
Pathname rpmsolvcookie = base/"cookie";
@@ -351,7 +354,7 @@
ZYPP_THROW(ex);
}
- ostringstream cmd;
+ std::ostringstream cmd;
cmd << "rpmdb2solv";
if ( ! _root.empty() )
cmd << " -r '" << _root << "'";
@@ -365,7 +368,7 @@
ExternalProgram prog( cmd.str(), ExternalProgram::Stderr_To_Stdout );
cmd << endl;
- for ( string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
+ for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
WAR << " " << output;
cmd << " " << output;
}
@@ -406,8 +409,8 @@
// now add the repos to the pool
sat::Pool satpool( sat::Pool::instance() );
Pathname rpmsolv( Pathname::assertprefix( _root,
- ZConfig::instance().repoSolvfilesPath() / satpool.systemRepoName() / "solv" ) );
- MIL << "adding " << rpmsolv << " to pool(" << satpool.systemRepoName() << ")" << endl;
+ ZConfig::instance().repoSolvfilesPath() / satpool.systemRepoAlias() / "solv" ) );
+ MIL << "adding " << rpmsolv << " to pool(" << satpool.systemRepoAlias() << ")" << endl;
// Providing an empty system repo, unload any old content
Repository system( sat::Pool::instance().findSystemRepo() );
@@ -529,7 +532,34 @@
MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl;
}
- commit (to_uninstall, policy_r, pool_r );
+ ///////////////////////////////////////////////////////////////////
+ // First collect and display all messages
+ // associated with patches to be installed.
+ ///////////////////////////////////////////////////////////////////
+ for_( it, to_install.begin(), to_install.end() )
+ {
+ if ( ! isKind<Patch>(it->resolvable()) )
+ continue;
+ if ( ! it->status().isToBeInstalled() )
+ continue;
+
+ Patch::constPtr patch( asKind<Patch>(it->resolvable()) );
+ if ( ! patch->message().empty() )
+ {
+ MIL << "Show message for " << patch << endl;
+ callback::SendReporttarget::PatchMessageReport report;
+ if ( ! report->show( patch ) )
+ {
+ WAR << "commit aborted by the user" << endl;
+ ZYPP_THROW( TargetAbortedException( N_("Installation has been aborted as directed.") ) );
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ // Remove/install packages.
+ ///////////////////////////////////////////////////////////////////
+ commit (to_uninstall, policy_r, pool_r );
if (policy_r.restrictToMedia() == 0)
{ // commit all
@@ -581,7 +611,9 @@
result._srcremaining.insert(result._srcremaining.end(), bad.begin(), bad.end());
}
+ ///////////////////////////////////////////////////////////////////
// Try to rebuild solv file while rpm database is still in cache.
+ ///////////////////////////////////////////////////////////////////
buildCache();
result._result = (to_install.size() - result._remaining.size());
@@ -597,12 +629,10 @@
{
TargetImpl::PoolItemList remaining;
repo::RepoMediaAccess access;
- MIL << "TargetImpl::commit(<list>" << policy_r << ")" << endl;
+ MIL << "TargetImpl::commit(<list>" << policy_r << ")" << items_r.size() << endl;
bool abort = false;
-
- // remember the last used source (if any)
- Repository lastUsedRepo;
+ std::vectorsat::Solvable successfullyInstalledPackages;
RepoProvidePackage repoProvidePackage( access, pool_r);
// prepare the package cache.
@@ -627,8 +657,15 @@
WAR << "Skipping package " << p << " in commit" << endl;
continue;
}
-
- lastUsedRepo = p->repository(); // remember the package source
+#if 0
+ // bnc #395704: missing catch causes abort. see if packageCache fails to handle
+ // errors correctly.
+ catch ( const Exception &e )
+ {
+ ZYPP_CAUGHT( e );
+ SEC << e << endl;
+ }
+#endif
#warning Exception handling
// create a installation progress report proxy
@@ -684,8 +721,8 @@
if ( success && !policy_r.dryRun() )
{
it->status().resetTransact( ResStatus::USER );
- // check for and run an update script
- RunUpdateScript(ZConfig::instance().update_scriptsPath(), p->name(), p->edition().version(), p->edition().release());
+ // Remember to check this package for presence of patch scripts.
+ successfullyInstalledPackages.push_back( it->satSolvable() );
}
progress.disconnect();
}
@@ -726,103 +763,29 @@
}
else if (!policy_r.dryRun()) // other resolvables (non-Package)
{
- if (it->status().isToBeInstalled())
- {
- bool success = false;
- try
- {
- if (isKind<Message>(it->resolvable()))
- {
- Message::constPtr m = dynamic_pointer_cast<const Message>(it->resolvable());
- std::string text = m->text().asString();
-
- callback::SendReporttarget::MessageResolvableReport report;
-
- report->show( m );
-
- MIL << "Displaying the text '" << text << "'" << endl;
- }
- else if (isKind<Script>(it->resolvable()))
- {
- ExecuteDoScript( access, asKind<Script>(it->resolvable()));
- }
- else if (!isKind<Atom>(it->resolvable())) // atoms are re-created from the patch data, no need to save them
- {
- // #160792 do not just add, also remove older versions
- if (true) // !installOnly - only on Package?!
- {
- // this would delete the same item over and over
- //for (PoolItem old = Helper::findInstalledItem (pool_r, *it); old; )
- #warning REMOVE ALL OLD VERSIONS AND NOT JUST ONE
- PoolItem old = Helper::findInstalledItem (pool_r, *it);
- if (old)
- {
- // FIXME _storage.deleteObject(old.resolvable());
- }
- }
- // FIXME _storage.storeObject(it->resolvable());
- }
- success = true;
- }
- catch (Exception & excpt_r)
- {
- ZYPP_CAUGHT(excpt_r);
- WAR << "Install of Resolvable from storage failed" << endl;
- }
- if (success)
- it->status().resetTransact( ResStatus::USER );
- }
- else
- { // isToBeUninstalled
- bool success = false;
- try
- {
- if (isKind<Atom>(it->resolvable()))
- {
- DBG << "Uninstalling atom - no-op" << endl;
- }
- else if (isKind<Message>(it->resolvable()))
- {
- DBG << "Uninstalling message - no-op" << endl;
- }
- else if (isKind<Script>(it->resolvable()))
- {
- ExecuteUndoScript( access, asKind<Script>(it->resolvable()));
- }
- else
- {
- //FIXME _storage.deleteObject(it->resolvable());
- }
- success = true;
- }
- catch (Exception & excpt_r)
- {
- ZYPP_CAUGHT(excpt_r);
- WAR << "Uninstall of Resolvable from storage failed" << endl;
- }
- if (success)
- it->status().resetTransact( ResStatus::USER );
- }
-
+ it->status().resetTransact( ResStatus::USER );
} // other resolvables
} // for
- // we're done with the commit, release the source media
- // In the case of a single media, end of commit means we don't need _this_
- // media any more.
- // In the case of 'commit any media', end of commit means we're completely
- // done and don't need the source's media anyways.
-
- if (lastUsedRepo)
- { // if a source was used
- //lastUsedRepo.release(); // release their medias
+ // Check presence of patch scripts. If aborting, at least log
+ // omitted scripts.
+ if ( ! successfullyInstalledPackages.empty() )
+ {
+ if ( ! RunUpdateScripts( _root, ZConfig::instance().update_scriptsPath(),
+ successfullyInstalledPackages, abort ) )
+ {
+ WAR << "Commit aborted by the user" << endl;
+ abort = true;
+ }
}
if ( abort )
+ {
ZYPP_THROW( TargetAbortedException( N_("Installation has been aborted as directed.") ) );
+ }
- return remaining;
+ return remaining;
}
rpm::RpmDb & TargetImpl::rpm()
--
To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org
For additional commands, e-mail: zypp-commit+help@opensuse.org