Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Revert "Backout support for provides/requires for pkg add"
Baptiste Daroussin committed 1 year ago
commit 1ca498bdea4f9e573469590cc2411088f44f0747
parent bf05f1f
4 files changed +206 -55
modified libpkg/pkg_add.c
@@ -1071,45 +1071,21 @@ pkg_extract_finalize(struct pkg *pkg, tempdirs_t *tempdirs)
	return (EPKG_OK);
}

-
static char *
-
pkg_globmatch(char *pattern, const char *name)
+
static bool
+
should_append_pkg(pkg_chain_t *localpkgs, struct pkg *p)
{
-
	glob_t g;
-
	int i;
-
	char *buf, *buf2;
-
	char *path = NULL;
-

-
	if (glob(pattern, 0, NULL, &g) == GLOB_NOMATCH) {
-
		globfree(&g);
-

-
		return (NULL);
-
	}
-

-
	for (i = 0; i < g.gl_pathc; i++) {
-
		/* the version starts here */
-
		buf = strrchr(g.gl_pathv[i], '-');
-
		if (buf == NULL)
-
			continue;
-
		buf2 = strrchr(g.gl_pathv[i], '/');
-
		if (buf2 == NULL)
-
			buf2 = g.gl_pathv[i];
-
		else
-
			buf2++;
-
		/* ensure we have match the proper name */
-
		if (strncmp(buf2, name, buf - buf2) != 0)
-
			continue;
-
		if (path == NULL) {
-
			path = g.gl_pathv[i];
-
			continue;
+
	/* only keep the highest version is we fine one */
+
	tll_foreach(*localpkgs, lp) {
+
		if (strcmp(lp->item->name, p->name) == 0) {
+
			if (pkg_version_cmp(lp->item->version, p->version) == -1) {
+
				tll_remove_and_free(*localpkgs, lp, pkg_free);
+
				return (true);
+
			}
+
			return (false);
		}
-
		if (pkg_version_cmp(path, g.gl_pathv[i]) == 1)
-
			path = g.gl_pathv[i];
	}
-
	if (path)
-
		path = xstrdup(path);
-
	globfree(&g);
-

-
	return (path);
+
	/* none found we should append */
+
	return (true);
}

static int
@@ -1120,10 +1096,14 @@ pkg_add_check_pkg_archive(struct pkgdb *db, struct pkg *pkg,
	int	ret, retcode;
	struct pkg_dep	*dep = NULL;
	char	bd[MAXPATHLEN];
-
	char	dpath[MAXPATHLEN], *ppath;
+
	char	dpath[MAXPATHLEN], *ppath, *basedir = NULL;
	const char	*ext = NULL;
	struct pkg	*pkg_inst = NULL;
	bool	fromstdin;
+
	pkg_chain_t localpkgs = tll_init();
+
	struct pkghash *lpkgs = NULL;
+
	struct pkghash *provides = NULL;
+
	struct pkghash *shlibs_provides = NULL;

	arch = pkg->abi != NULL ? pkg->abi : pkg->altabi;

@@ -1183,9 +1163,39 @@ pkg_add_check_pkg_archive(struct pkgdb *db, struct pkg *pkg,

	retcode = EPKG_FATAL;
	pkg_emit_add_deps_begin(pkg);
+
	if (!fromstdin) {
+
		glob_t g;
+
		char *pattern;
+

+
		xasprintf(&pattern, "%s/*%s" , bd, ext);
+
		if (glob(pattern, 0, NULL, &g) == 0) {
+
			for (int i = 0; i <g.gl_pathc; i++) {
+
				struct pkg *p = NULL;
+
				if (pkg_open(&p, g.gl_pathv[i],
+
				    PKG_OPEN_MANIFEST_COMPACT) == EPKG_OK) {
+
					if (should_append_pkg(&localpkgs, p)) {
+
						p->repopath = xstrdup(g.gl_pathv[i]);
+
						tll_push_back(localpkgs, p);
+
					}
+
				}
+
			}
+
		}
+
		globfree(&g);
+
		free(pattern);
+
		tll_foreach(localpkgs, p) {
+
			pkghash_safe_add(lpkgs, p->item->name, xstrdup(p->item->repopath), NULL);
+
			tll_foreach(p->item->shlibs_provided, sp) {
+
				pkghash_safe_add(shlibs_provides, sp->item, xstrdup(p->item->repopath), free);
+
			}
+
			tll_foreach(p->item->provides, sp) {
+
				pkghash_safe_add(provides, sp->item, xstrdup(p->item->repopath), free);
+
			}
+
		}
+
		tll_free_and_free(localpkgs, pkg_free);
+
	}

	while (pkg_deps(pkg, &dep) == EPKG_OK) {
-
		dpath[0] = '\0';
+
		pkghash_entry *founddep = NULL;

		if (pkg_is_installed(db, dep->name) == EPKG_OK)
			continue;
@@ -1197,28 +1207,76 @@ pkg_add_check_pkg_archive(struct pkgdb *db, struct pkg *pkg,
			continue;
		}

-
		if (dep->version != NULL && dep->version[0] != '\0') {
-
			snprintf(dpath, sizeof(dpath), "%s/%s-%s%s", bd,
-
				dep->name, dep->version, ext);
+
		if ((founddep = pkghash_get(lpkgs, dep->name)) == NULL) {
+
			pkg_emit_missing_dep(pkg, dep);
+
			if ((flags & PKG_ADD_FORCE_MISSING) == 0)
+
				goto cleanup;
+
			continue;
		}

-
		if (strlen(dpath) == 0 || access(dpath, F_OK) != 0) {
-
			snprintf(dpath, sizeof(dpath), "%s/%s-*%s", bd,
-
			    dep->name, ext);
-
			ppath = pkg_globmatch(dpath, dep->name);
-
			if (ppath == NULL) {
-
				pkg_emit_missing_dep(pkg, dep);
-
				if ((flags & PKG_ADD_FORCE_MISSING) == 0)
-
					goto cleanup;
-
				continue;
-
			}
-
			strlcpy(dpath, ppath, sizeof(dpath));
-
			free(ppath);
+
		if ((flags & PKG_ADD_UPGRADE) == 0 &&
+
				access(founddep->value, F_OK) == 0) {
+
			ret = pkg_add(db, founddep->value, PKG_ADD_AUTOMATIC, location);
+

+
			if (ret != EPKG_OK)
+
				goto cleanup;
+
		} else {
+
			pkg_emit_missing_dep(pkg, dep);
+
			if ((flags & PKG_ADD_FORCE_MISSING) == 0)
+
				goto cleanup;
+
		}
+
	}
+

+
	tll_foreach(pkg->shlibs_required, s) {
+
		pkghash_entry *founddep = NULL;
+
		if (pkgdb_is_shlib_provided(db, s->item))
+
			continue;
+

+
		if (fromstdin) {
+
			pkg_emit_error("Missing shlib dependency: %s", s->item);
+
			if ((flags & PKG_ADD_FORCE_MISSING) == 0)
+
				goto cleanup;
+
			continue;
+
		}
+
		if ((founddep = pkghash_get(shlibs_provides, s->item)) == NULL) {
+
			pkg_emit_error("Missing shlib dependency: %s", s->item);
+
			if ((flags & PKG_ADD_FORCE_MISSING) == 0)
+
				goto cleanup;
+
			continue;
+
		}
+
		if ((flags & PKG_ADD_UPGRADE) == 0 &&
+
				access(founddep->value, F_OK) == 0) {
+
			ret = pkg_add(db, founddep->value, PKG_ADD_AUTOMATIC, location);
+

+
			if (ret != EPKG_OK)
+
				goto cleanup;
+
		} else {
+
			pkg_emit_missing_dep(pkg, dep);
+
			if ((flags & PKG_ADD_FORCE_MISSING) == 0)
+
				goto cleanup;
		}
+
	}
+

+
	tll_foreach(pkg->requires, s) {
+
		pkghash_entry *founddep = NULL;
+
		if (pkgdb_is_provided(db, s->item))
+
			continue;

+
		if (fromstdin) {
+
			pkg_emit_error("Missing require dependency: %s", s->item);
+
			if ((flags & PKG_ADD_FORCE_MISSING) == 0)
+
				goto cleanup;
+
			continue;
+
		}
+
		if ((founddep = pkghash_get(provides, s->item)) == NULL) {
+
			pkg_emit_error("Missing require dependency: %s", s->item);
+
			if ((flags & PKG_ADD_FORCE_MISSING) == 0)
+
				goto cleanup;
+
			continue;
+
		}
		if ((flags & PKG_ADD_UPGRADE) == 0 &&
-
				access(dpath, F_OK) == 0) {
-
			ret = pkg_add(db, dpath, PKG_ADD_AUTOMATIC, location);
+
				access(founddep->value, F_OK) == 0) {
+
			ret = pkg_add(db, founddep->value, PKG_ADD_AUTOMATIC, location);

			if (ret != EPKG_OK)
				goto cleanup;
@@ -1231,6 +1289,9 @@ pkg_add_check_pkg_archive(struct pkgdb *db, struct pkg *pkg,

	retcode = EPKG_OK;
cleanup:
+
	pkghash_destroy(lpkgs);
+
	pkghash_destroy(provides);
+
	pkghash_destroy(shlibs_provides);
	pkg_emit_add_deps_finished(pkg);

	return (retcode);
modified libpkg/pkgdb.c
@@ -3018,3 +3018,53 @@ pkgdb_debug(int level, sqlite3_stmt *stmt)
	dbg(level, "running: '%s'", str);
	sqlite3_free(str);
}
+

+
bool
+
pkgdb_is_shlib_provided(struct pkgdb *db, const char *req)
+
{
+
	sqlite3_stmt *stmt;
+
	int ret;
+
	bool found = false;
+

+
	const char *sql = ""
+
		"select package_id from pkg_shlibs_provided INNER JOIN shlibs "
+
		"on pkg_shlibs_provided.shlib_id = shlibs.id "
+
		"where shlibs.name=?1" ;
+

+
	stmt = prepare_sql(db->sqlite, sql);
+
	if (stmt == NULL)
+
		return (false);
+

+
	sqlite3_bind_text(stmt, 1, req, -1, SQLITE_TRANSIENT);
+
	ret = sqlite3_step(stmt);
+
	if (ret == SQLITE_ROW)
+
		found = true;
+

+
	sqlite3_finalize(stmt);
+
	return (found);
+
}
+

+
bool
+
pkgdb_is_provided(struct pkgdb *db, const char *req)
+
{
+
	sqlite3_stmt *stmt;
+
	int ret;
+
	bool found = false;
+

+
	const char *sql = ""
+
		"select package_id from pkg_provides INNER JOIN provides "
+
		"on pkg_provides.provide_id = provides.id "
+
		"where provides.provide = ?1" ;
+

+
	stmt = prepare_sql(db->sqlite, sql);
+
	if (stmt == NULL)
+
		return (false);
+

+
	sqlite3_bind_text(stmt, 1, req, -1, SQLITE_TRANSIENT);
+
	ret = sqlite3_step(stmt);
+
	if (ret == SQLITE_ROW)
+
		found = true;
+

+
	sqlite3_finalize(stmt);
+
	return (found);
+
}
modified libpkg/private/pkgdb.h
@@ -170,4 +170,7 @@ bool pkgdb_file_exists(struct pkgdb *db, const char *path);
struct sqlite3_stmt *prepare_sql(sqlite3 *s, const char *sql);
void pkgdb_debug(int level, sqlite3_stmt *stmt);

+
bool pkgdb_is_provided(struct pkgdb *db, const char *req);
+
bool pkgdb_is_shlib_provided(struct pkgdb *db, const char *req);
+

#endif
modified tests/frontend/add.sh
@@ -13,6 +13,8 @@ tests_init \
		add_stdin_missing \
		add_no_version \
		add_no_version_multi \
+
		add_deps_multi \
+
		add_require \
		add_wrong_version

initialize_pkg() {
@@ -254,6 +256,41 @@ EOF
		pkg add final-1.pkg
}

+
add_deps_multi_body() {
+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg test test 2
+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg final final 1
+

+
	cat << EOF >> final.ucl
+
deps {
+
	test {
+
		origin = "test";
+
	},
+
}
+
EOF
+
	atf_check -o ignore -s exit:0 pkg create -M test.ucl
+
	atf_check -o ignore -s exit:0 pkg create -M final.ucl
+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg test test 1
+
	atf_check -o ignore -s exit:0 pkg create -M test.ucl
+
	atf_check -o "match:.*test-2.*" -e ignore -s exit:0 \
+
		pkg add final-1.pkg
+
}
+

+
add_require_body() {
+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg test test 1
+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg final final 1
+
	cat << EOF >> final.ucl
+
requires: [functionA]
+
EOF
+
	cat << EOF >> test.ucl
+
provides: [functionA]
+
EOF
+

+
	atf_check -o ignore -s exit:0 pkg create -M test.ucl
+
	atf_check  -s exit:0 pkg create -M final.ucl
+
	atf_check -o match:".*test-1.*" -e ignore -s exit:0 \
+
		pkg add final-1.pkg
+
}
+

add_wrong_version_body() {
	for p in test final ; do
		atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg ${p} ${p} 1