Support interactive issue resolution prompts

This adds a new flag, -i / --interactive, which enables opening a
Bash prompt whenever something goes wrong in the bootstrap. This is
highly useful when developing or debugging live-bootstrap, but it
needs to be off by default, for use in automated processes.

In the future, asking for variables at runtime could (and perhaps
should) also be gated behind this flag.
This commit is contained in:
Gábor Stefanik 2024-01-01 22:37:32 +01:00
parent f9cf916e5e
commit a0f13c0ed2
2 changed files with 40 additions and 26 deletions

View File

@ -32,6 +32,7 @@ def create_configuration_file(args):
config.write(f"UPDATE_CHECKSUMS={args.update_checksums}\n") config.write(f"UPDATE_CHECKSUMS={args.update_checksums}\n")
config.write(f"JOBS={args.cores}\n") config.write(f"JOBS={args.cores}\n")
config.write(f"INTERNAL_CI={args.internal_ci or False}\n") config.write(f"INTERNAL_CI={args.internal_ci or False}\n")
config.write(f"INTERACTIVE={args.interactive}\n")
config.write(f"BARE_METAL={args.bare_metal}\n") config.write(f"BARE_METAL={args.bare_metal}\n")
if (args.bare_metal or args.qemu) and not args.kernel: if (args.bare_metal or args.qemu) and not args.kernel:
if args.repo or args.external_sources: if args.repo or args.external_sources:
@ -70,21 +71,24 @@ def main():
help="Force all files timestamps to be 0 unix time", help="Force all files timestamps to be 0 unix time",
action="store_true") action="store_true")
parser.add_argument("--update-checksums", parser.add_argument("--update-checksums",
help="Update checksum files.", help="Update checksum files",
action="store_true") action="store_true")
parser.add_argument("--external-sources", parser.add_argument("--external-sources",
help="Download sources externally from live-bootstrap.", help="Download sources externally from live-bootstrap",
action="store_true") action="store_true")
parser.add_argument("--build-kernels", parser.add_argument("--build-kernels",
help="Also build kernels in chroot and bwrap builds.", help="Also build kernels in chroot and bwrap builds",
action="store_true") action="store_true")
parser.add_argument("--no-create-config", parser.add_argument("--no-create-config",
help="Do not automatically create config file", help="Do not automatically create config file",
action="store_true") action="store_true")
parser.add_argument("-i", "--interactive",
help="Use interactive prompts to resolve issues during bootstrap",
action="store_true")
parser.add_argument("-r", "--repo", parser.add_argument("-r", "--repo",
help="Path to prebuilt binary packages.", nargs=None) help="Path to prebuilt binary packages", nargs=None)
parser.add_argument("--early-preseed", parser.add_argument("--early-preseed",
help="Skip early stages of live-bootstrap.", nargs=None) help="Skip early stages of live-bootstrap", nargs=None)
parser.add_argument("--internal-ci", help="INTERNAL for github CI") parser.add_argument("--internal-ci", help="INTERNAL for github CI")
# QEMU arguments # QEMU arguments

View File

