Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
groups: implement basic pkg search group
Baptiste Daroussin committed 2 years ago
commit 6e2063497c0f6dbdac5132fdb825fa4eb081bc71
parent 24b197c
7 files changed +221 -9
modified libpkg/pkg.h.in
@@ -238,6 +238,14 @@ typedef enum {
	 * The pkg refers to a local file old archive.
	 */
	PKG_OLD_FILE = (1U << 4),
+
	/**
+
	 * The pkg is group available in a remove repository
+
	 */
+
	PKG_GROUP_REMOTE = (1U << 5),
+
	/**
+
	 * The pkg refers to an installed group
+
	 */
+
	PKG_GROUP_INSTALLED = (1U << 6),
} pkg_t;

/**
modified libpkg/pkgdb_query.c
@@ -519,6 +519,11 @@ pkgdb_repo_search(struct pkgdb *db, const char *pattern, match_t match,
				if (rit != NULL)
					pkgdb_it_repo_attach(it, rit);
			}
+
			if (cur->item->ops->groupsearch != NULL) {
+
				rit = cur->item->ops->groupsearch(cur->item, pattern, match, field);
+
				if (rit != NULL)
+
					pkgdb_it_repo_attach(it, rit);
+
			}
		}
	}

modified libpkg/private/pkg.h
@@ -508,6 +508,8 @@ struct pkg_repo_ops {
					const char *);
	struct pkg_repo_it * (*search)(struct pkg_repo *, const char *, match_t,
					pkgdb_field field, pkgdb_field sort);
+
	struct pkg_repo_it * (*groupsearch)(struct pkg_repo *, const char *,
+
	    match_t, pkgdb_field field);

	int64_t (*stat)(struct pkg_repo *, pkg_stats_t type);

modified libpkg/repo/binary/binary.c
@@ -37,6 +37,7 @@ struct pkg_repo_ops pkg_repo_binary_ops = {
	.provided = pkg_repo_binary_provide,
	.required = pkg_repo_binary_require,
	.search = pkg_repo_binary_search,
+
	.groupsearch = pkg_repo_binary_groupsearch,
	.fetch_pkg = pkg_repo_binary_fetch,
	.mirror_pkg = pkg_repo_binary_mirror,
	.get_cached_name = pkg_repo_binary_get_cached_name,
modified libpkg/repo/binary/binary.h
@@ -52,6 +52,8 @@ struct pkg_repo_it *pkg_repo_binary_require(struct pkg_repo *repo,
struct pkg_repo_it *pkg_repo_binary_search(struct pkg_repo *repo,
	const char *pattern, match_t match,
    pkgdb_field field, pkgdb_field sort);
+
struct pkg_repo_it *pkg_repo_binary_groupsearch(struct pkg_repo *repo,
+
	const char *pattern, match_t match, pkgdb_field field);
int pkg_repo_binary_ensure_loaded(struct pkg_repo *repo,
	struct pkg *pkg, unsigned flags);
int64_t pkg_repo_binary_stat(struct pkg_repo *repo, pkg_stats_t type);
modified libpkg/repo/binary/query.c
@@ -1,15 +1,16 @@
-
/* Copyright (c) 2014, Vsevolod Stakhov
+
/*
+
 * Copyright (c) 2014, Vsevolod Stakhov
+
 * Copyright (c) 2024, Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2023, Serenity Cyber Security, LLC
 *                     Author: Gleb Popov <arrowd@FreeBSD.org>
-
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
-
 *       * Redistributions of source code must retain the above copyright
-
 *         notice, this list of conditions and the following disclaimer.
-
 *       * Redistributions in binary form must reproduce the above copyright
-
 *         notice, this list of conditions and the following disclaimer in the
-
 *         documentation and/or other materials provided with the distribution.
+
 * * Redistributions of source code must retain the above copyright
+
 *   notice, this list of conditions and the following disclaimer.
+
 * * Redistributions in binary form must reproduce the above copyright
+
 *   notice, this list of conditions and the following disclaimer in the
+
 *   documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -33,6 +34,8 @@
#include <string.h>
#include <unistd.h>
#include <libgen.h>
+
#include <fcntl.h>
+
#include <fnmatch.h>

#include <sqlite3.h>

@@ -45,16 +48,31 @@

static struct pkg_repo_it* pkg_repo_binary_it_new(struct pkg_repo *repo,
	sqlite3_stmt *s, short flags);
+

+
struct pkg_repo_group {
+
	size_t index;
+
	ucl_object_t *groups;
+
};
static int pkg_repo_binary_it_next(struct pkg_repo_it *it, struct pkg **pkg_p, unsigned flags);
static void pkg_repo_binary_it_free(struct pkg_repo_it *it);
static void pkg_repo_binary_it_reset(struct pkg_repo_it *it);

+
static int pkg_repo_binary_group_it_next(struct pkg_repo_it *it, struct pkg **pkg_p, unsigned flags);
+
static void pkg_repo_binary_group_it_free(struct pkg_repo_it *it);
+
static void pkg_repo_binary_group_it_reset(struct pkg_repo_it *it);
+

static struct pkg_repo_it_ops pkg_repo_binary_it_ops = {
	.next = pkg_repo_binary_it_next,
	.free = pkg_repo_binary_it_free,
	.reset = pkg_repo_binary_it_reset
};

+
static struct pkg_repo_it_ops pkg_repo_binary_group_it_ops = {
+
	.next = pkg_repo_binary_group_it_next,
+
	.free = pkg_repo_binary_group_it_free,
+
	.reset = pkg_repo_binary_group_it_reset
+
};
+

static struct pkg_repo_it*
pkg_repo_binary_it_new(struct pkg_repo *repo, sqlite3_stmt *s, short flags)
{
@@ -78,12 +96,51 @@ pkg_repo_binary_it_new(struct pkg_repo *repo, sqlite3_stmt *s, short flags)
	return (it);
}

+
static struct pkg_repo_it *
+
pkg_repo_binary_group_it_new(struct pkg_repo *repo __unused, ucl_object_t *matching)
+
{
+
	struct pkg_repo_group *prg;
+
	struct pkg_repo_it *it;
+

+
	it = xcalloc(1, sizeof(*it));
+
	prg = xcalloc(1, sizeof(*prg));
+
	prg->groups = matching;
+
	it->ops = &pkg_repo_binary_group_it_ops;
+
	it->data = prg;
+

+
	return (it);
+
}
+

static int
pkg_repo_binary_it_next(struct pkg_repo_it *it, struct pkg **pkg_p, unsigned flags)
{
	return (pkgdb_it_next(it->data, pkg_p, flags));
}

+
static int
+
pkg_repo_binary_group_it_next(struct pkg_repo_it *it, struct pkg **pkg_p, unsigned flags __unused)
+
{
+
	int ret;
+
	struct pkg_repo_group *prg;
+
	const ucl_object_t *o, *el;
+

+
	prg = it->data;
+
	if (prg->index == ucl_array_size(prg->groups))
+
		return (EPKG_END);
+

+
	el = ucl_array_find_index(prg->groups, prg->index);
+
	prg->index++;
+
	pkg_free(*pkg_p);
+
	if ((ret = pkg_new(pkg_p, PKG_GROUP_REMOTE)) != EPKG_OK)
+
		return (ret);
+
	o = ucl_object_find_key(el, "name");
+
	xasprintf(&(*pkg_p)->name, ucl_object_tostring(o));
+
	o = ucl_object_find_key(el, "comment");
+
	xasprintf(&(*pkg_p)->comment, ucl_object_tostring(o));
+

+
	return (EPKG_OK);
+
}
+

static void
pkg_repo_binary_it_free(struct pkg_repo_it *it)
{
@@ -92,11 +149,28 @@ pkg_repo_binary_it_free(struct pkg_repo_it *it)
}

static void
+
pkg_repo_binary_group_it_free(struct pkg_repo_it *it)
+
{
+
	struct pkg_repo_group *prg = it->data;
+
	free(prg->groups);
+
	free(prg);
+
	free(it);
+
}
+

+
static void
pkg_repo_binary_it_reset(struct pkg_repo_it *it)
{
	pkgdb_it_reset(it->data);
}

+
static void
+
pkg_repo_binary_group_it_reset(struct pkg_repo_it *it)
+
{
+
	struct pkg_repo_group *prg = it->data;
+

+
	prg->index = 0;
+
}
+

struct pkg_repo_it *
pkg_repo_binary_query(struct pkg_repo *repo, const char *cond, const char *pattern, match_t match)
{
@@ -423,6 +497,120 @@ pkg_repo_binary_search(struct pkg_repo *repo, const char *pattern, match_t match
	return (pkg_repo_binary_it_new(repo, stmt, PKGDB_IT_FLAG_ONCE));
}

+
struct pkg_repo_it *
+
pkg_repo_binary_groupsearch(struct pkg_repo *repo, const char *pattern, match_t match,
+
    pkgdb_field field)
+
{
+
	ucl_object_t *groups, *ar, *el;
+
	const ucl_object_t *o;
+
	const char *cmp;
+
	struct ucl_parser *p;
+
	int fd;
+
	regex_t *re = NULL;
+
	int flag = 0;
+
	bool in_comment = false;
+

+
	switch (field) {
+
		case FIELD_NAME:
+
		case FIELD_NAMEVER:
+
			break;
+
		case FIELD_COMMENT:
+
			in_comment = true;
+
			break;
+
		default:
+
			/* we cannot search in other fields */
