Skip to content

Improve -i answers to prompt for y/n questions #1190

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ tool - which is quite useful to know that the user is using the most recent
version of the script. This was also done in `jparse/` but that doesn't matter
here; it's only mentioned due to the sync.

Enhance `mkiocccentry` prompting with `-i answers` used. Instead of always
answering yes even when an issue is found, unless the new option `-Y` is used,
give the user a chance to confirm things are okay (in particular, it allows one
to answer no to a question; it does not prompt you for everything as that would
defeat the purpose of the answers file). The use of `-Y` is highly discouraged
unless you are **certain** you're good to go and it is mostly used for
`mkiocccentry_test.sh` which needs to be non-interactive.

Updated `MKIOCCCENTRY_VERSION` to `"1.2.35 2025-02-27"`.
Updated `MKIOCCCENTRY_TEST_VERSION` to` "1.0.15 2025-02-26"`.


## Release 2.3.44 2025-02-26
Expand Down
147 changes: 93 additions & 54 deletions mkiocccentry.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ static const char * const usage_msg0 =
"\t\t\t NOTE: the judges will NOT use this option\n"
"\t-E\t\texit non-zero after the first warning (def: do not)\n"
"\t\t\t NOTE: one cannot use both -W and -E.\n"
"\t-y\t\tanswer yes to most questions (use with EXTREME caution!)";
"\t-y\t\tanswer yes to most questions (use with EXTREME caution!)\n"
"\t-Y\t\tforce answer yes even when using -i answers";
static const char * const usage_msg1 =
"\t-t tar\t\tpath to tar(1) that supports the -J (xz) option (def: %s)\n"
"\t-l ls\t\tpath to ls(1) (def: %s)\n"
Expand Down Expand Up @@ -184,6 +185,10 @@ static uintmax_t feathery = 3; /* for entertain option of txzchk (-e) */
static bool silence_prompt = false; /* true ==> do not display prompts */
static bool read_answers_flag_used = false; /* true ==> -i read answers from answers file */
static bool seed_used = false; /* true ==> -d or -s seed given */
static bool copying_topdir = false; /* true ==> copying topdir and checking submission dir */
static bool saved_answer_yes = false; /* set to answer_yes before modifying it for scanning/copying topdir */
static bool saved_silence_prompt = false; /* set to silence_prompt before modifying it for scanning/copying topdir */
static bool force_yes = false; /* force -y even when scanning/copying/verifying in -i answers mode */

/*
* forward declarations
Expand Down Expand Up @@ -245,7 +250,7 @@ main(int argc, char *argv[])
*/
input_stream = stdin; /* default to reading from standard in */
program = argv[0];
while ((i = getopt(argc, argv, ":hv:J:qVt:l:a:i:A:WT:ef:F:C:yds:m:I:")) != -1) {
while ((i = getopt(argc, argv, ":hv:J:qVt:l:a:i:A:WT:ef:F:C:yYds:m:I:")) != -1) {
switch (i) {
case 'h': /* -h - print help to stderr and exit 2 */
usage(2, program, ""); /*ooo*/
Expand Down Expand Up @@ -301,20 +306,21 @@ main(int argc, char *argv[])
answers_flag_used = true;
break;
case 'i': /* -i input_recorded_answers */
read_answers_flag_used = true;
/*
* set need_confirm to false to prevent problem where a user might
* have a different file set
*/
need_confirm = false;
/*
* set answer_yes to prevent problem where a user might have a
* different file set
*/
answer_yes = true;
need_hints = false;
silence_prompt = true;
answers = optarg;
read_answers_flag_used = true;
/*
* set need_confirm to false to prevent problem where a user might
* have a different file set
*/
need_confirm = false;
/*
* set answer_yes to prevent problem where a user might have a
* different file set
*/
answer_yes = true;
need_hints = false;
silence_prompt = true;
break;
case 'W': /* -W ignores all warnings (this does NOT the judges will! :) ) */
ignore_warnings = true;
Expand Down Expand Up @@ -347,6 +353,11 @@ main(int argc, char *argv[])
answer_yes = true;
need_confirm = false;
break;
case 'Y': /* force yes even when we would normally temporarily undo it */
force_yes = true;
answer_yes = true;
need_confirm = false;
break;
case 'd': /* alias for -s DEFAULT_SEED */
answer_seed = DEFAULT_SEED;
seed_used = true;
Expand All @@ -358,6 +369,7 @@ main(int argc, char *argv[])
silence_prompt = true;
/* set -E boolean */
abort_on_warning = true;
force_yes = true;
break;
case 's': /* set seed as seed & SEED_MASK */
/*
Expand All @@ -381,6 +393,7 @@ main(int argc, char *argv[])
silence_prompt = true;
/* set -E boolean */
abort_on_warning = true;
force_yes = true;
}
break;
case 'm': /* set path to make(1) */
Expand Down Expand Up @@ -643,6 +656,7 @@ main(int argc, char *argv[])
}
input_stream = answersp;
}

