Add --noconfirm-unsafe for advanced script usage

Message ID 20221101031728.74522-1-laszlth@gmail.com
State Rejected, archived
Headers show
Series Add --noconfirm-unsafe for advanced script usage | expand

Commit Message

Laszlo Toth Nov. 1, 2022, 3:17 a.m. UTC
This is intended for e.g., regular, automated cache clearing or
updating/creating Docker images.

There is --noconfirm, but that selects the default answer for yes/no questions,
which may be no when we want yes. Then 'yes | pacman -Scc' could be used,
but that does not work reliably w/ multiselection.
So, add a new option which always answers yes for yes/no, and the default
for multiselections.

Now --confirm disables both --noconfirm and --noconfirm-unsafe.

noask is not updated to use this mode as well... it's not safe.

Signed-off-by: Laszlo Toth <laszlth@gmail.com>
---
 doc/pacman.8.asciidoc | 11 ++++++++---
 src/pacman/conf.h     |  4 +++-
 src/pacman/pacman.c   |  8 ++++++++
 src/pacman/util.c     | 18 ++++++++++++++----
 4 files changed, 33 insertions(+), 8 deletions(-)

Comments

Andrew Gregory Nov. 3, 2022, 1:10 a.m. UTC | #1
On 10/31/22 at 11:17pm, Laszlo Toth wrote:
> This is intended for e.g., regular, automated cache clearing or
> updating/creating Docker images.
> 
> There is --noconfirm, but that selects the default answer for yes/no questions,
> which may be no when we want yes. Then 'yes | pacman -Scc' could be used,
> but that does not work reliably w/ multiselection.
> So, add a new option which always answers yes for yes/no, and the default
> for multiselections.
> 
> Now --confirm disables both --noconfirm and --noconfirm-unsafe.
> 
> noask is not updated to use this mode as well... it's not safe.

This has come up a number of times and I'm still not really a fan.   Automation
has never been a significant design goal for pacman and, even if we were to
make it one, the shotgun approach is extremely inelegant, completely ignoring
the needs of any scripts that require any level of specificity.  That's a big
part of why I wrote pacutils, which has advanced features for avoiding the
situations that result in prompts and specific options for dealing with prompts
when they are required.  It even includes a --yolo option for people who simply
insist on breaking things.

https://github.com/andrewgregory/pacutils/blob/master/doc/pactrans.pod#prompt-disposition-options

...