+
			return (NULL);
+
	}
+

+
	if (repo->dfd == -1 && pkg_repo_open(repo) == EPKG_FATAL)
+
		return (NULL);
+
	fd = openat(repo->dfd, "groups.ucl", O_RDONLY|O_CLOEXEC);
+
	if (fd == -1)
+
		return (NULL);
+
	p = ucl_parser_new(0);
+
	if (!ucl_parser_add_fd(p, fd)) {
+
		pkg_emit_error("Error parsing groups for: %s'",
+
		    repo->name);
+
		ucl_parser_free(p);
+
		close(fd);
+
		return (NULL);
+

+
	}
+
	groups = ucl_parser_get_object(p);
+
	ucl_parser_free(p);
+
	close(fd);
+

+
	if (ucl_object_type(groups) != UCL_ARRAY) {
+
		ucl_object_unref(groups);
+
		return (NULL);
+
	}
+

+
	ar = NULL;
+
	while (ucl_array_size(groups) > 0) {
+
		el = ucl_array_pop_first(groups);
+
		if (in_comment) {
+
			o = ucl_object_find_key(el, "comment");
+
		} else {
+
			o = ucl_object_find_key(el, "name");
+
		}
+
		if (o == NULL) {
+
			ucl_object_unref(el);
+
			continue;
+
		}
+
		cmp = ucl_object_tostring(o);
+
		switch (match) {
+
		case MATCH_ALL:
+
			break;
+
		case MATCH_INTERNAL:
+
			if (strcmp(cmp, pattern) == 0)
+
				continue;
+
			break;
+
		case MATCH_EXACT:
+
			if (pkgdb_case_sensitive()) {
+
				if (strcmp(cmp, pattern) == 0)
+
					continue;
+
			} else {
+
				if (strcasecmp(cmp, pattern) == 0)
+
					continue;
+
			}
+
			break;
+
		case MATCH_GLOB:
+
			if (pkgdb_case_sensitive() != 0)
+
				flag = FNM_CASEFOLD;
+
			if (fnmatch(cmp, pattern, flag) == FNM_NOMATCH)
+
				continue;
+
		case MATCH_REGEX:
+
			if (re == NULL) {
+
				flag = REG_EXTENDED | REG_NOSUB;
+
				if (pkgdb_case_sensitive() != 0)
+
					flag |= REG_ICASE;
+
				re = xmalloc(sizeof(regex_t));
+
				if (regcomp(re, pattern, flag) != 0) {
+
					pkg_emit_error("Invalid regex: 'pattern'");
+
					ucl_object_unref(groups);
+
					if (ar != NULL)
+
						ucl_object_unref(ar);
+
					return (NULL);
+
				}
+
			}
+
			if (regexec(re, cmp, 0, NULL, 0) == REG_NOMATCH)
+
				continue;
+
		}
+
		if (ar == NULL)
+
			ar = ucl_object_typed_new(UCL_ARRAY);
+
		ucl_array_append(ar, el);
+
	}
+

+
	if (re != NULL)
+
		regfree(re);
+
	ucl_object_unref(groups);
+

+
	if (ar == NULL)
+
		return (NULL);
+

+
	return (pkg_repo_binary_group_it_new(repo, ar));
+
}
+

int
pkg_repo_binary_ensure_loaded(struct pkg_repo *repo,
	struct pkg *pkg, unsigned flags)
modified src/utils.c
@@ -374,8 +374,14 @@ print_info(struct pkg * const pkg, uint64_t options)
		   preference).  This may be the only output from this
		   function */

-
		if (options & INFO_TAG_NAMEVER)
-
			cout = pkg_printf("%n-%v", pkg, pkg);
+
		if (options & INFO_TAG_NAMEVER) {
+
			if (pkg_type(pkg) != PKG_GROUP_REMOTE &&
+
			    pkg_type(pkg) != PKG_GROUP_INSTALLED) {
+
				cout = pkg_printf("%n-%v", pkg, pkg);
+
			} else {
+
				cout = pkg_printf("@%n", pkg);
+
			}
+
		}
		else if (options & INFO_TAG_ORIGIN)
			cout = pkg_printf("%o", pkg);
		else if (options & INFO_TAG_NAME)