/*
* obtain the IOCCC contest ID
*/
Expand Down Expand Up @@ -1190,6 +1204,7 @@ scan_topdir(char *args, struct info *infop, char const *make, char const *submis
not_reached();
}


/*
* list of required files (prog.c, Makefile and remarks.md) (this will be
* shown to the user too)
Expand Down Expand Up @@ -1803,13 +1818,29 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
* files list is empty (though in theory if that did happen we should never
* get here).
*/

/*
* free arrays IFF (if and only if) they are empty
* If -Y is not used and -i answers is used we need to temporarily disable
* the -y so that the user can verify different file sets (if something
* changes for example). Normally we don't need to do this as it would
* happen anyway but with -i answers it is disabled as it forces -y. If one
* is SURE they are okay they can use -Y instead and they won't be bothered
* even in this and the next function (check_submission_dir()).
*
* NOTE: we will undo these at the end of check_submission_dir().
*
* NOTE: we will always save the current status of the silence_prompt and
* answer_yes booleans.
*/
free_paths_array(&infop->required_files, true);
if (infop->required_files == NULL) {
err(4, __func__, "NULL required files list array");/*ooo*/
copying_topdir = true;
saved_silence_prompt = silence_prompt;
saved_answer_yes = answer_yes;
if (!force_yes) {
answer_yes = false;
silence_prompt = false;
}

if (paths_in_array(infop->required_files) <= 0) {
err(4, __func__, "required files list array is empty");/*ooo*/
not_reached();
}
/*
Expand Down Expand Up @@ -1933,7 +1964,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
}
print("%s\n", p);
}
if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you delete %s and try again\nwith the correct options used\n",
Expand Down Expand Up @@ -1981,7 +2012,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
}
print("%s\n", p);
}
if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
Expand Down Expand Up @@ -2022,7 +2053,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
}
print("%s\n", p);
}
if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
Expand Down Expand Up @@ -2072,7 +2103,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
}
print("%s\n", p);
}
if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
Expand Down Expand Up @@ -2112,7 +2143,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
}
print("%s\n", p);
}
if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
Expand Down Expand Up @@ -2149,7 +2180,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
}
print("%s\n", p);
}
if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
Expand Down Expand Up @@ -2183,7 +2214,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
}
print("%s\n", p);
}
if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
Expand Down Expand Up @@ -2243,7 +2274,7 @@ copy_topdir(struct info *infop, char const *make, char const *submission_dir, ch
print("%s\n", p);
}
}
if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
Expand Down Expand Up @@ -3362,7 +3393,7 @@ check_submission_dir(struct info *infop, char *submit_path, char *topdir_path,
print("%s\n", p);
}

if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
Expand Down Expand Up @@ -3421,7 +3452,7 @@ check_submission_dir(struct info *infop, char *submit_path, char *topdir_path,
}
}
}
if (!answer_yes && !read_answers_flag_used) {
if (!answer_yes) {
yorn = yes_or_no("\nIs this OK? [Yn]", true);
if (!yorn) {
print("we suggest you fix your %s directory,\ndelete %s and try again\n",
Expand Down Expand Up @@ -3484,6 +3515,12 @@ check_submission_dir(struct info *infop, char *submit_path, char *topdir_path,
errp(114, __func__, "failed to close(cwd)");
not_reached();
}
/*
* undo special checks for -i answers
*/
copying_topdir = false;
silence_prompt = saved_silence_prompt;
answer_yes = saved_answer_yes;
}

