/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+#include <string>
+
#include "zypp/ZYpp.h"
#include "zypp/ZYppFactory.h"
#include "zypp/base/Logger.h"
#include "zypp/base/Exception.h"
-using std::endl;
+using namespace std;
using namespace zypp;
#include <sqlite3.h>
#include "dbsource/DbSources.h"
#include "transactions.h"
+#include "zypp/solver/detail/ResolverInfo.h"
+
+using solver::detail::ResolverInfo_Ptr;
+
+static void
+append_dep_info (ResolverInfo_Ptr info, void *user_data)
+{
+ string *dep_failure_info = (string *)user_data;
+ bool debug = false;
+
+ if (info == NULL) {
+ ERR << "append_dep_info(NULL)" << endl;
+ return;
+ }
+
+ if (getenv ("RCD_DEBUG_DEPS"))
+ debug = true;
+
+ if (debug || info->important()) {
+ dep_failure_info->append( "\n" );
+ if (debug && info->error())
+ dep_failure_info->append( "ERR " );
+ if (debug && info->important())
+ dep_failure_info->append( "IMP " );
+ dep_failure_info->append( info->message() );
+ }
+ return;
+}
+
int
main (int argc, char **argv)
{
if (argc != 2) {
- ERR << "usage: " << argv[0] << " <database>" << endl;
+ ERR << "usage: " << argv[0] << " <database> [verify]" << endl;
return 1;
}
if (!read_transactions (God->pool(), db.db(), dbs))
return 1;
- God->resolver()->resolvePool();
+ bool success;
+ if (argc == 3) {
+ success = God->resolver()->verifySystem();
+ }
+ else {
+ success = God->resolver()->resolvePool();
+ }
+ MIL << "Solver " << (success?"was":"NOT") << " successful" << endl;
+
+ solver::detail::ResolverContext_Ptr context = God->resolver()->context();
+ if (context == NULL) {
+ ERR << "No context ?!" << endl;
+ return 1;
+ }
+ if (success) {
+ success = write_transactions (God->pool(), db.db(), context);
+ }
+ else {
+ string dep_failure_info( "Unresolved dependencies:\n" );
+
+ context->foreachInfo (PoolItem_Ref(), -1, append_dep_info, &dep_failure_info);
+
+ cout << dep_failure_info;
+ cout.flush();
+ }
- return 0;
+ return (success ? 0 : 1);
}
#include "zypp/ResFilters.h"
#include "zypp/CapFilters.h"
+#include "zypp/solver/detail/ResolverContext.h"
+#include "zypp/solver/detail/ResolverInfo.h"
+
using std::endl;
using namespace zypp;
using namespace std;
using namespace zypp;
+using solver::detail::ResolverInfo_Ptr;
+using solver::detail::ResolverContext_Ptr;
+
+typedef std::set<PoolItem_Ref> PoolItemSet;
//-----------------------------------------------------------------------------
const char *sql = "SELECT action, id FROM transactions";
int rc = sqlite3_prepare (db, sql, -1, &handle, NULL);
if (rc != SQLITE_OK) {
- ERR << "Can not prepare transaction insertion clause: " << sqlite3_errmsg (db) << endl;
+ ERR << "Can not prepare transaction selection clause: " << sqlite3_errmsg (db) << endl;
return false;
}
return true;
}
+//-----------------------------------------------------------------------------
+
+static void
+insert_item( PoolItem_Ref item, const ResStatus & status, void *data)
+{
+ PoolItemSet *pis = (PoolItemSet *)data;
+ pis->insert( item );
+}
+
+static void
+insert_item_pair (PoolItem_Ref install, const ResStatus & status1, PoolItem_Ref remove, const ResStatus & status2, void *data)
+{
+ PoolItemSet *pis = (PoolItemSet *)data;
+ pis->insert( install ); // only the install
+}
+
+
+
+static void
+dep_get_package_info_cb (ResolverInfo_Ptr info, void *user_data)
+{
+ string *msg = (string *)user_data;
+
+ msg->append( info->message() );
+ msg->append( "|" );
+
+} /* dep_get_package_info_cb */
+
+
+static string
+dep_get_package_info (ResolverContext_Ptr context, PoolItem_Ref item)
+{
+ string info;
+
+ context->foreachInfo (item, RESOLVER_INFO_PRIORITY_USER, dep_get_package_info_cb, &info);
+
+ return info;
+} /* dep_get_package_info */
+
+
+bool
+write_resobject_set( sqlite3_stmt *handle, const PoolItemSet & objects, PackageOpType op_type, ResolverContext_Ptr context)
+{
+ int rc = SQLITE_DONE;
+
+ for (PoolItemSet::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) {
+
+ string details = dep_get_package_info( context, *iter );
+
+ sqlite3_bind_int (handle, 1, (int) op_type);
+ sqlite3_bind_int (handle, 2, iter->resolvable()->zmdid());
+ sqlite3_bind_text (handle, 3, details.c_str(), -1, SQLITE_STATIC);
+
+ rc = sqlite3_step (handle);
+ sqlite3_reset (handle);
+ }
+ return (rc == SQLITE_DONE);
+}
+
+
+bool
+write_transactions (const ResPool & pool, sqlite3 *db, ResolverContext_Ptr context)
+{
+ MIL << "write_transactions" << endl;
+
+ sqlite3_stmt *handle = NULL;
+ const char *sql = "INSERT INTO transactions (action, id, details) VALUES (?, ?, ?)";
+ int rc = sqlite3_prepare (db, sql, -1, &handle, NULL);
+ if (rc != SQLITE_OK) {
+ ERR << "Can not prepare transaction insertion clause: " << sqlite3_errmsg (db) << endl;
+ return false;
+ }
+ PoolItemSet install_set;
+ PoolItemSet remove_set;
+
+ context->foreachInstall( insert_item, &install_set);
+ context->foreachUninstall( insert_item, &remove_set);
+ context->foreachUpgrade( insert_item_pair, &install_set);
+
+ bool result;
+ result = write_resobject_set (handle, install_set, PACKAGE_OP_INSTALL, context);
+ if (!result) {
+ ERR << "Error writing transaction install set: " << sqlite3_errmsg (db) << endl;
+ }
+ result = write_resobject_set (handle, remove_set, PACKAGE_OP_REMOVE, context);
+ if (!result) {
+ ERR << "Error writing transaction remove set: " << sqlite3_errmsg (db) << endl;
+ }
+
+ sqlite3_finalize (handle);
+
+ return result;
+}
+
+