Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
solver: introduce a new rule kind to handle vital packages
Gleb Popov committed 1 year ago
commit 62db44e719152e7fee5ad4b27f3e5625f6304f86
parent a5cfbe1
2 files changed +104 -7
modified libpkg/pkg_solve.c
@@ -58,6 +58,7 @@ enum pkg_solve_rule_type {
	PKG_RULE_REQUEST_CONFLICT,
	PKG_RULE_REQUEST,
	PKG_RULE_REQUIRE,
+
	PKG_RULE_VITAL,
	PKG_RULE_MAX
};

@@ -68,6 +69,7 @@ static const char *rule_reasons[] = {
	[PKG_RULE_EXPLICIT_CONFLICT] = "conflict",
	[PKG_RULE_REQUEST] = "request",
	[PKG_RULE_REQUIRE] = "require",
+
	[PKG_RULE_VITAL] = "vital",
	[PKG_RULE_MAX] = NULL
};

@@ -249,6 +251,13 @@ pkg_print_rule_buf(struct pkg_solve_rule *rule, xstring *sb)
					it->next ? ", " : "");
		}
		break;
+
	case PKG_RULE_VITAL:
+
		fprintf(sb->fp, "The following packages are vital: ");
+
		LL_FOREACH(rule->items, it) {
+
			fprintf(sb->fp, "%s-%s%s", it->var->uid, it->var->unit->pkg->version,
+
					it->next ? ", " : "");
+
		}
+
		break;
	default:
		break;
	}
@@ -499,6 +508,46 @@ pkg_solve_add_require_rule(struct pkg_solve_problem *problem,
	return (EPKG_OK);
}

+
static int
+
pkg_solve_add_vital_rule(struct pkg_solve_problem *problem,
+
		struct pkg_solve_variable *var)
+
{
+
	struct pkg_solve_variable *cur_var, *local_var = NULL, *remote_var = NULL;
+
	struct pkg_solve_rule *rule = NULL;
+
	struct pkg *pkg;
+

+
	LL_FOREACH(var, cur_var) {
+
		pkg = cur_var->unit->pkg;
+

+
		if (pkg->type == PKG_INSTALLED) {
+
			local_var = cur_var;
+
		} else {
+
			remote_var = cur_var;
+
		}
+
	}
+

+
	if (local_var && remote_var) {
+
		/* Vital upgrade rule: ( L | R ) must be true */
+
		dbg(4, "Add vital rule: want either %s(l) or %s(r)", local_var->unit->pkg->uid, remote_var->unit->pkg->uid);
+
		rule = pkg_solve_rule_new(PKG_RULE_VITAL);
+
		/* L */
+
		pkg_solve_item_new(rule, local_var, 1);
+
		/* R */
+
		pkg_solve_item_new(rule, remote_var, 1);
+
	} else if(local_var) {
+
		/* Vital keep local rule: ( L ) must be true */
+
		dbg(4, "Add vital rule: want %s(l) to stay", local_var->unit->pkg->uid);
+
		rule = pkg_solve_rule_new(PKG_RULE_VITAL);
+
		/* L */
+
		pkg_solve_item_new(rule, local_var, 1);
+
	}
+

+
	if (rule)
+
		tll_push_front(problem->rules, rule);
+

+
	return (EPKG_OK);
+
}
+

static struct pkg_solve_variable *
pkg_solve_find_var_in_chain(struct pkg_solve_variable *var,
	struct pkg_job_universe_item *item)
@@ -691,6 +740,13 @@ pkg_solve_process_universe_variable(struct pkg_solve_problem *problem,
			}
		}

+
		/* Vital flag */
+
		if (pkg->vital && !force) {
+
			if (pkg_solve_add_vital_rule(problem, cur_var) != EPKG_OK) {
+
				continue;
+
			}
+
		}
