Date: Mon, 8 Jul 2013 11:55:21 GMT From: mattbw@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r254408 - in soc2013/mattbw/backend: . actions query Message-ID: <201307081155.r68BtLlK042448@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mattbw Date: Mon Jul 8 11:55:21 2013 New Revision: 254408 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=254408 Log: so many query changes while FreeBSD.org was down... Added: soc2013/mattbw/backend/query/ soc2013/mattbw/backend/query/core.c - copied, changed from r254407, soc2013/mattbw/backend/query.c soc2013/mattbw/backend/query/core.h - copied, changed from r254407, soc2013/mattbw/backend/query.h soc2013/mattbw/backend/query/do.c soc2013/mattbw/backend/query/do.h soc2013/mattbw/backend/query/match.c soc2013/mattbw/backend/query/match.h Replaced: soc2013/mattbw/backend/query.h Deleted: soc2013/mattbw/backend/query.c soc2013/mattbw/backend/query_match.c soc2013/mattbw/backend/query_match.h Modified: soc2013/mattbw/backend/Makefile soc2013/mattbw/backend/actions/get-details.c soc2013/mattbw/backend/actions/get-files.c soc2013/mattbw/backend/actions/get-repo-list.c soc2013/mattbw/backend/actions/install-files.c soc2013/mattbw/backend/actions/install-packages.c soc2013/mattbw/backend/actions/resolve.c soc2013/mattbw/backend/utils.h Modified: soc2013/mattbw/backend/Makefile ============================================================================== --- soc2013/mattbw/backend/Makefile Mon Jul 8 07:12:20 2013 (r254407) +++ soc2013/mattbw/backend/Makefile Mon Jul 8 11:55:21 2013 (r254408) @@ -8,8 +8,6 @@ groups.c \ licenses.c \ pkgutils.c \ - query.c \ - query_match.c \ utils.c SRCS+= \ actions/get-details.c \ @@ -19,6 +17,11 @@ actions/install-packages.c \ actions/resolve.c +SRCS+= \ + query/core.c \ + query/do.c \ + query/match.c + LIBDIR= /usr/local/lib/packagekit-backend PKGS= pkg gio-2.0 gio-unix-2.0 Modified: soc2013/mattbw/backend/actions/get-details.c ============================================================================== --- soc2013/mattbw/backend/actions/get-details.c Mon Jul 8 07:12:20 2013 (r254407) +++ soc2013/mattbw/backend/actions/get-details.c Mon Jul 8 11:55:21 2013 (r254408) @@ -23,8 +23,8 @@ #include "pkg.h" #include "../groups.h" /* group_from_origin */ -#include "../query_match.h" /* query_match_... */ #include "../licenses.h" /* license_from_pkg */ +#include "../query.h" /* query_... */ #include "actions.h" /* get_details_thread prototype */ @@ -39,8 +39,11 @@ gboolean get_details_thread(PkBackend *backend) { + gboolean success; - return query_match_id_to_emitter(backend, LOAD_FLAGS, emit); + success = query_match_id_to_emitter(backend, LOAD_FLAGS, emit); + pk_backend_finished(backend); + return success; } /* @@ -49,25 +52,31 @@ static gboolean emit(struct pkg *pkg, const gchar *id, struct query *q) { + gboolean success; const char *description; const char *origin; const char *www; int64_t flatsize; + query_set_percentage(q, 0); + /* Information not already part of the PackageID */ description = origin = www = NULL; flatsize = 0; pkg_get(pkg, - PKG_DESC, &description, - PKG_FLATSIZE, &flatsize, - PKG_ORIGIN, &origin, - PKG_WWW, &www); - - return pk_backend_details(query_backend(q), - id, - license_name_from_pkg(pkg), - group_from_origin(origin), - description, - www, - flatsize); + PKG_DESC, &description, + PKG_FLATSIZE, &flatsize, + PKG_ORIGIN, &origin, + PKG_WWW, &www); + + success = pk_backend_details(query_backend(q), + id, + license_name_from_pkg(pkg), + group_from_origin(origin), + description, + www, + flatsize); + + query_set_percentage(q, 100); + return success; } Modified: soc2013/mattbw/backend/actions/get-files.c ============================================================================== --- soc2013/mattbw/backend/actions/get-files.c Mon Jul 8 07:12:20 2013 (r254407) +++ soc2013/mattbw/backend/actions/get-files.c Mon Jul 8 11:55:21 2013 (r254408) @@ -26,8 +26,8 @@ #include "../groups.h" /* group_from_origin */ #include "../hash_traverse.h" /* HASH_FOR */ -#include "../query_match.h" /* query_match_... */ #include "../licenses.h" /* license_from_pkg */ +#include "../query.h" /* query_... */ #include "actions.h" /* get_files_thread prototype */ @@ -43,9 +43,13 @@ gboolean get_files_thread(PkBackend *backend) { + gboolean success; (void)pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); - return query_match_id_to_emitter(backend, LOAD_FLAGS, emit); + success = query_match_id_to_emitter(backend, LOAD_FLAGS, emit); + + (void)pk_backend_finished(backend); + return success; } /* @@ -59,6 +63,8 @@ struct pkg_file *file; struct sbuf *sb; + query_set_percentage(q, 0); + success = FALSE; file = NULL; @@ -86,5 +92,6 @@ } sbuf_delete(sb); + query_set_percentage(q, 100); return success; } Modified: soc2013/mattbw/backend/actions/get-repo-list.c ============================================================================== --- soc2013/mattbw/backend/actions/get-repo-list.c Mon Jul 8 07:12:20 2013 (r254407) +++ soc2013/mattbw/backend/actions/get-repo-list.c Mon Jul 8 11:55:21 2013 (r254408) @@ -38,8 +38,7 @@ repo = NULL; (void)pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); - (void)pk_backend_set_percentage(backend, - PK_BACKEND_PERCENTAGE_INVALID); + (void)pk_backend_set_percentage(backend, 0); for (HASH_FOR(err, pkg_repos, &repo)) pk_backend_repo_detail(backend, @@ -47,6 +46,7 @@ pkg_repo_name(repo), pkg_repo_enabled(repo)); + (void)pk_backend_set_percentage(backend, 100); (void)pk_backend_finished(backend); return (err == EPKG_END ? TRUE : FALSE); Modified: soc2013/mattbw/backend/actions/install-files.c ============================================================================== --- soc2013/mattbw/backend/actions/install-files.c Mon Jul 8 07:12:20 2013 (r254407) +++ soc2013/mattbw/backend/actions/install-files.c Mon Jul 8 11:55:21 2013 (r254408) @@ -25,7 +25,6 @@ #include "../db.h" /* db_open_remote */ #include "../hash_traverse.h" /* HASH_FOR */ #include "../pkgutils.h" /* pkgutils_... */ -#include "../query_match.h" /* query_match_... */ #include "../utils.h" /* INTENTIONALLY_IGNORE */ #include "actions.h" /* install_files_thread prototype */ Modified: soc2013/mattbw/backend/actions/install-packages.c ============================================================================== --- soc2013/mattbw/backend/actions/install-packages.c Mon Jul 8 07:12:20 2013 (r254407) +++ soc2013/mattbw/backend/actions/install-packages.c Mon Jul 8 11:55:21 2013 (r254408) @@ -24,16 +24,14 @@ #include "../hash_traverse.h" /* HASH_FOR */ #include "../pkgutils.h" /* pkgutils_... */ -#include "../query_match.h" /* query_match_... */ +#include "../query.h" /* query_... */ #include "../utils.h" /* INTENTIONALLY_IGNORE */ #include "actions.h" /* install_packages_thread prototype */ -static gboolean do_install_packages(struct pkg_jobs *jobs, struct query *q, gboolean simulate); -static gboolean do_install_solved_job(struct pkg_jobs *jobs, PkBackend *backend, gboolean simulate); -static gboolean do_install_solved_job_real(struct pkg_jobs *jobs, PkBackend *backend); static gboolean job(struct pkg_jobs *jobs, struct query *q); static gboolean sim_job(struct pkg_jobs *jobs, struct query *q); +static gboolean solve_job(struct query *q, struct pkg_jobs *jobs); static int install_event_cb(void *backend_v, struct pkg_event *event); @@ -44,9 +42,13 @@ gboolean install_packages_thread(PkBackend *backend) { + gboolean success; + + (void)pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); + success = query_match_id_to_job(backend, PKG_JOBS_INSTALL, job); - pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); - return query_match_id_to_job(backend, PKG_JOBS_INSTALL, job); + (void)pk_backend_finished(backend); + return success; } /* @@ -56,107 +58,107 @@ gboolean simulate_install_packages_thread(PkBackend *backend) { + gboolean success; + + (void)pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); + success = query_match_id_to_job(backend, PKG_JOBS_INSTALL, sim_job); - return query_match_id_to_job(backend, PKG_JOBS_INSTALL, sim_job); + (void)pk_backend_finished(backend); + return success; } /* - * Installs (or pretends to install) an unsolved installation job. + * Tries to process the given solved installation jobs. */ static gboolean -do_install_packages(struct pkg_jobs *jobs, struct query *q, gboolean simulate) +job(struct pkg_jobs *jobs, struct query *q) { gboolean success; PkBackend *backend; success = FALSE; backend = query_backend(q); + query_set_percentage(q, 0); - pk_backend_set_status(backend, PK_STATUS_ENUM_DEP_RESOLVE); - if (pkg_jobs_solve(jobs) != EPKG_OK) - pk_backend_error_code(backend, - PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, - "could not solve the job"); - else if (pkg_jobs_count(jobs) == 0) + if (solve_job(q, jobs) == FALSE) + goto cleanup; + + pkg_event_register(install_event_cb, backend); + + pk_backend_set_status(backend, PK_STATUS_ENUM_INSTALL); + if (pkg_jobs_apply(jobs) != EPKG_OK) { pk_backend_error_code(backend, - PK_ERROR_ENUM_INTERNAL_ERROR, - "job contains no packages"); - else - success = do_install_solved_job(jobs, backend, simulate); + PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL, + "job failed"); + goto cleanup; + } + success = TRUE; +cleanup: + pkg_event_register(NULL, NULL); + query_set_percentage(q, 100); return success; } /* - * Installs (or pretends to install) a fully solved installation job. + * Tries to simulate processing the given installation jobs. */ static gboolean -do_install_solved_job(struct pkg_jobs *jobs, - PkBackend *backend, - gboolean simulate) +sim_job(struct pkg_jobs *jobs, struct query *q) { gboolean success; + PkBackend *backend; struct pkg *pkg; - success = TRUE; + backend = query_backend(q); + success = FALSE; + query_set_percentage(q, 0); + + if (solve_job(q, jobs) == FALSE) + goto cleanup; + + pk_backend_set_status(backend, PK_STATUS_ENUM_RUNNING); pkg = NULL; while (pkg_jobs(jobs, &pkg) == EPKG_OK) pkgutils_emit(pkg, backend, pkgutils_pkg_install_state(pkg)); - if (simulate == FALSE) - success = do_install_solved_job_real(jobs, backend); + success = TRUE; +cleanup: + query_set_percentage(q, 100); return success; } /* - * Actually installs a fully solved installation job. + * Solves a job and ensures it has packages available. */ static gboolean -do_install_solved_job_real(struct pkg_jobs *jobs, PkBackend *backend) +solve_job(struct query *q, struct pkg_jobs *jobs) { gboolean success; + PkBackend *backend; success = FALSE; + backend = query_backend(q); - pkg_event_register(install_event_cb, backend); - - pk_backend_set_status(backend, PK_STATUS_ENUM_INSTALL); - if (pkg_jobs_apply(jobs) == EPKG_OK) - success = TRUE; - else + pk_backend_set_status(backend, PK_STATUS_ENUM_DEP_RESOLVE); + if (pkg_jobs_solve(jobs) != EPKG_OK) pk_backend_error_code(backend, - PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL, - "job failed"); - - pkg_event_register(NULL, NULL); + PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, + "could not solve the job"); + else if (pkg_jobs_count(jobs) == 0) + pk_backend_error_code(backend, + PK_ERROR_ENUM_INTERNAL_ERROR, + "job contains no packages"); + else + success = TRUE; return success; } /* - * Tries to process the given solved installation jobs. - */ -static gboolean -job(struct pkg_jobs *jobs, struct query *q) -{ - - return do_install_packages(jobs, q, FALSE); -} - -/* - * Tries to simulate processing the given installation jobs. - */ -static gboolean -sim_job(struct pkg_jobs *jobs, struct query *q) -{ - - return do_install_packages(jobs, q, TRUE); -} - -/* * Event handler for events emitted by pkg during an installation. */ static int @@ -199,9 +201,15 @@ PK_INFO_ENUM_FINISHED); break; case PKG_EVENT_ERROR: + /* + * This is sometimes used for nonfatal errors, so we can't + * throw an error code here + */ +#if 0 pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL, event->e_pkg_error.msg); +#endif break; case PKG_EVENT_FILE_MISMATCH: pk_backend_error_code(backend, Modified: soc2013/mattbw/backend/actions/resolve.c ============================================================================== --- soc2013/mattbw/backend/actions/resolve.c Mon Jul 8 07:12:20 2013 (r254407) +++ soc2013/mattbw/backend/actions/resolve.c Mon Jul 8 11:55:21 2013 (r254408) @@ -22,6 +22,7 @@ #include "pkg.h" #include "../db.h" /* db_open_remote */ +#include "../query.h" /* query_* */ #include "actions.h" /* Prototype */ static gboolean resolve_id(struct pkgdb *db, PkBackend *backend, gchar *id); @@ -55,6 +56,7 @@ } else success = FALSE; + pkgdb_close(db); pk_backend_finished(backend); return success; } @@ -64,6 +66,15 @@ { /* TODO: implement */ + + /*struct query_target t; + + t.type = QUERY_EMIT; + t.data.emit.load_flags = load_flags; + t.data.emit.f = emitter; + + return query_do(backend, &t, query_find_match);*/ + (void)db; (void)backend; (void)id; Added: soc2013/mattbw/backend/query.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2013/mattbw/backend/query.h Mon Jul 8 11:55:21 2013 (r254408) @@ -0,0 +1,29 @@ +/*- + * Copyright (C) 2013 Matt Windsor <mattbw@FreeBSD.org> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _PKGNG_BACKEND_QUERY_H_ +#define _PKGNG_BACKEND_QUERY_H_ + +/* Meta-header for the public interfaces to the query system. */ + +#include "query/do.h" /* query_do_... */ +#include "query/match.h" /* query_match_... */ + +#endif /* !_PKGNG_BACKEND_QUERY_H_ */ Copied and modified: soc2013/mattbw/backend/query/core.c (from r254407, soc2013/mattbw/backend/query.c) ============================================================================== --- soc2013/mattbw/backend/query.c Mon Jul 8 07:12:20 2013 (r254407, copy source) +++ soc2013/mattbw/backend/query/core.c Mon Jul 8 11:55:21 2013 (r254408) @@ -20,38 +20,52 @@ #include <string.h> #include <glib.h> -#include "pk-backend.h" +#include "../pk-backend.h" #include "pkg.h" -#include "query.h" /* Prototypes */ -#include "db.h" /* db_open_remote */ -#include "hash_traverse.h" /* HASH_FOR */ -#include "utils.h" /* string_match */ -#include "pkgutils.h" /* pkgutils_... */ +#include "../db.h" /* db_open_remote */ +#include "../hash_traverse.h" /* HASH_FOR */ +#include "../utils.h" /* string_match */ +#include "../pkgutils.h" /* pkgutils_... */ +#include "core.h" /* Prototypes */ + +enum repo_type { + REPO_INVALID, + REPO_ANY, + REPO_LOCAL, + REPO_REMOTE +}; -struct query { - int load_flags; +struct query_unpacked_source { + gboolean skip_id_match; const gchar *name; const gchar *version; const gchar *arch; const gchar *data; gchar **strv; +}; + +struct query { PkBackend *backend; struct pkgdb *db; - gboolean any_repo; - gboolean local_repo; + struct query_unpacked_source *su; + enum repo_type rtype; + + struct query_source *s; struct query_target *t; }; -static gboolean match_id_in_it(struct pkgdb_it *it, struct query *q, struct pkg -**match_pkg_p, gchar **match_id_p); -static gboolean try_id_match(struct pkg *pkg, struct query *q, gchar **match_id); +static enum repo_type type_of_repo_name(const char *name); +static gboolean can_remote_iterate(struct query *q); +static gchar *match_pkg(struct pkg *pkg, struct query *q); static int jobs_add_pkg(struct pkg_jobs *jobs, match_t type, struct pkg *pkg); static int jobs_repo_from_query(struct pkg_jobs *jobs, struct query *q); -static void query_free_contents(struct query *q); +static struct pkg *match_iterator(struct pkgdb_it *it, struct query *q, gchar **match_id_p); +static struct query_unpacked_source *init_unpacked_source(PkBackend *backend, struct query_source *s); +static void free_unpacked_source(struct query_unpacked_source **su_p); /* Returns the backend stored inside the struct query. */ PkBackend * @@ -77,28 +91,24 @@ PkBitfield filters; const char *name; gchar *match_id; - struct pkg *match_pkg; + struct pkg *pkg; struct pkgdb *db; struct pkgdb_it *it; success = FALSE; match = MATCH_EXACT; match_id = NULL; - match_pkg = NULL; + pkg = NULL; db = q->db; - name = q->name; + name = q->su->name; /* * If we're not given a specific repository in the PackageID, we want * to try searching locally first and then remotely; otherwise which * database we query depends on the repository we have been given. */ - if (q->any_repo == TRUE) - try_local = try_remote = TRUE; - else { - try_local = (q->local_repo == TRUE); - try_remote = (q->local_repo == FALSE); - } + try_local = (q->rtype != REPO_REMOTE); + try_remote = (q->rtype != REPO_LOCAL); /* Apply filters, if any */ filters = pk_backend_get_uint(q->backend, "filters"); @@ -110,110 +120,33 @@ /* Try a local search first, if applicable. */ it = (try_local ? pkgdb_query(db, name, match) : NULL); if (it != NULL) - success = match_id_in_it(it, q, &match_pkg, &match_id); + pkg = match_iterator(it, q, &match_id); pkgdb_it_free(it); - if (success == TRUE) + /* No point trying remote if we got a local match */ + if (pkg != NULL) try_remote = FALSE; /* Next, try a remote search, again only if applicable. */ - it = (try_remote ? pkgdb_rquery(db, name, match, q->data) : NULL); - if (it != NULL) - success = match_id_in_it(it, q, &match_pkg, &match_id); + it = (try_remote ? pkgdb_rquery(db, name, match, q->su->data) : NULL); + if (it != NULL && can_remote_iterate(q)) + pkg = match_iterator(it, q, &match_id); pkgdb_it_free(it); - /* - * Assume any error is due to not finding packages. At time of - * writing this is true, but may change. - */ - if (success == TRUE) { - if (q->t->type == QUERY_EMIT) - q->t->data.emit.f(match_pkg, match_id, q); - else if (q->t->type == QUERY_JOB) - query_emit_to_job(match_pkg, match_id, q); - } else + if (pkg == NULL) pk_backend_error_code(q->backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "package not found"); - - pkg_free(match_pkg); - g_free(match_id); - - return success; -} - -/* - * Iterates a query function over all PackageIDs provided for this job. - * - * This provides each iterating function call with a query structure ready to - * run and updates the percentage after each iteration. - * - * It also *finishes* the backend job. - */ -gboolean -query_do(PkBackend *backend, struct query_target *t, query_body_ptr body) -{ - gboolean no_error_yet; - guint i; - guint len; - struct pkgdb *db; - struct query *q; - gchar **package_ids; - - (void)pk_backend_set_percentage(backend, - PK_BACKEND_PERCENTAGE_INVALID); - - /* - * We're using length/index instead of incrementing the pointer to NULL - * so that we can infer the progress bar percentage. - */ - package_ids = pk_backend_get_strv(backend, "package_ids"); - len = g_strv_length(package_ids); - - db = NULL; - q = NULL; - - no_error_yet = db_open_remote(&db, backend); - - pk_backend_set_percentage(backend, 0); - for (i = 0; i < len && no_error_yet; i++) { - no_error_yet = query_do_single(package_ids[i], - backend, - db, - t, - body); - pk_backend_set_percentage(backend, ((i * 100) / len)); + else { + if (q->t->type == QUERY_EMIT) + success = q->t->data.emit.f(pkg, match_id, q); + else if (q->t->type == QUERY_JOB) + success = query_emit_to_job(pkg, match_id, q); } - pkgdb_close(db); - - pk_backend_finished(backend); - - return no_error_yet; -} - -/* - * Runs a query over one PackageID. - * - * This provides the emitting function with a query structure ready to run, but - * does not do any backend housekeeping. - */ -gboolean -query_do_single(gchar *package_id, - PkBackend *backend, - struct pkgdb *db, - struct query_target *t, - query_body_ptr body) -{ - gboolean success; - struct query *q; - - q = NULL; - success = query_init(package_id, backend, db, t, &q); - if (success) - success = body(q); + pkg_free(pkg); + g_free(match_id); - query_free(q); return success; } @@ -262,145 +195,193 @@ return success; } +/* + * Runs an assembled query. + */ +gboolean +query_run(struct query *q) +{ + return q->s->body(q); +} -/* Creates a struct query for the given backend and target ID. */ -gboolean -query_init(const gchar *id, - PkBackend *backend, +/* + * Creates a struct query for the given backend, database, source and target. + * + * Usually you'll want to use "query_do" instead of calling this directly. + */ +struct query * +query_init(PkBackend *backend, struct pkgdb *db, - struct query_target *t, - struct query **q_p) + struct query_source *s, + struct query_target *t) { gboolean success; struct query *q; - q = *q_p; - if (q == NULL) - q = g_new0(struct query, 1); - else - query_free_contents(q); + success = FALSE; + q = calloc(1, sizeof(struct query)); + if (q == NULL) { + ERR(backend, PK_ERROR_ENUM_OOM, "couldn't allocate query"); + goto cleanup; + } q->backend = backend; q->db = db; + q->s = s; q->t = t; - success = split_id(id, - &(q->strv), - &(q->name), - &(q->version), - &(q->arch), - &(q->data)); - if (success == FALSE) { - pk_backend_error_code(backend, - PK_ERROR_ENUM_PACKAGE_ID_INVALID, - "invalid package id"); + q->su = init_unpacked_source(backend, s); + if (q->su == NULL) goto cleanup; - } - /* - * Check the repository to make sure it's sane, and populate the repo - * type flags in the state for later consumption. - */ - if (q->data == NULL) - q->any_repo = TRUE; - else if (strcmp(q->data, "installed") == 0) - q->local_repo = TRUE; - else if (pkg_repo_find_ident(q->data) == NULL) { - pk_backend_error_code(backend, - PK_ERROR_ENUM_REPO_NOT_FOUND, - "no such repository"); - success = FALSE; + + q->rtype = type_of_repo_name(q->su->data); + if (q->rtype == REPO_INVALID) { + ERR(backend, PK_ERROR_ENUM_REPO_NOT_FOUND, "no such repo"); goto cleanup; } - /* - * Stop pkg from catching fire if we try to load files from - * non-installed packages. - */ - if (q->t->type == QUERY_EMIT) { - gboolean loading_files; + success = TRUE; - loading_files = (q->t->data.emit.load_flags & - PKG_LOAD_FILES) ? TRUE : FALSE; - if (q->local_repo == FALSE && loading_files) { - pk_backend_error_code(backend, - PK_ERROR_ENUM_CANNOT_GET_FILELIST, - "cannot get files for remote package"); - success = FALSE; - goto cleanup; - } - } cleanup: - if (success == FALSE) { - query_free(q); - q = NULL; - } - *q_p = q; - return success; + if (success == FALSE) + query_free(&q); + + return q; } /* Deallocates a struct query and any contents it owns. */ void -query_free(struct query *q) +query_free(struct query **q_p) { + struct query *q; + + q = (q_p == NULL ? NULL : *q_p); if (q != NULL) { - query_free_contents(q); - g_free(q); + /* + * The database, source and target structures are owned by + * the creator and not freed here. + */ + + if (q->su != NULL) + free_unpacked_source(&(q->su)); + + free(q); + *q_p = NULL; } } -static gboolean -match_id_in_it(struct pkgdb_it *it, - struct query *q, - struct pkg **match_pkg_p, - gchar **match_id_p) +/* + * Updates the PackageKit percentage to reflect progress on this query. If + * this query is part of a subquery, then the percentage will be scaled + * appropriately. + */ +void +query_set_percentage(struct query *q, unsigned char percent) { - int err; - int load_flags; + guint scaled_percent; - /* TODO: Filters */ + if (percent == PK_BACKEND_PERCENTAGE_INVALID) + scaled_percent = PK_BACKEND_PERCENTAGE_INVALID; + else { + if (percent > 100) + percent = 100; - *match_pkg_p = NULL; - *match_id_p = NULL; + scaled_percent = (((100 * q->s->position) + + (percent * (q->s->position + 1))) / (q->s->total)); + } - if (q->t->type == QUERY_EMIT) - load_flags = q->t->data.emit.load_flags; - else - load_flags = PKG_LOAD_BASIC; + (void)pk_backend_set_percentage(q->backend, scaled_percent); +} - for (HASH_FOR(err, pkgdb_it_next, it, match_pkg_p, load_flags)) - if (try_id_match(*match_pkg_p, q, match_id_p) == TRUE) - break; +/* Finds the type of the given PackageKit repository name. */ +static enum repo_type +type_of_repo_name(const char *name) +{ + enum repo_type rtype; + + if (name == NULL) + rtype = REPO_ANY; + else if (strcmp(name, "installed") == 0) + rtype = REPO_LOCAL; + else if (pkg_repo_find_ident(name) != NULL) + rtype = REPO_REMOTE; + else + rtype = REPO_INVALID; - return (err == EPKG_OK && *match_id_p != NULL) ? TRUE : FALSE; + return rtype; } +/* + * Checks to see if trying to do a remote package iteration with this query + * could spell disaster. + */ static gboolean -try_id_match(struct pkg *pkg, struct query *q, char **match_id) +can_remote_iterate(struct query *q) +{ + gboolean sane; + + /* Innocent until proven guilty */ + sane = TRUE; + + /* + * Stop pkg from catching fire if we try to load files from + * non-installed packages. + */ + if (q->t->type == QUERY_EMIT) { + int loading_files; + + loading_files = (q->t->data.emit.load_flags & PKG_LOAD_FILES); + if (loading_files) { + ERR(q->backend, + PK_ERROR_ENUM_CANNOT_GET_FILELIST, + "cannot get files for remote package"); + sane = FALSE; + } + } + return sane; +} + +/* + * Checks whether a candidate package matches any constraints provided by the + * query and, if so, returns its full PackageID; otherwise NULL. + */ +static gchar * +match_pkg(struct pkg *pkg, struct query *q) { gboolean matches; int i; + gchar *match_id; const gchar **pkg_id_bits; pkg_id_bits = g_new0(const gchar *, 4); - g_free(*match_id); - *match_id = pkgutils_pkg_to_id_through(pkg, pkg_id_bits); + match_id = pkgutils_pkg_to_id_through(pkg, pkg_id_bits); - /* - * Succeed if this package's PackageID fields match the original - * PackageID. Of course, the original ID might have missing fields - * (NULLs), so we treat a comparison involving one as a success. This - * means using our "weak strcmp" instead of normal strcmp or even - * g_strcmp0. - */ - for (matches = TRUE, i = PK_PACKAGE_ID_NAME; - matches == TRUE && i <= PK_PACKAGE_ID_DATA; - i++) - matches = string_match((q->strv)[i], pkg_id_bits[i]); + if (q->su->skip_id_match == TRUE) + matches = TRUE; + else { + /* + * Succeed if this package's PackageID fields match the + * original PackageID. Of course, the original ID might have + * missing fields (NULLs), so we treat a comparison involving + * one as a success. This means using our "weak strcmp" + * instead of normal strcmp or even g_strcmp0. + */ + for (matches = TRUE, i = PK_PACKAGE_ID_NAME; + matches == TRUE && i <= PK_PACKAGE_ID_DATA; + i++) + matches = string_match((q->su->strv)[i], + pkg_id_bits[i]); + } g_free(pkg_id_bits); - return matches; + + if (matches == FALSE) { + g_free(match_id); + match_id = NULL; + } + return match_id; } /* Adds a single package to a jobs structure. */ @@ -420,21 +401,109 @@ { int err; - if (q->data == NULL) + if (q->su->data == NULL) err = EPKG_OK; else - err = pkg_jobs_set_repository(jobs, q->data); + err = pkg_jobs_set_repository(jobs, q->su->data); return err; } -/* Frees the owned contents of a struct query, but not the struct itself. */ +/* + * Tries to find a query-matching package in a database iterator. Returns the + * package if one matches, or NULL; if match_id_p is non-null, its full + * PackageID will be emitted there. + */ +static struct pkg * +match_iterator(struct pkgdb_it *it, struct query *q, gchar **match_id_p) +{ + int load_flags; + gchar *match_id; + struct pkg *pkg; + + if (q->t->type == QUERY_EMIT) + load_flags = q->t->data.emit.load_flags; + else + load_flags = PKG_LOAD_BASIC; + + match_id = NULL; + pkg = NULL; + while (pkgdb_it_next(it, &pkg, load_flags) == EPKG_OK) { + match_id = match_pkg(pkg, q); + /* Did it match? */ + if (match_id != NULL) + break; + } + *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307081155.r68BtLlK042448>