Date: Fri, 5 Jul 2013 02:12:22 GMT From: mattbw@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r254090 - soc2013/mattbw/backend Message-ID: <201307050212.r652CM2K006327@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mattbw Date: Fri Jul 5 02:12:22 2013 New Revision: 254090 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=254090 Log: (fixed?) rearranged and corrected the packageID checks; string_match now works on empty strings as well as null ones so strv comparisons work directly Modified: soc2013/mattbw/backend/query.c soc2013/mattbw/backend/query.h soc2013/mattbw/backend/utils.c Modified: soc2013/mattbw/backend/query.c ============================================================================== --- soc2013/mattbw/backend/query.c Fri Jul 5 01:53:51 2013 (r254089) +++ soc2013/mattbw/backend/query.c Fri Jul 5 02:12:22 2013 (r254090) @@ -59,156 +59,27 @@ return (q == NULL ? NULL : q->backend); } -/* Converts a package to a PackageID. */ -void -query_pkg_to_id(struct pkg *pkg, gchar **id_p) -{ - const gchar **id_bits; - - /* Make sure the initial string vector's pointers are all NULL */ - id_bits = g_new0(const gchar *, 4); - - /* This is split through an intermediate function so the same code - * can be used for the ID-checking logic. - */ - query_pkg_to_id_through(pkg, id_p, id_bits); - - /* AFAIK we don't own any of the strings, so we don't use g_strfreev. */ - g_free(id_bits); -} - -/* Gets the PackageKit repository name for the package. */ -static const char * -get_repo_of(struct pkg *pkg) -{ - const char *repo; - - switch (pkg_type(pkg)) { - case PKG_FILE: - repo = "local"; - break; - case PKG_INSTALLED: - repo = "installed"; - break; - case PKG_REMOTE: - repo = get_repo_of_remote(pkg); - break; - default: - repo = "unknown"; - break; - } - - return repo; -} - /* - * Gets the PackageKit repository name for the (remote) package. - * - * Currently this is actually the pkgng repository ident. This might change. - * - * This does not need to be freed (possibly, TODO: check). + * Performs a package database query against a PackageID, and then hands the + * matching result to an emitter function. */ -static const char * -get_repo_of_remote(struct pkg *pkg) -{ - const char *repo; - const char *repo_name; - struct pkg_repo *repo_struct; - - repo = NULL; - - /* - * We can get the repo NAME directly, but we need the repo IDENT. - * Short of chopping bits of the string off in the assumption that - * the name is repo-IDENT, we'll have to grab it from the repo - * structure itself. - */ - pkg_get(pkg, PKG_REPONAME, &repo_name); - - repo_struct = pkg_repo_find_name(repo_name); - if (repo_struct) - repo = pkg_repo_ident(repo_struct); - - return repo; -} - -static gboolean -match_id_in_it(struct pkgdb_it *it, - struct query *q, - gchar **match_id_p, - struct pkg **match_pkg_p) -{ - /* TODO: Filters */ - gboolean found; - int err; - int load_flags; - - found = FALSE; - *match_pkg_p = NULL; - *match_id_p = NULL; - load_flags = q->load_flags; - - 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) { - found = TRUE; - break; - } - } - - return found; -} - -static gboolean -try_id_match(struct pkg *pkg, struct query *q, char **match_id) -{ - gboolean cmp; - const gchar **pkg_id_bits; - - pkg_id_bits = g_new0(const gchar *, 4); - query_pkg_to_id_through(pkg, match_id, 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. - */ - cmp = (string_match(q->name, pkg_id_bits[0]) && - string_match(q->version, pkg_id_bits[1]) && - string_match(q->arch, pkg_id_bits[2]) && - string_match(q->data, pkg_id_bits[3])) ? TRUE : FALSE; - g_free(pkg_id_bits); - - return cmp; -} - -/* Adds a single package to a jobs structure. */ -static int -jobs_add_pkg(struct pkg_jobs *jobs, match_t type, struct pkg *pkg) +gboolean +query_emit_match(struct query *q, emit_ptr emitter) { - char *name; - - pkg_get(pkg, PKG_NAME, &name); - return pkg_jobs_add(jobs, type, &name, 1); -} + gboolean success; + gchar *match_id; + struct pkg *match_pkg; -/* Converts a package to a PackageID, dumping the intermediate information into - * the pointed-to string vector (which must have at least 4 places, and they - * should be NULL). - */ -static void -query_pkg_to_id_through(struct pkg *pkg, gchar **id_p, const gchar **strv) -{ - pkg_get(pkg, - PKG_NAME, strv, - PKG_ARCH, strv + 1, - PKG_VERSION, strv + 2); + match_id = NULL; + match_pkg = NULL; + success = match(q, &match_id, &match_pkg); + if (success == TRUE && match_id != NULL && match_pkg != NULL) + emitter(match_pkg, match_id, q); - *(strv + 3) = get_repo_of(pkg); + pkg_free(match_pkg); + g_free(match_id); - if (*id_p != NULL) - g_free(*id_p); - *id_p = pk_package_id_build(strv[0], strv[1], strv[2], strv[3]); + return success; } /* @@ -254,26 +125,71 @@ return no_error_yet; } -/* - * Performs a package database query against a PackageID, and then hands the - * matching result to an emitter function. - */ +/* Creates a struct query for the given backend and target ID. */ gboolean -query_emit_match(struct query *q, emit_ptr emitter) +query_init(const gchar *id, + PkBackend *backend, + struct pkgdb *db, + int load_flags, + struct query **q_p) { gboolean success; - gchar *match_id; - struct pkg *match_pkg; + gboolean loading_files; + struct query *q; - match_id = NULL; - match_pkg = NULL; - success = match(q, &match_id, &match_pkg); - if (success == TRUE && match_id != NULL && match_pkg != NULL) - emitter(match_pkg, match_id, q); + q = *q_p; + if (q == NULL) + q = g_new0(struct query, 1); + else + query_free_contents(q); - pkg_free(match_pkg); - g_free(match_id); + q->backend = backend; + q->load_flags = load_flags; + q->db = db; + + 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"); + /* + * Check the repository to make sure it's sane, and populate the repo + * type flags in the state for later consumption. + */ + if (success == TRUE) { + 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_PACKAGE_ID_INVALID, + "no such repository"); + success = FALSE; + } + } + /* + * Stop pkg from catching fire if we try to load files from + * non-installed packages. + */ + loading_files = (load_flags & PKG_LOAD_FILES) ? TRUE : FALSE; + if (success == TRUE && 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; + } + if (success == FALSE) { + query_free(q); + q = NULL; + } + *q_p = q; return success; } @@ -316,6 +232,90 @@ } +/* Deallocates a struct query and any contents it owns. */ +void +query_free(struct query *q) +{ + if (q != NULL) { + query_free_contents(q); + g_free(q); + } +} + +/* Converts a package to a PackageID. */ +void +query_pkg_to_id(struct pkg *pkg, gchar **id_p) +{ + const gchar **id_bits; + + /* Make sure the initial string vector's pointers are all NULL */ + id_bits = g_new0(const gchar *, 4); + + /* + * This is split through an intermediate function so the same code + * can be used for the ID-checking logic. + */ + query_pkg_to_id_through(pkg, id_p, id_bits); + + /* we don't own any of the strings, so we don't use g_strfreev. */ + g_free(id_bits); +} + +/* Gets the PackageKit repository name for the package. */ +static const char * +get_repo_of(struct pkg *pkg) +{ + const char *repo; + + switch (pkg_type(pkg)) { + case PKG_FILE: + repo = "local"; + break; + case PKG_INSTALLED: + repo = "installed"; + break; + case PKG_REMOTE: + repo = get_repo_of_remote(pkg); + break; + default: + repo = "unknown"; + break; + } + + return repo; +} + +/* + * Gets the PackageKit repository name for the (remote) package. + * + * Currently this is actually the pkgng repository ident. This might change. + * + * This does not need to be freed (possibly, TODO: check). + */ +static const char * +get_repo_of_remote(struct pkg *pkg) +{ + const char *repo; + const char *repo_name; + struct pkg_repo *repo_struct; + + repo = NULL; + + /* + * We can get the repo NAME directly, but we need the repo IDENT. + * Short of chopping bits of the string off in the assumption that + * the name is repo-IDENT, we'll have to grab it from the repo + * structure itself. + */ + pkg_get(pkg, PKG_REPONAME, &repo_name); + + repo_struct = pkg_repo_find_name(repo_name); + if (repo_struct) + repo = pkg_repo_ident(repo_struct); + + return repo; +} + /* * Performs a package database query against a (potentially partial) * PackageID, retrieving the matched package and its full PackageID. @@ -374,81 +374,85 @@ return success; } -/* Creates a struct query for the given backend and target ID. */ -gboolean -query_init(const gchar *id, - PkBackend *backend, - struct pkgdb *db, - int load_flags, - struct query **q_p) +static gboolean +match_id_in_it(struct pkgdb_it *it, + struct query *q, + gchar **match_id_p, + struct pkg **match_pkg_p) { - gboolean success; - gboolean loading_files; - struct query *q; + /* TODO: Filters */ + int err; + int load_flags; - q = *q_p; - if (q == NULL) - q = g_new0(struct query, 1); - else - query_free_contents(q); + *match_pkg_p = NULL; + *match_id_p = NULL; + load_flags = q->load_flags; - q->backend = backend; - q->load_flags = load_flags; - q->db = db; + 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; - 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"); + return (err == EPKG_OK && *match_id_p != NULL) ? TRUE : FALSE; +} + +static gboolean +try_id_match(struct pkg *pkg, struct query *q, char **match_id) +{ + gboolean matches; + int i; + const gchar **pkg_id_bits; + + pkg_id_bits = g_new0(const gchar *, 4); + query_pkg_to_id_through(pkg, match_id, pkg_id_bits); /* - * Check the repository to make sure it's sane, and populate the repo - * type flags in the state for later consumption. - */ - if (success == TRUE) { - 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_PACKAGE_ID_INVALID, - "no such repository"); - success = FALSE; - } - } - /* - * Stop pkg from catching fire if we try to load files from - * non-installed packages. + * 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. */ - loading_files = (load_flags & PKG_LOAD_FILES) ? TRUE : FALSE; - if (success == TRUE && 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; - } - if (success == FALSE) { - query_free(q); - q = NULL; - } - *q_p = q; - return success; + 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]); + + g_free(pkg_id_bits); + return matches; } -void -query_free(struct query *q) +/* Adds a single package to a jobs structure. */ +static int +jobs_add_pkg(struct pkg_jobs *jobs, match_t type, struct pkg *pkg) { - if (q != NULL) { - query_free_contents(q); - g_free(q); - } + char *name; + + pkg_get(pkg, PKG_NAME, &name); + return pkg_jobs_add(jobs, type, &name, 1); +} + +/* + * Converts a package to a PackageID, dumping the intermediate information + * into the pointed-to string vector (which must have at least 4 places, and + * they should be NULL). + */ +static void +query_pkg_to_id_through(struct pkg *pkg, gchar **id_p, const gchar **strv) +{ + + pkg_get(pkg, + PKG_NAME, strv + PK_PACKAGE_ID_NAME, + PKG_VERSION, strv + PK_PACKAGE_ID_VERSION, + PKG_ARCH, strv + PK_PACKAGE_ID_ARCH); + + strv[PK_PACKAGE_ID_DATA] = get_repo_of(pkg); + + if (*id_p != NULL) + g_free(*id_p); + *id_p = pk_package_id_build(strv[PK_PACKAGE_ID_NAME], + strv[PK_PACKAGE_ID_VERSION], + strv[PK_PACKAGE_ID_ARCH], + strv[PK_PACKAGE_ID_DATA]); } static void Modified: soc2013/mattbw/backend/query.h ============================================================================== --- soc2013/mattbw/backend/query.h Fri Jul 5 01:53:51 2013 (r254089) +++ soc2013/mattbw/backend/query.h Fri Jul 5 02:12:22 2013 (r254090) @@ -31,7 +31,6 @@ typedef void (*job_emit_ptr) (struct pkg_jobs *jobs, struct query *q); typedef gboolean (*query_body_ptr) (struct query *q); - PkBackend *query_backend(struct query *q); gboolean query_emit_match(struct query *q, emit_ptr emitter); gboolean query_for_all_ids(PkBackend *backend, int load_flags, query_body_ptr body); Modified: soc2013/mattbw/backend/utils.c ============================================================================== --- soc2013/mattbw/backend/utils.c Fri Jul 5 01:53:51 2013 (r254089) +++ soc2013/mattbw/backend/utils.c Fri Jul 5 02:12:22 2013 (r254090) @@ -78,7 +78,7 @@ /* * Checks two strings with strcmp and emits TRUE if they match. If either - * string is NULL, emit TRUE as well (this is so that missing PackageID + * string is NULL or empty, emit TRUE as well (this is so that missing PackageID * elements trigger matches). */ gboolean @@ -88,6 +88,8 @@ if (left == NULL || right == NULL) result = TRUE; + else if (*left == '\0' || *right == '\0') + result = TRUE; else result = (strcmp(left, right) == 0 ? TRUE : FALSE);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307050212.r652CM2K006327>