+

		/*
		 * If this var chain contains mutually conflicting vars
		 * we need to register conflicts with all following
@@ -1132,7 +1188,7 @@ reiterate:
		for (i = 0; i < problem->nvars; i ++) {
			struct pkg_solve_variable *var = &problem->variables[i];

-
			if (var->flags & PKG_VAR_TOP || var->unit->pkg->vital) {
+
			if (var->flags & PKG_VAR_TOP) {
				if (var->flags & PKG_VAR_FAILED) {
					var->flags ^= PKG_VAR_INSTALL | PKG_VAR_FAILED;
				}
modified tests/frontend/upgrade.sh
@@ -10,7 +10,8 @@ tests_init \
	file_become_dir \
	dir_become_file \
	dir_is_symlink_to_a_dir \
-
	vital
+
	vital \
+
	vital_force

issue1881_body() {
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg pkg1 pkg_a 1
@@ -322,6 +323,45 @@ Checking integrity... done (1 conflicting)
  - myplop-2 conflicts with mymeta-1 on ${TMPDIR}/file-pkg-1/file
Cannot solve problem using SAT solver, trying another plan
Checking integrity... done (0 conflicting)
+
Your packages are up to date.
+
"
+
	ERROR=""
+
	atf_check -o inline:"${OUTPUT}" -e inline:"${ERROR}" -s exit:0 pkg -o REPOS_DIR="$TMPDIR/repoconf" -r ${TMPDIR}/target -o PKG_CACHEDIR="$TMPDIR" upgrade -y
+
}
+

+
vital_force_body() {
+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg "meta" "mymeta" "1"
+
	mkdir file-pkg-1
+
	cat << EOF >> meta.ucl
+
vital = true;
+
EOF
+
	echo entry > file-pkg-1/file
+
	echo "${TMPDIR}/file-pkg-1/file" > plist-1
+
	atf_check pkg create -M meta.ucl -p plist-1
+
	mkdir target
+
	atf_check -o ignore pkg -o REPOS_DIR="${TMPDIR}" -r ${TMPDIR}/target install -Uy ${TMPDIR}/mymeta-1.pkg
+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg "plop" "myplop" "1"
+
	atf_check pkg create -M plop.ucl
+
	atf_check -o ignore pkg -o REPOS_DIR="${TMPDIR}" -r ${TMPDIR}/target install -Uy ${TMPDIR}/myplop-1.pkg
+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg "plop" "myplop" "2"
+
	echo "${TMPDIR}/file-pkg-1/file" > plist-2
+
	atf_check pkg create -M plop.ucl -p plist-2
+
	mkdir repoconf
+
	cat << EOF > repoconf/repo.conf
+
local: {
+
	url: file:///$TMPDIR,
+
	enabled: true
+
}
+
EOF
+

+
	atf_check -o ignore pkg repo .
+
	atf_check -o ignore pkg -o REPOS_DIR="$TMPDIR/repoconf" -r ${TMPDIR}/target -o PKG_CACHEDIR="$TMPDIR" update
+
	OUTPUT="Updating local repository catalogue...
+
local repository is up to date.
+
All repositories are up to date.
+
Checking integrity... done (1 conflicting)
+
  - myplop-2 conflicts with mymeta-1 on ${TMPDIR}/file-pkg-1/file
+
Checking integrity... done (0 conflicting)
The following 2 package(s) will be affected (of 0 checked):

Installed packages to be UPGRADED:
@@ -332,10 +372,11 @@ Installed packages to be REMOVED:

Number of packages to be removed: 1
Number of packages to be upgraded: 1
+
[1/2] Deinstalling mymeta-1...
+
[1/2] Deleting files for mymeta-1:  done
+
[2/2] Upgrading myplop from 1 to 2...
+
[2/2] Extracting myplop-2:  done
"
-
	ERROR="pkg: Cannot delete vital package: mymeta!
-
pkg: If you are sure you want to remove mymeta
-
pkg: unset the 'vital' flag with: pkg set -v 0 mymeta
-
"
-
	atf_check -o inline:"${OUTPUT}" -e inline:"${ERROR}" -s exit:3 pkg -o REPOS_DIR="$TMPDIR/repoconf" -r ${TMPDIR}/target -o PKG_CACHEDIR="$TMPDIR" upgrade -y
+
	ERROR=""
+
	atf_check -o inline:"${OUTPUT}" -e inline:"${ERROR}" -s exit:0 pkg -o REPOS_DIR="$TMPDIR/repoconf" -r ${TMPDIR}/target -o PKG_CACHEDIR="$TMPDIR" upgrade -fy myplop-2
}