Skip site navigation (1)Skip section navigation (2)
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>