Greetings pacman-dev:

Currently, pacman does not allow one to run `pacman -S --search=-doc`, because despite documentation saying `--search` takes `<regexp>`, actually it is implemented as using the targets to determine what to search for.

It is quite difficult to figure out how to carry out this search query, and needlessly so, though `--search '\\-doc'` does work.

The cumulative effect of the two attached patches fixes it, allowing an easier way to search for arbitrary strings which may conflict with command line options.

--
Best,
Fred Brennan

  [[[ To any NSA and FBI agents reading my email: please consider    ]]]
  [[[ whether defending the US Constitution against all enemies,     ]]]
  [[[ foreign or domestic, requires you to follow Snowden's example. ]]]

GnuPG: 6F12 EC72 A82A BCA3 5235 063A 10DD C983 901A A183
Twitter: @fr_brennan
Personal website <https://dba.gg/>
From d1fe855b2ca9c81cf33a2f44637d2f7487a4b893 Mon Sep 17 00:00:00 2001
From: Fredrick Brennan <[email protected]>
Date: Fri, 19 Nov 2021 16:01:24 -0500
Subject: [PATCH 1/2] =?UTF-8?q?Make=20`checkargs=5F*(=E2=80=A6)`=20accept?=
 =?UTF-8?q?=20global=20parse=20state?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Fredrick Brennan <[email protected]>
---
 src/pacman/pacman.c | 39 +++++++++++++++++++--------------------
 1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index db64e05a..ed2d19b2 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -495,7 +495,7 @@ static int parsearg_database(int opt)
 	return 0;
 }
 
-static void checkargs_database(void)
+static void checkargs_database(__attribute__((unused)) int parse_err)
 {
 	invalid_opt(config->flags & ALPM_TRANS_FLAG_ALLDEPS
 			&& config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT,
@@ -594,7 +594,7 @@ static void checkargs_query_filter_opts(const char *opname) {
 	invalid_opt(config->op_q_locality & PKG_LOCALITY_FOREIGN, opname, "--foreign");
 }
 
-static void checkargs_query(void)
+static void checkargs_query(int parse_err)
 {
 	if(config->op_q_isfile) {
 		invalid_opt(config->group, "--file", "--groups");
@@ -660,7 +660,7 @@ static int parsearg_trans(int opt)
 	return 0;
 }
 
-static void checkargs_trans(void)
+static void checkargs_trans(__attribute__((unused)) int parse_err)
 {
 	if(config->print) {
 		invalid_opt(config->flags & ALPM_TRANS_FLAG_DBONLY,
@@ -702,9 +702,9 @@ static int parsearg_remove(int opt)
 	return 0;
 }
 
-static void checkargs_remove(void)
+static void checkargs_remove(int parse_err)
 {
-	checkargs_trans();
+	checkargs_trans(parse_err);
 	if(config->flags & ALPM_TRANS_FLAG_NOSAVE) {
 		invalid_opt(config->print, "--nosave", "--print");
 		invalid_opt(config->flags & ALPM_TRANS_FLAG_DBONLY,
@@ -748,9 +748,9 @@ static int parsearg_upgrade(int opt)
 	return 0;
 }
 
-static void checkargs_upgrade(void)
+static void checkargs_upgrade(int parse_err)
 {
-	checkargs_trans();
+	checkargs_trans(parse_err);
 	invalid_opt(config->flags & ALPM_TRANS_FLAG_ALLDEPS
 			&& config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT,
 			"--asdeps", "--asexplicit");
@@ -787,7 +787,7 @@ static int parsearg_files(int opt)
 	return 0;
 }
 
-static void checkargs_files(void)
+static void checkargs_files(__attribute__((unused)) int parse_err)
 {
 	if(config->op_q_search) {
 		invalid_opt(config->op_q_list, "--regex", "--list");
@@ -838,9 +838,9 @@ static int parsearg_sync(int opt)
 	return 0;
 }
 
-static void checkargs_sync(void)
+static void checkargs_sync(int parse_err)
 {
-	checkargs_upgrade();
+	checkargs_upgrade(parse_err);
 	if(config->op_s_clean) {
 		invalid_opt(config->group, "--clean", "--groups");
 		invalid_opt(config->op_s_info, "--clean", "--info");
@@ -879,7 +879,7 @@ static int parseargs(int argc, char *argv[])
 {
 	int opt;
 	int option_index = 0;
-	int result;
+	int result = 0;
 	const char *optstring = "DFQRSTUVb:cdefghiklmnopqr:stuvwxy";
 	static const struct option opts[] =
 	{
@@ -1019,14 +1019,13 @@ static int parseargs(int argc, char *argv[])
 		/* fall back to global options */
 		result = parsearg_global(opt);
 		if(result != 0) {
-			/* global option parsing failed, abort */
+			/* global option parsing failed, only continue parsing to give user more hints */
 			if(opt < OP_LONG_FLAG_MIN) {
 				pm_printf(ALPM_LOG_ERROR, _("invalid option '-%c'\n"), opt);
 			} else {
 				pm_printf(ALPM_LOG_ERROR, _("invalid option '--%s'\n"),
 						opts[option_index].name);
 			}
-			return result;
 		}
 	}
 
@@ -1038,31 +1037,31 @@ static int parseargs(int argc, char *argv[])
 
 	switch(config->op) {
 		case PM_OP_DATABASE:
-			checkargs_database();
+			checkargs_database(result);
 			break;
 		case PM_OP_DEPTEST:
 			/* no conflicting options */
 			break;
 		case PM_OP_SYNC:
-			checkargs_sync();
+			checkargs_sync(result);
 			break;
 		case PM_OP_QUERY:
-			checkargs_query();
+			checkargs_query(result);
 			break;
 		case PM_OP_REMOVE:
-			checkargs_remove();
+			checkargs_remove(result);
 			break;
 		case PM_OP_UPGRADE:
-			checkargs_upgrade();
+			checkargs_upgrade(result);
 			break;
 		case PM_OP_FILES:
-			checkargs_files();
+			checkargs_files(result);
 			break;
 		default:
 			break;
 	}
 
-	return 0;
+	return result;
 }
 
 /** Print command line to logfile.
-- 
2.34.0

From 04aa99ea014f5c52bb59070c63c3989d17e35388 Mon Sep 17 00:00:00 2001
From: Fredrick Brennan <[email protected]>
Date: Fri, 19 Nov 2021 16:10:51 -0500
Subject: [PATCH 2/2] =?UTF-8?q?Permit=20`--search=3D=E2=80=A6`=20in=20`-Q`?=
 =?UTF-8?q?=20and=20`-S`?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Allows for e.g. `pacman -S --search=-doc`, right now difficult to
discover how to do (`pacman -S --search '\\-doc'`)

Signed-off-by: Fredrick Brennan <[email protected]>
---
 src/pacman/pacman.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index ed2d19b2..ee575602 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -563,6 +563,8 @@ static int parsearg_query(int opt)
 		case OP_SEARCH:
 		case 's':
 			config->op_q_search = 1;
+			if (optarg != NULL)
+				parsearg_util_addlist(&(pm_targets));
 			break;
 		case OP_UNREQUIRED:
 		case 't':
@@ -605,6 +607,10 @@ static void checkargs_query(int parse_err)
 		invalid_opt(config->op_q_owns, "--search", "--owns");
 		checkargs_query_display_opts("--search");
 		checkargs_query_filter_opts("--search");
+		if (alpm_list_count(pm_targets) == 0 && parse_err) {
+			pm_printf(ALPM_LOG_ERROR, "No targets and --search, did you mean to use --search=…?");
+			cleanup(1);
+		}
 	} else if(config->op_q_owns) {
 		invalid_opt(config->group, "--owns", "--groups");
 		checkargs_query_display_opts("--owns");
@@ -823,6 +829,8 @@ static int parsearg_sync(int opt)
 		case OP_SEARCH:
 		case 's':
 			config->op_s_search = 1;
+			if (optarg != NULL)
+				parsearg_util_addlist(&(pm_targets));
 			break;
 		case OP_SYSUPGRADE:
 		case 'u':
@@ -860,6 +868,10 @@ static void checkargs_sync(int parse_err)
 		invalid_opt(config->op_q_list, "--search", "--list");
 		invalid_opt(config->op_s_upgrade, "--search", "--sysupgrade");
 		invalid_opt(config->op_s_downloadonly, "--search", "--downloadonly");
+		if (alpm_list_count(pm_targets) == 0 && parse_err) {
+			pm_printf(ALPM_LOG_ERROR, "No targets and --search, did you mean to use --search=…?");
+			cleanup(1);
+		}
 	} else if(config->op_q_list) {
 		invalid_opt(config->group, "--list", "--groups");
 		invalid_opt(config->op_s_upgrade, "--list", "--sysupgrade");
@@ -914,7 +926,7 @@ static int parseargs(int argc, char *argv[])
 		{"root",       required_argument, 0, OP_ROOT},
 		{"sysroot",    required_argument, 0, OP_SYSROOT},
 		{"recursive",  no_argument,       0, OP_RECURSIVE},
-		{"search",     no_argument,       0, OP_SEARCH},
+		{"search",     optional_argument, 0, OP_SEARCH},
 		{"regex",      no_argument,       0, OP_REGEX},
 		{"machinereadable",      no_argument,       0, OP_MACHINEREADABLE},
 		{"unrequired", no_argument,       0, OP_UNREQUIRED},
-- 
2.34.0

Reply via email to