/*
Expand Down Expand Up @@ -3986,6 +4023,7 @@ prompt(char const *str, size_t *lenp)
int ret; /* libc function return value */
size_t len; /* length of input */
char *buf; /* allocated input string */
FILE *stream = NULL; /* input_stream or stdin depending on options used */

/*
* firewall
Expand All @@ -3997,6 +4035,13 @@ prompt(char const *str, size_t *lenp)
not_reached();
}

if (copying_topdir) {
stream = stdin;
} else {
stream = input_stream;
}


/*
* prompt + :<space> if silence_prompt is false
*/
Expand Down Expand Up @@ -4051,7 +4096,7 @@ prompt(char const *str, size_t *lenp)
/*
* read user input - return input length
*/
buf = readline_dup(&linep, true, &len, input_stream);
buf = readline_dup(&linep, true, &len, stream);
if (buf == NULL) {
err(148, __func__, "EOF while reading prompt input");
not_reached();
Expand Down Expand Up @@ -5970,7 +6015,7 @@ get_abstract(struct info *infop)
* true ==> input is yes in some form,
* false ==> input is not yes or there was a read error.
*
* NOTE: The -y (answer_yes) as no impact on this function as
* NOTE: The -y (answer_yes) has no impact on this function as
* the yes or no input will be read regardless.
*/
static bool
Expand All @@ -5980,12 +6025,18 @@ noprompt_yes_or_no(void)
size_t len; /* length of input */
char *response; /* yes or no response */
char *p;
FILE *stream = NULL; /* we need this so we can prompt users with -i answers */

if (read_answers_flag_used && !answer_yes) {
stream = stdin;
} else {
stream = input_stream;
}
/*
* read user input - return input length
*/
errno = 0; /* pre-clear errno for warnp() */
response = readline_dup(&linep, true, &len, input_stream);
response = readline_dup(&linep, true, &len, stream);
if (response == NULL) {

/*
Expand Down Expand Up @@ -7402,16 +7453,14 @@ verify_submission_dir(char const *submission_dir, char const *ls)
ls_stream = NULL;

/*
* if either -d or -s seed are used, temporarily turn on prompting
* we make sure that unless -Y is used the user always has a chance to look
* at the final directory output
*/
if (seed_used) {
silence_prompt = false;

/*
* however, if -i input_recorded_answers is used, force prompting
*/
} else if (read_answers_flag_used) {
silence_prompt = false;
saved_silence_prompt = silence_prompt;
saved_answer_yes = answer_yes;
if (!force_yes) {
answer_yes = false;
silence_prompt = false;
}

/*
Expand All @@ -7430,23 +7479,13 @@ verify_submission_dir(char const *submission_dir, char const *ls)
"not the topdir where your submission files are) and then rerun this tool",
"again.",
NULL);
err(14, __func__, "user rejected listing of submission directory: %s", submission_dir);
err(5, __func__, "user rejected listing of submission directory: %s", submission_dir);/*ooo*/
not_reached();
}
}

/*
* if either -d or -s seed are used, silence prompting again
*/
if (seed_used) {
silence_prompt = true;

/*
* and of input_recorded_answers was used, silence prompting and turn back on -y
*/
} else if (read_answers_flag_used) {
silence_prompt = true;
}
silence_prompt = saved_silence_prompt;
answer_yes = saved_answer_yes;

/*
* free storage
Expand Down
7 changes: 6 additions & 1 deletion soup/man/man1/mkiocccentry.1
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
.\" "Share and Enjoy!"
.\" -- Sirius Cybernetics Corporation Complaints Division, JSON spec department. :-)
.\"
.TH mkiocccentry 1 "21 February 2025" "mkiocccentry" "IOCCC tools"
.TH mkiocccentry 1 "27 February 2025" "mkiocccentry" "IOCCC tools"
.SH NAME
.B mkiocccentry
\- make an IOCCC compressed tarball for an IOCCC entry
Expand Down Expand Up @@ -173,6 +173,11 @@ See:
.ft R
for information on the IOCCC rules and guidelines.
.TP
.B \-Y
Force answer yes to questions even when you would otherwise be prompted.
This is mostly for the test-suite and in particular for the reading of answers from a file.
That is because when scanning the topdir and making directories and copying files from the topdir to the submission directory and checking that the directory ended up okay, we do prompt the user again.
.TP
.BI \-t\ tar
Set path to
.B tar
Expand Down
Loading