Merge branch 'retry-prompt' into 'master'
Add `--retry-prompt` to make `Y/N`-prompts more uniform to other prompts. See merge request pacman/pacman!221
This commit is contained in:
commit
39b47ceec8
5 changed files with 139 additions and 30 deletions
|
@ -59,6 +59,7 @@ typedef struct __config_t {
|
||||||
unsigned short color;
|
unsigned short color;
|
||||||
unsigned short disable_dl_timeout;
|
unsigned short disable_dl_timeout;
|
||||||
unsigned short disable_sandbox;
|
unsigned short disable_sandbox;
|
||||||
|
unsigned short retry_input;
|
||||||
char *print_format;
|
char *print_format;
|
||||||
/* unfortunately, we have to keep track of paths both here and in the library
|
/* unfortunately, we have to keep track of paths both here and in the library
|
||||||
* because they can come from both the command line or config file, and we
|
* because they can come from both the command line or config file, and we
|
||||||
|
@ -214,7 +215,8 @@ enum {
|
||||||
OP_REFRESH,
|
OP_REFRESH,
|
||||||
OP_ASSUMEINSTALLED,
|
OP_ASSUMEINSTALLED,
|
||||||
OP_DISABLEDLTIMEOUT,
|
OP_DISABLEDLTIMEOUT,
|
||||||
OP_DISABLESANDBOX
|
OP_DISABLESANDBOX,
|
||||||
|
OP_RETRYINPUT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* clean method */
|
/* clean method */
|
||||||
|
|
|
@ -228,6 +228,7 @@ static void usage(int op, const char * const myname)
|
||||||
" use relaxed timeouts for download\n"));
|
" use relaxed timeouts for download\n"));
|
||||||
addlist(_(" --disable-sandbox\n"
|
addlist(_(" --disable-sandbox\n"
|
||||||
" disable the sandbox used for the downloader process\n"));
|
" disable the sandbox used for the downloader process\n"));
|
||||||
|
addlist(_(" --retry-prompt repeat prompts until a valid answer is supplied\n"));
|
||||||
}
|
}
|
||||||
list = alpm_list_msort(list, alpm_list_count(list), options_cmp);
|
list = alpm_list_msort(list, alpm_list_count(list), options_cmp);
|
||||||
for(i = list; i; i = alpm_list_next(i)) {
|
for(i = list; i; i = alpm_list_next(i)) {
|
||||||
|
@ -499,6 +500,9 @@ static int parsearg_global(int opt)
|
||||||
case 'v':
|
case 'v':
|
||||||
(config->verbose)++;
|
(config->verbose)++;
|
||||||
break;
|
break;
|
||||||
|
case OP_RETRYINPUT:
|
||||||
|
config->retry_input = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -982,6 +986,7 @@ static int parseargs(int argc, char *argv[])
|
||||||
{"color", required_argument, 0, OP_COLOR},
|
{"color", required_argument, 0, OP_COLOR},
|
||||||
{"disable-download-timeout", no_argument, 0, OP_DISABLEDLTIMEOUT},
|
{"disable-download-timeout", no_argument, 0, OP_DISABLEDLTIMEOUT},
|
||||||
{"disable-sandbox", no_argument, 0, OP_DISABLESANDBOX},
|
{"disable-sandbox", no_argument, 0, OP_DISABLESANDBOX},
|
||||||
|
{"retry-prompt", no_argument, 0, OP_RETRYINPUT},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1317,6 +1317,13 @@ msgid ""
|
||||||
" --disable-sandbox\n"
|
" --disable-sandbox\n"
|
||||||
" disable the sandbox used for the downloader process\n"
|
" disable the sandbox used for the downloader process\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
" --disable-sandbox\n"
|
||||||
|
" shaltet Sandbox für den Download-Prozess aus\n"
|
||||||
|
|
||||||
|
#: src/pacman/pacman.c:231
|
||||||
|
#, c-format
|
||||||
|
msgid " --retry-prompt repeat prompts until a valid answer is supplied\n"
|
||||||
|
msgstr " --retry-prompt wiederholt Frage, bis eine valide Antwort gegeben wird\n"
|
||||||
|
|
||||||
#: src/pacman/pacman.c:249
|
#: src/pacman/pacman.c:249
|
||||||
#, c-format
|
#, c-format
|
||||||
|
@ -1866,6 +1873,11 @@ msgstr "[J/n]"
|
||||||
msgid "[y/N]"
|
msgid "[y/N]"
|
||||||
msgstr "[j/N]"
|
msgstr "[j/N]"
|
||||||
|
|
||||||
|
#: src/pacman/util.c:1741
|
||||||
|
#, c-format
|
||||||
|
msgid "vsnprintf failure: Failed to cache prompt: %s\n"
|
||||||
|
msgstr "vsnprintf-fehler: Kann Frage nicht cachen: %s\n"
|
||||||
|
|
||||||
#: src/pacman/util.c:1751
|
#: src/pacman/util.c:1751
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Y"
|
msgid "Y"
|
||||||
|
@ -1886,6 +1898,11 @@ msgstr "N"
|
||||||
msgid "NO"
|
msgid "NO"
|
||||||
msgstr "NEIN"
|
msgstr "NEIN"
|
||||||
|
|
||||||
|
#: src/pacman/util.c:1769
|
||||||
|
#, c-format
|
||||||
|
msgid "vsnprintf failure: Failed to cache prompt: Required size changed: %zu -> %i bytes\n"
|
||||||
|
msgstr "vsnprintf-fehler: Kann Frage nicht cachen: Benötigte Größe hat sich geändert: %zu -> %i bytes\n"
|
||||||
|
|
||||||
#: src/pacman/util.c:1820
|
#: src/pacman/util.c:1820
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to allocate string\n"
|
msgid "failed to allocate string\n"
|
||||||
|
|
|
@ -1232,6 +1232,11 @@ msgstr ""
|
||||||
" --disable-sandbox\n"
|
" --disable-sandbox\n"
|
||||||
" disable the sandbox used for the downloader process\n"
|
" disable the sandbox used for the downloader process\n"
|
||||||
|
|
||||||
|
#: src/pacman/pacman.c:231
|
||||||
|
#, c-format
|
||||||
|
msgid " --retry-prompt repeat prompts until a valid answer is supplied\n"
|
||||||
|
msgstr " --retry-prompt repeat prompts until a valid answer is supplied\n"
|
||||||
|
|
||||||
#: src/pacman/pacman.c:249
|
#: src/pacman/pacman.c:249
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
|
@ -1777,6 +1782,10 @@ msgstr "[Y/n]"
|
||||||
msgid "[y/N]"
|
msgid "[y/N]"
|
||||||
msgstr "[y/N]"
|
msgstr "[y/N]"
|
||||||
|
|
||||||
|
#: src/pacman/util.c:1741 src/pacman/util.c:1759
|
||||||
|
msgid "vsnprintf failure: Failed to cache prompt: %s\n"
|
||||||
|
msgstr "vsnprintf failure: Failed to cache prompt: %s\n"
|
||||||
|
|
||||||
#: src/pacman/util.c:1751
|
#: src/pacman/util.c:1751
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Y"
|
msgid "Y"
|
||||||
|
@ -1797,6 +1806,11 @@ msgstr "N"
|
||||||
msgid "NO"
|
msgid "NO"
|
||||||
msgstr "NO"
|
msgstr "NO"
|
||||||
|
|
||||||
|
#: src/pacman/util.c:1767
|
||||||
|
#, c-format
|
||||||
|
msgid "vsnprintf failure: Failed to cache prompt: Required size changed: %zu -> %i bytes\n"
|
||||||
|
msgstr "vsnprintf failure: Failed to cache prompt: Required size changed: %zu -> %i bytes\n"
|
||||||
|
|
||||||
#: src/pacman/util.c:1820
|
#: src/pacman/util.c:1820
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "failed to allocate string\n"
|
msgid "failed to allocate string\n"
|
||||||
|
|
|
@ -1706,10 +1706,19 @@ static int mbscasecmp(const char *s1, const char *s2)
|
||||||
__attribute__((format(printf, 2, 0)))
|
__attribute__((format(printf, 2, 0)))
|
||||||
static int question(short preset, const char *format, va_list args)
|
static int question(short preset, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
|
int return_code = 0;
|
||||||
char response[32];
|
char response[32];
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
int fd_in = fileno(stdin);
|
int fd_in = fileno(stdin);
|
||||||
|
|
||||||
|
va_list args_copy;
|
||||||
|
int format_len;
|
||||||
|
/* No need to initialize:
|
||||||
|
* the other calls also print a termination character */
|
||||||
|
char prompt_cache_stack[256];
|
||||||
|
char *prompt_cache = prompt_cache_stack;
|
||||||
|
size_t prompt_cache_size = sizeof(prompt_cache_stack);
|
||||||
|
|
||||||
if(config->noconfirm) {
|
if(config->noconfirm) {
|
||||||
stream = stdout;
|
stream = stdout;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1717,48 +1726,110 @@ static int question(short preset, const char *format, va_list args)
|
||||||
stream = stderr;
|
stream = stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ensure all text makes it to the screen before we prompt the user */
|
/* Cache prompt, because we can't call v*printf() multiple times
|
||||||
fflush(stdout);
|
* on the same arguments. */
|
||||||
fflush(stderr);
|
/* Copy args so we can retry when the buffer is too small */
|
||||||
|
va_copy(args_copy, args);
|
||||||
|
|
||||||
fputs(config->colstr.colon, stream);
|
/* Don't ask me why v*printf() returns an Integer instead of a long */
|
||||||
vfprintf(stream, format, args);
|
format_len = vsnprintf(
|
||||||
|
prompt_cache,
|
||||||
|
prompt_cache_size,
|
||||||
|
format, args);
|
||||||
|
|
||||||
if(preset) {
|
/* Something has gone wrong */
|
||||||
fprintf(stream, " %s ", _("[Y/n]"));
|
if (format_len < 1) {
|
||||||
} else {
|
pm_printf(ALPM_LOG_ERROR, _("vsnprintf failure: Failed to cache prompt: %s\n"), strerror(errno));
|
||||||
fprintf(stream, " %s ", _("[y/N]"));
|
|
||||||
|
goto free_args_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs(config->colstr.nocolor, stream);
|
/* Buffer is too small */
|
||||||
fflush(stream);
|
if ((size_t)format_len + 1 > prompt_cache_size) {
|
||||||
|
prompt_cache = malloc(format_len + 1);
|
||||||
|
prompt_cache_size = format_len + 1;
|
||||||
|
if (prompt_cache == 0) {
|
||||||
|
pm_printf(ALPM_LOG_ERROR, _("malloc failure: could not allocate %i bytes\n"), format_len + 1);
|
||||||
|
|
||||||
if(config->noconfirm) {
|
goto free_args_copy;
|
||||||
fprintf(stream, "\n");
|
}
|
||||||
return preset;
|
|
||||||
|
format_len = vsnprintf(prompt_cache, prompt_cache_size, format, args_copy);
|
||||||
|
/* Something has gone wrong */
|
||||||
|
if (format_len < 1) {
|
||||||
|
pm_printf(ALPM_LOG_ERROR, _("vsnprintf failure: Failed to cache prompt: %s\n"), strerror(errno));
|
||||||
|
|
||||||
|
goto free_args_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just in case */
|
||||||
|
if ((size_t)format + 1 != prompt_cache_size) {
|
||||||
|
pm_printf(ALPM_LOG_ERROR, _("vsnprintf failure: Failed to cache prompt: Required size changed: %zu -> %i bytes\n"), prompt_cache_size, format_len + 1);
|
||||||
|
|
||||||
|
goto free_args_copy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_term_input(fd_in);
|
/* We can free the argument-copy now */
|
||||||
|
va_end(args_copy);
|
||||||
|
|
||||||
if(safe_fgets_stdin(response, sizeof(response))) {
|
/* Prompt the user at least once before exiting */
|
||||||
size_t len = strtrim(response);
|
do {
|
||||||
if(len == 0) {
|
/* Ensure all text makes it to the screen before we prompt the user */
|
||||||
|
fflush(stdout);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
fputs(config->colstr.colon, stream);
|
||||||
|
fputs(prompt_cache, stream);
|
||||||
|
|
||||||
|
if(preset) {
|
||||||
|
fprintf(stream, " %s ", _("[Y/n]"));
|
||||||
|
} else {
|
||||||
|
fprintf(stream, " %s ", _("[y/N]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs(config->colstr.nocolor, stream);
|
||||||
|
fflush(stream);
|
||||||
|
|
||||||
|
if(config->noconfirm) {
|
||||||
|
fprintf(stream, "\n");
|
||||||
return preset;
|
return preset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if stdin is piped, response does not get printed out, and as a result
|
flush_term_input(fd_in);
|
||||||
* a \n is missing, resulting in broken output */
|
|
||||||
if(!isatty(fd_in)) {
|
|
||||||
fprintf(stream, "%s\n", response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mbscasecmp(response, _("Y")) == 0 || mbscasecmp(response, _("YES")) == 0) {
|
if(safe_fgets_stdin(response, sizeof(response))) {
|
||||||
return 1;
|
size_t len = strtrim(response);
|
||||||
} else if(mbscasecmp(response, _("N")) == 0 || mbscasecmp(response, _("NO")) == 0) {
|
if(len == 0) {
|
||||||
return 0;
|
return_code = preset;
|
||||||
|
goto opt_free_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if stdin is piped, response does not get printed out, and as a result
|
||||||
|
* a \n is missing, resulting in broken output */
|
||||||
|
if(!isatty(fd_in)) {
|
||||||
|
fprintf(stream, "%s\n", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mbscasecmp(response, _("Y")) == 0 || mbscasecmp(response, _("YES")) == 0) {
|
||||||
|
return_code = 1;
|
||||||
|
goto opt_free_cache;
|
||||||
|
} else if(mbscasecmp(response, _("N")) == 0 || mbscasecmp(response, _("NO")) == 0) {
|
||||||
|
goto opt_free_cache;
|
||||||
|
} else
|
||||||
|
/* Emulate same behaviour as multiselect_question() and select_question() */
|
||||||
|
fprintf(stream, _("invalid input: prompt requires `%s' or `%s'\n\n"), _("Y"), _("N"));
|
||||||
}
|
}
|
||||||
}
|
} while (config->retry_input);
|
||||||
return 0;
|
|
||||||
|
opt_free_cache:
|
||||||
|
if (prompt_cache != prompt_cache_stack)
|
||||||
|
free(prompt_cache);
|
||||||
|
return return_code;
|
||||||
|
|
||||||
|
free_args_copy:
|
||||||
|
va_end(args_copy);
|
||||||
|
return return_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int yesno(const char *format, ...)
|
int yesno(const char *format, ...)
|
||||||
|
|
Loading…
Add table
Reference in a new issue