From: Klaus Kaempf Date: Sun, 26 Feb 2006 16:37:05 +0000 (+0000) Subject: new helper: package-files X-Git-Tag: BASE-SuSE-SLE-10-SP2-Branch~1873 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=20a28eb65d1d0d135beb4395346574d70977f60b;p=platform%2Fupstream%2Flibzypp.git new helper: package-files --- diff --git a/zmd/backend/Makefile.am b/zmd/backend/Makefile.am index ffc3293..7f53e10 100644 --- a/zmd/backend/Makefile.am +++ b/zmd/backend/Makefile.am @@ -17,6 +17,7 @@ bin_PROGRAMS = \ query-system \ query-files \ resolve-dependencies \ + package-files \ parse-metadata \ transact @@ -25,4 +26,4 @@ query_files_SOURCES = query-files.cc resolve_dependencies_SOURCES = resolve-dependencies.cc transactions.cc transactions.h transact_SOURCES = transact.cc transactions.cc transactions.h parse_metadata_SOURCES = parse-metadata.cc - +package_files_SOURCES = package-files.cc diff --git a/zmd/backend/package-files.cc b/zmd/backend/package-files.cc new file mode 100644 index 0000000..b447c31 --- /dev/null +++ b/zmd/backend/package-files.cc @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +// package-files.cc +// ZMD backend helper + +#include +#include +#include + +#include "zmd-backend.h" + +#include "zypp/ZYpp.h" +#include "zypp/ZYppFactory.h" +#include "zypp/SourceManager.h" +#include "zypp/Source.h" +#include "zypp/base/Logger.h" +#include "zypp/base/Exception.h" + +#include "zypp/base/Algorithm.h" +#include "zypp/ResPool.h" +#include "zypp/ResFilters.h" +#include "zypp/CapFilters.h" + +#include "zypp/Target.h" +#include "zypp/target/rpm/RpmHeader.h" + +using namespace zypp; +using namespace std; +using target::rpm::RpmHeader; + +#include +#include + +#include + +#include "dbsource/DbAccess.h" + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "package-files" + +//----------------------------------------------------------------------------- + +class LookFor : public resfilter::PoolItemFilterFunctor +{ + public: + PoolItem_Ref item; + + bool operator()( PoolItem_Ref provider ) + { + item = provider; + return false; // stop here, we found it + } +}; + +static int +package_files( sqlite3 *db, long id, const ResPool & pool ) +{ + int result = 0; + + // prepare SQL query +MIL << "package_files id " << id << endl; + sqlite3_stmt *handle = NULL; + const char *sql = + // 0 1 2 3 4 + "SELECT name, version, release, epoch, arch, " + // 5 6 + " installed, package_filename " + "FROM packages " + "WHERE id = ?"; + + int rc = sqlite3_prepare (db, sql, -1, &handle, NULL); + if (rc != SQLITE_OK) { + ERR << "Can not prepare get-package-by-id clause: " << sqlite3_errmsg (db) << endl; + return 1; + } + rc = sqlite3_bind_int64 (handle, 1, id); + + // execute the query + + rc = sqlite3_step (handle); + + if (rc != SQLITE_ROW) { + if (rc == SQLITE_DONE) + WAR << "Can not read package: package not found" << endl; + else + ERR << "Can not read package: %s" << sqlite3_errmsg (db) << endl; + sqlite3_finalize (handle); + return 1; + } + + // extract query results + + string name; + const char *cptr = (const char *) sqlite3_column_text (handle, 0); + if (cptr) name = cptr; + string version; + cptr = (const char *) sqlite3_column_text (handle, 1); + if (cptr) version = cptr; + string release; + cptr = (const char *) sqlite3_column_text (handle, 2); + if (cptr) release = cptr; + int epoch = sqlite3_column_int (handle, 3); + Arch arch( DbAccess::Rc2Arch( (RCArch) sqlite3_column_int (handle, 4) ) ); + int installed = sqlite3_column_int (handle, 5); + Pathname package_filename; + cptr = (const char *) sqlite3_column_text (handle, 6); + if (cptr) package_filename = cptr; +MIL << "=> " << name << "-" << version << "-" << release << "." << arch << ": " << ((installed==0)?"not ":"") << "installed" << ", file '" << package_filename.asString() << "'" << endl; + + sqlite3_finalize (handle); + + // get package data + + if (installed) { + + Edition edition( version, release, epoch ); + LookFor info; + + // find package in pool + invokeOnEach( pool.byNameBegin( name ), pool.byNameEnd( name ), + functor::chain ( + functor::chain (resfilter::ByInstalled (), + resfilter::ByKind( ResTraits::kind ) ), + resfilter::byEdition >( edition )), + functor::functorRef (info) ); + + if (!info.item) { + ERR << "Installed package" << name << "-" << edition << " NOT found" < " << endl; + return 1; + } + + DbAccess db(argv[1]); + + db.openDb( true ); // open for writing + + God->initTarget( "/" ); + + int result = package_files( db.db(), str::strtonum( argv[2] ), God->pool() ); + + God->finishTarget(); + + db.closeDb(); + + return result; +} diff --git a/zmd/backend/query-files.cc b/zmd/backend/query-files.cc index ecdb6af..d39f220 100644 --- a/zmd/backend/query-files.cc +++ b/zmd/backend/query-files.cc @@ -1,5 +1,7 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ - +// query-files.cc +// zmd helper to extract data from .rpm files +// #include #include #include @@ -35,7 +37,9 @@ query_file (Target_Ptr target, const char *path) { ResStore store; #if 0 - Resolvable::constPtr resolvable = target->rpm-qp (path); // FIXME, needs rpm -qp + RpmHeader::constPtr = RpmHeader::readPackage( path ); // rpm -qp + // RpmDb::getData( path ); + Resolvable::constPtr resolvable = RpmHeader::readPackage( path ); if (resolvable != NULL) { store.insert( resolvable ); } @@ -43,48 +47,255 @@ query_file (Target_Ptr target, const char *path) return store; } -static char * -extract_value (char *token) +// +// extract value from "key=value" token string +// + +static string +extract_value (const string & token) { - char *eq, *value; + char *eq; - eq = strchr (token, '='); + eq = strchr (token.c_str(), '='); if (!eq) - return NULL; + return string(); while (*(++eq) == ' '); /* Move past the equals sign and strip leading whitespace */ - return strdup (value); + return string (eq); } + +// check query for "recursive=N" +// set recursive = true in N numeric and > 0 +// + static void -parse_query (const char *query, bool *recursive) +parse_query (const string & query, bool *recursive) { -#if 0 char **tokens, **t; - tokens = g_strsplit (query, ";", 0); - - for (t = tokens; t && *t; t++) { - if (g_strncasecmp (*t, "recursive", 9) == 0) { - char *tmp = extract_value (*t); + std::vector tokens; + str::split( query, std::back_inserter( tokens ), ";" ); - if (atoi (tmp)) - *recursive = TRUE; + for (int pos = 0; pos < tokens.size(); ++pos) { + string tok = str.toLower( tokens[pos] ); + if (strncmp (tok.c_str(), "recursive", 9) == 0) { + string val = extract_value( tok ); - free (tmp); + if (str::strtonum( val ) > 0) + *recursive = true; } /* Ignore unknown parts */ } +} + +//----------------------------------------------------------------------------- + +#if 0 +typedef struct { + RCResolvableFn user_callback; + gpointer user_data; + const gchar *path; +} PackagesFromDirInfo; + +static gboolean +packages_from_dir_cb (RCPackage *package, gpointer user_data) +{ + PackagesFromDirInfo *info = user_data; + RCPackageUpdate *update; + + /* Set package path */ + update = rc_package_get_latest_update (package); + if (update && update->package_url) + package->package_filename = g_build_path (G_DIR_SEPARATOR_S, + info->path, + update->package_url, + NULL); + if (info->user_callback) + return info->user_callback ((RCResolvable *)package, info->user_data); + + return TRUE; +} - g_strfreev (tokens); +gint +rc_extract_packages_from_directory (const char *path, + RCChannel *channel, + RCPackman *packman, + gboolean recursive, + RCResolvableFn callback, + gpointer user_data) +{ + GDir *dir; + GHashTable *hash; + struct HashIterInfo info; + const char *filename; + char *magic; + gboolean distro_magic, pkginfo_magic; + + g_return_val_if_fail (path && *path, -1); + g_return_val_if_fail (channel != NULL, -1); + + /* + Check for magic files that indicate how to treat the + directory. The files aren't read -- it is sufficient that + they exist. + */ + + magic = g_strconcat (path, "/RC_SKIP", NULL); + if (g_file_test (magic, G_FILE_TEST_EXISTS)) { + g_free (magic); + return 0; + } + g_free (magic); + + magic = g_strconcat (path, "/RC_RECURSIVE", NULL); + if (g_file_test (magic, G_FILE_TEST_EXISTS)) + recursive = TRUE; + g_free (magic); + + magic = g_strconcat (path, "/RC_BY_DISTRO", NULL); + distro_magic = g_file_test (magic, G_FILE_TEST_EXISTS); + g_free (magic); + + pkginfo_magic = TRUE; + magic = g_strconcat (path, "/RC_IGNORE_PKGINFO", NULL); + if (g_file_test (magic, G_FILE_TEST_EXISTS)) + pkginfo_magic = FALSE; + g_free (magic); + + /* If distro_magic is set, we search for packages in two + subdirectories of path: path/distro-target (i.e. + path/redhat-9-i386) and path/x-cross. + */ + +#if 0 + if (distro_magic) { + char *distro_path, *cross_distro_path; + gboolean found_distro_magic = FALSE; + int count = 0, c; + + distro_path = g_strconcat (path, "/", rc_distro_get_target (), NULL); + if (g_file_test (distro_path, G_FILE_TEST_IS_DIR)) { + found_distro_magic = TRUE; + + c = rc_extract_packages_from_directory (distro_path, + channel, packman, + callback, user_data); + if (c >= 0) + count += c; + } + + cross_distro_path = g_strconcat (path, "/x-distro", NULL); + if (g_file_test (cross_distro_path, G_FILE_TEST_IS_DIR)) { + c = rc_extract_packages_from_directory (cross_distro_path, + channel, packman, + callback, user_data); + if (c >= 0) + count += c; + } + + g_free (cross_distro_path); + g_free (distro_path); + + return count; + } #endif + + /* If pkginfo_magic is set and if a packageinfo.xml or + packageinfo.xml.gz file exists in the directory, use it + instead of just scanning the files in the directory + looking for packages. */ + + if (pkginfo_magic) { + int i, count; + gchar *pkginfo_path = NULL; + const gchar *pkginfo[] = { "packageinfo.xml", + "packageinfo.xml.gz", + NULL }; + + for (i = 0; pkginfo[i]; i++) { + pkginfo_path = g_build_path (G_DIR_SEPARATOR_S, path, pkginfo[i], NULL); + if (g_file_test (pkginfo_path, G_FILE_TEST_EXISTS)) + break; + + g_free (pkginfo_path); + pkginfo_path = NULL; + } + + if (pkginfo_path) { + PackagesFromDirInfo info; + + info.user_callback = callback; + info.user_data = user_data; + info.path = path; + + count = rc_extract_packages_from_helix_file (pkginfo_path, + channel, + packages_from_dir_cb, + &info); + g_free (pkginfo_path); + return count; + } + } + + dir = g_dir_open (path, 0, NULL); + if (dir == NULL) + return -1; + + hash = g_hash_table_new (NULL, NULL); + + while ( (filename = g_dir_read_name (dir)) ) { + gchar *file_path; + + file_path = g_strconcat (path, "/", filename, NULL); + + if (recursive && g_file_test (file_path, G_FILE_TEST_IS_DIR)) { + rc_extract_packages_from_directory (file_path, + channel, + packman, + TRUE, + hash_recurse_cb, + hash); + } else if (g_file_test (file_path, G_FILE_TEST_IS_REGULAR)) { + RCPackage *pkg; + + pkg = rc_packman_query_file (packman, file_path, TRUE); + if (pkg != NULL) { + rc_resolvable_set_channel (RC_RESOLVABLE (pkg), channel); + pkg->package_filename = g_strdup (file_path); + pkg->local_package = FALSE; + add_fake_history (pkg); + package_into_hash (pkg, hash); + g_object_unref (pkg); + } + } + + g_free (file_path); + } + + g_dir_close (dir); + + info.callback = callback; + info.user_data = user_data; + info.count = 0; + + /* Walk across the hash and: + 1) Invoke the callback on each package + 2) Unref each package + */ + g_hash_table_foreach (hash, hash_iter_cb, &info); + + g_hash_table_destroy (hash); + + return info.count; } +#endif static ResStore -query_directory (Target_Ptr target, const char *path, bool recursive) +query_directory (Target_Ptr target, const Pathname & path, bool recursive) { ResStore store; #warning Unclear semantics