@ -407,7 +407,7 @@ void add_to_fiwix_filelist(char *filename) {
} }
/* Script generator. */ /* Script generator. */
FILE *start_script(int id, int using_bash) { FILE *start_script(int id, int bash_build) {
/* Create the file /steps/$id.sh */ /* Create the file /steps/$id.sh */
char *filename = calloc(MAX_STRING, sizeof(char)); char *filename = calloc(MAX_STRING, sizeof(char));
strcpy(filename, "/steps/"); strcpy(filename, "/steps/");
@ -423,9 +423,19 @@ FILE *start_script(int id, int using_bash) {
exit(1); exit(1);
} }
if (using_bash) { if (bash_build) {
fputs("#!/bin/bash\n", out); fputs("#!/bin/bash\n", out);
fputs("set -e\n", out); if (strcmp(get_var("INTERACTIVE"), "True") == 0) {
if (bash_build != 1) {
fputs("set -E\ntrap 'env PS1=\"[TRAP] \\w # \" bash -i' ERR\n", out);
} else {
fputs("set -E\ntrap 'bash -c '\"'\"'while true; do printf \""
"[TRAP - use Ctrl+D] $(pwd) # \"; $(cat); done'\"'\"'' ERR\n",
out);
}
} else {
fputs("set -e\n", out);
}
fputs("cd /steps\n", out); fputs("cd /steps\n", out);
fputs(". ./bootstrap.cfg\n", out); fputs(". ./bootstrap.cfg\n", out);
fputs(". ./env\n", out); fputs(". ./env\n", out);
@ -450,8 +460,8 @@ FILE *start_script(int id, int using_bash) {
return out; return out;
} }
void output_call_script(FILE *out, char *type, char *name, int using_bash, int source) { void output_call_script(FILE *out, char *type, char *name, int bash_build, int source) {
if (using_bash) { if (bash_build) {
if (source) { if (source) {
fputs(". ", out); fputs(". ", out);
} else { } else {
@ -469,8 +479,8 @@ void output_call_script(FILE *out, char *type, char *name, int using_bash, int s
fputs(".sh\n", out); fputs(".sh\n", out);
} }
void output_build(FILE *out, Directive *directive, int pass_no, int using_bash) { void output_build(FILE *out, Directive *directive, int pass_no, int bash_build) {
if (using_bash) { if (bash_build) {
fputs("build ", out); fputs("build ", out);
fputs(directive->arg, out); fputs(directive->arg, out);
fputs(" pass", out); fputs(" pass", out);
@ -510,9 +520,9 @@ void generate(Directive *directives) {
int counter = 0; int counter = 0;
/* Initially, we use kaem, not bash. */ /* Initially, we use kaem, not bash. */
int using_bash = 0; int bash_build = 0;
FILE *out = start_script(counter, using_bash); FILE *out = start_script(counter, bash_build);
counter += 1; counter += 1;
Directive *directive; Directive *directive;
@ -528,24 +538,24 @@ void generate(Directive *directives) {
pass_no += 1; pass_no += 1;
} }
} }
output_build(out, directive, pass_no, using_bash); output_build(out, directive, pass_no, bash_build);
if (strncmp(directive->arg, "bash-", 5) == 0) { if (strncmp(directive->arg, "bash-", 5) == 0) {
if (!using_bash) { if (!bash_build) {
/* /*
* We are transitioning from bash to kaem, the point at which "early * We are transitioning from bash to kaem, the point at which "early
* preseed" occurs. So generate the preseed jump script at this point. * preseed" occurs. So generate the preseed jump script at this point.
*/ */
generate_preseed_jump(counter); generate_preseed_jump(counter);
} }
using_bash = 1; bash_build = 1;
/* Create call to new script. */ /* Create call to new script. */
output_call_script(out, "", int2str(counter, 10, 0), using_bash, 0); output_call_script(out, "", int2str(counter, 10, 0), bash_build, 0);
fclose(out); fclose(out);
out = start_script(counter, using_bash); out = start_script(counter, bash_build);
counter += 1; counter += 1;
} }
} else if (directive->type == TYPE_IMPROVE) { } else if (directive->type == TYPE_IMPROVE) {
output_call_script(out, "improve", directive->arg, using_bash, 1); output_call_script(out, "improve", directive->arg, bash_build, 1);
} else if (directive->type == TYPE_JUMP) { } else if (directive->type == TYPE_JUMP) {
/* /*
* Create /init to call new script. * Create /init to call new script.
@ -553,7 +563,7 @@ void generate(Directive *directives) {
* moving that to /init at the appropriate time. * moving that to /init at the appropriate time.
*/ */
filename = calloc(MAX_STRING, sizeof(char)); filename = calloc(MAX_STRING, sizeof(char));
if (using_bash) { if (bash_build) {
fputs("mv /init /init.bak\n", out); fputs("mv /init /init.bak\n", out);
/* Move new init to /init. */ /* Move new init to /init. */
strcpy(filename, "/init."); strcpy(filename, "/init.");
@ -572,7 +582,7 @@ void generate(Directive *directives) {
fputs("chmod 755 /init\n", out); fputs("chmod 755 /init\n", out);
} }
output_call_script(out, "jump", directive->arg, using_bash, 1); output_call_script(out, "jump", directive->arg, bash_build, 1);
fclose(out); fclose(out);
/* /*
@ -581,7 +591,7 @@ void generate(Directive *directives) {
*/ */
add_to_fiwix_filelist(filename); add_to_fiwix_filelist(filename);
if (using_bash) { if (bash_build) {
out = fopen(filename, "w"); out = fopen(filename, "w");
if (out == NULL) { if (out == NULL) {
fputs("Error opening /init\n", stderr); fputs("Error opening /init\n", stderr);
@ -596,12 +606,12 @@ void generate(Directive *directives) {
} }
fputs("set -ex\n", out); fputs("set -ex\n", out);
} }
output_call_script(out, "", int2str(counter, 10, 0), using_bash, 0); output_call_script(out, "", int2str(counter, 10, 0), bash_build, 0);
fclose(out); fclose(out);
out = start_script(counter, using_bash); out = start_script(counter, bash_build);
counter += 1; counter += 1;
} else if (directive->type == TYPE_MAINT) { } else if (directive->type == TYPE_MAINT) {
output_call_script(out, "maint", directive->arg, using_bash, 1); output_call_script(out, "maint", directive->arg, bash_build, 1);
} }
} }
fclose(out); fclose(out);