> @@ -1617,6 +1617,11 @@ int select_question(int count)
>  		fprintf(stream, ": ");
>  		fflush(stream);
>  
> +		if(config->noconfirmunsafe) {
> +			fprintf(stream, "y\n");

This makes no sense, the user is selecting an item from a list.  "y" is not a
valid response.

...

> @@ -1705,6 +1710,11 @@ static int question(short preset, const char *format, va_list args)
>  	fputs(config->colstr.nocolor, stream);
>  	fflush(stream);
>  
> +	if(config->noconfirmunsafe) {
> +		fprintf(stream, "y\n");
> +		return preset;

You're still just returning the default, what is noconfirm-unsafe actually
doing?
Björn Bidar Nov. 9, 2022, 6:14 a.m. UTC | #2
Andrew Gregory <andrew.gregory.8@gmail.com> writes:

> This has come up a number of times and I'm still not really a fan.   Automation
> has never been a significant design goal for pacman and, even if we were to
> make it one, the shotgun approach is extremely inelegant

Would it work better if there's an option in pacman.conf to include N of
the last package versions instead?

Br,

Björn

Patch

diff --git a/doc/pacman.8.asciidoc b/doc/pacman.8.asciidoc
index 630ff0d9..ec400175 100644
--- a/doc/pacman.8.asciidoc
+++ b/doc/pacman.8.asciidoc
@@ -185,11 +185,16 @@  Options
 	the installation root setting.
 
 *\--noconfirm*::
-	Bypass any and all ``Are you sure?'' messages. It's not a good idea to do
-	this unless you want to run pacman from a script.
+	Bypass any and all ``Are you sure?'' messages via using the default answer.
+	It's not a good idea to do this unless you want to run pacman from a script.
+
+*\--noconfirm-unsafe*::
+	Bypass any and all ``Are you sure?'' messages via answering yes or
+	selecting the default option.
+	It's NOT a good idea to do this unless you want to run pacman from a script.
 
 *\--confirm*::
-	Cancels the effects of a previous '\--noconfirm'.
+	Cancels the effects of a previous '\--noconfirm' or '\--noconfirm-unsafe'.
 
 *\--disable-download-timeout*::
 	Disable defaults for low speed limit and timeout on downloads. Use this
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index f7916ca9..fbed3055 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -57,6 +57,7 @@  typedef struct __config_t {
 	unsigned short usesyslog;
 	unsigned short color;
 	unsigned short disable_dl_timeout;
+	unsigned short noconfirmunsafe;
 	char *print_format;
 	/* 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
@@ -210,7 +211,8 @@  enum {
 	OP_DOWNLOADONLY,
 	OP_REFRESH,
 	OP_ASSUMEINSTALLED,
-	OP_DISABLEDLTIMEOUT
+	OP_DISABLEDLTIMEOUT,
+	OP_NOCONFIRMUNSAFE
 };
 
 /* clean method */
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index e5c6e420..bb04fdc8 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -226,6 +226,8 @@  static void usage(int op, const char * const myname)
 		addlist(_("      --confirm        always ask for confirmation\n"));
 		addlist(_("      --disable-download-timeout\n"
 		          "                       use relaxed timeouts for download\n"));
+		addlist(_("      --noconfirm-unsafe\n"
+		          "                       answer yes or default for every confirmation\n"));
 	}
 	list = alpm_list_msort(list, alpm_list_count(list), options_cmp);
 	for(i = list; i; i = alpm_list_next(i)) {
@@ -442,8 +444,13 @@  static int parsearg_global(int opt)
 		case OP_NOCONFIRM:
 			config->noconfirm = 1;
 			break;
+		case OP_NOCONFIRMUNSAFE:
+			config->noconfirm = 0;
+			config->noconfirmunsafe = 1;
+			break;
 		case OP_CONFIRM:
 			config->noconfirm = 0;
+			config->noconfirmunsafe = 0;
 			break;
 		case OP_DBPATH:
 		case 'b':
@@ -948,6 +955,7 @@  static int parseargs(int argc, char *argv[])
 		{"dbonly",     no_argument,       0, OP_DBONLY},
 		{"color",      required_argument, 0, OP_COLOR},
 		{"disable-download-timeout", no_argument, 0, OP_DISABLEDLTIMEOUT},
+		{"noconfirm-unsafe",      no_argument,       0, OP_NOCONFIRMUNSAFE},
 		{0, 0, 0, 0}
 	};
 
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 5f5c7c54..532e058d 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1527,7 +1527,7 @@  int multiselect_question(char *array, int count)
 	FILE *stream;
 	size_t response_len = 64;
 
-	if(config->noconfirm) {
+	if(config->noconfirm || config->noconfirmunsafe) {
 		stream = stdout;
 	} else {
 		/* Use stderr so questions are always displayed when redirecting output */
@@ -1550,7 +1550,7 @@  int multiselect_question(char *array, int count)
 		fprintf(stream, ": ");
 		fflush(stream);
 
-		if(config->noconfirm) {
+		if(config->noconfirm || config->noconfirmunsafe) {
 			fprintf(stream, "\n");
 			break;
 		}
@@ -1604,7 +1604,7 @@  int select_question(int count)
 	FILE *stream;
 	int preset = 1;
 
-	if(config->noconfirm) {
+	if(config->noconfirm || config->noconfirmunsafe) {
 		stream = stdout;
 	} else {
 		/* Use stderr so questions are always displayed when redirecting output */
@@ -1617,6 +1617,11 @@  int select_question(int count)
 		fprintf(stream, ": ");
 		fflush(stream);
 
+		if(config->noconfirmunsafe) {
+			fprintf(stream, "y\n");
+			break;
+		}
+
 		if(config->noconfirm) {
 			fprintf(stream, "\n");
 			break;
@@ -1682,7 +1687,7 @@  static int question(short preset, const char *format, va_list args)
 	FILE *stream;
 	int fd_in = fileno(stdin);
 
-	if(config->noconfirm) {
+	if(config->noconfirm || config->noconfirmunsafe) {
 		stream = stdout;
 	} else {
 		/* Use stderr so questions are always displayed when redirecting output */
@@ -1705,6 +1710,11 @@  static int question(short preset, const char *format, va_list args)
 	fputs(config->colstr.nocolor, stream);
 	fflush(stream);
 
+	if(config->noconfirmunsafe) {
+		fprintf(stream, "y\n");
+		return preset;
+	}
+
 	if(config->noconfirm) {
 		fprintf(stream, "\n");
 		return preset;