commit: bbe121f382365bf2582f9a4925cb564c497ae612
parent 8cc26fa60ad34493a33f379728796983ab15630d
Author: fosslinux <fosslinux@aussies.space>
Date: Fri, 12 Jan 2024 22:06:23 +1100
Add uninstall directive to manifest
Allows for removal of old files or packages
Diffstat:
3 files changed, 99 insertions(+), 17 deletions(-)
diff --git a/seed/script-generator.c b/seed/script-generator.c
@@ -11,7 +11,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <bootstrappable.h>
struct Token {
char *val;
@@ -23,6 +22,7 @@ typedef struct Token Token;
#define TYPE_IMPROVE 2
#define TYPE_DEFINE 3
#define TYPE_JUMP 4
+#define TYPE_UNINSTALL 5
struct Directive {
Token *tok;
@@ -212,12 +212,12 @@ Token *fill(Token *tok, Directive *directive, int type) {
Token *logic(Token *tok, char **val) {
/* logic = "("
- * (name |
- * (name "==" value) |
- * (name "!=" value) |
- * (logic "||" logic) |
- * (logic "&&" logic))
- * ")"
+ * (name |
+ * (name "==" value) |
+ * (name "!=" value) |
+ * (logic "||" logic) |
+ * (logic "&&" logic))
+ * ")"
*/
char *lhs = tok->val;
@@ -237,15 +237,15 @@ Token *logic(Token *tok, char **val) {
lhs = "False";
}
} else if (strcmp(tok->val, "!=") == 0) {
- /* Case for inequality. */
- rhs = tok->next->val;
- tok = tok->next->next;
- if (strcmp(get_var(lhs), rhs) == 0) {
- lhs = "False";
- } else {
- lhs = "True";
- }
- } else {
+ /* Case for inequality. */
+ rhs = tok->next->val;
+ tok = tok->next->next;
+ if (strcmp(get_var(lhs), rhs) == 0) {
+ lhs = "False";
+ } else {
+ lhs = "True";
+ }
+ } else {
fputs("Expected == or != after ", stderr);
fputs(lhs, stderr);
fputs(" in logic\n", stderr);
@@ -360,7 +360,7 @@ Token *define(Token *tok, Directive *directive) {
}
int interpret(Directive *directive) {
- /* directive = (build | improve | define | jump) predicate? */
+ /* directive = (build | improve | define | jump | uninstall) predicate? */
Token *tok = directive->tok;
if (strcmp(tok->val, "build:") == 0) {
tok = fill(tok->next, directive, TYPE_BUILD);
@@ -371,6 +371,20 @@ int interpret(Directive *directive) {
} else if (strcmp(tok->val, "define:") == 0) {
tok = define(tok->next, directive);
return 1; /* There is no codegen for a define. */
+ } else if (strcmp(tok->val, "uninstall:") == 0) {
+ tok = fill(tok->next, directive, TYPE_UNINSTALL);
+ while (tok != NULL) {
+ if (strcmp(tok->val, "(") == 0) {
+ break;
+ }
+ if (strlen(directive->arg) + strlen(tok->val) + 1 > MAX_STRING) {
+ fputs("somehow you have managed to have too many uninstall arguments.\n", stderr);
+ exit(1);
+ }
+ directive->arg = strcat(directive->arg, " ");
+ directive->arg = strcat(directive->arg, tok->val);
+ tok = tok->next;
+ }
}
if (tok != NULL) {
@@ -618,6 +632,10 @@ void generate(Directive *directives) {
fclose(out);
out = start_script(counter, bash_build);
counter += 1;
+ } else if (directive->type == TYPE_UNINSTALL) {
+ fputs("uninstall ", out);
+ fputs(directive->arg, out);
+ fputs("\n", out);
}
}
fclose(out);
diff --git a/steps/helpers.sh b/steps/helpers.sh
@@ -79,9 +79,11 @@ _grep() {
get_revision() {
local pkg=$1
+ local oldpwd="${PWD}"
cd "/external/repo"
# Get revision (n time this package has been built)
revision=$( (ls -1 "${pkg}"* 2>/dev/null || true) | wc -l | sed 's/ *//g')
+ cd "${oldpwd}"
}
# Installs binary packages from an earlier run
@@ -108,6 +110,64 @@ bin_preseed() {
return 1
}
+# Removes either an existing package or file
+uninstall() {
+ local in_fs in_pkg symlinks
+ while [ $# -gt 0 ]; do
+ removing="$1"
+ case "${removing}" in
+ /*)
+ # Removing a file
+ echo "removing file: ${removing}."
+ rm -f "${removing}"
+ ;;
+ *)
+ echo "${removing}: uninstalling."
+ local oldpwd="${PWD}"
+ mkdir -p "/tmp/removing"
+ cd "/tmp/removing"
+ get_revision "${removing}"
+ local filename="/external/repo/${removing}_$((revision-1)).tar.bz2"
+ # Initial bzip2 built against meslibc has broken pipes
+ bzip2 -dc "${filename}" | tar -xf -
+ # reverse to have files before directories
+ if command -v find >/dev/null 2>&1; then
+ find . | sort -r > ../filelist
+ else
+ get_files . | tac > ../filelist
+ fi
+ # shellcheck disable=SC2162
+ while read file; do
+ if [ -d "${file}" ]; then
+ if [ -z "$(ls -A "/${file}")" ]; then
+ rmdir "/${file}"
+ fi
+ else
+ # in some cases we might be uninstalling a file that has already been overwritten
+ # in this case we don't want to remove it
+ in_fs="$(sha256sum "${file}" 2>/dev/null | cut -d' ' -f1)"
+ in_pkg="$(sha256sum "/${file}" 2>/dev/null | cut -d' ' -f1)"
+ if [ "${in_fs}" = "${in_pkg}" ]; then
+ rm -f "/${file}"
+ fi
+ if [ -h "${file}" ]; then
+ symlinks="${symlinks} ${file}"
+ fi
+ fi
+ done < ../filelist
+ rm -f ../filelist
+ for link in ${symlinks}; do
+ if [ ! -e "/${link}" ]; then
+ rm -f "/${link}"
+ fi
+ done
+ cd "${oldpwd}"
+ ;;
+ esac
+ shift
+ done
+}
+
# Common build steps
# Build function provides a few common stages with default implementation
# that can be overridden on per package basis in the build script.
@@ -236,6 +296,7 @@ extract_file() {
*)
case "${f}" in
*.tar* | *.tgz)
+ # shellcheck disable=SC2153
if test -e "${PREFIX}/libexec/rmt"; then
# Again, we want to split out into words.
# shellcheck disable=SC2086
diff --git a/steps/manifest b/steps/manifest
@@ -15,6 +15,9 @@
# eg, define: BUILD_FIWIX = KERNEL_BOOTSTRAP == True || BUILD_KERNELS == True
# - jump: jump (usually) to a new kernel, executes a script with that name
# eg, jump: fiwix
+# - uninstall; removes a package or filenames
+# eg, uninstall: perl-5.6.2
+# eg, uninstall: /usr/bin/lex /usr/bin/flex
#
# The following directives have special significance:
# - build directives beginning with "bash" (as well as jumps) trigger the generation of