git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 0/4] Factorize i18n
@ 2022-01-22 18:35 Jean-Noël Avila via GitGitGadget
  2022-01-22 18:35 ` [PATCH 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
                   ` (4 more replies)
  0 siblings, 5 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-22 18:35 UTC (permalink / raw)
  To: git; +Cc: Jean-Noël Avila

This is a small series of i18n factorizations. Again the idea is to:

 * reduce the number of strings to translate
 * make life easier for translators by removing constant parts of the
   strings to translate
 * uniformize the UI by using a type of message for the a given type of
   condition.

Jean-Noël Avila (4):
  i18n: factorize more 'incompatible options' messages
  i18n: factorize "invalid value" messages
  i18n: remove from i18n strings that do not hold translatable parts
  i18n: transfer variables into placeholders in command synopsis

 archive.c                                 |  2 +-
 builtin/am.c                              |  7 ++--
 builtin/bisect--helper.c                  |  6 ++--
 builtin/blame.c                           |  6 ++--
 builtin/commit.c                          | 39 ++++++++++++++---------
 builtin/count-objects.c                   |  2 +-
 builtin/difftool.c                        | 18 +++++++++--
 builtin/fast-export.c                     |  2 +-
 builtin/fetch.c                           |  4 +--
 builtin/grep.c                            |  4 +--
 builtin/hash-object.c                     |  2 +-
 builtin/help.c                            |  4 +--
 builtin/log.c                             | 20 ++++++++++--
 builtin/merge-base.c                      |  4 +--
 builtin/mktag.c                           |  2 +-
 builtin/mktree.c                          |  2 +-
 builtin/notes.c                           |  6 ++--
 builtin/pack-objects.c                    |  2 +-
 builtin/prune-packed.c                    |  2 +-
 builtin/pull.c                            |  6 ++--
 builtin/push.c                            |  2 +-
 builtin/rebase.c                          |  2 +-
 builtin/reflog.c                          |  6 ++--
 builtin/remote.c                          |  2 +-
 builtin/replace.c                         |  2 +-
 builtin/rev-list.c                        |  2 +-
 builtin/send-pack.c                       |  2 +-
 builtin/sparse-checkout.c                 |  8 ++---
 builtin/stripspace.c                      |  4 +--
 builtin/submodule--helper.c               |  2 +-
 builtin/update-server-info.c              |  2 +-
 diff-merges.c                             |  2 +-
 gpg-interface.c                           |  4 +--
 ls-refs.c                                 |  2 +-
 parallel-checkout.c                       |  3 +-
 sequencer.c                               |  2 +-
 setup.c                                   |  2 +-
 submodule-config.c                        |  2 +-
 t/t4150-am.sh                             |  2 +-
 t/t7500-commit-template-squash-signoff.sh |  2 +-
 40 files changed, 118 insertions(+), 77 deletions(-)


base-commit: 90d242d36e248acfae0033274b524bfa55a947fd
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1123%2Fjnavila%2Ffactorize_i18n-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1123/jnavila/factorize_i18n-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1123
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-22 18:35 [PATCH 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
@ 2022-01-22 18:35 ` Jean-Noël Avila via GitGitGadget
  2022-01-24  7:14   ` Johannes Sixt
  2022-01-22 18:35 ` [PATCH 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-22 18:35 UTC (permalink / raw)
  To: git; +Cc: Jean-Noël Avila, Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

When more than two options are mutually exclusive, print the ones
which are actually on the command line.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/commit.c                          | 39 ++++++++++++++---------
 builtin/difftool.c                        | 18 +++++++++--
 builtin/grep.c                            |  4 +--
 builtin/log.c                             | 20 ++++++++++--
 builtin/merge-base.c                      |  4 +--
 t/t7500-commit-template-squash-signoff.sh |  2 +-
 6 files changed, 63 insertions(+), 24 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index b9ed0374e30..910f4c912bf 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1243,6 +1243,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
 				      struct wt_status *s)
 {
 	int f = 0;
+	char * f_options[4];
 
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
 	finalize_deferred_config(s);
@@ -1251,7 +1252,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
 		force_author = find_author_by_nickname(force_author);
 
 	if (force_author && renew_authorship)
-		die(_("Using both --reset-author and --author does not make sense"));
+		die(_("options '%s' and '%s' cannot be used together"), "--reset-author", "--author");
 
 	if (logfile || have_option_m || use_message)
 		use_editor = 0;
@@ -1268,19 +1269,19 @@ static int parse_and_validate_options(int argc, const char *argv[],
 			die(_("You are in the middle of a rebase -- cannot amend."));
 	}
 	if (fixup_message && squash_message)
-		die(_("Options --squash and --fixup cannot be used together"));
-	if (use_message)
-		f++;
-	if (edit_message)
-		f++;
-	if (fixup_message)
-		f++;
-	if (logfile)
-		f++;
+		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
+	f_options[f] = "-C";
+	f+=	!!use_message;
+	f_options[f] = "-c";
+	f+=!!edit_message;
+	f_options[f] = "-F";
+	f+=!!logfile;
+	f_options[f] = "--fixup";
+	f+=!!fixup_message;
 	if (f > 1)
-		die(_("Only one of -c/-C/-F/--fixup can be used."));
+		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
 	if (have_option_m && (edit_message || use_message || logfile))
-		die((_("Option -m cannot be combined with -c/-C/-F.")));
+		die(_("options '%s' and '%s' cannot be used together"), "-m", f_options[0]);
 	if (f || have_option_m)
 		template_file = NULL;
 	if (edit_message)
@@ -1305,9 +1306,17 @@ static int parse_and_validate_options(int argc, const char *argv[],
 
 	if (patch_interactive)
 		interactive = 1;
-
-	if (also + only + all + interactive > 1)
-		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
+	f = 0;
+	f_options[f] = "-i/--include";
+	f += also;
+	f_options[f] = "-o/--only";
+	f += only;
+	f_options[f] = "-a/--all";
+	f += all;
+	f_options[f] = "--interactive/-p/--patch";
+	f += interactive;
+	if (f > 1)
+		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
 
 	if (fixup_message) {
 		/*
diff --git a/builtin/difftool.c b/builtin/difftool.c
index c79fbbf67e5..92854bc7737 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -685,6 +685,8 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 	int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
 	    tool_help = 0, no_index = 0;
 	static char *difftool_cmd = NULL, *extcmd = NULL;
+	int f = 0;
+	char *f_options[3];
 	struct option builtin_difftool_options[] = {
 		OPT_BOOL('g', "gui", &use_gui_tool,
 			 N_("use `diff.guitool` instead of `diff.tool`")),
@@ -732,8 +734,20 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 	} else if (dir_diff)
 		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
 
-	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
+	if (use_gui_tool) {
+		f_options[f] = "--gui";
+		f++;
+	}
+	if (difftool_cmd) {
+		f_options[f] = "--tool";
+		f++;
+	}
+	if (extcmd) {
+		f_options[f] = "--extcmd";
+		f++;
+	}
+	if (f > 1)
+		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
 
 	if (use_gui_tool)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
diff --git a/builtin/grep.c b/builtin/grep.c
index 9e34a820ad4..b199781cb27 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1168,10 +1168,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		setup_pager();
 
 	if (!use_index && (untracked || cached))
-		die(_("--cached or --untracked cannot be used with --no-index"));
+		die(_("options '%s' and '%s' cannot be used together"),"--cached/--untracked", "--no-index");
 
 	if (untracked && cached)
-		die(_("--untracked cannot be used with --cached"));
+		die(_("options '%s' and '%s' cannot be used together"), "--untracked", "--cached");
 
 	if (!use_index || untracked) {
 		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
diff --git a/builtin/log.c b/builtin/log.c
index 4b493408cc5..59b4a2fd380 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1759,6 +1759,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	struct strbuf rdiff_title = STRBUF_INIT;
 	int creation_factor = -1;
 
+	int f = 0;
+	char * f_options[4];
+
 	const struct option builtin_format_patch_options[] = {
 		OPT_CALLBACK_F('n', "numbered", &numbered, NULL,
 			    N_("use [PATCH n/m] even with a single patch"),
@@ -1978,8 +1981,21 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	if (rev.show_notes)
 		load_display_notes(&rev.notes_opt);
 
-	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
+	if (use_stdout) {
+		f_options[f] = "--stdout";
+		f++;
+	}
+	if (rev.diffopt.close_file) {
+		f_options[f] = "--output";
+		f++;
+	}
+	if (output_directory) {
+		f_options[f] = "--output-directory";
+		f++;
+	}
+
+	if (f > 1)
+		die(_("options '%s'and '%s' cannot be used together"), f_options[0], f_options[1]);
 
 	if (use_stdout) {
 		setup_pager();
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 6719ac198dc..1447f1c493a 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -159,12 +159,12 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
 		if (argc < 2)
 			usage_with_options(merge_base_usage, options);
 		if (show_all)
-			die("--is-ancestor cannot be used with --all");
+			die(_("options '%s' and '%s' cannot be used together"),"--is-ancestor", "--all");
 		return handle_is_ancestor(argc, argv);
 	}
 
 	if (cmdmode == 'r' && show_all)
-		die("--independent cannot be used with --all");
+		die(_("options '%s' and '%s' cannot be used together"),"--independent", "--all");
 
 	if (cmdmode == 'o')
 		return handle_octopus(argc, argv, show_all);
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 91964653a0b..5fcaa0b4f2a 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
 '
 
 test_expect_success '--fixup=reword: -F give error message' '
-	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
+	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
 	test_cmp expect actual
 '
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 2/4] i18n: factorize "invalid value" messages
  2022-01-22 18:35 [PATCH 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  2022-01-22 18:35 ` [PATCH 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
@ 2022-01-22 18:35 ` Jean-Noël Avila via GitGitGadget
  2022-01-24 11:09   ` Phillip Wood
  2022-01-22 18:35 ` [PATCH 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-22 18:35 UTC (permalink / raw)
  To: git; +Cc: Jean-Noël Avila, Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Use the same message when an invalid value is passed to a command line
option or a configuration variable.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/am.c           | 7 ++++---
 builtin/blame.c        | 6 +++---
 builtin/fetch.c        | 4 ++--
 builtin/pack-objects.c | 2 +-
 builtin/pull.c         | 6 +++---
 builtin/push.c         | 2 +-
 builtin/send-pack.c    | 2 +-
 diff-merges.c          | 2 +-
 gpg-interface.c        | 4 ++--
 ls-refs.c              | 2 +-
 parallel-checkout.c    | 3 ++-
 sequencer.c            | 2 +-
 setup.c                | 2 +-
 submodule-config.c     | 2 +-
 t/t4150-am.sh          | 2 +-
 15 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index b6be1f1cb11..ba1dacbc034 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -199,7 +199,7 @@ static int am_option_parse_empty(const struct option *opt,
 	else if (!strcmp(arg, "keep"))
 		*opt_value = KEEP_EMPTY_COMMIT;
 	else
-		return error(_("Invalid value for --empty: %s"), arg);
+		return error(_("invalid value for '%s': '%s'"), "--empty", arg);
 
 	return 0;
 }
@@ -2239,7 +2239,7 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
 	 * when you add new options
 	 */
 	else
-		return error(_("Invalid value for --patch-format: %s"), arg);
+		return error(_("invalid value for '%s': '%s'"), "--patch-format", arg);
 	return 0;
 }
 
@@ -2282,7 +2282,8 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 				break;
 		}
 		if (new_value >= ARRAY_SIZE(valid_modes))
-			return error(_("Invalid value for --show-current-patch: %s"), arg);
+			return error(_("invalid value for '%s': '%s'"),
+						 "--show-current-patch", arg);
 	}
 
 	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
diff --git a/builtin/blame.c b/builtin/blame.c
index 7fafeac4081..ca821420d68 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -721,8 +721,8 @@ static int git_blame_config(const char *var, const char *value, void *cb)
 	}
 	if (!strcmp(var, "color.blame.repeatedlines")) {
 		if (color_parse_mem(value, strlen(value), repeated_meta_color))
-			warning(_("invalid color '%s' in color.blame.repeatedLines"),
-				value);
+			warning(_("invalid value for '%s': '%s'"),
+					"color.blame.repeatedLines", value);
 		return 0;
 	}
 	if (!strcmp(var, "color.blame.highlightrecent")) {
@@ -739,7 +739,7 @@ static int git_blame_config(const char *var, const char *value, void *cb)
 			coloring_mode &= ~(OUTPUT_COLOR_LINE |
 					    OUTPUT_SHOW_AGE_WITH_COLOR);
 		} else {
-			warning(_("invalid value for blame.coloring"));
+			warning(_("invalid value for '%s': '%s'"), "blame.coloring", value);
 			return 0;
 		}
 	}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index eaab8056bf9..19ec48f3330 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -758,8 +758,8 @@ static void prepare_format_display(struct ref *ref_map)
 	else if (!strcasecmp(format, "compact"))
 		compact_format = 1;
 	else
-		die(_("configuration fetch.output contains invalid value %s"),
-		    format);
+		die(_("invalid value for '%s': '%s'"),
+			  "fetch.output", format);
 
 	for (rm = ref_map; rm; rm = rm->next) {
 		if (rm->status == REF_STATUS_REJECT_SHALLOW ||
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index ba2006f2212..192c3ca305e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3504,7 +3504,7 @@ static int option_parse_missing_action(const struct option *opt,
 		return 0;
 	}
 
-	die(_("invalid value for --missing"));
+	die(_("invalid value for '%s': '%s'"), "--missing", arg);
 	return 0;
 }
 
diff --git a/builtin/pull.c b/builtin/pull.c
index 100cbf9fb85..e54a0ccadc6 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -42,9 +42,9 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
 		return v;
 
 	if (fatal)
-		die(_("Invalid value for %s: %s"), key, value);
+		die(_("invalid value for '%s': '%s'"), key, value);
 	else
-		error(_("Invalid value for %s: %s"), key, value);
+		error(_("invalid value for '%s': '%s'"), key, value);
 
 	return REBASE_INVALID;
 }
@@ -318,7 +318,7 @@ static const char *config_get_ff(void)
 	if (!strcmp(value, "only"))
 		return "--ff-only";
 
-	die(_("Invalid value for pull.ff: %s"), value);
+	die(_("invalid value for '%s': '%s'"), "pull.ff", value);
 }
 
 /**
diff --git a/builtin/push.c b/builtin/push.c
index 359db90321c..cad997965a7 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -486,7 +486,7 @@ static int git_push_config(const char *k, const char *v, void *cb)
 				if (value && !strcasecmp(value, "if-asked"))
 					set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_IF_ASKED);
 				else
-					return error("Invalid value for '%s'", k);
+					return error(_("invalid value for '%s'"), k);
 			}
 		}
 	} else if (!strcmp(k, "push.recursesubmodules")) {
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 69c432ef1a6..64962be0168 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -145,7 +145,7 @@ static int send_pack_config(const char *k, const char *v, void *cb)
 				if (value && !strcasecmp(value, "if-asked"))
 					args.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
 				else
-					return error("Invalid value for '%s'", k);
+					return error(_("invalid value for '%s'"), k);
 			}
 		}
 	}
diff --git a/diff-merges.c b/diff-merges.c
index 5060ccd890b..cd6c102a0d5 100644
--- a/diff-merges.c
+++ b/diff-merges.c
@@ -67,7 +67,7 @@ static void set_diff_merges(struct rev_info *revs, const char *optarg)
 	diff_merges_setup_func_t func = func_by_opt(optarg);
 
 	if (!func)
-		die(_("unknown value for --diff-merges: %s"), optarg);
+		die(_("invalid value for '%s': '%s'"), "--diff-merges", optarg);
 
 	func(revs);
 
diff --git a/gpg-interface.c b/gpg-interface.c
index b52eb0e2e04..04d751a16a8 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -702,7 +702,7 @@ int git_gpg_config(const char *var, const char *value, void *cb)
 			return config_error_nonbool(var);
 		fmt = get_format_by_name(value);
 		if (!fmt)
-			return error("unsupported value for %s: %s",
+			return error("invalid value for '%s': '%s'",
 				     var, value);
 		use_format = fmt;
 		return 0;
@@ -717,7 +717,7 @@ int git_gpg_config(const char *var, const char *value, void *cb)
 		free(trust);
 
 		if (ret)
-			return error("unsupported value for %s: %s", var,
+			return error("invalid value for '%s': '%s'", var,
 				     value);
 		return 0;
 	}
diff --git a/ls-refs.c b/ls-refs.c
index 54078323dcb..ae09dd59478 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -34,7 +34,7 @@ static void ensure_config_read(void)
 		} else if (!strcmp(str, "ignore")) {
 			/* do nothing */
 		} else {
-			die(_("invalid value '%s' for lsrefs.unborn"), str);
+			die(_("invalid value for '%s': '%s'"), "lsrefs.unborn", str);
 		}
 	}
 	config_read = 1;
diff --git a/parallel-checkout.c b/parallel-checkout.c
index 8dd7e7bad40..237c02f1d81 100644
--- a/parallel-checkout.c
+++ b/parallel-checkout.c
@@ -39,7 +39,8 @@ void get_parallel_checkout_configs(int *num_workers, int *threshold)
 
 	if (env_workers && *env_workers) {
 		if (strtol_i(env_workers, 10, num_workers)) {
-			die("invalid value for GIT_TEST_CHECKOUT_WORKERS: '%s'",
+			die(_("invalid value for '%s': '%s'"),
+				"GIT_TEST_CHECKOUT_WORKERS",
 			    env_workers);
 		}
 		if (*num_workers < 1)
diff --git a/sequencer.c b/sequencer.c
index 6abd72160cc..9b985e8648d 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2806,7 +2806,7 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
 		return error(_("invalid key: %s"), key);
 
 	if (!error_flag)
-		return error(_("invalid value for %s: %s"), key, value);
+		return error(_("invalid value for '%s': '%s'"), key, value);
 
 	return 0;
 }
diff --git a/setup.c b/setup.c
index af3b8c09abe..fe74092a022 100644
--- a/setup.c
+++ b/setup.c
@@ -559,7 +559,7 @@ static enum extension_result handle_extension(const char *var,
 			return config_error_nonbool(var);
 		format = hash_algo_by_name(value);
 		if (format == GIT_HASH_UNKNOWN)
-			return error("invalid value for 'extensions.objectformat'");
+			return error(_("invalid value for '%s': '%s'"), "extensions.objectformat", value);
 		data->hash_algo = format;
 		return EXTENSION_OK;
 	}
diff --git a/submodule-config.c b/submodule-config.c
index f95344028b5..fb95a026f48 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -496,7 +496,7 @@ static int parse_config(const char *var, const char *value, void *data)
 		else if (parse_submodule_update_strategy(value,
 			 &submodule->update_strategy) < 0 ||
 			 submodule->update_strategy.type == SM_UPDATE_COMMAND)
-			die(_("invalid value for %s"), var);
+			die(_("invalid value for '%s'"), var);
 	} else if (!strcmp(item.buf, "shallow")) {
 		if (!me->overwrite && submodule->recommend_shallow != -1)
 			warn_multiple_config(me->treeish_name, submodule->name,
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 6caff0ca397..159fae8d016 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -1169,7 +1169,7 @@ test_expect_success 'invalid when passing the --empty option alone' '
 	test_when_finished "git am --abort || :" &&
 	git checkout empty-commit^ &&
 	test_must_fail git am --empty empty-commit.patch 2>err &&
-	echo "error: Invalid value for --empty: empty-commit.patch" >expected &&
+	echo "error: invalid value for '\''--empty'\'': '\''empty-commit.patch'\''" >expected &&
 	test_cmp expected err
 '
 
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 3/4] i18n: remove from i18n strings that do not hold translatable parts
  2022-01-22 18:35 [PATCH 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  2022-01-22 18:35 ` [PATCH 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
  2022-01-22 18:35 ` [PATCH 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
@ 2022-01-22 18:35 ` Jean-Noël Avila via GitGitGadget
  2022-01-22 18:35 ` [PATCH 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
  2022-01-28 22:23 ` [PATCH v2 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  4 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-22 18:35 UTC (permalink / raw)
  To: git; +Cc: Jean-Noël Avila, Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 archive.c                    | 2 +-
 builtin/bisect--helper.c     | 6 +++---
 builtin/count-objects.c      | 2 +-
 builtin/hash-object.c        | 2 +-
 builtin/help.c               | 4 ++--
 builtin/mktag.c              | 2 +-
 builtin/mktree.c             | 2 +-
 builtin/notes.c              | 6 +++---
 builtin/prune-packed.c       | 2 +-
 builtin/rebase.c             | 2 +-
 builtin/reflog.c             | 2 +-
 builtin/remote.c             | 2 +-
 builtin/replace.c            | 2 +-
 builtin/sparse-checkout.c    | 8 ++++----
 builtin/stripspace.c         | 4 ++--
 builtin/submodule--helper.c  | 2 +-
 builtin/update-server-info.c | 2 +-
 17 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/archive.c b/archive.c
index d571249cf39..e29d0e00f6c 100644
--- a/archive.c
+++ b/archive.c
@@ -12,7 +12,7 @@
 
 static char const * const archive_usage[] = {
 	N_("git archive [<options>] <tree-ish> [<path>...]"),
-	N_("git archive --list"),
+	"git archive --list",
 	N_("git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"),
 	N_("git archive --remote <repo> [--exec <cmd>] --list"),
 	NULL
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 28a2e6a5750..f962dbd4303 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -22,15 +22,15 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
 
 static const char * const git_bisect_helper_usage[] = {
 	N_("git bisect--helper --bisect-reset [<commit>]"),
-	N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
+	"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]",
 	N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
 					    " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
-	N_("git bisect--helper --bisect-next"),
+	"git bisect--helper --bisect-next",
 	N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
 	N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
 	N_("git bisect--helper --bisect-replay <filename>"),
 	N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
-	N_("git bisect--helper --bisect-visualize"),
+	"git bisect--helper --bisect-visualize",
 	N_("git bisect--helper --bisect-run <cmd>..."),
 	NULL
 };
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 3fae474f6f1..07b94195962 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -87,7 +87,7 @@ static int print_alternate(struct object_directory *odb, void *data)
 }
 
 static char const * const count_objects_usage[] = {
-	N_("git count-objects [-v] [-H | --human-readable]"),
+	"git count-objects [-v] [-H | --human-readable]",
 	NULL
 };
 
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index c7b3ad74c60..04e2442ec7c 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -81,7 +81,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
 {
 	static const char * const hash_object_usage[] = {
 		N_("git hash-object [-t <type>] [-w] [--path=<file> | --no-filters] [--stdin] [--] <file>..."),
-		N_("git hash-object  --stdin-paths"),
+		"git hash-object  --stdin-paths",
 		NULL
 	};
 	const char *type = blob_type;
diff --git a/builtin/help.c b/builtin/help.c
index d387131dd83..b4f2ad3f94e 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -77,8 +77,8 @@ static struct option builtin_help_options[] = {
 static const char * const builtin_help_usage[] = {
 	N_("git help [-a|--all] [--[no-]verbose]]\n"
 	   "         [[-i|--info] [-m|--man] [-w|--web]] [<command>]"),
-	N_("git help [-g|--guides]"),
-	N_("git help [-c|--config]"),
+	"git help [-g|--guides]",
+	"git help [-c|--config]",
 	NULL
 };
 
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 3b2dbbb37e6..c7b905c614b 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 static char const * const builtin_mktag_usage[] = {
-	N_("git mktag"),
+	"git mktag",
 	NULL
 };
 static int option_strict = 1;
diff --git a/builtin/mktree.c b/builtin/mktree.c
index ae78ca1c029..8bdaada922a 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -63,7 +63,7 @@ static void write_tree(struct object_id *oid)
 }
 
 static const char *mktree_usage[] = {
-	N_("git mktree [-z] [--missing] [--batch]"),
+	"git mktree [-z] [--missing] [--batch]",
 	NULL
 };
 
diff --git a/builtin/notes.c b/builtin/notes.c
index 05d60483e82..f99593a1853 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -32,8 +32,8 @@ static const char * const git_notes_usage[] = {
 	N_("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"),
 	N_("git notes [--ref <notes-ref>] show [<object>]"),
 	N_("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"),
-	N_("git notes merge --commit [-v | -q]"),
-	N_("git notes merge --abort [-v | -q]"),
+	"git notes merge --commit [-v | -q]",
+	"git notes merge --abort [-v | -q]",
 	N_("git notes [--ref <notes-ref>] remove [<object>...]"),
 	N_("git notes [--ref <notes-ref>] prune [-n] [-v]"),
 	N_("git notes [--ref <notes-ref>] get-ref"),
@@ -89,7 +89,7 @@ static const char * const git_notes_prune_usage[] = {
 };
 
 static const char * const git_notes_get_ref_usage[] = {
-	N_("git notes get-ref"),
+	"git notes get-ref",
 	NULL
 };
 
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index b7b9281a8ce..da3273a268b 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -3,7 +3,7 @@
 #include "prune-packed.h"
 
 static const char * const prune_packed_usage[] = {
-	N_("git prune-packed [-n | --dry-run] [-q | --quiet]"),
+	"git prune-packed [-n | --dry-run] [-q | --quiet]",
 	NULL
 };
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 36490d06c8a..64796c6a785 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -36,7 +36,7 @@ static char const * const builtin_rebase_usage[] = {
 		"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
 	N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
 		"--root [<branch>]"),
-	N_("git rebase --continue | --abort | --skip | --edit-todo"),
+	"git rebase --continue | --abort | --skip | --edit-todo",
 	NULL
 };
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index a4b1dd27e13..ee5ee8d8cf6 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -800,7 +800,7 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
  */
 
 static const char reflog_usage[] =
-N_("git reflog [ show | expire | delete | exists ]");
+"git reflog [ show | expire | delete | exists ]";
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin/remote.c b/builtin/remote.c
index 299c466116d..6f27ddc47bd 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -14,7 +14,7 @@
 #include "commit-reach.h"
 
 static const char * const builtin_remote_usage[] = {
-	N_("git remote [-v | --verbose]"),
+	"git remote [-v | --verbose]",
 	N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>"),
 	N_("git remote rename <old> <new>"),
 	N_("git remote remove <name>"),
diff --git a/builtin/replace.c b/builtin/replace.c
index 6ff1734d587..ac92337c0ec 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -22,7 +22,7 @@ static const char * const git_replace_usage[] = {
 	N_("git replace [-f] <object> <replacement>"),
 	N_("git replace [-f] --edit <object>"),
 	N_("git replace [-f] --graft <commit> [<parent>...]"),
-	N_("git replace [-f] --convert-graft-file"),
+	"git replace [-f] --convert-graft-file",
 	N_("git replace -d <object>..."),
 	N_("git replace [--format=<format>] [-l [<pattern>]]"),
 	NULL
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 679c1070368..771c9869a1c 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -43,7 +43,7 @@ static void write_patterns_to_file(FILE *fp, struct pattern_list *pl)
 }
 
 static char const * const builtin_sparse_checkout_list_usage[] = {
-	N_("git sparse-checkout list"),
+	"git sparse-checkout list",
 	NULL
 };
 
@@ -419,7 +419,7 @@ static int update_modes(int *cone_mode, int *sparse_index)
 }
 
 static char const * const builtin_sparse_checkout_init_usage[] = {
-	N_("git sparse-checkout init [--cone] [--[no-]sparse-index]"),
+	"git sparse-checkout init [--cone] [--[no-]sparse-index]",
 	NULL
 };
 
@@ -762,7 +762,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
 }
 
 static char const * const builtin_sparse_checkout_reapply_usage[] = {
-	N_("git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]"),
+	"git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]",
 	NULL
 };
 
@@ -800,7 +800,7 @@ static int sparse_checkout_reapply(int argc, const char **argv)
 }
 
 static char const * const builtin_sparse_checkout_disable_usage[] = {
-	N_("git sparse-checkout disable"),
+	"git sparse-checkout disable",
 	NULL
 };
 
diff --git a/builtin/stripspace.c b/builtin/stripspace.c
index be33eb83c1b..1e34cf2bebd 100644
--- a/builtin/stripspace.c
+++ b/builtin/stripspace.c
@@ -15,8 +15,8 @@ static void comment_lines(struct strbuf *buf)
 }
 
 static const char * const stripspace_usage[] = {
-	N_("git stripspace [-s | --strip-comments]"),
-	N_("git stripspace [-c | --comment-lines]"),
+	"git stripspace [-s | --strip-comments]",
+	"git stripspace [-c | --comment-lines]",
 	NULL
 };
 
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index c5d3fc3817f..b80aa9898ac 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2883,7 +2883,7 @@ static int module_config(int argc, const char **argv, const char *prefix)
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule--helper config <name> [<value>]"),
 		N_("git submodule--helper config --unset <name>"),
-		N_("git submodule--helper config --check-writeable"),
+		"git submodule--helper config --check-writeable",
 		NULL
 	};
 
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index 4321a344567..880fffec587 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -4,7 +4,7 @@
 #include "parse-options.h"
 
 static const char * const update_server_info_usage[] = {
-	N_("git update-server-info [--force]"),
+	"git update-server-info [--force]",
 	NULL
 };
 
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 4/4] i18n: transfer variables into placeholders in command synopsis
  2022-01-22 18:35 [PATCH 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
                   ` (2 preceding siblings ...)
  2022-01-22 18:35 ` [PATCH 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
@ 2022-01-22 18:35 ` Jean-Noël Avila via GitGitGadget
  2022-01-28 22:23 ` [PATCH v2 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  4 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-22 18:35 UTC (permalink / raw)
  To: git; +Cc: Jean-Noël Avila, Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

This applies the style guide for documentation.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/fast-export.c | 2 +-
 builtin/reflog.c      | 4 ++--
 builtin/rev-list.c    | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 9f1c730e587..510139e9b54 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -26,7 +26,7 @@
 #include "commit-slab.h"
 
 static const char *fast_export_usage[] = {
-	N_("git fast-export [rev-list-opts]"),
+	N_("git fast-export [<rev-list-opts>]"),
 	NULL
 };
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index ee5ee8d8cf6..343a10d371b 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -17,10 +17,10 @@ static const char reflog_expire_usage[] =
 N_("git reflog expire [--expire=<time>] "
    "[--expire-unreachable=<time>] "
    "[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] "
-   "[--verbose] [--all] <refs>...");
+   "[--verbose] [--all] <ref>...");
 static const char reflog_delete_usage[] =
 N_("git reflog delete [--rewrite] [--updateref] "
-   "[--dry-run | -n] [--verbose] <refs>...");
+   "[--dry-run | -n] [--verbose] <ref>...");
 static const char reflog_exists_usage[] =
 N_("git reflog exists <ref>");
 
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 777558e9b06..38528c7f156 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -20,7 +20,7 @@
 #include "packfile.h"
 
 static const char rev_list_usage[] =
-"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
+"git rev-list [<options>] <commit-id>... [-- <path>...]\n"
 "  limiting output:\n"
 "    --max-count=<n>\n"
 "    --max-age=<epoch>\n"
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-22 18:35 ` [PATCH 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
@ 2022-01-24  7:14   ` Johannes Sixt
  2022-01-24 11:06     ` Phillip Wood
  0 siblings, 1 reply; 41+ messages in thread
From: Johannes Sixt @ 2022-01-24  7:14 UTC (permalink / raw)
  To: Jean-Noël Avila; +Cc: git, Jean-Noël Avila via GitGitGadget

Am 22.01.22 um 19:35 schrieb Jean-Noël Avila via GitGitGadget:
> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
> 
> When more than two options are mutually exclusive, print the ones
> which are actually on the command line.

Reading this, I expect that all mutually exclusive options are listed in
the error messages. But the updated code lists only the first and second
option even if more are on the command line. What is the justification
for that? Just "make the work for translators easier"? I am not 100%
sure that this is the right balance. Wouldn't it be helpful for users to
get to know which set of options is incompatible, or is an error message
not the right place for this kind of education? Don't know...

> 
> Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
> ---
>  builtin/commit.c                          | 39 ++++++++++++++---------
>  builtin/difftool.c                        | 18 +++++++++--
>  builtin/grep.c                            |  4 +--
>  builtin/log.c                             | 20 ++++++++++--
>  builtin/merge-base.c                      |  4 +--
>  t/t7500-commit-template-squash-signoff.sh |  2 +-
>  6 files changed, 63 insertions(+), 24 deletions(-)
> 
> diff --git a/builtin/commit.c b/builtin/commit.c
> index b9ed0374e30..910f4c912bf 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -1243,6 +1243,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
>  				      struct wt_status *s)
>  {
>  	int f = 0;
> +	char * f_options[4];
>  
>  	argc = parse_options(argc, argv, prefix, options, usage, 0);
>  	finalize_deferred_config(s);
> @@ -1251,7 +1252,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
>  		force_author = find_author_by_nickname(force_author);
>  
>  	if (force_author && renew_authorship)
> -		die(_("Using both --reset-author and --author does not make sense"));
> +		die(_("options '%s' and '%s' cannot be used together"), "--reset-author", "--author");
>  
>  	if (logfile || have_option_m || use_message)
>  		use_editor = 0;
> @@ -1268,19 +1269,19 @@ static int parse_and_validate_options(int argc, const char *argv[],
>  			die(_("You are in the middle of a rebase -- cannot amend."));
>  	}
>  	if (fixup_message && squash_message)
> -		die(_("Options --squash and --fixup cannot be used together"));
> -	if (use_message)
> -		f++;
> -	if (edit_message)
> -		f++;
> -	if (fixup_message)
> -		f++;
> -	if (logfile)
> -		f++;
> +		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
> +	f_options[f] = "-C";
> +	f+=	!!use_message;
> +	f_options[f] = "-c";
> +	f+=!!edit_message;
> +	f_options[f] = "-F";
> +	f+=!!logfile;
> +	f_options[f] = "--fixup";
> +	f+=!!fixup_message;

The format style violations are quite obvious here. But see below for a
suggestion to write this differently.

>  	if (f > 1)
> -		die(_("Only one of -c/-C/-F/--fixup can be used."));
> +		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
>  	if (have_option_m && (edit_message || use_message || logfile))
> -		die((_("Option -m cannot be combined with -c/-C/-F.")));
> +		die(_("options '%s' and '%s' cannot be used together"), "-m", f_options[0]);
>  	if (f || have_option_m)
>  		template_file = NULL;
>  	if (edit_message)
> @@ -1305,9 +1306,17 @@ static int parse_and_validate_options(int argc, const char *argv[],
>  
>  	if (patch_interactive)
>  		interactive = 1;
> -
> -	if (also + only + all + interactive > 1)
> -		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
> +	f = 0;
> +	f_options[f] = "-i/--include";
> +	f += also;
> +	f_options[f] = "-o/--only";
> +	f += only;
> +	f_options[f] = "-a/--all";
> +	f += all;
> +	f_options[f] = "--interactive/-p/--patch";

Interesting. -p and --interactive do different things, but can be used
together (-p overrides --interactive). The original error message
suggests that this is not the case. Just a marginal note...

> +	f += interactive;
> +	if (f > 1)
> +		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
>  
>  	if (fixup_message) {
>  		/*
> diff --git a/builtin/difftool.c b/builtin/difftool.c
> index c79fbbf67e5..92854bc7737 100644
> --- a/builtin/difftool.c
> +++ b/builtin/difftool.c
> @@ -685,6 +685,8 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
>  	int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
>  	    tool_help = 0, no_index = 0;
>  	static char *difftool_cmd = NULL, *extcmd = NULL;
> +	int f = 0;
> +	char *f_options[3];
>  	struct option builtin_difftool_options[] = {
>  		OPT_BOOL('g', "gui", &use_gui_tool,
>  			 N_("use `diff.guitool` instead of `diff.tool`")),
> @@ -732,8 +734,20 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
>  	} else if (dir_diff)
>  		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
>  
> -	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
> -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
> +	if (use_gui_tool) {
> +		f_options[f] = "--gui";
> +		f++;
> +	}
> +	if (difftool_cmd) {
> +		f_options[f] = "--tool";
> +		f++;
> +	}
> +	if (extcmd) {
> +		f_options[f] = "--extcmd";
> +		f++;
> +	}
> +	if (f > 1)
> +		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);

I prefer this if-cascade over the "f += truth_value" style, because I
find it is easier to understand. If you write it as

	if (extcmd)
		f_options[f++] = "--extcmd";

you get each branch down to two lines. (But then others may disagree
with the easy-to-understand argument due to the f++ buried in the
expression. Unsure...)

>  
>  	if (use_gui_tool)
>  		setenv("GIT_MERGETOOL_GUI", "true", 1);
> diff --git a/builtin/grep.c b/builtin/grep.c
> index 9e34a820ad4..b199781cb27 100644
> --- a/builtin/grep.c
> +++ b/builtin/grep.c
> @@ -1168,10 +1168,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
>  		setup_pager();
>  
>  	if (!use_index && (untracked || cached))
> -		die(_("--cached or --untracked cannot be used with --no-index"));
> +		die(_("options '%s' and '%s' cannot be used together"),"--cached/--untracked", "--no-index");

Huh? "--cached/--untracked"? Which one was used on the command line? But...

>  
>  	if (untracked && cached)
> -		die(_("--untracked cannot be used with --cached"));
> +		die(_("options '%s' and '%s' cannot be used together"), "--untracked", "--cached");
>  
>  	if (!use_index || untracked) {
>  		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;

... doesn't this logic imply that --cached, --untracked, and --no-index
are three mutually exclusive options?

> diff --git a/builtin/log.c b/builtin/log.c
> index 4b493408cc5..59b4a2fd380 100644
> --- a/builtin/log.c
> +++ b/builtin/log.c
> @@ -1759,6 +1759,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
>  	struct strbuf rdiff_title = STRBUF_INIT;
>  	int creation_factor = -1;
>  
> +	int f = 0;
> +	char * f_options[4];
> +

Style: char *f_options[4]; don't needlessly separate these new variables
from the others by an empty line.

>  	const struct option builtin_format_patch_options[] = {
>  		OPT_CALLBACK_F('n', "numbered", &numbered, NULL,
>  			    N_("use [PATCH n/m] even with a single patch"),
> @@ -1978,8 +1981,21 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
>  	if (rev.show_notes)
>  		load_display_notes(&rev.notes_opt);
>  
> -	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
> -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
> +	if (use_stdout) {
> +		f_options[f] = "--stdout";
> +		f++;
> +	}
> +	if (rev.diffopt.close_file) {
> +		f_options[f] = "--output";
> +		f++;
> +	}
> +	if (output_directory) {
> +		f_options[f] = "--output-directory";
> +		f++;
> +	}
> +
> +	if (f > 1)
> +		die(_("options '%s'and '%s' cannot be used together"), f_options[0], f_options[1]);
>  
>  	if (use_stdout) {
>  		setup_pager();
> diff --git a/builtin/merge-base.c b/builtin/merge-base.c
> index 6719ac198dc..1447f1c493a 100644
> --- a/builtin/merge-base.c
> +++ b/builtin/merge-base.c
> @@ -159,12 +159,12 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
>  		if (argc < 2)
>  			usage_with_options(merge_base_usage, options);
>  		if (show_all)
> -			die("--is-ancestor cannot be used with --all");
> +			die(_("options '%s' and '%s' cannot be used together"),"--is-ancestor", "--all");
>  		return handle_is_ancestor(argc, argv);
>  	}
>  
>  	if (cmdmode == 'r' && show_all)
> -		die("--independent cannot be used with --all");
> +		die(_("options '%s' and '%s' cannot be used together"),"--independent", "--all");
>  
>  	if (cmdmode == 'o')
>  		return handle_octopus(argc, argv, show_all);
> diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
> index 91964653a0b..5fcaa0b4f2a 100755
> --- a/t/t7500-commit-template-squash-signoff.sh
> +++ b/t/t7500-commit-template-squash-signoff.sh
> @@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
>  '
>  
>  test_expect_success '--fixup=reword: -F give error message' '
> -	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
> +	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
>  	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
>  	test_cmp expect actual
>  '

A general comment: To me, it looks like you didn't want to change the
variable name 'f' in the first hunk above, and then just named the array
'f_options' to go with 'f'. Perhaps `exclusive_opt` (not plural!) for
the array. Now, renaming 'f' to something longer makes the code a bit
unwieldy. Therefore, let me suggest yet another approach: factor out
functions check_exclusive_opts3(), check_exclusive_opts4(), to be used like

	check_exclusive_opts3(use_stdout, "--stdout",
		rev.diffopt.close_file, "--output",
		output_directory, "--output-directory");

I am not yet proposing check_exclusive_opts2(), but others may think it
is an improvement, too, (if they think that such functions are an
improvement in the first place).

-- Hannes

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-24  7:14   ` Johannes Sixt
@ 2022-01-24 11:06     ` Phillip Wood
  2022-01-25 20:52       ` Jean-Noël AVILA
  0 siblings, 1 reply; 41+ messages in thread
From: Phillip Wood @ 2022-01-24 11:06 UTC (permalink / raw)
  To: Johannes Sixt, Jean-Noël Avila
  Cc: git, Jean-Noël Avila via GitGitGadget

On 24/01/2022 07:14, Johannes Sixt wrote:
> Am 22.01.22 um 19:35 schrieb Jean-Noël Avila via GitGitGadget:
>> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
>>
>> When more than two options are mutually exclusive, print the ones
>> which are actually on the command line.
> 
> Reading this, I expect that all mutually exclusive options are listed in
> the error messages. But the updated code lists only the first and second
> option even if more are on the command line. What is the justification
> for that? Just "make the work for translators easier"? I am not 100%
> sure that this is the right balance. Wouldn't it be helpful for users to
> get to know which set of options is incompatible, or is an error message
> not the right place for this kind of education? Don't know...

That was my feeling as well when reading this patch, I think the loss of 
information in the error messages is a shame.

>> Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
>> ---
>>   builtin/commit.c                          | 39 ++++++++++++++---------
>>   builtin/difftool.c                        | 18 +++++++++--
>>   builtin/grep.c                            |  4 +--
>>   builtin/log.c                             | 20 ++++++++++--
>>   builtin/merge-base.c                      |  4 +--
>>   t/t7500-commit-template-squash-signoff.sh |  2 +-
>>   6 files changed, 63 insertions(+), 24 deletions(-)
>>
>> diff --git a/builtin/commit.c b/builtin/commit.c
>> index b9ed0374e30..910f4c912bf 100644
>> --- a/builtin/commit.c
>> +++ b/builtin/commit.c
>> @@ -1243,6 +1243,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
>>   				      struct wt_status *s)
>>   {
>>   	int f = 0;
>> +	char * f_options[4];
>>   
>>   	argc = parse_options(argc, argv, prefix, options, usage, 0);
>>   	finalize_deferred_config(s);
>> @@ -1251,7 +1252,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
>>   		force_author = find_author_by_nickname(force_author);
>>   
>>   	if (force_author && renew_authorship)
>> -		die(_("Using both --reset-author and --author does not make sense"));
>> +		die(_("options '%s' and '%s' cannot be used together"), "--reset-author", "--author");
>>   
>>   	if (logfile || have_option_m || use_message)
>>   		use_editor = 0;
>> @@ -1268,19 +1269,19 @@ static int parse_and_validate_options(int argc, const char *argv[],
>>   			die(_("You are in the middle of a rebase -- cannot amend."));
>>   	}
>>   	if (fixup_message && squash_message)
>> -		die(_("Options --squash and --fixup cannot be used together"));
>> -	if (use_message)
>> -		f++;
>> -	if (edit_message)
>> -		f++;
>> -	if (fixup_message)
>> -		f++;
>> -	if (logfile)
>> -		f++;
>> +		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
>> +	f_options[f] = "-C";
>> +	f+=	!!use_message;
>> +	f_options[f] = "-c";
>> +	f+=!!edit_message;
>> +	f_options[f] = "-F";
>> +	f+=!!logfile;
>> +	f_options[f] = "--fixup";
>> +	f+=!!fixup_message;

This feels like an out of bounds access waiting to happen when someone 
adds a new option but forgets to increase the size of f_options above

Best Wishes

Phillip

> The format style violations are quite obvious here. But see below for a
> suggestion to write this differently.
> 
>>   	if (f > 1)
>> -		die(_("Only one of -c/-C/-F/--fixup can be used."));
>> +		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
>>   	if (have_option_m && (edit_message || use_message || logfile))
>> -		die((_("Option -m cannot be combined with -c/-C/-F.")));
>> +		die(_("options '%s' and '%s' cannot be used together"), "-m", f_options[0]);
>>   	if (f || have_option_m)
>>   		template_file = NULL;
>>   	if (edit_message)
>> @@ -1305,9 +1306,17 @@ static int parse_and_validate_options(int argc, const char *argv[],
>>   
>>   	if (patch_interactive)
>>   		interactive = 1;
>> -
>> -	if (also + only + all + interactive > 1)
>> -		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
>> +	f = 0;
>> +	f_options[f] = "-i/--include";
>> +	f += also;
>> +	f_options[f] = "-o/--only";
>> +	f += only;
>> +	f_options[f] = "-a/--all";
>> +	f += all;
>> +	f_options[f] = "--interactive/-p/--patch";
> 
> Interesting. -p and --interactive do different things, but can be used
> together (-p overrides --interactive). The original error message
> suggests that this is not the case. Just a marginal note...
> 
>> +	f += interactive;
>> +	if (f > 1)
>> +		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
>>   
>>   	if (fixup_message) {
>>   		/*
>> diff --git a/builtin/difftool.c b/builtin/difftool.c
>> index c79fbbf67e5..92854bc7737 100644
>> --- a/builtin/difftool.c
>> +++ b/builtin/difftool.c
>> @@ -685,6 +685,8 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
>>   	int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
>>   	    tool_help = 0, no_index = 0;
>>   	static char *difftool_cmd = NULL, *extcmd = NULL;
>> +	int f = 0;
>> +	char *f_options[3];
>>   	struct option builtin_difftool_options[] = {
>>   		OPT_BOOL('g', "gui", &use_gui_tool,
>>   			 N_("use `diff.guitool` instead of `diff.tool`")),
>> @@ -732,8 +734,20 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
>>   	} else if (dir_diff)
>>   		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
>>   
>> -	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
>> -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
>> +	if (use_gui_tool) {
>> +		f_options[f] = "--gui";
>> +		f++;
>> +	}
>> +	if (difftool_cmd) {
>> +		f_options[f] = "--tool";
>> +		f++;
>> +	}
>> +	if (extcmd) {
>> +		f_options[f] = "--extcmd";
>> +		f++;
>> +	}
>> +	if (f > 1)
>> +		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
> 
> I prefer this if-cascade over the "f += truth_value" style, because I
> find it is easier to understand. If you write it as
> 
> 	if (extcmd)
> 		f_options[f++] = "--extcmd";
> 
> you get each branch down to two lines. (But then others may disagree
> with the easy-to-understand argument due to the f++ buried in the
> expression. Unsure...)
> 
>>   
>>   	if (use_gui_tool)
>>   		setenv("GIT_MERGETOOL_GUI", "true", 1);
>> diff --git a/builtin/grep.c b/builtin/grep.c
>> index 9e34a820ad4..b199781cb27 100644
>> --- a/builtin/grep.c
>> +++ b/builtin/grep.c
>> @@ -1168,10 +1168,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
>>   		setup_pager();
>>   
>>   	if (!use_index && (untracked || cached))
>> -		die(_("--cached or --untracked cannot be used with --no-index"));
>> +		die(_("options '%s' and '%s' cannot be used together"),"--cached/--untracked", "--no-index");
> 
> Huh? "--cached/--untracked"? Which one was used on the command line? But...
> 
>>   
>>   	if (untracked && cached)
>> -		die(_("--untracked cannot be used with --cached"));
>> +		die(_("options '%s' and '%s' cannot be used together"), "--untracked", "--cached");
>>   
>>   	if (!use_index || untracked) {
>>   		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
> 
> ... doesn't this logic imply that --cached, --untracked, and --no-index
> are three mutually exclusive options?
> 
>> diff --git a/builtin/log.c b/builtin/log.c
>> index 4b493408cc5..59b4a2fd380 100644
>> --- a/builtin/log.c
>> +++ b/builtin/log.c
>> @@ -1759,6 +1759,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
>>   	struct strbuf rdiff_title = STRBUF_INIT;
>>   	int creation_factor = -1;
>>   
>> +	int f = 0;
>> +	char * f_options[4];
>> +
> 
> Style: char *f_options[4]; don't needlessly separate these new variables
> from the others by an empty line.
> 
>>   	const struct option builtin_format_patch_options[] = {
>>   		OPT_CALLBACK_F('n', "numbered", &numbered, NULL,
>>   			    N_("use [PATCH n/m] even with a single patch"),
>> @@ -1978,8 +1981,21 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
>>   	if (rev.show_notes)
>>   		load_display_notes(&rev.notes_opt);
>>   
>> -	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
>> -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
>> +	if (use_stdout) {
>> +		f_options[f] = "--stdout";
>> +		f++;
>> +	}
>> +	if (rev.diffopt.close_file) {
>> +		f_options[f] = "--output";
>> +		f++;
>> +	}
>> +	if (output_directory) {
>> +		f_options[f] = "--output-directory";
>> +		f++;
>> +	}
>> +
>> +	if (f > 1)
>> +		die(_("options '%s'and '%s' cannot be used together"), f_options[0], f_options[1]);
>>   
>>   	if (use_stdout) {
>>   		setup_pager();
>> diff --git a/builtin/merge-base.c b/builtin/merge-base.c
>> index 6719ac198dc..1447f1c493a 100644
>> --- a/builtin/merge-base.c
>> +++ b/builtin/merge-base.c
>> @@ -159,12 +159,12 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
>>   		if (argc < 2)
>>   			usage_with_options(merge_base_usage, options);
>>   		if (show_all)
>> -			die("--is-ancestor cannot be used with --all");
>> +			die(_("options '%s' and '%s' cannot be used together"),"--is-ancestor", "--all");
>>   		return handle_is_ancestor(argc, argv);
>>   	}
>>   
>>   	if (cmdmode == 'r' && show_all)
>> -		die("--independent cannot be used with --all");
>> +		die(_("options '%s' and '%s' cannot be used together"),"--independent", "--all");
>>   
>>   	if (cmdmode == 'o')
>>   		return handle_octopus(argc, argv, show_all);
>> diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
>> index 91964653a0b..5fcaa0b4f2a 100755
>> --- a/t/t7500-commit-template-squash-signoff.sh
>> +++ b/t/t7500-commit-template-squash-signoff.sh
>> @@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
>>   '
>>   
>>   test_expect_success '--fixup=reword: -F give error message' '
>> -	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
>> +	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
>>   	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
>>   	test_cmp expect actual
>>   '
> 
> A general comment: To me, it looks like you didn't want to change the
> variable name 'f' in the first hunk above, and then just named the array
> 'f_options' to go with 'f'. Perhaps `exclusive_opt` (not plural!) for
> the array. Now, renaming 'f' to something longer makes the code a bit
> unwieldy. Therefore, let me suggest yet another approach: factor out
> functions check_exclusive_opts3(), check_exclusive_opts4(), to be used like
> 
> 	check_exclusive_opts3(use_stdout, "--stdout",
> 		rev.diffopt.close_file, "--output",
> 		output_directory, "--output-directory");
> 
> I am not yet proposing check_exclusive_opts2(), but others may think it
> is an improvement, too, (if they think that such functions are an
> improvement in the first place).
> 
> -- Hannes


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 2/4] i18n: factorize "invalid value" messages
  2022-01-22 18:35 ` [PATCH 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
@ 2022-01-24 11:09   ` Phillip Wood
  0 siblings, 0 replies; 41+ messages in thread
From: Phillip Wood @ 2022-01-24 11:09 UTC (permalink / raw)
  To: Jean-Noël Avila via GitGitGadget, git; +Cc: Jean-Noël Avila

Hi Jean-Noël

On 22/01/2022 18:35, Jean-Noël Avila via GitGitGadget wrote:
> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
> 
> Use the same message when an invalid value is passed to a command line
> option or a configuration variable.

I think the factorization works well here. I think in the previous 
series you mentioned the possibility of creating macros for standard 
messages, reading this patch that or some standard functions like 
error_invalid_value() seem like a good idea to keep the messages 
consistent in the future.

Best Wishes

Phillip

> Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
> ---
>   builtin/am.c           | 7 ++++---
>   builtin/blame.c        | 6 +++---
>   builtin/fetch.c        | 4 ++--
>   builtin/pack-objects.c | 2 +-
>   builtin/pull.c         | 6 +++---
>   builtin/push.c         | 2 +-
>   builtin/send-pack.c    | 2 +-
>   diff-merges.c          | 2 +-
>   gpg-interface.c        | 4 ++--
>   ls-refs.c              | 2 +-
>   parallel-checkout.c    | 3 ++-
>   sequencer.c            | 2 +-
>   setup.c                | 2 +-
>   submodule-config.c     | 2 +-
>   t/t4150-am.sh          | 2 +-
>   15 files changed, 25 insertions(+), 23 deletions(-)
> 
> diff --git a/builtin/am.c b/builtin/am.c
> index b6be1f1cb11..ba1dacbc034 100644
> --- a/builtin/am.c
> +++ b/builtin/am.c
> @@ -199,7 +199,7 @@ static int am_option_parse_empty(const struct option *opt,
>   	else if (!strcmp(arg, "keep"))
>   		*opt_value = KEEP_EMPTY_COMMIT;
>   	else
> -		return error(_("Invalid value for --empty: %s"), arg);
> +		return error(_("invalid value for '%s': '%s'"), "--empty", arg);
>   
>   	return 0;
>   }
> @@ -2239,7 +2239,7 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
>   	 * when you add new options
>   	 */
>   	else
> -		return error(_("Invalid value for --patch-format: %s"), arg);
> +		return error(_("invalid value for '%s': '%s'"), "--patch-format", arg);
>   	return 0;
>   }
>   
> @@ -2282,7 +2282,8 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
>   				break;
>   		}
>   		if (new_value >= ARRAY_SIZE(valid_modes))
> -			return error(_("Invalid value for --show-current-patch: %s"), arg);
> +			return error(_("invalid value for '%s': '%s'"),
> +						 "--show-current-patch", arg);
>   	}
>   
>   	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
> diff --git a/builtin/blame.c b/builtin/blame.c
> index 7fafeac4081..ca821420d68 100644
> --- a/builtin/blame.c
> +++ b/builtin/blame.c
> @@ -721,8 +721,8 @@ static int git_blame_config(const char *var, const char *value, void *cb)
>   	}
>   	if (!strcmp(var, "color.blame.repeatedlines")) {
>   		if (color_parse_mem(value, strlen(value), repeated_meta_color))
> -			warning(_("invalid color '%s' in color.blame.repeatedLines"),
> -				value);
> +			warning(_("invalid value for '%s': '%s'"),
> +					"color.blame.repeatedLines", value);
>   		return 0;
>   	}
>   	if (!strcmp(var, "color.blame.highlightrecent")) {
> @@ -739,7 +739,7 @@ static int git_blame_config(const char *var, const char *value, void *cb)
>   			coloring_mode &= ~(OUTPUT_COLOR_LINE |
>   					    OUTPUT_SHOW_AGE_WITH_COLOR);
>   		} else {
> -			warning(_("invalid value for blame.coloring"));
> +			warning(_("invalid value for '%s': '%s'"), "blame.coloring", value);
>   			return 0;
>   		}
>   	}
> diff --git a/builtin/fetch.c b/builtin/fetch.c
> index eaab8056bf9..19ec48f3330 100644
> --- a/builtin/fetch.c
> +++ b/builtin/fetch.c
> @@ -758,8 +758,8 @@ static void prepare_format_display(struct ref *ref_map)
>   	else if (!strcasecmp(format, "compact"))
>   		compact_format = 1;
>   	else
> -		die(_("configuration fetch.output contains invalid value %s"),
> -		    format);
> +		die(_("invalid value for '%s': '%s'"),
> +			  "fetch.output", format);
>   
>   	for (rm = ref_map; rm; rm = rm->next) {
>   		if (rm->status == REF_STATUS_REJECT_SHALLOW ||
> diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
> index ba2006f2212..192c3ca305e 100644
> --- a/builtin/pack-objects.c
> +++ b/builtin/pack-objects.c
> @@ -3504,7 +3504,7 @@ static int option_parse_missing_action(const struct option *opt,
>   		return 0;
>   	}
>   
> -	die(_("invalid value for --missing"));
> +	die(_("invalid value for '%s': '%s'"), "--missing", arg);
>   	return 0;
>   }
>   
> diff --git a/builtin/pull.c b/builtin/pull.c
> index 100cbf9fb85..e54a0ccadc6 100644
> --- a/builtin/pull.c
> +++ b/builtin/pull.c
> @@ -42,9 +42,9 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
>   		return v;
>   
>   	if (fatal)
> -		die(_("Invalid value for %s: %s"), key, value);
> +		die(_("invalid value for '%s': '%s'"), key, value);
>   	else
> -		error(_("Invalid value for %s: %s"), key, value);
> +		error(_("invalid value for '%s': '%s'"), key, value);
>   
>   	return REBASE_INVALID;
>   }
> @@ -318,7 +318,7 @@ static const char *config_get_ff(void)
>   	if (!strcmp(value, "only"))
>   		return "--ff-only";
>   
> -	die(_("Invalid value for pull.ff: %s"), value);
> +	die(_("invalid value for '%s': '%s'"), "pull.ff", value);
>   }
>   
>   /**
> diff --git a/builtin/push.c b/builtin/push.c
> index 359db90321c..cad997965a7 100644
> --- a/builtin/push.c
> +++ b/builtin/push.c
> @@ -486,7 +486,7 @@ static int git_push_config(const char *k, const char *v, void *cb)
>   				if (value && !strcasecmp(value, "if-asked"))
>   					set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_IF_ASKED);
>   				else
> -					return error("Invalid value for '%s'", k);
> +					return error(_("invalid value for '%s'"), k);
>   			}
>   		}
>   	} else if (!strcmp(k, "push.recursesubmodules")) {
> diff --git a/builtin/send-pack.c b/builtin/send-pack.c
> index 69c432ef1a6..64962be0168 100644
> --- a/builtin/send-pack.c
> +++ b/builtin/send-pack.c
> @@ -145,7 +145,7 @@ static int send_pack_config(const char *k, const char *v, void *cb)
>   				if (value && !strcasecmp(value, "if-asked"))
>   					args.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
>   				else
> -					return error("Invalid value for '%s'", k);
> +					return error(_("invalid value for '%s'"), k);
>   			}
>   		}
>   	}
> diff --git a/diff-merges.c b/diff-merges.c
> index 5060ccd890b..cd6c102a0d5 100644
> --- a/diff-merges.c
> +++ b/diff-merges.c
> @@ -67,7 +67,7 @@ static void set_diff_merges(struct rev_info *revs, const char *optarg)
>   	diff_merges_setup_func_t func = func_by_opt(optarg);
>   
>   	if (!func)
> -		die(_("unknown value for --diff-merges: %s"), optarg);
> +		die(_("invalid value for '%s': '%s'"), "--diff-merges", optarg);
>   
>   	func(revs);
>   
> diff --git a/gpg-interface.c b/gpg-interface.c
> index b52eb0e2e04..04d751a16a8 100644
> --- a/gpg-interface.c
> +++ b/gpg-interface.c
> @@ -702,7 +702,7 @@ int git_gpg_config(const char *var, const char *value, void *cb)
>   			return config_error_nonbool(var);
>   		fmt = get_format_by_name(value);
>   		if (!fmt)
> -			return error("unsupported value for %s: %s",
> +			return error("invalid value for '%s': '%s'",
>   				     var, value);
>   		use_format = fmt;
>   		return 0;
> @@ -717,7 +717,7 @@ int git_gpg_config(const char *var, const char *value, void *cb)
>   		free(trust);
>   
>   		if (ret)
> -			return error("unsupported value for %s: %s", var,
> +			return error("invalid value for '%s': '%s'", var,
>   				     value);
>   		return 0;
>   	}
> diff --git a/ls-refs.c b/ls-refs.c
> index 54078323dcb..ae09dd59478 100644
> --- a/ls-refs.c
> +++ b/ls-refs.c
> @@ -34,7 +34,7 @@ static void ensure_config_read(void)
>   		} else if (!strcmp(str, "ignore")) {
>   			/* do nothing */
>   		} else {
> -			die(_("invalid value '%s' for lsrefs.unborn"), str);
> +			die(_("invalid value for '%s': '%s'"), "lsrefs.unborn", str);
>   		}
>   	}
>   	config_read = 1;
> diff --git a/parallel-checkout.c b/parallel-checkout.c
> index 8dd7e7bad40..237c02f1d81 100644
> --- a/parallel-checkout.c
> +++ b/parallel-checkout.c
> @@ -39,7 +39,8 @@ void get_parallel_checkout_configs(int *num_workers, int *threshold)
>   
>   	if (env_workers && *env_workers) {
>   		if (strtol_i(env_workers, 10, num_workers)) {
> -			die("invalid value for GIT_TEST_CHECKOUT_WORKERS: '%s'",
> +			die(_("invalid value for '%s': '%s'"),
> +				"GIT_TEST_CHECKOUT_WORKERS",
>   			    env_workers);
>   		}
>   		if (*num_workers < 1)
> diff --git a/sequencer.c b/sequencer.c
> index 6abd72160cc..9b985e8648d 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -2806,7 +2806,7 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
>   		return error(_("invalid key: %s"), key);
>   
>   	if (!error_flag)
> -		return error(_("invalid value for %s: %s"), key, value);
> +		return error(_("invalid value for '%s': '%s'"), key, value);
>   
>   	return 0;
>   }
> diff --git a/setup.c b/setup.c
> index af3b8c09abe..fe74092a022 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -559,7 +559,7 @@ static enum extension_result handle_extension(const char *var,
>   			return config_error_nonbool(var);
>   		format = hash_algo_by_name(value);
>   		if (format == GIT_HASH_UNKNOWN)
> -			return error("invalid value for 'extensions.objectformat'");
> +			return error(_("invalid value for '%s': '%s'"), "extensions.objectformat", value);
>   		data->hash_algo = format;
>   		return EXTENSION_OK;
>   	}
> diff --git a/submodule-config.c b/submodule-config.c
> index f95344028b5..fb95a026f48 100644
> --- a/submodule-config.c
> +++ b/submodule-config.c
> @@ -496,7 +496,7 @@ static int parse_config(const char *var, const char *value, void *data)
>   		else if (parse_submodule_update_strategy(value,
>   			 &submodule->update_strategy) < 0 ||
>   			 submodule->update_strategy.type == SM_UPDATE_COMMAND)
> -			die(_("invalid value for %s"), var);
> +			die(_("invalid value for '%s'"), var);
>   	} else if (!strcmp(item.buf, "shallow")) {
>   		if (!me->overwrite && submodule->recommend_shallow != -1)
>   			warn_multiple_config(me->treeish_name, submodule->name,
> diff --git a/t/t4150-am.sh b/t/t4150-am.sh
> index 6caff0ca397..159fae8d016 100755
> --- a/t/t4150-am.sh
> +++ b/t/t4150-am.sh
> @@ -1169,7 +1169,7 @@ test_expect_success 'invalid when passing the --empty option alone' '
>   	test_when_finished "git am --abort || :" &&
>   	git checkout empty-commit^ &&
>   	test_must_fail git am --empty empty-commit.patch 2>err &&
> -	echo "error: Invalid value for --empty: empty-commit.patch" >expected &&
> +	echo "error: invalid value for '\''--empty'\'': '\''empty-commit.patch'\''" >expected &&
>   	test_cmp expected err
>   '
>   


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-24 11:06     ` Phillip Wood
@ 2022-01-25 20:52       ` Jean-Noël AVILA
  2022-01-25 21:26         ` Johannes Sixt
  0 siblings, 1 reply; 41+ messages in thread
From: Jean-Noël AVILA @ 2022-01-25 20:52 UTC (permalink / raw)
  To: Johannes Sixt, phillip.wood; +Cc: git, Jean-Noël Avila via GitGitGadget

Le lundi 24 janvier 2022, 12:06:19 CET Phillip Wood a écrit :
> On 24/01/2022 07:14, Johannes Sixt wrote:
> > Am 22.01.22 um 19:35 schrieb Jean-Noël Avila via GitGitGadget:
> >> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
> >>
> >> When more than two options are mutually exclusive, print the ones
> >> which are actually on the command line.
> > 
> > Reading this, I expect that all mutually exclusive options are listed in
> > the error messages. But the updated code lists only the first and second
> > option even if more are on the command line. What is the justification
> > for that? Just "make the work for translators easier"? I am not 100%
> > sure that this is the right balance. Wouldn't it be helpful for users to
> > get to know which set of options is incompatible, or is an error message
> > not the right place for this kind of education? Don't know...
> 
> That was my feeling as well when reading this patch, I think the loss of 
> information in the error messages is a shame.

The enhancement aims at being more precise as to which options actually 
present on 
the command line are mutually exclusive, instead of letting the user sort out 
where the clash comes from. Personal taste, but the "--foo/--bar" is poor user 
interaction: better a partial but precise message than a (hopefully) complete 
but generic one.



> >> @@ -1268,19 +1269,19 @@ static int parse_and_validate_options(int argc, 
const char *argv[],
> >>   			die(_("You are in the middle of a rebase -- 
cannot amend."));
> >>   	}
> >>   	if (fixup_message && squash_message)
> >> -		die(_("Options --squash and --fixup cannot be used 
together"));
> >> -	if (use_message)
> >> -		f++;
> >> -	if (edit_message)
> >> -		f++;
> >> -	if (fixup_message)
> >> -		f++;
> >> -	if (logfile)
> >> -		f++;
> >> +		die(_("options '%s' and '%s' cannot be used together"), 
"--squash", "--fixup");
> >> +	f_options[f] = "-C";
> >> +	f+=	!!use_message;
> >> +	f_options[f] = "-c";
> >> +	f+=!!edit_message;
> >> +	f_options[f] = "-F";
> >> +	f+=!!logfile;
> >> +	f_options[f] = "--fixup";
> >> +	f+=!!fixup_message;
> 
> This feels like an out of bounds access waiting to happen when someone 
> adds a new option but forgets to increase the size of f_options above

That's one of the advantages of C99: declaring the variables near their use 
site so that you can keep them in you brain while reading the code.

> 
> Best Wishes
> 
> Phillip
> 
> > 
> > I prefer this if-cascade over the "f += truth_value" style, because I
> > find it is easier to understand. If you write it as
> > 
> > 	if (extcmd)
> > 		f_options[f++] = "--extcmd";
> > 
> > you get each branch down to two lines. (But then others may disagree
> > with the easy-to-understand argument due to the f++ buried in the
> > expression. Unsure...)




> > 
> >>   
> >>   	if (use_gui_tool)
> >>   		setenv("GIT_MERGETOOL_GUI", "true", 1);
> >> diff --git a/builtin/grep.c b/builtin/grep.c
> >> index 9e34a820ad4..b199781cb27 100644
> >> --- a/builtin/grep.c
> >> +++ b/builtin/grep.c
> >> @@ -1168,10 +1168,10 @@ int cmd_grep(int argc, const char **argv, const 
char *prefix)
> >>   		setup_pager();
> >>   
> >>   	if (!use_index && (untracked || cached))
> >> -		die(_("--cached or --untracked cannot be used with --
no-index"));
> >> +		die(_("options '%s' and '%s' cannot be used 
together"),"--cached/--untracked", "--no-index");
> > 
> > Huh? "--cached/--untracked"? Which one was used on the command line? 
But...
> > 
> >>   
> >>   	if (untracked && cached)
> >> -		die(_("--untracked cannot be used with --cached"));
> >> +		die(_("options '%s' and '%s' cannot be used together"), 
"--untracked", "--cached");
> >>   
> >>   	if (!use_index || untracked) {
> >>   		int use_exclude = (opt_exclude < 0) ? use_index : !!
opt_exclude;
> > 
> > ... doesn't this logic imply that --cached, --untracked, and --no-index
> > are three mutually exclusive options?
> > 
> >> diff --git a/builtin/log.c b/builtin/log.c
> >> index 4b493408cc5..59b4a2fd380 100644
> >> --- a/builtin/log.c
> >> +++ b/builtin/log.c
> >> @@ -1759,6 +1759,9 @@ int cmd_format_patch(int argc, const char **argv, 
const char *prefix)
> >>   	struct strbuf rdiff_title = STRBUF_INIT;
> >>   	int creation_factor = -1;
> >>   
> >> +	int f = 0;
> >> +	char * f_options[4];
> >> +
> > 
> > Style: char *f_options[4]; don't needlessly separate these new variables
> > from the others by an empty line.
> > 
> >>   	const struct option builtin_format_patch_options[] = {
> >>   		OPT_CALLBACK_F('n', "numbered", &numbered, NULL,
> >>   			    N_("use [PATCH n/m] even with a single 
patch"),
> >> @@ -1978,8 +1981,21 @@ int cmd_format_patch(int argc, const char **argv, 
const char *prefix)
> >>   	if (rev.show_notes)
> >>   		load_display_notes(&rev.notes_opt);
> >>   
> >> -	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
> >> -		die(_("options '%s', '%s', and '%s' cannot be used 
together"), "--stdout", "--output", "--output-directory");
> >> +	if (use_stdout) {
> >> +		f_options[f] = "--stdout";
> >> +		f++;
> >> +	}
> >> +	if (rev.diffopt.close_file) {
> >> +		f_options[f] = "--output";
> >> +		f++;
> >> +	}
> >> +	if (output_directory) {
> >> +		f_options[f] = "--output-directory";
> >> +		f++;
> >> +	}
> >> +
> >> +	if (f > 1)
> >> +		die(_("options '%s'and '%s' cannot be used together"), 
f_options[0], f_options[1]);
> >>   
> >>   	if (use_stdout) {
> >>   		setup_pager();
> >> diff --git a/builtin/merge-base.c b/builtin/merge-base.c
> >> index 6719ac198dc..1447f1c493a 100644
> >> --- a/builtin/merge-base.c
> >> +++ b/builtin/merge-base.c
> >> @@ -159,12 +159,12 @@ int cmd_merge_base(int argc, const char **argv, 
const char *prefix)
> >>   		if (argc < 2)
> >>   			usage_with_options(merge_base_usage, 
options);
> >>   		if (show_all)
> >> -			die("--is-ancestor cannot be used with --
all");
> >> +			die(_("options '%s' and '%s' cannot be used 
together"),"--is-ancestor", "--all");
> >>   		return handle_is_ancestor(argc, argv);
> >>   	}
> >>   
> >>   	if (cmdmode == 'r' && show_all)
> >> -		die("--independent cannot be used with --all");
> >> +		die(_("options '%s' and '%s' cannot be used 
together"),"--independent", "--all");
> >>   
> >>   	if (cmdmode == 'o')
> >>   		return handle_octopus(argc, argv, show_all);
> >> diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-
template-squash-signoff.sh
> >> index 91964653a0b..5fcaa0b4f2a 100755
> >> --- a/t/t7500-commit-template-squash-signoff.sh
> >> +++ b/t/t7500-commit-template-squash-signoff.sh
> >> @@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with 
pathsec' '
> >>   '
> >>   
> >>   test_expect_success '--fixup=reword: -F give error message' '
> >> -	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
> >> +	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used 
together" >expect &&
> >>   	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
> >>   	test_cmp expect actual
> >>   '
> > 
> > A general comment: To me, it looks like you didn't want to change the
> > variable name 'f' in the first hunk above, and then just named the array
> > 'f_options' to go with 'f'. Perhaps `exclusive_opt` (not plural!) for
> > the array. Now, renaming 'f' to something longer makes the code a bit
> > unwieldy. Therefore, let me suggest yet another approach: factor out
> > functions check_exclusive_opts3(), check_exclusive_opts4(), to be used 
like
> > 
> > 	check_exclusive_opts3(use_stdout, "--stdout",
> > 		rev.diffopt.close_file, "--output",
> > 		output_directory, "--output-directory");
> > 
> > I am not yet proposing check_exclusive_opts2(), but others may think it
> > is an improvement, too, (if they think that such functions are an
> > improvement in the first place).
> > 
> > -- Hannes
> 

Will factorize away such exclusive options, but I'm not sure where. Should it 
be in git-compat-util.h?



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-25 20:52       ` Jean-Noël AVILA
@ 2022-01-25 21:26         ` Johannes Sixt
  0 siblings, 0 replies; 41+ messages in thread
From: Johannes Sixt @ 2022-01-25 21:26 UTC (permalink / raw)
  To: Jean-Noël AVILA
  Cc: git, Jean-Noël Avila via GitGitGadget, phillip.wood

Am 25.01.22 um 21:52 schrieb Jean-Noël AVILA:
> Le lundi 24 janvier 2022, 12:06:19 CET Phillip Wood a écrit :
>> On 24/01/2022 07:14, Johannes Sixt wrote:
>>> A general comment: To me, it looks like you didn't want to change the
>>> variable name 'f' in the first hunk above, and then just named the array
>>> 'f_options' to go with 'f'. Perhaps `exclusive_opt` (not plural!) for
>>> the array. Now, renaming 'f' to something longer makes the code a bit
>>> unwieldy. Therefore, let me suggest yet another approach: factor out
>>> functions check_exclusive_opts3(), check_exclusive_opts4(), to be used 
> like
>>>
>>> 	check_exclusive_opts3(use_stdout, "--stdout",
>>> 		rev.diffopt.close_file, "--output",
>>> 		output_directory, "--output-directory");
>>>
>>> I am not yet proposing check_exclusive_opts2(), but others may think it
>>> is an improvement, too, (if they think that such functions are an
>>> improvement in the first place).
> 
> Will factorize away such exclusive options, but I'm not sure where. Should it 
> be in git-compat-util.h?

How about parse-options.*? There are already some helper functions near
the end of parse-options.c. Perhaps the names I suggested must be
revised, though.

-- Hannes

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v2 0/4] Factorize i18n
  2022-01-22 18:35 [PATCH 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
                   ` (3 preceding siblings ...)
  2022-01-22 18:35 ` [PATCH 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
@ 2022-01-28 22:23 ` Jean-Noël Avila via GitGitGadget
  2022-01-28 22:24   ` [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
                     ` (4 more replies)
  4 siblings, 5 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-28 22:23 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila

This is a small series of i18n factorizations. Again the idea is to:

 * reduce the number of strings to translate
 * make life easier for translators by removing constant parts of the
   strings to translate
 * uniformize the UI by using a type of message for the a given type of
   condition.

Changes since V1:

 * factorize checks of more than 2 incompatible options into dedicated
   functions which list all the incompatible options present on the command
   line

Jean-Noël Avila (4):
  i18n: factorize more 'incompatible options' messages
  i18n: factorize "invalid value" messages
  i18n: remove from i18n strings that do not hold translatable parts
  i18n: transfer variables into placeholders in command synopsis

 archive.c                                 |  2 +-
 builtin/am.c                              |  7 ++--
 builtin/bisect--helper.c                  |  6 +--
 builtin/blame.c                           |  6 +--
 builtin/commit.c                          | 39 +++++++++---------
 builtin/count-objects.c                   |  2 +-
 builtin/difftool.c                        |  5 ++-
 builtin/fast-export.c                     |  2 +-
 builtin/fetch.c                           |  4 +-
 builtin/grep.c                            |  8 ++--
 builtin/hash-object.c                     |  2 +-
 builtin/help.c                            |  4 +-
 builtin/log.c                             |  5 ++-
 builtin/merge-base.c                      |  4 +-
 builtin/mktag.c                           |  2 +-
 builtin/mktree.c                          |  2 +-
 builtin/notes.c                           |  6 +--
 builtin/pack-objects.c                    |  2 +-
 builtin/prune-packed.c                    |  2 +-
 builtin/pull.c                            |  6 +--
 builtin/push.c                            |  2 +-
 builtin/rebase.c                          |  2 +-
 builtin/reflog.c                          |  6 +--
 builtin/remote.c                          |  2 +-
 builtin/replace.c                         |  2 +-
 builtin/rev-list.c                        |  2 +-
 builtin/send-pack.c                       |  2 +-
 builtin/sparse-checkout.c                 |  8 ++--
 builtin/stripspace.c                      |  4 +-
 builtin/submodule--helper.c               |  2 +-
 builtin/update-server-info.c              |  2 +-
 diff-merges.c                             |  2 +-
 gpg-interface.c                           |  4 +-
 ls-refs.c                                 |  2 +-
 parallel-checkout.c                       |  3 +-
 parse-options.c                           | 50 +++++++++++++++++++++++
 parse-options.h                           |  9 ++++
 sequencer.c                               |  2 +-
 setup.c                                   |  2 +-
 submodule-config.c                        |  2 +-
 t/t4150-am.sh                             |  2 +-
 t/t7500-commit-template-squash-signoff.sh |  2 +-
 42 files changed, 145 insertions(+), 85 deletions(-)


base-commit: 90d242d36e248acfae0033274b524bfa55a947fd
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1123%2Fjnavila%2Ffactorize_i18n-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1123/jnavila/factorize_i18n-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1123

Range-diff vs v1:

 1:  81ff928567f ! 1:  844e01391e1 i18n: factorize more 'incompatible options' messages
     @@ Metadata
       ## Commit message ##
          i18n: factorize more 'incompatible options' messages
      
     +    Find more incompatible options to factorize.
     +
          When more than two options are mutually exclusive, print the ones
          which are actually on the command line.
      
     @@ Commit message
      
       ## builtin/commit.c ##
      @@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *argv[],
     + 				      struct commit *current_head,
       				      struct wt_status *s)
       {
     - 	int f = 0;
     -+	char * f_options[4];
     - 
     +-	int f = 0;
     +-
       	argc = parse_options(argc, argv, prefix, options, usage, 0);
       	finalize_deferred_config(s);
     + 
      @@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *argv[],
       		force_author = find_author_by_nickname(force_author);
       
     @@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *ar
      -		f++;
      -	if (logfile)
      -		f++;
     -+		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
     -+	f_options[f] = "-C";
     -+	f+=	!!use_message;
     -+	f_options[f] = "-c";
     -+	f+=!!edit_message;
     -+	f_options[f] = "-F";
     -+	f+=!!logfile;
     -+	f_options[f] = "--fixup";
     -+	f+=!!fixup_message;
     - 	if (f > 1)
     +-	if (f > 1)
      -		die(_("Only one of -c/-C/-F/--fixup can be used."));
     -+		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
     - 	if (have_option_m && (edit_message || use_message || logfile))
     +-	if (have_option_m && (edit_message || use_message || logfile))
      -		die((_("Option -m cannot be combined with -c/-C/-F.")));
     -+		die(_("options '%s' and '%s' cannot be used together"), "-m", f_options[0]);
     - 	if (f || have_option_m)
     +-	if (f || have_option_m)
     ++		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
     ++	die_if_incompatible_opt4(!!use_message, "-C",
     ++							 !!edit_message, "-c",
     ++							 !!logfile, "-F",
     ++							 !!fixup_message, "--fixup");
     ++	if (have_option_m) {
     ++		if (edit_message)
     ++			die(_("options '%s' and '%s' cannot be used together"), "-m", "-c");
     ++		else if  (use_message)
     ++			die(_("options '%s' and '%s' cannot be used together"), "-m", "-C");
     ++		else if (logfile)
     ++			die(_("options '%s' and '%s' cannot be used together"), "-m", "-F");
     ++	}
     ++	if (use_message || edit_message || logfile ||fixup_message || have_option_m)
       		template_file = NULL;
       	if (edit_message)
     + 		use_message = edit_message;
      @@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *argv[],
     - 
       	if (patch_interactive)
       		interactive = 1;
     --
     + 
      -	if (also + only + all + interactive > 1)
      -		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
     -+	f = 0;
     -+	f_options[f] = "-i/--include";
     -+	f += also;
     -+	f_options[f] = "-o/--only";
     -+	f += only;
     -+	f_options[f] = "-a/--all";
     -+	f += all;
     -+	f_options[f] = "--interactive/-p/--patch";
     -+	f += interactive;
     -+	if (f > 1)
     -+		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
     - 
     +-
     ++	die_if_incompatible_opt4(also, "-i/--include",
     ++							 only, "-o/--only",
     ++							 all, "-a/--all",
     ++							 interactive, "--interactive/-p/--patch");
       	if (fixup_message) {
       		/*
     + 		 * We limit --fixup's suboptions to only alpha characters.
      
       ## builtin/difftool.c ##
     -@@ builtin/difftool.c: int cmd_difftool(int argc, const char **argv, const char *prefix)
     - 	int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
     - 	    tool_help = 0, no_index = 0;
     - 	static char *difftool_cmd = NULL, *extcmd = NULL;
     -+	int f = 0;
     -+	char *f_options[3];
     - 	struct option builtin_difftool_options[] = {
     - 		OPT_BOOL('g', "gui", &use_gui_tool,
     - 			 N_("use `diff.guitool` instead of `diff.tool`")),
      @@ builtin/difftool.c: int cmd_difftool(int argc, const char **argv, const char *prefix)
       	} else if (dir_diff)
       		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
       
      -	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
      -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
     -+	if (use_gui_tool) {
     -+		f_options[f] = "--gui";
     -+		f++;
     -+	}
     -+	if (difftool_cmd) {
     -+		f_options[f] = "--tool";
     -+		f++;
     -+	}
     -+	if (extcmd) {
     -+		f_options[f] = "--extcmd";
     -+		f++;
     -+	}
     -+	if (f > 1)
     -+		die(_("options '%s' and '%s' cannot be used together"), f_options[0], f_options[1]);
     ++	die_if_incompatible_opt3(use_gui_tool, "--gui",
     ++							 !!difftool_cmd, "--tool",
     ++							 !!extcmd, "--extcmd");
       
       	if (use_gui_tool)
       		setenv("GIT_MERGETOOL_GUI", "true", 1);
      
       ## builtin/grep.c ##
      @@ builtin/grep.c: int cmd_grep(int argc, const char **argv, const char *prefix)
     + 	if (!show_in_pager && !opt.status_only)
       		setup_pager();
       
     - 	if (!use_index && (untracked || cached))
     +-	if (!use_index && (untracked || cached))
      -		die(_("--cached or --untracked cannot be used with --no-index"));
     -+		die(_("options '%s' and '%s' cannot be used together"),"--cached/--untracked", "--no-index");
     - 
     - 	if (untracked && cached)
     +-
     +-	if (untracked && cached)
      -		die(_("--untracked cannot be used with --cached"));
     -+		die(_("options '%s' and '%s' cannot be used together"), "--untracked", "--cached");
     ++	die_if_incompatible_opt3(!use_index, "--no-index",
     ++							 untracked, "--untracked",
     ++							 cached, "--cached");
       
       	if (!use_index || untracked) {
       		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
      
       ## builtin/log.c ##
     -@@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *prefix)
     - 	struct strbuf rdiff_title = STRBUF_INIT;
     - 	int creation_factor = -1;
     - 
     -+	int f = 0;
     -+	char * f_options[4];
     -+
     - 	const struct option builtin_format_patch_options[] = {
     - 		OPT_CALLBACK_F('n', "numbered", &numbered, NULL,
     - 			    N_("use [PATCH n/m] even with a single patch"),
      @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *prefix)
       	if (rev.show_notes)
       		load_display_notes(&rev.notes_opt);
       
      -	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
      -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
     -+	if (use_stdout) {
     -+		f_options[f] = "--stdout";
     -+		f++;
     -+	}
     -+	if (rev.diffopt.close_file) {
     -+		f_options[f] = "--output";
     -+		f++;
     -+	}
     -+	if (output_directory) {
     -+		f_options[f] = "--output-directory";
     -+		f++;
     -+	}
     -+
     -+	if (f > 1)
     -+		die(_("options '%s'and '%s' cannot be used together"), f_options[0], f_options[1]);
     ++	die_if_incompatible_opt3(use_stdout, "--stdout",
     ++							 rev.diffopt.close_file, "--output",
     ++							 !!output_directory, "--output-directory");
       
       	if (use_stdout) {
       		setup_pager();
     @@ builtin/merge-base.c: int cmd_merge_base(int argc, const char **argv, const char
       	if (cmdmode == 'o')
       		return handle_octopus(argc, argv, show_all);
      
     + ## parse-options.c ##
     +@@ parse-options.c: void NORETURN usage_msg_opt(const char *msg,
     + 	die_message("%s\n", msg); /* The extra \n is intentional */
     + 	usage_with_options(usagestr, options);
     + }
     ++
     ++void die_if_incompatible_opt3(int opt1, const char *opt1_name,
     ++							  int opt2, const char *opt2_name,
     ++							  int opt3, const char *opt3_name)
     ++{
     ++	int count = 0;
     ++	const char *options[3];
     ++
     ++	if (opt1)
     ++		options[count++] = opt1_name;
     ++	if (opt2)
     ++		options[count++] = opt2_name;
     ++	if (opt3)
     ++		options[count++] = opt3_name;
     ++	if (count > 2)
     ++		die(_("options '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name);
     ++	else if (count > 1)
     ++		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
     ++}
     ++
     ++void die_if_incompatible_opt4(int opt1, const char *opt1_name,
     ++							  int opt2, const char *opt2_name,
     ++							  int opt3, const char *opt3_name,
     ++							  int opt4, const char *opt4_name)
     ++{
     ++	int count = 0;
     ++	const char *options[4];
     ++
     ++	if (opt1)
     ++		options[count++] = opt1_name;
     ++	if (opt2)
     ++		options[count++] = opt2_name;
     ++	if (opt3)
     ++		options[count++] = opt3_name;
     ++	if (opt4)
     ++		options[count++] = opt4_name;
     ++	switch (count) {
     ++	case 4:
     ++		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name, opt4_name);
     ++		break;
     ++	case 3:
     ++		die(_("options '%s', '%s', and '%s' cannot be used together"), options[0], options[1], options[2]);
     ++		break;
     ++	case 2:
     ++		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
     ++		break;
     ++	default:
     ++		break;
     ++	}
     ++}
     +
     + ## parse-options.h ##
     +@@ parse-options.h: int parse_opt_tracking_mode(const struct option *, const char *, int);
     + #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
     + #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
     + 
     ++void die_if_incompatible_opt3(int opt1, const char *opt1_name,
     ++							  int opt2, const char *opt2_name,
     ++							  int opt3, const char *opt3_name);
     ++
     ++void die_if_incompatible_opt4(int opt1, const char *opt1_name,
     ++							  int opt2, const char *opt2_name,
     ++							  int opt3, const char *opt3_name,
     ++							  int opt4, const char *opt4_name);
     ++
     + #endif
     +
       ## t/t7500-commit-template-squash-signoff.sh ##
      @@ t/t7500-commit-template-squash-signoff.sh: test_expect_success '--fixup=reword: give error with pathsec' '
       '
 2:  ca48e82a6b4 = 2:  4c860698d69 i18n: factorize "invalid value" messages
 3:  ead191faad9 = 3:  376f8b56908 i18n: remove from i18n strings that do not hold translatable parts
 4:  643be0d82de = 4:  8b0057f6180 i18n: transfer variables into placeholders in command synopsis

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-28 22:23 ` [PATCH v2 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
@ 2022-01-28 22:24   ` Jean-Noël Avila via GitGitGadget
  2022-01-28 23:21     ` Johannes Sixt
  2022-02-01 21:01     ` Ævar Arnfjörð Bjarmason
  2022-01-28 22:24   ` [PATCH v2 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
                     ` (3 subsequent siblings)
  4 siblings, 2 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-28 22:24 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Find more incompatible options to factorize.

When more than two options are mutually exclusive, print the ones
which are actually on the command line.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/commit.c                          | 39 +++++++++---------
 builtin/difftool.c                        |  5 ++-
 builtin/grep.c                            |  8 ++--
 builtin/log.c                             |  5 ++-
 builtin/merge-base.c                      |  4 +-
 parse-options.c                           | 50 +++++++++++++++++++++++
 parse-options.h                           |  9 ++++
 t/t7500-commit-template-squash-signoff.sh |  2 +-
 8 files changed, 90 insertions(+), 32 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index b9ed0374e30..1966f965008 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1242,8 +1242,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
 				      struct commit *current_head,
 				      struct wt_status *s)
 {
-	int f = 0;
-
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
 	finalize_deferred_config(s);
 
@@ -1251,7 +1249,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
 		force_author = find_author_by_nickname(force_author);
 
 	if (force_author && renew_authorship)
-		die(_("Using both --reset-author and --author does not make sense"));
+		die(_("options '%s' and '%s' cannot be used together"), "--reset-author", "--author");
 
 	if (logfile || have_option_m || use_message)
 		use_editor = 0;
@@ -1268,20 +1266,20 @@ static int parse_and_validate_options(int argc, const char *argv[],
 			die(_("You are in the middle of a rebase -- cannot amend."));
 	}
 	if (fixup_message && squash_message)
-		die(_("Options --squash and --fixup cannot be used together"));
-	if (use_message)
-		f++;
-	if (edit_message)
-		f++;
-	if (fixup_message)
-		f++;
-	if (logfile)
-		f++;
-	if (f > 1)
-		die(_("Only one of -c/-C/-F/--fixup can be used."));
-	if (have_option_m && (edit_message || use_message || logfile))
-		die((_("Option -m cannot be combined with -c/-C/-F.")));
-	if (f || have_option_m)
+		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
+	die_if_incompatible_opt4(!!use_message, "-C",
+							 !!edit_message, "-c",
+							 !!logfile, "-F",
+							 !!fixup_message, "--fixup");
+	if (have_option_m) {
+		if (edit_message)
+			die(_("options '%s' and '%s' cannot be used together"), "-m", "-c");
+		else if  (use_message)
+			die(_("options '%s' and '%s' cannot be used together"), "-m", "-C");
+		else if (logfile)
+			die(_("options '%s' and '%s' cannot be used together"), "-m", "-F");
+	}
+	if (use_message || edit_message || logfile ||fixup_message || have_option_m)
 		template_file = NULL;
 	if (edit_message)
 		use_message = edit_message;
@@ -1306,9 +1304,10 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (patch_interactive)
 		interactive = 1;
 
-	if (also + only + all + interactive > 1)
-		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
-
+	die_if_incompatible_opt4(also, "-i/--include",
+							 only, "-o/--only",
+							 all, "-a/--all",
+							 interactive, "--interactive/-p/--patch");
 	if (fixup_message) {
 		/*
 		 * We limit --fixup's suboptions to only alpha characters.
diff --git a/builtin/difftool.c b/builtin/difftool.c
index c79fbbf67e5..ae487785735 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -732,8 +732,9 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 	} else if (dir_diff)
 		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
 
-	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
+	die_if_incompatible_opt3(use_gui_tool, "--gui",
+							 !!difftool_cmd, "--tool",
+							 !!extcmd, "--extcmd");
 
 	if (use_gui_tool)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
diff --git a/builtin/grep.c b/builtin/grep.c
index 9e34a820ad4..cdf52667710 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1167,11 +1167,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	if (!show_in_pager && !opt.status_only)
 		setup_pager();
 
-	if (!use_index && (untracked || cached))
-		die(_("--cached or --untracked cannot be used with --no-index"));
-
-	if (untracked && cached)
-		die(_("--untracked cannot be used with --cached"));
+	die_if_incompatible_opt3(!use_index, "--no-index",
+							 untracked, "--untracked",
+							 cached, "--cached");
 
 	if (!use_index || untracked) {
 		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
diff --git a/builtin/log.c b/builtin/log.c
index 4b493408cc5..048b2c37470 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1978,8 +1978,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	if (rev.show_notes)
 		load_display_notes(&rev.notes_opt);
 
-	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
+	die_if_incompatible_opt3(use_stdout, "--stdout",
+							 rev.diffopt.close_file, "--output",
+							 !!output_directory, "--output-directory");
 
 	if (use_stdout) {
 		setup_pager();
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 6719ac198dc..1447f1c493a 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -159,12 +159,12 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
 		if (argc < 2)
 			usage_with_options(merge_base_usage, options);
 		if (show_all)
-			die("--is-ancestor cannot be used with --all");
+			die(_("options '%s' and '%s' cannot be used together"),"--is-ancestor", "--all");
 		return handle_is_ancestor(argc, argv);
 	}
 
 	if (cmdmode == 'r' && show_all)
-		die("--independent cannot be used with --all");
+		die(_("options '%s' and '%s' cannot be used together"),"--independent", "--all");
 
 	if (cmdmode == 'o')
 		return handle_octopus(argc, argv, show_all);
diff --git a/parse-options.c b/parse-options.c
index a8283037be9..fb9e1976ab3 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -1079,3 +1079,53 @@ void NORETURN usage_msg_opt(const char *msg,
 	die_message("%s\n", msg); /* The extra \n is intentional */
 	usage_with_options(usagestr, options);
 }
+
+void die_if_incompatible_opt3(int opt1, const char *opt1_name,
+							  int opt2, const char *opt2_name,
+							  int opt3, const char *opt3_name)
+{
+	int count = 0;
+	const char *options[3];
+
+	if (opt1)
+		options[count++] = opt1_name;
+	if (opt2)
+		options[count++] = opt2_name;
+	if (opt3)
+		options[count++] = opt3_name;
+	if (count > 2)
+		die(_("options '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name);
+	else if (count > 1)
+		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
+}
+
+void die_if_incompatible_opt4(int opt1, const char *opt1_name,
+							  int opt2, const char *opt2_name,
+							  int opt3, const char *opt3_name,
+							  int opt4, const char *opt4_name)
+{
+	int count = 0;
+	const char *options[4];
+
+	if (opt1)
+		options[count++] = opt1_name;
+	if (opt2)
+		options[count++] = opt2_name;
+	if (opt3)
+		options[count++] = opt3_name;
+	if (opt4)
+		options[count++] = opt4_name;
+	switch (count) {
+	case 4:
+		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name, opt4_name);
+		break;
+	case 3:
+		die(_("options '%s', '%s', and '%s' cannot be used together"), options[0], options[1], options[2]);
+		break;
+	case 2:
+		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/parse-options.h b/parse-options.h
index e22846d3b7b..cf393839ac4 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -339,4 +339,13 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);
 #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
 #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
 
+void die_if_incompatible_opt3(int opt1, const char *opt1_name,
+							  int opt2, const char *opt2_name,
+							  int opt3, const char *opt3_name);
+
+void die_if_incompatible_opt4(int opt1, const char *opt1_name,
+							  int opt2, const char *opt2_name,
+							  int opt3, const char *opt3_name,
+							  int opt4, const char *opt4_name);
+
 #endif
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 91964653a0b..5fcaa0b4f2a 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
 '
 
 test_expect_success '--fixup=reword: -F give error message' '
-	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
+	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
 	test_cmp expect actual
 '
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v2 2/4] i18n: factorize "invalid value" messages
  2022-01-28 22:23 ` [PATCH v2 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  2022-01-28 22:24   ` [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
@ 2022-01-28 22:24   ` Jean-Noël Avila via GitGitGadget
  2022-01-28 22:24   ` [PATCH v2 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-28 22:24 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Use the same message when an invalid value is passed to a command line
option or a configuration variable.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/am.c           | 7 ++++---
 builtin/blame.c        | 6 +++---
 builtin/fetch.c        | 4 ++--
 builtin/pack-objects.c | 2 +-
 builtin/pull.c         | 6 +++---
 builtin/push.c         | 2 +-
 builtin/send-pack.c    | 2 +-
 diff-merges.c          | 2 +-
 gpg-interface.c        | 4 ++--
 ls-refs.c              | 2 +-
 parallel-checkout.c    | 3 ++-
 sequencer.c            | 2 +-
 setup.c                | 2 +-
 submodule-config.c     | 2 +-
 t/t4150-am.sh          | 2 +-
 15 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index b6be1f1cb11..ba1dacbc034 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -199,7 +199,7 @@ static int am_option_parse_empty(const struct option *opt,
 	else if (!strcmp(arg, "keep"))
 		*opt_value = KEEP_EMPTY_COMMIT;
 	else
-		return error(_("Invalid value for --empty: %s"), arg);
+		return error(_("invalid value for '%s': '%s'"), "--empty", arg);
 
 	return 0;
 }
@@ -2239,7 +2239,7 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
 	 * when you add new options
 	 */
 	else
-		return error(_("Invalid value for --patch-format: %s"), arg);
+		return error(_("invalid value for '%s': '%s'"), "--patch-format", arg);
 	return 0;
 }
 
@@ -2282,7 +2282,8 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 				break;
 		}
 		if (new_value >= ARRAY_SIZE(valid_modes))
-			return error(_("Invalid value for --show-current-patch: %s"), arg);
+			return error(_("invalid value for '%s': '%s'"),
+						 "--show-current-patch", arg);
 	}
 
 	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
diff --git a/builtin/blame.c b/builtin/blame.c
index 7fafeac4081..ca821420d68 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -721,8 +721,8 @@ static int git_blame_config(const char *var, const char *value, void *cb)
 	}
 	if (!strcmp(var, "color.blame.repeatedlines")) {
 		if (color_parse_mem(value, strlen(value), repeated_meta_color))
-			warning(_("invalid color '%s' in color.blame.repeatedLines"),
-				value);
+			warning(_("invalid value for '%s': '%s'"),
+					"color.blame.repeatedLines", value);
 		return 0;
 	}
 	if (!strcmp(var, "color.blame.highlightrecent")) {
@@ -739,7 +739,7 @@ static int git_blame_config(const char *var, const char *value, void *cb)
 			coloring_mode &= ~(OUTPUT_COLOR_LINE |
 					    OUTPUT_SHOW_AGE_WITH_COLOR);
 		} else {
-			warning(_("invalid value for blame.coloring"));
+			warning(_("invalid value for '%s': '%s'"), "blame.coloring", value);
 			return 0;
 		}
 	}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index eaab8056bf9..19ec48f3330 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -758,8 +758,8 @@ static void prepare_format_display(struct ref *ref_map)
 	else if (!strcasecmp(format, "compact"))
 		compact_format = 1;
 	else
-		die(_("configuration fetch.output contains invalid value %s"),
-		    format);
+		die(_("invalid value for '%s': '%s'"),
+			  "fetch.output", format);
 
 	for (rm = ref_map; rm; rm = rm->next) {
 		if (rm->status == REF_STATUS_REJECT_SHALLOW ||
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index ba2006f2212..192c3ca305e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3504,7 +3504,7 @@ static int option_parse_missing_action(const struct option *opt,
 		return 0;
 	}
 
-	die(_("invalid value for --missing"));
+	die(_("invalid value for '%s': '%s'"), "--missing", arg);
 	return 0;
 }
 
diff --git a/builtin/pull.c b/builtin/pull.c
index 100cbf9fb85..e54a0ccadc6 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -42,9 +42,9 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
 		return v;
 
 	if (fatal)
-		die(_("Invalid value for %s: %s"), key, value);
+		die(_("invalid value for '%s': '%s'"), key, value);
 	else
-		error(_("Invalid value for %s: %s"), key, value);
+		error(_("invalid value for '%s': '%s'"), key, value);
 
 	return REBASE_INVALID;
 }
@@ -318,7 +318,7 @@ static const char *config_get_ff(void)
 	if (!strcmp(value, "only"))
 		return "--ff-only";
 
-	die(_("Invalid value for pull.ff: %s"), value);
+	die(_("invalid value for '%s': '%s'"), "pull.ff", value);
 }
 
 /**
diff --git a/builtin/push.c b/builtin/push.c
index 359db90321c..cad997965a7 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -486,7 +486,7 @@ static int git_push_config(const char *k, const char *v, void *cb)
 				if (value && !strcasecmp(value, "if-asked"))
 					set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_IF_ASKED);
 				else
-					return error("Invalid value for '%s'", k);
+					return error(_("invalid value for '%s'"), k);
 			}
 		}
 	} else if (!strcmp(k, "push.recursesubmodules")) {
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 69c432ef1a6..64962be0168 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -145,7 +145,7 @@ static int send_pack_config(const char *k, const char *v, void *cb)
 				if (value && !strcasecmp(value, "if-asked"))
 					args.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
 				else
-					return error("Invalid value for '%s'", k);
+					return error(_("invalid value for '%s'"), k);
 			}
 		}
 	}
diff --git a/diff-merges.c b/diff-merges.c
index 5060ccd890b..cd6c102a0d5 100644
--- a/diff-merges.c
+++ b/diff-merges.c
@@ -67,7 +67,7 @@ static void set_diff_merges(struct rev_info *revs, const char *optarg)
 	diff_merges_setup_func_t func = func_by_opt(optarg);
 
 	if (!func)
-		die(_("unknown value for --diff-merges: %s"), optarg);
+		die(_("invalid value for '%s': '%s'"), "--diff-merges", optarg);
 
 	func(revs);
 
diff --git a/gpg-interface.c b/gpg-interface.c
index b52eb0e2e04..04d751a16a8 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -702,7 +702,7 @@ int git_gpg_config(const char *var, const char *value, void *cb)
 			return config_error_nonbool(var);
 		fmt = get_format_by_name(value);
 		if (!fmt)
-			return error("unsupported value for %s: %s",
+			return error("invalid value for '%s': '%s'",
 				     var, value);
 		use_format = fmt;
 		return 0;
@@ -717,7 +717,7 @@ int git_gpg_config(const char *var, const char *value, void *cb)
 		free(trust);
 
 		if (ret)
-			return error("unsupported value for %s: %s", var,
+			return error("invalid value for '%s': '%s'", var,
 				     value);
 		return 0;
 	}
diff --git a/ls-refs.c b/ls-refs.c
index 54078323dcb..ae09dd59478 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -34,7 +34,7 @@ static void ensure_config_read(void)
 		} else if (!strcmp(str, "ignore")) {
 			/* do nothing */
 		} else {
-			die(_("invalid value '%s' for lsrefs.unborn"), str);
+			die(_("invalid value for '%s': '%s'"), "lsrefs.unborn", str);
 		}
 	}
 	config_read = 1;
diff --git a/parallel-checkout.c b/parallel-checkout.c
index 8dd7e7bad40..237c02f1d81 100644
--- a/parallel-checkout.c
+++ b/parallel-checkout.c
@@ -39,7 +39,8 @@ void get_parallel_checkout_configs(int *num_workers, int *threshold)
 
 	if (env_workers && *env_workers) {
 		if (strtol_i(env_workers, 10, num_workers)) {
-			die("invalid value for GIT_TEST_CHECKOUT_WORKERS: '%s'",
+			die(_("invalid value for '%s': '%s'"),
+				"GIT_TEST_CHECKOUT_WORKERS",
 			    env_workers);
 		}
 		if (*num_workers < 1)
diff --git a/sequencer.c b/sequencer.c
index 6abd72160cc..9b985e8648d 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2806,7 +2806,7 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
 		return error(_("invalid key: %s"), key);
 
 	if (!error_flag)
-		return error(_("invalid value for %s: %s"), key, value);
+		return error(_("invalid value for '%s': '%s'"), key, value);
 
 	return 0;
 }
diff --git a/setup.c b/setup.c
index af3b8c09abe..fe74092a022 100644
--- a/setup.c
+++ b/setup.c
@@ -559,7 +559,7 @@ static enum extension_result handle_extension(const char *var,
 			return config_error_nonbool(var);
 		format = hash_algo_by_name(value);
 		if (format == GIT_HASH_UNKNOWN)
-			return error("invalid value for 'extensions.objectformat'");
+			return error(_("invalid value for '%s': '%s'"), "extensions.objectformat", value);
 		data->hash_algo = format;
 		return EXTENSION_OK;
 	}
diff --git a/submodule-config.c b/submodule-config.c
index f95344028b5..fb95a026f48 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -496,7 +496,7 @@ static int parse_config(const char *var, const char *value, void *data)
 		else if (parse_submodule_update_strategy(value,
 			 &submodule->update_strategy) < 0 ||
 			 submodule->update_strategy.type == SM_UPDATE_COMMAND)
-			die(_("invalid value for %s"), var);
+			die(_("invalid value for '%s'"), var);
 	} else if (!strcmp(item.buf, "shallow")) {
 		if (!me->overwrite && submodule->recommend_shallow != -1)
 			warn_multiple_config(me->treeish_name, submodule->name,
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 6caff0ca397..159fae8d016 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -1169,7 +1169,7 @@ test_expect_success 'invalid when passing the --empty option alone' '
 	test_when_finished "git am --abort || :" &&
 	git checkout empty-commit^ &&
 	test_must_fail git am --empty empty-commit.patch 2>err &&
-	echo "error: Invalid value for --empty: empty-commit.patch" >expected &&
+	echo "error: invalid value for '\''--empty'\'': '\''empty-commit.patch'\''" >expected &&
 	test_cmp expected err
 '
 
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v2 3/4] i18n: remove from i18n strings that do not hold translatable parts
  2022-01-28 22:23 ` [PATCH v2 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  2022-01-28 22:24   ` [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
  2022-01-28 22:24   ` [PATCH v2 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
@ 2022-01-28 22:24   ` Jean-Noël Avila via GitGitGadget
  2022-01-28 22:24   ` [PATCH v2 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
  2022-01-30 22:01   ` [PATCH v3 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  4 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-28 22:24 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 archive.c                    | 2 +-
 builtin/bisect--helper.c     | 6 +++---
 builtin/count-objects.c      | 2 +-
 builtin/hash-object.c        | 2 +-
 builtin/help.c               | 4 ++--
 builtin/mktag.c              | 2 +-
 builtin/mktree.c             | 2 +-
 builtin/notes.c              | 6 +++---
 builtin/prune-packed.c       | 2 +-
 builtin/rebase.c             | 2 +-
 builtin/reflog.c             | 2 +-
 builtin/remote.c             | 2 +-
 builtin/replace.c            | 2 +-
 builtin/sparse-checkout.c    | 8 ++++----
 builtin/stripspace.c         | 4 ++--
 builtin/submodule--helper.c  | 2 +-
 builtin/update-server-info.c | 2 +-
 17 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/archive.c b/archive.c
index d571249cf39..e29d0e00f6c 100644
--- a/archive.c
+++ b/archive.c
@@ -12,7 +12,7 @@
 
 static char const * const archive_usage[] = {
 	N_("git archive [<options>] <tree-ish> [<path>...]"),
-	N_("git archive --list"),
+	"git archive --list",
 	N_("git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"),
 	N_("git archive --remote <repo> [--exec <cmd>] --list"),
 	NULL
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 28a2e6a5750..f962dbd4303 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -22,15 +22,15 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
 
 static const char * const git_bisect_helper_usage[] = {
 	N_("git bisect--helper --bisect-reset [<commit>]"),
-	N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
+	"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]",
 	N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
 					    " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
-	N_("git bisect--helper --bisect-next"),
+	"git bisect--helper --bisect-next",
 	N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
 	N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
 	N_("git bisect--helper --bisect-replay <filename>"),
 	N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
-	N_("git bisect--helper --bisect-visualize"),
+	"git bisect--helper --bisect-visualize",
 	N_("git bisect--helper --bisect-run <cmd>..."),
 	NULL
 };
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 3fae474f6f1..07b94195962 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -87,7 +87,7 @@ static int print_alternate(struct object_directory *odb, void *data)
 }
 
 static char const * const count_objects_usage[] = {
-	N_("git count-objects [-v] [-H | --human-readable]"),
+	"git count-objects [-v] [-H | --human-readable]",
 	NULL
 };
 
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index c7b3ad74c60..04e2442ec7c 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -81,7 +81,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
 {
 	static const char * const hash_object_usage[] = {
 		N_("git hash-object [-t <type>] [-w] [--path=<file> | --no-filters] [--stdin] [--] <file>..."),
-		N_("git hash-object  --stdin-paths"),
+		"git hash-object  --stdin-paths",
 		NULL
 	};
 	const char *type = blob_type;
diff --git a/builtin/help.c b/builtin/help.c
index d387131dd83..b4f2ad3f94e 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -77,8 +77,8 @@ static struct option builtin_help_options[] = {
 static const char * const builtin_help_usage[] = {
 	N_("git help [-a|--all] [--[no-]verbose]]\n"
 	   "         [[-i|--info] [-m|--man] [-w|--web]] [<command>]"),
-	N_("git help [-g|--guides]"),
-	N_("git help [-c|--config]"),
+	"git help [-g|--guides]",
+	"git help [-c|--config]",
 	NULL
 };
 
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 3b2dbbb37e6..c7b905c614b 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 static char const * const builtin_mktag_usage[] = {
-	N_("git mktag"),
+	"git mktag",
 	NULL
 };
 static int option_strict = 1;
diff --git a/builtin/mktree.c b/builtin/mktree.c
index ae78ca1c029..8bdaada922a 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -63,7 +63,7 @@ static void write_tree(struct object_id *oid)
 }
 
 static const char *mktree_usage[] = {
-	N_("git mktree [-z] [--missing] [--batch]"),
+	"git mktree [-z] [--missing] [--batch]",
 	NULL
 };
 
diff --git a/builtin/notes.c b/builtin/notes.c
index 05d60483e82..f99593a1853 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -32,8 +32,8 @@ static const char * const git_notes_usage[] = {
 	N_("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"),
 	N_("git notes [--ref <notes-ref>] show [<object>]"),
 	N_("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"),
-	N_("git notes merge --commit [-v | -q]"),
-	N_("git notes merge --abort [-v | -q]"),
+	"git notes merge --commit [-v | -q]",
+	"git notes merge --abort [-v | -q]",
 	N_("git notes [--ref <notes-ref>] remove [<object>...]"),
 	N_("git notes [--ref <notes-ref>] prune [-n] [-v]"),
 	N_("git notes [--ref <notes-ref>] get-ref"),
@@ -89,7 +89,7 @@ static const char * const git_notes_prune_usage[] = {
 };
 
 static const char * const git_notes_get_ref_usage[] = {
-	N_("git notes get-ref"),
+	"git notes get-ref",
 	NULL
 };
 
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index b7b9281a8ce..da3273a268b 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -3,7 +3,7 @@
 #include "prune-packed.h"
 
 static const char * const prune_packed_usage[] = {
-	N_("git prune-packed [-n | --dry-run] [-q | --quiet]"),
+	"git prune-packed [-n | --dry-run] [-q | --quiet]",
 	NULL
 };
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 36490d06c8a..64796c6a785 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -36,7 +36,7 @@ static char const * const builtin_rebase_usage[] = {
 		"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
 	N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
 		"--root [<branch>]"),
-	N_("git rebase --continue | --abort | --skip | --edit-todo"),
+	"git rebase --continue | --abort | --skip | --edit-todo",
 	NULL
 };
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index a4b1dd27e13..ee5ee8d8cf6 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -800,7 +800,7 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
  */
 
 static const char reflog_usage[] =
-N_("git reflog [ show | expire | delete | exists ]");
+"git reflog [ show | expire | delete | exists ]";
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin/remote.c b/builtin/remote.c
index 299c466116d..6f27ddc47bd 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -14,7 +14,7 @@
 #include "commit-reach.h"
 
 static const char * const builtin_remote_usage[] = {
-	N_("git remote [-v | --verbose]"),
+	"git remote [-v | --verbose]",
 	N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>"),
 	N_("git remote rename <old> <new>"),
 	N_("git remote remove <name>"),
diff --git a/builtin/replace.c b/builtin/replace.c
index 6ff1734d587..ac92337c0ec 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -22,7 +22,7 @@ static const char * const git_replace_usage[] = {
 	N_("git replace [-f] <object> <replacement>"),
 	N_("git replace [-f] --edit <object>"),
 	N_("git replace [-f] --graft <commit> [<parent>...]"),
-	N_("git replace [-f] --convert-graft-file"),
+	"git replace [-f] --convert-graft-file",
 	N_("git replace -d <object>..."),
 	N_("git replace [--format=<format>] [-l [<pattern>]]"),
 	NULL
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 679c1070368..771c9869a1c 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -43,7 +43,7 @@ static void write_patterns_to_file(FILE *fp, struct pattern_list *pl)
 }
 
 static char const * const builtin_sparse_checkout_list_usage[] = {
-	N_("git sparse-checkout list"),
+	"git sparse-checkout list",
 	NULL
 };
 
@@ -419,7 +419,7 @@ static int update_modes(int *cone_mode, int *sparse_index)
 }
 
 static char const * const builtin_sparse_checkout_init_usage[] = {
-	N_("git sparse-checkout init [--cone] [--[no-]sparse-index]"),
+	"git sparse-checkout init [--cone] [--[no-]sparse-index]",
 	NULL
 };
 
@@ -762,7 +762,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
 }
 
 static char const * const builtin_sparse_checkout_reapply_usage[] = {
-	N_("git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]"),
+	"git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]",
 	NULL
 };
 
@@ -800,7 +800,7 @@ static int sparse_checkout_reapply(int argc, const char **argv)
 }
 
 static char const * const builtin_sparse_checkout_disable_usage[] = {
-	N_("git sparse-checkout disable"),
+	"git sparse-checkout disable",
 	NULL
 };
 
diff --git a/builtin/stripspace.c b/builtin/stripspace.c
index be33eb83c1b..1e34cf2bebd 100644
--- a/builtin/stripspace.c
+++ b/builtin/stripspace.c
@@ -15,8 +15,8 @@ static void comment_lines(struct strbuf *buf)
 }
 
 static const char * const stripspace_usage[] = {
-	N_("git stripspace [-s | --strip-comments]"),
-	N_("git stripspace [-c | --comment-lines]"),
+	"git stripspace [-s | --strip-comments]",
+	"git stripspace [-c | --comment-lines]",
 	NULL
 };
 
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index c5d3fc3817f..b80aa9898ac 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2883,7 +2883,7 @@ static int module_config(int argc, const char **argv, const char *prefix)
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule--helper config <name> [<value>]"),
 		N_("git submodule--helper config --unset <name>"),
-		N_("git submodule--helper config --check-writeable"),
+		"git submodule--helper config --check-writeable",
 		NULL
 	};
 
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index 4321a344567..880fffec587 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -4,7 +4,7 @@
 #include "parse-options.h"
 
 static const char * const update_server_info_usage[] = {
-	N_("git update-server-info [--force]"),
+	"git update-server-info [--force]",
 	NULL
 };
 
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v2 4/4] i18n: transfer variables into placeholders in command synopsis
  2022-01-28 22:23 ` [PATCH v2 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
                     ` (2 preceding siblings ...)
  2022-01-28 22:24   ` [PATCH v2 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
@ 2022-01-28 22:24   ` Jean-Noël Avila via GitGitGadget
  2022-01-30 22:01   ` [PATCH v3 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  4 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-28 22:24 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

This applies the style guide for documentation.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/fast-export.c | 2 +-
 builtin/reflog.c      | 4 ++--
 builtin/rev-list.c    | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 9f1c730e587..510139e9b54 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -26,7 +26,7 @@
 #include "commit-slab.h"
 
 static const char *fast_export_usage[] = {
-	N_("git fast-export [rev-list-opts]"),
+	N_("git fast-export [<rev-list-opts>]"),
 	NULL
 };
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index ee5ee8d8cf6..343a10d371b 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -17,10 +17,10 @@ static const char reflog_expire_usage[] =
 N_("git reflog expire [--expire=<time>] "
    "[--expire-unreachable=<time>] "
    "[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] "
-   "[--verbose] [--all] <refs>...");
+   "[--verbose] [--all] <ref>...");
 static const char reflog_delete_usage[] =
 N_("git reflog delete [--rewrite] [--updateref] "
-   "[--dry-run | -n] [--verbose] <refs>...");
+   "[--dry-run | -n] [--verbose] <ref>...");
 static const char reflog_exists_usage[] =
 N_("git reflog exists <ref>");
 
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 777558e9b06..38528c7f156 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -20,7 +20,7 @@
 #include "packfile.h"
 
 static const char rev_list_usage[] =
-"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
+"git rev-list [<options>] <commit-id>... [-- <path>...]\n"
 "  limiting output:\n"
 "    --max-count=<n>\n"
 "    --max-age=<epoch>\n"
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-28 22:24   ` [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
@ 2022-01-28 23:21     ` Johannes Sixt
  2022-01-28 23:58       ` Junio C Hamano
  2022-02-01 21:01     ` Ævar Arnfjörð Bjarmason
  1 sibling, 1 reply; 41+ messages in thread
From: Johannes Sixt @ 2022-01-28 23:21 UTC (permalink / raw)
  To: Jean-Noël Avila
  Cc: Phillip Wood, git, Jean-Noël Avila via GitGitGadget

Am 28.01.22 um 23:24 schrieb Jean-Noël Avila via GitGitGadget:
> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
> 
> Find more incompatible options to factorize.
> 
> When more than two options are mutually exclusive, print the ones
> which are actually on the command line.
> 
> Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
> ---
>  builtin/commit.c                          | 39 +++++++++---------
>  builtin/difftool.c                        |  5 ++-
>  builtin/grep.c                            |  8 ++--
>  builtin/log.c                             |  5 ++-
>  builtin/merge-base.c                      |  4 +-
>  parse-options.c                           | 50 +++++++++++++++++++++++
>  parse-options.h                           |  9 ++++
>  t/t7500-commit-template-squash-signoff.sh |  2 +-
>  8 files changed, 90 insertions(+), 32 deletions(-)
> 
> diff --git a/builtin/commit.c b/builtin/commit.c
> index b9ed0374e30..1966f965008 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -1242,8 +1242,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
>  				      struct commit *current_head,
>  				      struct wt_status *s)
>  {
> -	int f = 0;
> -
>  	argc = parse_options(argc, argv, prefix, options, usage, 0);
>  	finalize_deferred_config(s);
>  
> @@ -1251,7 +1249,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
>  		force_author = find_author_by_nickname(force_author);
>  
>  	if (force_author && renew_authorship)
> -		die(_("Using both --reset-author and --author does not make sense"));
> +		die(_("options '%s' and '%s' cannot be used together"), "--reset-author", "--author");
>  
>  	if (logfile || have_option_m || use_message)
>  		use_editor = 0;
> @@ -1268,20 +1266,20 @@ static int parse_and_validate_options(int argc, const char *argv[],
>  			die(_("You are in the middle of a rebase -- cannot amend."));
>  	}
>  	if (fixup_message && squash_message)
> -		die(_("Options --squash and --fixup cannot be used together"));
> -	if (use_message)
> -		f++;
> -	if (edit_message)
> -		f++;
> -	if (fixup_message)
> -		f++;
> -	if (logfile)
> -		f++;
> -	if (f > 1)
> -		die(_("Only one of -c/-C/-F/--fixup can be used."));
> -	if (have_option_m && (edit_message || use_message || logfile))
> -		die((_("Option -m cannot be combined with -c/-C/-F.")));
> -	if (f || have_option_m)
> +		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
> +	die_if_incompatible_opt4(!!use_message, "-C",
> +							 !!edit_message, "-c",
> +							 !!logfile, "-F",
> +							 !!fixup_message, "--fixup");
Please check the tab width setting of your editor; indentations here and
in other calls and function declarations below are too wide. Looks like
you have it at 4 instead of 8.

> +	if (have_option_m) {
> +		if (edit_message)
> +			die(_("options '%s' and '%s' cannot be used together"), "-m", "-c");
> +		else if  (use_message)
> +			die(_("options '%s' and '%s' cannot be used together"), "-m", "-C");
> +		else if (logfile)
> +			die(_("options '%s' and '%s' cannot be used together"), "-m", "-F");
> +	}

This conditional could have been another die_if_incompatible_opt4()
call, although it would only check a conflict of -m with at most one of
-c, -C, or -F.

> +	if (use_message || edit_message || logfile ||fixup_message || have_option_m)

Missing space before fixup_message.

>  		template_file = NULL;
>  	if (edit_message)
>  		use_message = edit_message;

The rewrite of the logic in this hunk looks correct.

> @@ -1306,9 +1304,10 @@ static int parse_and_validate_options(int argc, const char *argv[],
>  	if (patch_interactive)
>  		interactive = 1;
>  
> -	if (also + only + all + interactive > 1)
> -		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
> -
> +	die_if_incompatible_opt4(also, "-i/--include",
> +							 only, "-o/--only",
> +							 all, "-a/--all",
> +							 interactive, "--interactive/-p/--patch");
>  	if (fixup_message) {
>  		/*
>  		 * We limit --fixup's suboptions to only alpha characters.
> diff --git a/builtin/difftool.c b/builtin/difftool.c
> index c79fbbf67e5..ae487785735 100644
> --- a/builtin/difftool.c
> +++ b/builtin/difftool.c
> @@ -732,8 +732,9 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
>  	} else if (dir_diff)
>  		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
>  
> -	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
> -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
> +	die_if_incompatible_opt3(use_gui_tool, "--gui",
> +							 !!difftool_cmd, "--tool",
> +							 !!extcmd, "--extcmd");
>  
>  	if (use_gui_tool)
>  		setenv("GIT_MERGETOOL_GUI", "true", 1);
> diff --git a/builtin/grep.c b/builtin/grep.c
> index 9e34a820ad4..cdf52667710 100644
> --- a/builtin/grep.c
> +++ b/builtin/grep.c
> @@ -1167,11 +1167,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
>  	if (!show_in_pager && !opt.status_only)
>  		setup_pager();
>  
> -	if (!use_index && (untracked || cached))
> -		die(_("--cached or --untracked cannot be used with --no-index"));
> -
> -	if (untracked && cached)
> -		die(_("--untracked cannot be used with --cached"));
> +	die_if_incompatible_opt3(!use_index, "--no-index",
> +							 untracked, "--untracked",
> +							 cached, "--cached");
>  
>  	if (!use_index || untracked) {
>  		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
> diff --git a/builtin/log.c b/builtin/log.c
> index 4b493408cc5..048b2c37470 100644
> --- a/builtin/log.c
> +++ b/builtin/log.c
> @@ -1978,8 +1978,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
>  	if (rev.show_notes)
>  		load_display_notes(&rev.notes_opt);
>  
> -	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
> -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
> +	die_if_incompatible_opt3(use_stdout, "--stdout",
> +							 rev.diffopt.close_file, "--output",
> +							 !!output_directory, "--output-directory");
>  
>  	if (use_stdout) {
>  		setup_pager();
> diff --git a/builtin/merge-base.c b/builtin/merge-base.c
> index 6719ac198dc..1447f1c493a 100644
> --- a/builtin/merge-base.c
> +++ b/builtin/merge-base.c
> @@ -159,12 +159,12 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
>  		if (argc < 2)
>  			usage_with_options(merge_base_usage, options);
>  		if (show_all)
> -			die("--is-ancestor cannot be used with --all");
> +			die(_("options '%s' and '%s' cannot be used together"),"--is-ancestor", "--all");
>  		return handle_is_ancestor(argc, argv);
>  	}
>  
>  	if (cmdmode == 'r' && show_all)
> -		die("--independent cannot be used with --all");
> +		die(_("options '%s' and '%s' cannot be used together"),"--independent", "--all");
>  
>  	if (cmdmode == 'o')
>  		return handle_octopus(argc, argv, show_all);

These rewrites are good. Note the unusually wide indentation in the new
function calls, though.

> diff --git a/parse-options.c b/parse-options.c
> index a8283037be9..fb9e1976ab3 100644
> --- a/parse-options.c
> +++ b/parse-options.c
> @@ -1079,3 +1079,53 @@ void NORETURN usage_msg_opt(const char *msg,
>  	die_message("%s\n", msg); /* The extra \n is intentional */
>  	usage_with_options(usagestr, options);
>  }
> +
> +void die_if_incompatible_opt3(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name)
> +{
> +	int count = 0;
> +	const char *options[3];
> +
> +	if (opt1)
> +		options[count++] = opt1_name;
> +	if (opt2)
> +		options[count++] = opt2_name;
> +	if (opt3)
> +		options[count++] = opt3_name;
> +	if (count > 2)
> +		die(_("options '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name);
> +	else if (count > 1)
> +		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
> +}
> +
> +void die_if_incompatible_opt4(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name,
> +							  int opt4, const char *opt4_name)
> +{
> +	int count = 0;
> +	const char *options[4];
> +
> +	if (opt1)
> +		options[count++] = opt1_name;
> +	if (opt2)
> +		options[count++] = opt2_name;
> +	if (opt3)
> +		options[count++] = opt3_name;
> +	if (opt4)
> +		options[count++] = opt4_name;
> +	switch (count) {
> +	case 4:
> +		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name, opt4_name);
> +		break;
> +	case 3:
> +		die(_("options '%s', '%s', and '%s' cannot be used together"), options[0], options[1], options[2]);
> +		break;
> +	case 2:
> +		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
> +		break;
> +	default:
> +		break;
> +	}
> +}

Generally, this is good. I wonder whether we have to expect compiler
warnings about unreachable break statements after the die() calls.

A bit of code duplication could be avoided if die_if_incompatible_opt3()
forwarded with an additional pair 0, "" to die_if_incompatible_opt4().

> diff --git a/parse-options.h b/parse-options.h
> index e22846d3b7b..cf393839ac4 100644
> --- a/parse-options.h
> +++ b/parse-options.h
> @@ -339,4 +339,13 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);
>  #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
>  #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
>  
> +void die_if_incompatible_opt3(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name);
> +
> +void die_if_incompatible_opt4(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name,
> +							  int opt4, const char *opt4_name);
> +
>  #endif

I would have placed these declarations near usage_msg_opt further above
in the header file.

> diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
> index 91964653a0b..5fcaa0b4f2a 100755
> --- a/t/t7500-commit-template-squash-signoff.sh
> +++ b/t/t7500-commit-template-squash-signoff.sh
> @@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
>  '
>  
>  test_expect_success '--fixup=reword: -F give error message' '
> -	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
> +	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
>  	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
>  	test_cmp expect actual
>  '

-- Hannes

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-28 23:21     ` Johannes Sixt
@ 2022-01-28 23:58       ` Junio C Hamano
  2022-01-29  8:08         ` Johannes Sixt
  0 siblings, 1 reply; 41+ messages in thread
From: Junio C Hamano @ 2022-01-28 23:58 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Jean-Noël Avila, Phillip Wood, git,
	Jean-Noël Avila via GitGitGadget

Johannes Sixt <j6t@kdbg.org> writes:

>> +void die_if_incompatible_opt4(int opt1, const char *opt1_name,
>> +							  int opt2, const char *opt2_name,
>> +							  int opt3, const char *opt3_name,
>> +							  int opt4, const char *opt4_name)
>> +{
>> +	int count = 0;
>> +	const char *options[4];
>> +
>> +	if (opt1)
>> +		options[count++] = opt1_name;
>> +	if (opt2)
>> +		options[count++] = opt2_name;
>> +	if (opt3)
>> +		options[count++] = opt3_name;
>> +	if (opt4)
>> +		options[count++] = opt4_name;
>> +	switch (count) {
>> +	case 4:
>> +		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name, opt4_name);
>> +		break;
>> +	case 3:
>> +		die(_("options '%s', '%s', and '%s' cannot be used together"), options[0], options[1], options[2]);
>> +		break;
>> +	case 2:
>> +		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +}
>
> Generally, this is good. I wonder whether we have to expect compiler
> warnings about unreachable break statements after the die() calls.
>
> A bit of code duplication could be avoided if die_if_incompatible_opt3()
> forwarded with an additional pair 0, "" to die_if_incompatible_opt4().

I wondered if a single varargs function

    void die_if_incompatible_optN(const char *name1, int opt1, ...);

that takes a name=NULL terminated sequence of <name, opt> would
work, but

 (1) it would require the caller to always spell out the terminating
     NULL, which may be ugly.

 (2) it would tempt people to programatically generate message for N
     options, which leads to sentence lego, which is the exact
     opposite of what this series wants to achieve.

In any case, I do agree with you that the callers of _opt3()
variants can just pass (0, "unused") in the 4-th slot.  If this were
made varargs, then it only needs to pass NULL at the end, so that
might be an improvement, though.

Also, isn't "if" in the name of the function misleading?  as far as
I can tell, this function is not "check if these options are
compatible and die if some are incompatible with each other", but
the caller is convinced that these options are incompatible before
it decides to call this function and there is no "if" in what this
function can do.

void die_for_incompatible_opts(const char *name1, int opt1, ...)
{
	const char *name[4];
	int count = 0;
        va_list params;

        va_start(params, name1);

        if (opt1)
	        name[count++] = name1;
        while (count < ARRAY_SIZE(name)) {
                const char *n = va_arg(params, const char *);

                if (!n)
			break;
                if (va_arg(params, int))
	                name[count++] = n;
        }
        va_end(params);

        switch (count) {
	default:
		BUG("die-for-incompatible-opts can only take up to %d args",
		    ARRAY_SIZE(name));
	case 4:
		die(_("options '%s', '%s', '%s', and '%s'"
		      " cannot be used together"),
		    name[0], name[1], name[2], name[3]);
		break;
	case 3:
		die(_("options '%s', '%s', and '%s'"
		      " cannot be used together"),
		    name[0], name[1], name[2]);
		break;
	...
	}
}

might be easier to extend when somebody discovers there needs the
"opt5" variant. 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-28 23:58       ` Junio C Hamano
@ 2022-01-29  8:08         ` Johannes Sixt
  2022-01-29 10:41           ` Jean-Noël AVILA
  0 siblings, 1 reply; 41+ messages in thread
From: Johannes Sixt @ 2022-01-29  8:08 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Jean-Noël Avila, Phillip Wood, git,
	Jean-Noël Avila via GitGitGadget

Am 29.01.22 um 00:58 schrieb Junio C Hamano:
> Johannes Sixt <j6t@kdbg.org> writes:
>> A bit of code duplication could be avoided if die_if_incompatible_opt3()
>> forwarded with an additional pair 0, "" to die_if_incompatible_opt4().
> 
> I wondered if a single varargs function
> 
>     void die_if_incompatible_optN(const char *name1, int opt1, ...);
> 
> that takes a name=NULL terminated sequence of <name, opt> would
> work, but
> 
>  (1) it would require the caller to always spell out the terminating
>      NULL, which may be ugly.
> 
>  (2) it would tempt people to programatically generate message for N
>      options, which leads to sentence lego, which is the exact
>      opposite of what this series wants to achieve.

The reason I did not suggest a varargs version is because

  (3) it is not typesafe.

A varargs implementation could be used as an implementation helper, but
should not be a public interface.

> In any case, I do agree with you that the callers of _opt3()
> variants can just pass (0, "unused") in the 4-th slot.  If this were
> made varargs, then it only needs to pass NULL at the end, so that
> might be an improvement, though.
> 
> Also, isn't "if" in the name of the function misleading?  as far as
> I can tell, this function is not "check if these options are
> compatible and die if some are incompatible with each other", but
> the caller is convinced that these options are incompatible before
> it decides to call this function and there is no "if" in what this
> function can do.

Good point.

> void die_for_incompatible_opts(const char *name1, int opt1, ...)
> {
> 	const char *name[4];
> 	int count = 0;
>         va_list params;
> 
>         va_start(params, name1);
> 
>         if (opt1)
> 	        name[count++] = name1;
>         while (count < ARRAY_SIZE(name)) {
>                 const char *n = va_arg(params, const char *);
> 
>                 if (!n)
> 			break;
>                 if (va_arg(params, int))
> 	                name[count++] = n;
>         }
>         va_end(params);
> 
>         switch (count) {
> 	default:
> 		BUG("die-for-incompatible-opts can only take up to %d args",
> 		    ARRAY_SIZE(name));

The problems here are: (1) this case triggers only if there is an actual
invocation with all 5+ incompatible options, and (2) at that time, the
out-of-bounds write to the name array has already happened.

I know this implementation is just a rough show-case. But since it's
been written by a very proficient mind, I'm now convinced: it's not
sufficiently easy to write the varargs version, so let's not go there.

> 	case 4:
> 		die(_("options '%s', '%s', '%s', and '%s'"
> 		      " cannot be used together"),
> 		    name[0], name[1], name[2], name[3]);
> 		break;
> 	case 3:
> 		die(_("options '%s', '%s', and '%s'"
> 		      " cannot be used together"),
> 		    name[0], name[1], name[2]);
> 		break;
> 	...
> 	}
> }
> 
> might be easier to extend when somebody discovers there needs the
> "opt5" variant. 

-- Hannes

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-29  8:08         ` Johannes Sixt
@ 2022-01-29 10:41           ` Jean-Noël AVILA
  2022-01-29 13:18             ` Johannes Sixt
  0 siblings, 1 reply; 41+ messages in thread
From: Jean-Noël AVILA @ 2022-01-29 10:41 UTC (permalink / raw)
  To: Junio C Hamano, Johannes Sixt
  Cc: Phillip Wood, git, Jean-Noël Avila via GitGitGadget

Le samedi 29 janvier 2022, 09:08:34 CET Johannes Sixt a écrit :
> Am 29.01.22 um 00:58 schrieb Junio C Hamano:
> > Johannes Sixt <j6t@kdbg.org> writes:
> >> A bit of code duplication could be avoided if die_if_incompatible_opt3()
> >> forwarded with an additional pair 0, "" to die_if_incompatible_opt4().
> > 
> > I wondered if a single varargs function
> > 
> >     void die_if_incompatible_optN(const char *name1, int opt1, ...);
> > 
> > that takes a name=NULL terminated sequence of <name, opt> would
> > work, but
> > 
> >  (1) it would require the caller to always spell out the terminating
> >      NULL, which may be ugly.
> > 
> >  (2) it would tempt people to programatically generate message for N
> >      options, which leads to sentence lego, which is the exact
> >      opposite of what this series wants to achieve.

This is the second part of the functions, and they need a finite number of args 
to check in order to use the correct i18n string. This function cannot be made 
generic for any number of options to check.


> 
> The reason I did not suggest a varargs version is because
> 
>   (3) it is not typesafe.
> 
> A varargs implementation could be used as an implementation helper, but
> should not be a public interface.
> 
> > In any case, I do agree with you that the callers of _opt3()
> > variants can just pass (0, "unused") in the 4-th slot.  If this were
> > made varargs, then it only needs to pass NULL at the end, so that
> > might be an improvement, though.

I still prefer to keep a public function signature which is explicit. Using 
varargs for alternating types is really not type safe.

In such case, declaring the functions with less options as inline calls to the 
one with the greatest number is a good balance.

> > 
> > Also, isn't "if" in the name of the function misleading?  as far as
> > I can tell, this function is not "check if these options are
> > compatible and die if some are incompatible with each other", but
> > the caller is convinced that these options are incompatible before
> > it decides to call this function and there is no "if" in what this
> > function can do.
> 
> Good point.
> 

I don't get the point: the function checks if incompatible options are present 
on the command line and dies in such case. The caller does not know whether 
the function will make the program die, it really depends on the result of the 
check performed in the function. In case there's no or only one of the 
options, the function does nothing.

JN



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-29 10:41           ` Jean-Noël AVILA
@ 2022-01-29 13:18             ` Johannes Sixt
  0 siblings, 0 replies; 41+ messages in thread
From: Johannes Sixt @ 2022-01-29 13:18 UTC (permalink / raw)
  To: Jean-Noël AVILA
  Cc: Phillip Wood, git, Jean-Noël Avila via GitGitGadget,
	Junio C Hamano

Am 29.01.22 um 11:41 schrieb Jean-Noël AVILA:
> Le samedi 29 janvier 2022, 09:08:34 CET Johannes Sixt a écrit :
>> Am 29.01.22 um 00:58 schrieb Junio C Hamano:
>>> Also, isn't "if" in the name of the function misleading?  as far as
>>> I can tell, this function is not "check if these options are
>>> compatible and die if some are incompatible with each other", but
>>> the caller is convinced that these options are incompatible before
>>> it decides to call this function and there is no "if" in what this
>>> function can do.
>>
>> Good point.
> 
> I don't get the point: the function checks if incompatible options are present 
> on the command line and dies in such case. The caller does not know whether 
> the function will make the program die, it really depends on the result of the 
> check performed in the function. In case there's no or only one of the 
> options, the function does nothing.

The function call reads like

     die if options are incompatible

That sounds as if the caller were asking "are these options
incompatible?" But that is not what it wants to ask because it already
knows that the options are incompatible. It actually wants to ask "is
there any problem with these incompatible options?" The name Junio
suggested is die_for_incompatible_opts().

-- Hannes

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v3 0/4] Factorize i18n
  2022-01-28 22:23 ` [PATCH v2 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
                     ` (3 preceding siblings ...)
  2022-01-28 22:24   ` [PATCH v2 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
@ 2022-01-30 22:01   ` Jean-Noël Avila via GitGitGadget
  2022-01-30 22:01     ` [PATCH v3 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
                       ` (5 more replies)
  4 siblings, 6 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-30 22:01 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila

This is a small series of i18n factorizations. Again the idea is to:

 * reduce the number of strings to translate
 * make life easier for translators by removing constant parts of the
   strings to translate
 * uniformize the UI by using a type of message for the a given type of
   condition.

Changes since V1:

 * factorize checks of more than 2 incompatible options into dedicated
   functions which list all the incompatible options present on the command
   line

Changes since V2:

 * switch to tab size 8
 * rename die_if* to die_for*
 * make 3 arg check a call to 4 arg check
 * switch another part to die_for_incompatible_opt4

Jean-Noël Avila (4):
  i18n: factorize more 'incompatible options' messages
  i18n: factorize "invalid value" messages
  i18n: remove from i18n strings that do not hold translatable parts
  i18n: transfer variables into placeholders in command synopsis

 archive.c                                 |  2 +-
 builtin/am.c                              |  8 ++++--
 builtin/bisect--helper.c                  |  6 ++--
 builtin/blame.c                           |  7 +++--
 builtin/commit.c                          | 35 ++++++++++-------------
 builtin/count-objects.c                   |  2 +-
 builtin/difftool.c                        |  5 ++--
 builtin/fast-export.c                     |  2 +-
 builtin/fetch.c                           |  4 +--
 builtin/grep.c                            |  8 ++----
 builtin/hash-object.c                     |  2 +-
 builtin/help.c                            |  4 +--
 builtin/log.c                             |  5 ++--
 builtin/merge-base.c                      |  6 ++--
 builtin/mktag.c                           |  2 +-
 builtin/mktree.c                          |  2 +-
 builtin/notes.c                           |  6 ++--
 builtin/pack-objects.c                    |  2 +-
 builtin/prune-packed.c                    |  2 +-
 builtin/pull.c                            |  6 ++--
 builtin/push.c                            |  2 +-
 builtin/rebase.c                          |  2 +-
 builtin/reflog.c                          |  6 ++--
 builtin/remote.c                          |  2 +-
 builtin/replace.c                         |  2 +-
 builtin/rev-list.c                        |  2 +-
 builtin/send-pack.c                       |  2 +-
 builtin/sparse-checkout.c                 |  8 +++---
 builtin/stripspace.c                      |  4 +--
 builtin/submodule--helper.c               |  2 +-
 builtin/update-server-info.c              |  2 +-
 diff-merges.c                             |  2 +-
 gpg-interface.c                           |  6 ++--
 ls-refs.c                                 |  3 +-
 parallel-checkout.c                       |  4 +--
 parse-options.c                           | 34 ++++++++++++++++++++++
 parse-options.h                           | 17 +++++++++++
 sequencer.c                               |  2 +-
 setup.c                                   |  3 +-
 submodule-config.c                        |  2 +-
 t/t4150-am.sh                             |  2 +-
 t/t7500-commit-template-squash-signoff.sh |  2 +-
 42 files changed, 140 insertions(+), 87 deletions(-)


base-commit: 5d01301f2b865aa8dba1654d3f447ce9d21db0b5
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1123%2Fjnavila%2Ffactorize_i18n-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1123/jnavila/factorize_i18n-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/1123

Range-diff vs v2:

 1:  844e01391e1 ! 1:  aac3f9821c7 i18n: factorize more 'incompatible options' messages
     @@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *ar
      -		die((_("Option -m cannot be combined with -c/-C/-F.")));
      -	if (f || have_option_m)
      +		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
     -+	die_if_incompatible_opt4(!!use_message, "-C",
     -+							 !!edit_message, "-c",
     -+							 !!logfile, "-F",
     -+							 !!fixup_message, "--fixup");
     -+	if (have_option_m) {
     -+		if (edit_message)
     -+			die(_("options '%s' and '%s' cannot be used together"), "-m", "-c");
     -+		else if  (use_message)
     -+			die(_("options '%s' and '%s' cannot be used together"), "-m", "-C");
     -+		else if (logfile)
     -+			die(_("options '%s' and '%s' cannot be used together"), "-m", "-F");
     -+	}
     ++	die_for_incompatible_opt4(!!use_message, "-C",
     ++				  !!edit_message, "-c",
     ++				  !!logfile, "-F",
     ++				  !!fixup_message, "--fixup");
     ++	die_for_incompatible_opt4(have_option_m, "-m",
     ++				  !!edit_message, "-c",
     ++				  !!use_message, "-C",
     ++				  !!logfile, "-F");
      +	if (use_message || edit_message || logfile ||fixup_message || have_option_m)
       		template_file = NULL;
       	if (edit_message)
     @@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *ar
      -	if (also + only + all + interactive > 1)
      -		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
      -
     -+	die_if_incompatible_opt4(also, "-i/--include",
     -+							 only, "-o/--only",
     -+							 all, "-a/--all",
     -+							 interactive, "--interactive/-p/--patch");
     ++	die_for_incompatible_opt4(also, "-i/--include",
     ++				  only, "-o/--only",
     ++				  all, "-a/--all",
     ++				  interactive, "--interactive/-p/--patch");
       	if (fixup_message) {
       		/*
       		 * We limit --fixup's suboptions to only alpha characters.
     @@ builtin/difftool.c: int cmd_difftool(int argc, const char **argv, const char *pr
       
      -	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
      -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
     -+	die_if_incompatible_opt3(use_gui_tool, "--gui",
     -+							 !!difftool_cmd, "--tool",
     -+							 !!extcmd, "--extcmd");
     ++	die_for_incompatible_opt3(use_gui_tool, "--gui",
     ++				  !!difftool_cmd, "--tool",
     ++				  !!extcmd, "--extcmd");
       
       	if (use_gui_tool)
       		setenv("GIT_MERGETOOL_GUI", "true", 1);
     @@ builtin/grep.c: int cmd_grep(int argc, const char **argv, const char *prefix)
      -
      -	if (untracked && cached)
      -		die(_("--untracked cannot be used with --cached"));
     -+	die_if_incompatible_opt3(!use_index, "--no-index",
     -+							 untracked, "--untracked",
     -+							 cached, "--cached");
     ++	die_for_incompatible_opt3(!use_index, "--no-index",
     ++				  untracked, "--untracked",
     ++				  cached, "--cached");
       
       	if (!use_index || untracked) {
       		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
     @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *pre
       
      -	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
      -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
     -+	die_if_incompatible_opt3(use_stdout, "--stdout",
     -+							 rev.diffopt.close_file, "--output",
     -+							 !!output_directory, "--output-directory");
     ++	die_for_incompatible_opt3(use_stdout, "--stdout",
     ++				  rev.diffopt.close_file, "--output",
     ++				  !!output_directory, "--output-directory");
       
       	if (use_stdout) {
       		setup_pager();
     @@ builtin/merge-base.c: int cmd_merge_base(int argc, const char **argv, const char
       			usage_with_options(merge_base_usage, options);
       		if (show_all)
      -			die("--is-ancestor cannot be used with --all");
     -+			die(_("options '%s' and '%s' cannot be used together"),"--is-ancestor", "--all");
     ++			die(_("options '%s' and '%s' cannot be used together"),
     ++			    "--is-ancestor", "--all");
       		return handle_is_ancestor(argc, argv);
       	}
       
       	if (cmdmode == 'r' && show_all)
      -		die("--independent cannot be used with --all");
     -+		die(_("options '%s' and '%s' cannot be used together"),"--independent", "--all");
     ++		die(_("options '%s' and '%s' cannot be used together"),
     ++		    "--independent", "--all");
       
       	if (cmdmode == 'o')
       		return handle_octopus(argc, argv, show_all);
     @@ parse-options.c: void NORETURN usage_msg_opt(const char *msg,
       	usage_with_options(usagestr, options);
       }
      +
     -+void die_if_incompatible_opt3(int opt1, const char *opt1_name,
     -+							  int opt2, const char *opt2_name,
     -+							  int opt3, const char *opt3_name)
     -+{
     -+	int count = 0;
     -+	const char *options[3];
     -+
     -+	if (opt1)
     -+		options[count++] = opt1_name;
     -+	if (opt2)
     -+		options[count++] = opt2_name;
     -+	if (opt3)
     -+		options[count++] = opt3_name;
     -+	if (count > 2)
     -+		die(_("options '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name);
     -+	else if (count > 1)
     -+		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
     -+}
     -+
     -+void die_if_incompatible_opt4(int opt1, const char *opt1_name,
     -+							  int opt2, const char *opt2_name,
     -+							  int opt3, const char *opt3_name,
     -+							  int opt4, const char *opt4_name)
     ++void die_for_incompatible_opt4(int opt1, const char *opt1_name,
     ++			       int opt2, const char *opt2_name,
     ++			       int opt3, const char *opt3_name,
     ++			       int opt4, const char *opt4_name)
      +{
      +	int count = 0;
      +	const char *options[4];
     @@ parse-options.c: void NORETURN usage_msg_opt(const char *msg,
      +		options[count++] = opt4_name;
      +	switch (count) {
      +	case 4:
     -+		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name, opt4_name);
     ++		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
     ++		    opt1_name, opt2_name, opt3_name, opt4_name);
      +		break;
      +	case 3:
     -+		die(_("options '%s', '%s', and '%s' cannot be used together"), options[0], options[1], options[2]);
     ++		die(_("options '%s', '%s', and '%s' cannot be used together"),
     ++		    options[0], options[1], options[2]);
      +		break;
      +	case 2:
     -+		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
     ++		die(_("options '%s' and '%s' cannot be used together"),
     ++		    options[0], options[1]);
      +		break;
      +	default:
      +		break;
     @@ parse-options.c: void NORETURN usage_msg_opt(const char *msg,
      +}
      
       ## parse-options.h ##
     +@@ parse-options.h: NORETURN void usage_msg_opt(const char *msg,
     + 			    const char * const *usagestr,
     + 			    const struct option *options);
     + 
     ++void die_for_incompatible_opt4(int opt1, const char *opt1_name,
     ++			       int opt2, const char *opt2_name,
     ++			       int opt3, const char *opt3_name,
     ++			       int opt4, const char *opt4_name);
     ++
     ++
     ++inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
     ++				      int opt2, const char *opt2_name,
     ++				      int opt3, const char *opt3_name)
     ++{
     ++	die_for_incompatible_opt4(opt1, opt1_name,
     ++				  opt2, opt2_name,
     ++				  opt3, opt3_name,
     ++				  0, "");
     ++}
     ++
     + /*
     +  * Use these assertions for callbacks that expect to be called with NONEG and
     +  * NOARG respectively, and do not otherwise handle the "unset" and "arg"
      @@ parse-options.h: int parse_opt_tracking_mode(const struct option *, const char *, int);
       #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
       #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
       
     -+void die_if_incompatible_opt3(int opt1, const char *opt1_name,
     -+							  int opt2, const char *opt2_name,
     -+							  int opt3, const char *opt3_name);
     -+
     -+void die_if_incompatible_opt4(int opt1, const char *opt1_name,
     -+							  int opt2, const char *opt2_name,
     -+							  int opt3, const char *opt3_name,
     -+							  int opt4, const char *opt4_name);
      +
       #endif
      
 2:  4c860698d69 ! 2:  078336ae418 i18n: factorize "invalid value" messages
     @@ builtin/am.c: static int parse_opt_patchformat(const struct option *opt, const c
       	 */
       	else
      -		return error(_("Invalid value for --patch-format: %s"), arg);
     -+		return error(_("invalid value for '%s': '%s'"), "--patch-format", arg);
     ++		return error(_("invalid value for '%s': '%s'"),
     ++			     "--patch-format", arg);
       	return 0;
       }
       
     @@ builtin/am.c: static int parse_opt_show_current_patch(const struct option *opt,
       		if (new_value >= ARRAY_SIZE(valid_modes))
      -			return error(_("Invalid value for --show-current-patch: %s"), arg);
      +			return error(_("invalid value for '%s': '%s'"),
     -+						 "--show-current-patch", arg);
     ++				     "--show-current-patch", arg);
       	}
       
       	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
     @@ builtin/blame.c: static int git_blame_config(const char *var, const char *value,
      -			warning(_("invalid color '%s' in color.blame.repeatedLines"),
      -				value);
      +			warning(_("invalid value for '%s': '%s'"),
     -+					"color.blame.repeatedLines", value);
     ++				"color.blame.repeatedLines", value);
       		return 0;
       	}
       	if (!strcmp(var, "color.blame.highlightrecent")) {
     @@ builtin/blame.c: static int git_blame_config(const char *var, const char *value,
       					    OUTPUT_SHOW_AGE_WITH_COLOR);
       		} else {
      -			warning(_("invalid value for blame.coloring"));
     -+			warning(_("invalid value for '%s': '%s'"), "blame.coloring", value);
     ++			warning(_("invalid value for '%s': '%s'"),
     ++				"blame.coloring", value);
       			return 0;
       		}
       	}
     @@ builtin/fetch.c: static void prepare_format_display(struct ref *ref_map)
      -		die(_("configuration fetch.output contains invalid value %s"),
      -		    format);
      +		die(_("invalid value for '%s': '%s'"),
     -+			  "fetch.output", format);
     ++		    "fetch.output", format);
       
       	for (rm = ref_map; rm; rm = rm->next) {
       		if (rm->status == REF_STATUS_REJECT_SHALLOW ||
     @@ gpg-interface.c: int git_gpg_config(const char *var, const char *value, void *cb
       		fmt = get_format_by_name(value);
       		if (!fmt)
      -			return error("unsupported value for %s: %s",
     -+			return error("invalid value for '%s': '%s'",
     ++			return error(_("invalid value for '%s': '%s'"),
       				     var, value);
       		use_format = fmt;
       		return 0;
     @@ gpg-interface.c: int git_gpg_config(const char *var, const char *value, void *cb
       
       		if (ret)
      -			return error("unsupported value for %s: %s", var,
     -+			return error("invalid value for '%s': '%s'", var,
     - 				     value);
     +-				     value);
     ++			return error(_("invalid value for '%s': '%s'"),
     ++				     var, value);
       		return 0;
       	}
     + 
      
       ## ls-refs.c ##
      @@ ls-refs.c: static void ensure_config_read(void)
     @@ ls-refs.c: static void ensure_config_read(void)
       			/* do nothing */
       		} else {
      -			die(_("invalid value '%s' for lsrefs.unborn"), str);
     -+			die(_("invalid value for '%s': '%s'"), "lsrefs.unborn", str);
     ++			die(_("invalid value for '%s': '%s'"),
     ++			    "lsrefs.unborn", str);
       		}
       	}
       	config_read = 1;
     @@ parallel-checkout.c: void get_parallel_checkout_configs(int *num_workers, int *t
       	if (env_workers && *env_workers) {
       		if (strtol_i(env_workers, 10, num_workers)) {
      -			die("invalid value for GIT_TEST_CHECKOUT_WORKERS: '%s'",
     +-			    env_workers);
      +			die(_("invalid value for '%s': '%s'"),
     -+				"GIT_TEST_CHECKOUT_WORKERS",
     - 			    env_workers);
     ++			    "GIT_TEST_CHECKOUT_WORKERS", env_workers);
       		}
       		if (*num_workers < 1)
     + 			*num_workers = online_cpus();
      
       ## sequencer.c ##
      @@ sequencer.c: static int populate_opts_cb(const char *key, const char *value, void *data)
     @@ setup.c: static enum extension_result handle_extension(const char *var,
       		format = hash_algo_by_name(value);
       		if (format == GIT_HASH_UNKNOWN)
      -			return error("invalid value for 'extensions.objectformat'");
     -+			return error(_("invalid value for '%s': '%s'"), "extensions.objectformat", value);
     ++			return error(_("invalid value for '%s': '%s'"),
     ++				     "extensions.objectformat", value);
       		data->hash_algo = format;
       		return EXTENSION_OK;
       	}
 3:  376f8b56908 = 3:  d5ddd903df7 i18n: remove from i18n strings that do not hold translatable parts
 4:  8b0057f6180 = 4:  b8e80e178ee i18n: transfer variables into placeholders in command synopsis

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v3 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-30 22:01   ` [PATCH v3 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
@ 2022-01-30 22:01     ` Jean-Noël Avila via GitGitGadget
  2022-01-31  7:15       ` Johannes Sixt
  2022-01-31 10:56       ` Phillip Wood
  2022-01-30 22:01     ` [PATCH v3 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
                       ` (4 subsequent siblings)
  5 siblings, 2 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-30 22:01 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Find more incompatible options to factorize.

When more than two options are mutually exclusive, print the ones
which are actually on the command line.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/commit.c                          | 35 ++++++++++-------------
 builtin/difftool.c                        |  5 ++--
 builtin/grep.c                            |  8 ++----
 builtin/log.c                             |  5 ++--
 builtin/merge-base.c                      |  6 ++--
 parse-options.c                           | 34 ++++++++++++++++++++++
 parse-options.h                           | 17 +++++++++++
 t/t7500-commit-template-squash-signoff.sh |  2 +-
 8 files changed, 80 insertions(+), 32 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index b9ed0374e30..33ca9e99c80 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1242,8 +1242,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
 				      struct commit *current_head,
 				      struct wt_status *s)
 {
-	int f = 0;
-
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
 	finalize_deferred_config(s);
 
@@ -1251,7 +1249,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
 		force_author = find_author_by_nickname(force_author);
 
 	if (force_author && renew_authorship)
-		die(_("Using both --reset-author and --author does not make sense"));
+		die(_("options '%s' and '%s' cannot be used together"), "--reset-author", "--author");
 
 	if (logfile || have_option_m || use_message)
 		use_editor = 0;
@@ -1268,20 +1266,16 @@ static int parse_and_validate_options(int argc, const char *argv[],
 			die(_("You are in the middle of a rebase -- cannot amend."));
 	}
 	if (fixup_message && squash_message)
-		die(_("Options --squash and --fixup cannot be used together"));
-	if (use_message)
-		f++;
-	if (edit_message)
-		f++;
-	if (fixup_message)
-		f++;
-	if (logfile)
-		f++;
-	if (f > 1)
-		die(_("Only one of -c/-C/-F/--fixup can be used."));
-	if (have_option_m && (edit_message || use_message || logfile))
-		die((_("Option -m cannot be combined with -c/-C/-F.")));
-	if (f || have_option_m)
+		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
+	die_for_incompatible_opt4(!!use_message, "-C",
+				  !!edit_message, "-c",
+				  !!logfile, "-F",
+				  !!fixup_message, "--fixup");
+	die_for_incompatible_opt4(have_option_m, "-m",
+				  !!edit_message, "-c",
+				  !!use_message, "-C",
+				  !!logfile, "-F");
+	if (use_message || edit_message || logfile ||fixup_message || have_option_m)
 		template_file = NULL;
 	if (edit_message)
 		use_message = edit_message;
@@ -1306,9 +1300,10 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (patch_interactive)
 		interactive = 1;
 
-	if (also + only + all + interactive > 1)
-		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
-
+	die_for_incompatible_opt4(also, "-i/--include",
+				  only, "-o/--only",
+				  all, "-a/--all",
+				  interactive, "--interactive/-p/--patch");
 	if (fixup_message) {
 		/*
 		 * We limit --fixup's suboptions to only alpha characters.
diff --git a/builtin/difftool.c b/builtin/difftool.c
index c79fbbf67e5..faa3507369a 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -732,8 +732,9 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 	} else if (dir_diff)
 		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
 
-	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
+	die_for_incompatible_opt3(use_gui_tool, "--gui",
+				  !!difftool_cmd, "--tool",
+				  !!extcmd, "--extcmd");
 
 	if (use_gui_tool)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
diff --git a/builtin/grep.c b/builtin/grep.c
index 9e34a820ad4..88144f06300 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1167,11 +1167,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	if (!show_in_pager && !opt.status_only)
 		setup_pager();
 
-	if (!use_index && (untracked || cached))
-		die(_("--cached or --untracked cannot be used with --no-index"));
-
-	if (untracked && cached)
-		die(_("--untracked cannot be used with --cached"));
+	die_for_incompatible_opt3(!use_index, "--no-index",
+				  untracked, "--untracked",
+				  cached, "--cached");
 
 	if (!use_index || untracked) {
 		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
diff --git a/builtin/log.c b/builtin/log.c
index 4b493408cc5..970aa3483c4 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1978,8 +1978,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	if (rev.show_notes)
 		load_display_notes(&rev.notes_opt);
 
-	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
+	die_for_incompatible_opt3(use_stdout, "--stdout",
+				  rev.diffopt.close_file, "--output",
+				  !!output_directory, "--output-directory");
 
 	if (use_stdout) {
 		setup_pager();
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 6719ac198dc..26b84980dbd 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -159,12 +159,14 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
 		if (argc < 2)
 			usage_with_options(merge_base_usage, options);
 		if (show_all)
-			die("--is-ancestor cannot be used with --all");
+			die(_("options '%s' and '%s' cannot be used together"),
+			    "--is-ancestor", "--all");
 		return handle_is_ancestor(argc, argv);
 	}
 
 	if (cmdmode == 'r' && show_all)
-		die("--independent cannot be used with --all");
+		die(_("options '%s' and '%s' cannot be used together"),
+		    "--independent", "--all");
 
 	if (cmdmode == 'o')
 		return handle_octopus(argc, argv, show_all);
diff --git a/parse-options.c b/parse-options.c
index a8283037be9..276e3911a74 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -1079,3 +1079,37 @@ void NORETURN usage_msg_opt(const char *msg,
 	die_message("%s\n", msg); /* The extra \n is intentional */
 	usage_with_options(usagestr, options);
 }
+
+void die_for_incompatible_opt4(int opt1, const char *opt1_name,
+			       int opt2, const char *opt2_name,
+			       int opt3, const char *opt3_name,
+			       int opt4, const char *opt4_name)
+{
+	int count = 0;
+	const char *options[4];
+
+	if (opt1)
+		options[count++] = opt1_name;
+	if (opt2)
+		options[count++] = opt2_name;
+	if (opt3)
+		options[count++] = opt3_name;
+	if (opt4)
+		options[count++] = opt4_name;
+	switch (count) {
+	case 4:
+		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
+		    opt1_name, opt2_name, opt3_name, opt4_name);
+		break;
+	case 3:
+		die(_("options '%s', '%s', and '%s' cannot be used together"),
+		    options[0], options[1], options[2]);
+		break;
+	case 2:
+		die(_("options '%s' and '%s' cannot be used together"),
+		    options[0], options[1]);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/parse-options.h b/parse-options.h
index e22846d3b7b..68f7ae9c31a 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -225,6 +225,22 @@ NORETURN void usage_msg_opt(const char *msg,
 			    const char * const *usagestr,
 			    const struct option *options);
 
+void die_for_incompatible_opt4(int opt1, const char *opt1_name,
+			       int opt2, const char *opt2_name,
+			       int opt3, const char *opt3_name,
+			       int opt4, const char *opt4_name);
+
+
+inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
+				      int opt2, const char *opt2_name,
+				      int opt3, const char *opt3_name)
+{
+	die_for_incompatible_opt4(opt1, opt1_name,
+				  opt2, opt2_name,
+				  opt3, opt3_name,
+				  0, "");
+}
+
 /*
  * Use these assertions for callbacks that expect to be called with NONEG and
  * NOARG respectively, and do not otherwise handle the "unset" and "arg"
@@ -339,4 +355,5 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);
 #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
 #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
 
+
 #endif
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 91964653a0b..5fcaa0b4f2a 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
 '
 
 test_expect_success '--fixup=reword: -F give error message' '
-	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
+	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
 	test_cmp expect actual
 '
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 2/4] i18n: factorize "invalid value" messages
  2022-01-30 22:01   ` [PATCH v3 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  2022-01-30 22:01     ` [PATCH v3 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
@ 2022-01-30 22:01     ` Jean-Noël Avila via GitGitGadget
  2022-01-30 22:01     ` [PATCH v3 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
                       ` (3 subsequent siblings)
  5 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-30 22:01 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Use the same message when an invalid value is passed to a command line
option or a configuration variable.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/am.c           | 8 +++++---
 builtin/blame.c        | 7 ++++---
 builtin/fetch.c        | 4 ++--
 builtin/pack-objects.c | 2 +-
 builtin/pull.c         | 6 +++---
 builtin/push.c         | 2 +-
 builtin/send-pack.c    | 2 +-
 diff-merges.c          | 2 +-
 gpg-interface.c        | 6 +++---
 ls-refs.c              | 3 ++-
 parallel-checkout.c    | 4 ++--
 sequencer.c            | 2 +-
 setup.c                | 3 ++-
 submodule-config.c     | 2 +-
 t/t4150-am.sh          | 2 +-
 15 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index b6be1f1cb11..97dbeb8e49e 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -199,7 +199,7 @@ static int am_option_parse_empty(const struct option *opt,
 	else if (!strcmp(arg, "keep"))
 		*opt_value = KEEP_EMPTY_COMMIT;
 	else
-		return error(_("Invalid value for --empty: %s"), arg);
+		return error(_("invalid value for '%s': '%s'"), "--empty", arg);
 
 	return 0;
 }
@@ -2239,7 +2239,8 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
 	 * when you add new options
 	 */
 	else
-		return error(_("Invalid value for --patch-format: %s"), arg);
+		return error(_("invalid value for '%s': '%s'"),
+			     "--patch-format", arg);
 	return 0;
 }
 
@@ -2282,7 +2283,8 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 				break;
 		}
 		if (new_value >= ARRAY_SIZE(valid_modes))
-			return error(_("Invalid value for --show-current-patch: %s"), arg);
+			return error(_("invalid value for '%s': '%s'"),
+				     "--show-current-patch", arg);
 	}
 
 	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
diff --git a/builtin/blame.c b/builtin/blame.c
index 7fafeac4081..9c142f17a2e 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -721,8 +721,8 @@ static int git_blame_config(const char *var, const char *value, void *cb)
 	}
 	if (!strcmp(var, "color.blame.repeatedlines")) {
 		if (color_parse_mem(value, strlen(value), repeated_meta_color))
-			warning(_("invalid color '%s' in color.blame.repeatedLines"),
-				value);
+			warning(_("invalid value for '%s': '%s'"),
+				"color.blame.repeatedLines", value);
 		return 0;
 	}
 	if (!strcmp(var, "color.blame.highlightrecent")) {
@@ -739,7 +739,8 @@ static int git_blame_config(const char *var, const char *value, void *cb)
 			coloring_mode &= ~(OUTPUT_COLOR_LINE |
 					    OUTPUT_SHOW_AGE_WITH_COLOR);
 		} else {
-			warning(_("invalid value for blame.coloring"));
+			warning(_("invalid value for '%s': '%s'"),
+				"blame.coloring", value);
 			return 0;
 		}
 	}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 5f06b21f8e9..8be19bb8799 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -763,8 +763,8 @@ static void prepare_format_display(struct ref *ref_map)
 	else if (!strcasecmp(format, "compact"))
 		compact_format = 1;
 	else
-		die(_("configuration fetch.output contains invalid value %s"),
-		    format);
+		die(_("invalid value for '%s': '%s'"),
+		    "fetch.output", format);
 
 	for (rm = ref_map; rm; rm = rm->next) {
 		if (rm->status == REF_STATUS_REJECT_SHALLOW ||
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index ba2006f2212..192c3ca305e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3504,7 +3504,7 @@ static int option_parse_missing_action(const struct option *opt,
 		return 0;
 	}
 
-	die(_("invalid value for --missing"));
+	die(_("invalid value for '%s': '%s'"), "--missing", arg);
 	return 0;
 }
 
diff --git a/builtin/pull.c b/builtin/pull.c
index 100cbf9fb85..e54a0ccadc6 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -42,9 +42,9 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
 		return v;
 
 	if (fatal)
-		die(_("Invalid value for %s: %s"), key, value);
+		die(_("invalid value for '%s': '%s'"), key, value);
 	else
-		error(_("Invalid value for %s: %s"), key, value);
+		error(_("invalid value for '%s': '%s'"), key, value);
 
 	return REBASE_INVALID;
 }
@@ -318,7 +318,7 @@ static const char *config_get_ff(void)
 	if (!strcmp(value, "only"))
 		return "--ff-only";
 
-	die(_("Invalid value for pull.ff: %s"), value);
+	die(_("invalid value for '%s': '%s'"), "pull.ff", value);
 }
 
 /**
diff --git a/builtin/push.c b/builtin/push.c
index 359db90321c..cad997965a7 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -486,7 +486,7 @@ static int git_push_config(const char *k, const char *v, void *cb)
 				if (value && !strcasecmp(value, "if-asked"))
 					set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_IF_ASKED);
 				else
-					return error("Invalid value for '%s'", k);
+					return error(_("invalid value for '%s'"), k);
 			}
 		}
 	} else if (!strcmp(k, "push.recursesubmodules")) {
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 69c432ef1a6..64962be0168 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -145,7 +145,7 @@ static int send_pack_config(const char *k, const char *v, void *cb)
 				if (value && !strcasecmp(value, "if-asked"))
 					args.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
 				else
-					return error("Invalid value for '%s'", k);
+					return error(_("invalid value for '%s'"), k);
 			}
 		}
 	}
diff --git a/diff-merges.c b/diff-merges.c
index 5060ccd890b..cd6c102a0d5 100644
--- a/diff-merges.c
+++ b/diff-merges.c
@@ -67,7 +67,7 @@ static void set_diff_merges(struct rev_info *revs, const char *optarg)
 	diff_merges_setup_func_t func = func_by_opt(optarg);
 
 	if (!func)
-		die(_("unknown value for --diff-merges: %s"), optarg);
+		die(_("invalid value for '%s': '%s'"), "--diff-merges", optarg);
 
 	func(revs);
 
diff --git a/gpg-interface.c b/gpg-interface.c
index b52eb0e2e04..4e084b08f67 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -702,7 +702,7 @@ int git_gpg_config(const char *var, const char *value, void *cb)
 			return config_error_nonbool(var);
 		fmt = get_format_by_name(value);
 		if (!fmt)
-			return error("unsupported value for %s: %s",
+			return error(_("invalid value for '%s': '%s'"),
 				     var, value);
 		use_format = fmt;
 		return 0;
@@ -717,8 +717,8 @@ int git_gpg_config(const char *var, const char *value, void *cb)
 		free(trust);
 
 		if (ret)
-			return error("unsupported value for %s: %s", var,
-				     value);
+			return error(_("invalid value for '%s': '%s'"),
+				     var, value);
 		return 0;
 	}
 
diff --git a/ls-refs.c b/ls-refs.c
index 54078323dcb..98e69373c84 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -34,7 +34,8 @@ static void ensure_config_read(void)
 		} else if (!strcmp(str, "ignore")) {
 			/* do nothing */
 		} else {
-			die(_("invalid value '%s' for lsrefs.unborn"), str);
+			die(_("invalid value for '%s': '%s'"),
+			    "lsrefs.unborn", str);
 		}
 	}
 	config_read = 1;
diff --git a/parallel-checkout.c b/parallel-checkout.c
index 8dd7e7bad40..31a3d0ee1bf 100644
--- a/parallel-checkout.c
+++ b/parallel-checkout.c
@@ -39,8 +39,8 @@ void get_parallel_checkout_configs(int *num_workers, int *threshold)
 
 	if (env_workers && *env_workers) {
 		if (strtol_i(env_workers, 10, num_workers)) {
-			die("invalid value for GIT_TEST_CHECKOUT_WORKERS: '%s'",
-			    env_workers);
+			die(_("invalid value for '%s': '%s'"),
+			    "GIT_TEST_CHECKOUT_WORKERS", env_workers);
 		}
 		if (*num_workers < 1)
 			*num_workers = online_cpus();
diff --git a/sequencer.c b/sequencer.c
index 5213d16e971..683f5392eba 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2806,7 +2806,7 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
 		return error(_("invalid key: %s"), key);
 
 	if (!error_flag)
-		return error(_("invalid value for %s: %s"), key, value);
+		return error(_("invalid value for '%s': '%s'"), key, value);
 
 	return 0;
 }
diff --git a/setup.c b/setup.c
index af3b8c09abe..04ce33cdcd4 100644
--- a/setup.c
+++ b/setup.c
@@ -559,7 +559,8 @@ static enum extension_result handle_extension(const char *var,
 			return config_error_nonbool(var);
 		format = hash_algo_by_name(value);
 		if (format == GIT_HASH_UNKNOWN)
-			return error("invalid value for 'extensions.objectformat'");
+			return error(_("invalid value for '%s': '%s'"),
+				     "extensions.objectformat", value);
 		data->hash_algo = format;
 		return EXTENSION_OK;
 	}
diff --git a/submodule-config.c b/submodule-config.c
index f95344028b5..fb95a026f48 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -496,7 +496,7 @@ static int parse_config(const char *var, const char *value, void *data)
 		else if (parse_submodule_update_strategy(value,
 			 &submodule->update_strategy) < 0 ||
 			 submodule->update_strategy.type == SM_UPDATE_COMMAND)
-			die(_("invalid value for %s"), var);
+			die(_("invalid value for '%s'"), var);
 	} else if (!strcmp(item.buf, "shallow")) {
 		if (!me->overwrite && submodule->recommend_shallow != -1)
 			warn_multiple_config(me->treeish_name, submodule->name,
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 6caff0ca397..159fae8d016 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -1169,7 +1169,7 @@ test_expect_success 'invalid when passing the --empty option alone' '
 	test_when_finished "git am --abort || :" &&
 	git checkout empty-commit^ &&
 	test_must_fail git am --empty empty-commit.patch 2>err &&
-	echo "error: Invalid value for --empty: empty-commit.patch" >expected &&
+	echo "error: invalid value for '\''--empty'\'': '\''empty-commit.patch'\''" >expected &&
 	test_cmp expected err
 '
 
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 3/4] i18n: remove from i18n strings that do not hold translatable parts
  2022-01-30 22:01   ` [PATCH v3 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
  2022-01-30 22:01     ` [PATCH v3 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
  2022-01-30 22:01     ` [PATCH v3 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
@ 2022-01-30 22:01     ` Jean-Noël Avila via GitGitGadget
  2022-01-30 22:01     ` [PATCH v3 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
                       ` (2 subsequent siblings)
  5 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-30 22:01 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 archive.c                    | 2 +-
 builtin/bisect--helper.c     | 6 +++---
 builtin/count-objects.c      | 2 +-
 builtin/hash-object.c        | 2 +-
 builtin/help.c               | 4 ++--
 builtin/mktag.c              | 2 +-
 builtin/mktree.c             | 2 +-
 builtin/notes.c              | 6 +++---
 builtin/prune-packed.c       | 2 +-
 builtin/rebase.c             | 2 +-
 builtin/reflog.c             | 2 +-
 builtin/remote.c             | 2 +-
 builtin/replace.c            | 2 +-
 builtin/sparse-checkout.c    | 8 ++++----
 builtin/stripspace.c         | 4 ++--
 builtin/submodule--helper.c  | 2 +-
 builtin/update-server-info.c | 2 +-
 17 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/archive.c b/archive.c
index d571249cf39..e29d0e00f6c 100644
--- a/archive.c
+++ b/archive.c
@@ -12,7 +12,7 @@
 
 static char const * const archive_usage[] = {
 	N_("git archive [<options>] <tree-ish> [<path>...]"),
-	N_("git archive --list"),
+	"git archive --list",
 	N_("git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"),
 	N_("git archive --remote <repo> [--exec <cmd>] --list"),
 	NULL
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 28a2e6a5750..f962dbd4303 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -22,15 +22,15 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
 
 static const char * const git_bisect_helper_usage[] = {
 	N_("git bisect--helper --bisect-reset [<commit>]"),
-	N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
+	"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]",
 	N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
 					    " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
-	N_("git bisect--helper --bisect-next"),
+	"git bisect--helper --bisect-next",
 	N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
 	N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
 	N_("git bisect--helper --bisect-replay <filename>"),
 	N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
-	N_("git bisect--helper --bisect-visualize"),
+	"git bisect--helper --bisect-visualize",
 	N_("git bisect--helper --bisect-run <cmd>..."),
 	NULL
 };
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 3fae474f6f1..07b94195962 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -87,7 +87,7 @@ static int print_alternate(struct object_directory *odb, void *data)
 }
 
 static char const * const count_objects_usage[] = {
-	N_("git count-objects [-v] [-H | --human-readable]"),
+	"git count-objects [-v] [-H | --human-readable]",
 	NULL
 };
 
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index c7b3ad74c60..04e2442ec7c 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -81,7 +81,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
 {
 	static const char * const hash_object_usage[] = {
 		N_("git hash-object [-t <type>] [-w] [--path=<file> | --no-filters] [--stdin] [--] <file>..."),
-		N_("git hash-object  --stdin-paths"),
+		"git hash-object  --stdin-paths",
 		NULL
 	};
 	const char *type = blob_type;
diff --git a/builtin/help.c b/builtin/help.c
index d387131dd83..b4f2ad3f94e 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -77,8 +77,8 @@ static struct option builtin_help_options[] = {
 static const char * const builtin_help_usage[] = {
 	N_("git help [-a|--all] [--[no-]verbose]]\n"
 	   "         [[-i|--info] [-m|--man] [-w|--web]] [<command>]"),
-	N_("git help [-g|--guides]"),
-	N_("git help [-c|--config]"),
+	"git help [-g|--guides]",
+	"git help [-c|--config]",
 	NULL
 };
 
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 3b2dbbb37e6..c7b905c614b 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 static char const * const builtin_mktag_usage[] = {
-	N_("git mktag"),
+	"git mktag",
 	NULL
 };
 static int option_strict = 1;
diff --git a/builtin/mktree.c b/builtin/mktree.c
index ae78ca1c029..8bdaada922a 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -63,7 +63,7 @@ static void write_tree(struct object_id *oid)
 }
 
 static const char *mktree_usage[] = {
-	N_("git mktree [-z] [--missing] [--batch]"),
+	"git mktree [-z] [--missing] [--batch]",
 	NULL
 };
 
diff --git a/builtin/notes.c b/builtin/notes.c
index 05d60483e82..f99593a1853 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -32,8 +32,8 @@ static const char * const git_notes_usage[] = {
 	N_("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"),
 	N_("git notes [--ref <notes-ref>] show [<object>]"),
 	N_("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"),
-	N_("git notes merge --commit [-v | -q]"),
-	N_("git notes merge --abort [-v | -q]"),
+	"git notes merge --commit [-v | -q]",
+	"git notes merge --abort [-v | -q]",
 	N_("git notes [--ref <notes-ref>] remove [<object>...]"),
 	N_("git notes [--ref <notes-ref>] prune [-n] [-v]"),
 	N_("git notes [--ref <notes-ref>] get-ref"),
@@ -89,7 +89,7 @@ static const char * const git_notes_prune_usage[] = {
 };
 
 static const char * const git_notes_get_ref_usage[] = {
-	N_("git notes get-ref"),
+	"git notes get-ref",
 	NULL
 };
 
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index b7b9281a8ce..da3273a268b 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -3,7 +3,7 @@
 #include "prune-packed.h"
 
 static const char * const prune_packed_usage[] = {
-	N_("git prune-packed [-n | --dry-run] [-q | --quiet]"),
+	"git prune-packed [-n | --dry-run] [-q | --quiet]",
 	NULL
 };
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 36490d06c8a..64796c6a785 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -36,7 +36,7 @@ static char const * const builtin_rebase_usage[] = {
 		"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
 	N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
 		"--root [<branch>]"),
-	N_("git rebase --continue | --abort | --skip | --edit-todo"),
+	"git rebase --continue | --abort | --skip | --edit-todo",
 	NULL
 };
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index a4b1dd27e13..ee5ee8d8cf6 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -800,7 +800,7 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
  */
 
 static const char reflog_usage[] =
-N_("git reflog [ show | expire | delete | exists ]");
+"git reflog [ show | expire | delete | exists ]";
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin/remote.c b/builtin/remote.c
index 299c466116d..6f27ddc47bd 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -14,7 +14,7 @@
 #include "commit-reach.h"
 
 static const char * const builtin_remote_usage[] = {
-	N_("git remote [-v | --verbose]"),
+	"git remote [-v | --verbose]",
 	N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>"),
 	N_("git remote rename <old> <new>"),
 	N_("git remote remove <name>"),
diff --git a/builtin/replace.c b/builtin/replace.c
index 6ff1734d587..ac92337c0ec 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -22,7 +22,7 @@ static const char * const git_replace_usage[] = {
 	N_("git replace [-f] <object> <replacement>"),
 	N_("git replace [-f] --edit <object>"),
 	N_("git replace [-f] --graft <commit> [<parent>...]"),
-	N_("git replace [-f] --convert-graft-file"),
+	"git replace [-f] --convert-graft-file",
 	N_("git replace -d <object>..."),
 	N_("git replace [--format=<format>] [-l [<pattern>]]"),
 	NULL
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 679c1070368..771c9869a1c 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -43,7 +43,7 @@ static void write_patterns_to_file(FILE *fp, struct pattern_list *pl)
 }
 
 static char const * const builtin_sparse_checkout_list_usage[] = {
-	N_("git sparse-checkout list"),
+	"git sparse-checkout list",
 	NULL
 };
 
@@ -419,7 +419,7 @@ static int update_modes(int *cone_mode, int *sparse_index)
 }
 
 static char const * const builtin_sparse_checkout_init_usage[] = {
-	N_("git sparse-checkout init [--cone] [--[no-]sparse-index]"),
+	"git sparse-checkout init [--cone] [--[no-]sparse-index]",
 	NULL
 };
 
@@ -762,7 +762,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
 }
 
 static char const * const builtin_sparse_checkout_reapply_usage[] = {
-	N_("git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]"),
+	"git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]",
 	NULL
 };
 
@@ -800,7 +800,7 @@ static int sparse_checkout_reapply(int argc, const char **argv)
 }
 
 static char const * const builtin_sparse_checkout_disable_usage[] = {
-	N_("git sparse-checkout disable"),
+	"git sparse-checkout disable",
 	NULL
 };
 
diff --git a/builtin/stripspace.c b/builtin/stripspace.c
index be33eb83c1b..1e34cf2bebd 100644
--- a/builtin/stripspace.c
+++ b/builtin/stripspace.c
@@ -15,8 +15,8 @@ static void comment_lines(struct strbuf *buf)
 }
 
 static const char * const stripspace_usage[] = {
-	N_("git stripspace [-s | --strip-comments]"),
-	N_("git stripspace [-c | --comment-lines]"),
+	"git stripspace [-s | --strip-comments]",
+	"git stripspace [-c | --comment-lines]",
 	NULL
 };
 
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index c5d3fc3817f..b80aa9898ac 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2883,7 +2883,7 @@ static int module_config(int argc, const char **argv, const char *prefix)
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule--helper config <name> [<value>]"),
 		N_("git submodule--helper config --unset <name>"),
-		N_("git submodule--helper config --check-writeable"),
+		"git submodule--helper config --check-writeable",
 		NULL
 	};
 
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index 4321a344567..880fffec587 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -4,7 +4,7 @@
 #include "parse-options.h"
 
 static const char * const update_server_info_usage[] = {
-	N_("git update-server-info [--force]"),
+	"git update-server-info [--force]",
 	NULL
 };
 
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v3 4/4] i18n: transfer variables into placeholders in command synopsis
  2022-01-30 22:01   ` [PATCH v3 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
                       ` (2 preceding siblings ...)
  2022-01-30 22:01     ` [PATCH v3 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
@ 2022-01-30 22:01     ` Jean-Noël Avila via GitGitGadget
  2022-01-31 11:00       ` Phillip Wood
  2022-01-31  7:15     ` [PATCH v3 0/4] Factorize i18n Johannes Sixt
  2022-01-31 22:07     ` [PATCH v4 " Jean-Noël Avila via GitGitGadget
  5 siblings, 1 reply; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-30 22:01 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

This applies the style guide for documentation.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/fast-export.c | 2 +-
 builtin/reflog.c      | 4 ++--
 builtin/rev-list.c    | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 9f1c730e587..510139e9b54 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -26,7 +26,7 @@
 #include "commit-slab.h"
 
 static const char *fast_export_usage[] = {
-	N_("git fast-export [rev-list-opts]"),
+	N_("git fast-export [<rev-list-opts>]"),
 	NULL
 };
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index ee5ee8d8cf6..343a10d371b 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -17,10 +17,10 @@ static const char reflog_expire_usage[] =
 N_("git reflog expire [--expire=<time>] "
    "[--expire-unreachable=<time>] "
    "[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] "
-   "[--verbose] [--all] <refs>...");
+   "[--verbose] [--all] <ref>...");
 static const char reflog_delete_usage[] =
 N_("git reflog delete [--rewrite] [--updateref] "
-   "[--dry-run | -n] [--verbose] <refs>...");
+   "[--dry-run | -n] [--verbose] <ref>...");
 static const char reflog_exists_usage[] =
 N_("git reflog exists <ref>");
 
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 777558e9b06..38528c7f156 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -20,7 +20,7 @@
 #include "packfile.h"
 
 static const char rev_list_usage[] =
-"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
+"git rev-list [<options>] <commit-id>... [-- <path>...]\n"
 "  limiting output:\n"
 "    --max-count=<n>\n"
 "    --max-age=<epoch>\n"
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-30 22:01     ` [PATCH v3 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
@ 2022-01-31  7:15       ` Johannes Sixt
  2022-01-31 10:56       ` Phillip Wood
  1 sibling, 0 replies; 41+ messages in thread
From: Johannes Sixt @ 2022-01-31  7:15 UTC (permalink / raw)
  To: Jean-Noël Avila via GitGitGadget
  Cc: Phillip Wood, Jean-Noël Avila, git

Am 30.01.22 um 23:01 schrieb Jean-Noël Avila via GitGitGadget:
> diff --git a/parse-options.h b/parse-options.h
> index e22846d3b7b..68f7ae9c31a 100644
> --- a/parse-options.h
> +++ b/parse-options.h

> @@ -339,4 +355,5 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);
>  #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
>  #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
>  
> +
>  #endif

An unnecessary remnant from the earlier round?

Except for this, the patch looks good.

-- Hannes

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 0/4] Factorize i18n
  2022-01-30 22:01   ` [PATCH v3 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
                       ` (3 preceding siblings ...)
  2022-01-30 22:01     ` [PATCH v3 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
@ 2022-01-31  7:15     ` Johannes Sixt
  2022-01-31 22:07     ` [PATCH v4 " Jean-Noël Avila via GitGitGadget
  5 siblings, 0 replies; 41+ messages in thread
From: Johannes Sixt @ 2022-01-31  7:15 UTC (permalink / raw)
  To: Jean-Noël Avila via GitGitGadget
  Cc: Phillip Wood, Jean-Noël Avila, git

Am 30.01.22 um 23:01 schrieb Jean-Noël Avila via GitGitGadget:
> This is a small series of i18n factorizations. Again the idea is to:
> 
>  * reduce the number of strings to translate
>  * make life easier for translators by removing constant parts of the
>    strings to translate
>  * uniformize the UI by using a type of message for the a given type of
>    condition.
> 
> Changes since V1:
> 
>  * factorize checks of more than 2 incompatible options into dedicated
>    functions which list all the incompatible options present on the command
>    line
> 
> Changes since V2:
> 
>  * switch to tab size 8
>  * rename die_if* to die_for*
>  * make 3 arg check a call to 4 arg check
>  * switch another part to die_for_incompatible_opt4

This iteration looks good overall. There is an unnecessary empty-line
addition hunk in 1/2, though.

-- Hannes

> 
> Jean-Noël Avila (4):
>   i18n: factorize more 'incompatible options' messages
>   i18n: factorize "invalid value" messages
>   i18n: remove from i18n strings that do not hold translatable parts
>   i18n: transfer variables into placeholders in command synopsis
> 
>  archive.c                                 |  2 +-
>  builtin/am.c                              |  8 ++++--
>  builtin/bisect--helper.c                  |  6 ++--
>  builtin/blame.c                           |  7 +++--
>  builtin/commit.c                          | 35 ++++++++++-------------
>  builtin/count-objects.c                   |  2 +-
>  builtin/difftool.c                        |  5 ++--
>  builtin/fast-export.c                     |  2 +-
>  builtin/fetch.c                           |  4 +--
>  builtin/grep.c                            |  8 ++----
>  builtin/hash-object.c                     |  2 +-
>  builtin/help.c                            |  4 +--
>  builtin/log.c                             |  5 ++--
>  builtin/merge-base.c                      |  6 ++--
>  builtin/mktag.c                           |  2 +-
>  builtin/mktree.c                          |  2 +-
>  builtin/notes.c                           |  6 ++--
>  builtin/pack-objects.c                    |  2 +-
>  builtin/prune-packed.c                    |  2 +-
>  builtin/pull.c                            |  6 ++--
>  builtin/push.c                            |  2 +-
>  builtin/rebase.c                          |  2 +-
>  builtin/reflog.c                          |  6 ++--
>  builtin/remote.c                          |  2 +-
>  builtin/replace.c                         |  2 +-
>  builtin/rev-list.c                        |  2 +-
>  builtin/send-pack.c                       |  2 +-
>  builtin/sparse-checkout.c                 |  8 +++---
>  builtin/stripspace.c                      |  4 +--
>  builtin/submodule--helper.c               |  2 +-
>  builtin/update-server-info.c              |  2 +-
>  diff-merges.c                             |  2 +-
>  gpg-interface.c                           |  6 ++--
>  ls-refs.c                                 |  3 +-
>  parallel-checkout.c                       |  4 +--
>  parse-options.c                           | 34 ++++++++++++++++++++++
>  parse-options.h                           | 17 +++++++++++
>  sequencer.c                               |  2 +-
>  setup.c                                   |  3 +-
>  submodule-config.c                        |  2 +-
>  t/t4150-am.sh                             |  2 +-
>  t/t7500-commit-template-squash-signoff.sh |  2 +-
>  42 files changed, 140 insertions(+), 87 deletions(-)
> 
> 
> base-commit: 5d01301f2b865aa8dba1654d3f447ce9d21db0b5
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1123%2Fjnavila%2Ffactorize_i18n-v3
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1123/jnavila/factorize_i18n-v3
> Pull-Request: https://github.com/gitgitgadget/git/pull/1123
> 
> Range-diff vs v2:
> 
>  1:  844e01391e1 ! 1:  aac3f9821c7 i18n: factorize more 'incompatible options' messages
>      @@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *ar
>       -		die((_("Option -m cannot be combined with -c/-C/-F.")));
>       -	if (f || have_option_m)
>       +		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
>      -+	die_if_incompatible_opt4(!!use_message, "-C",
>      -+							 !!edit_message, "-c",
>      -+							 !!logfile, "-F",
>      -+							 !!fixup_message, "--fixup");
>      -+	if (have_option_m) {
>      -+		if (edit_message)
>      -+			die(_("options '%s' and '%s' cannot be used together"), "-m", "-c");
>      -+		else if  (use_message)
>      -+			die(_("options '%s' and '%s' cannot be used together"), "-m", "-C");
>      -+		else if (logfile)
>      -+			die(_("options '%s' and '%s' cannot be used together"), "-m", "-F");
>      -+	}
>      ++	die_for_incompatible_opt4(!!use_message, "-C",
>      ++				  !!edit_message, "-c",
>      ++				  !!logfile, "-F",
>      ++				  !!fixup_message, "--fixup");
>      ++	die_for_incompatible_opt4(have_option_m, "-m",
>      ++				  !!edit_message, "-c",
>      ++				  !!use_message, "-C",
>      ++				  !!logfile, "-F");
>       +	if (use_message || edit_message || logfile ||fixup_message || have_option_m)
>        		template_file = NULL;
>        	if (edit_message)
>      @@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *ar
>       -	if (also + only + all + interactive > 1)
>       -		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
>       -
>      -+	die_if_incompatible_opt4(also, "-i/--include",
>      -+							 only, "-o/--only",
>      -+							 all, "-a/--all",
>      -+							 interactive, "--interactive/-p/--patch");
>      ++	die_for_incompatible_opt4(also, "-i/--include",
>      ++				  only, "-o/--only",
>      ++				  all, "-a/--all",
>      ++				  interactive, "--interactive/-p/--patch");
>        	if (fixup_message) {
>        		/*
>        		 * We limit --fixup's suboptions to only alpha characters.
>      @@ builtin/difftool.c: int cmd_difftool(int argc, const char **argv, const char *pr
>        
>       -	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
>       -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
>      -+	die_if_incompatible_opt3(use_gui_tool, "--gui",
>      -+							 !!difftool_cmd, "--tool",
>      -+							 !!extcmd, "--extcmd");
>      ++	die_for_incompatible_opt3(use_gui_tool, "--gui",
>      ++				  !!difftool_cmd, "--tool",
>      ++				  !!extcmd, "--extcmd");
>        
>        	if (use_gui_tool)
>        		setenv("GIT_MERGETOOL_GUI", "true", 1);
>      @@ builtin/grep.c: int cmd_grep(int argc, const char **argv, const char *prefix)
>       -
>       -	if (untracked && cached)
>       -		die(_("--untracked cannot be used with --cached"));
>      -+	die_if_incompatible_opt3(!use_index, "--no-index",
>      -+							 untracked, "--untracked",
>      -+							 cached, "--cached");
>      ++	die_for_incompatible_opt3(!use_index, "--no-index",
>      ++				  untracked, "--untracked",
>      ++				  cached, "--cached");
>        
>        	if (!use_index || untracked) {
>        		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
>      @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *pre
>        
>       -	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
>       -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
>      -+	die_if_incompatible_opt3(use_stdout, "--stdout",
>      -+							 rev.diffopt.close_file, "--output",
>      -+							 !!output_directory, "--output-directory");
>      ++	die_for_incompatible_opt3(use_stdout, "--stdout",
>      ++				  rev.diffopt.close_file, "--output",
>      ++				  !!output_directory, "--output-directory");
>        
>        	if (use_stdout) {
>        		setup_pager();
>      @@ builtin/merge-base.c: int cmd_merge_base(int argc, const char **argv, const char
>        			usage_with_options(merge_base_usage, options);
>        		if (show_all)
>       -			die("--is-ancestor cannot be used with --all");
>      -+			die(_("options '%s' and '%s' cannot be used together"),"--is-ancestor", "--all");
>      ++			die(_("options '%s' and '%s' cannot be used together"),
>      ++			    "--is-ancestor", "--all");
>        		return handle_is_ancestor(argc, argv);
>        	}
>        
>        	if (cmdmode == 'r' && show_all)
>       -		die("--independent cannot be used with --all");
>      -+		die(_("options '%s' and '%s' cannot be used together"),"--independent", "--all");
>      ++		die(_("options '%s' and '%s' cannot be used together"),
>      ++		    "--independent", "--all");
>        
>        	if (cmdmode == 'o')
>        		return handle_octopus(argc, argv, show_all);
>      @@ parse-options.c: void NORETURN usage_msg_opt(const char *msg,
>        	usage_with_options(usagestr, options);
>        }
>       +
>      -+void die_if_incompatible_opt3(int opt1, const char *opt1_name,
>      -+							  int opt2, const char *opt2_name,
>      -+							  int opt3, const char *opt3_name)
>      -+{
>      -+	int count = 0;
>      -+	const char *options[3];
>      -+
>      -+	if (opt1)
>      -+		options[count++] = opt1_name;
>      -+	if (opt2)
>      -+		options[count++] = opt2_name;
>      -+	if (opt3)
>      -+		options[count++] = opt3_name;
>      -+	if (count > 2)
>      -+		die(_("options '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name);
>      -+	else if (count > 1)
>      -+		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
>      -+}
>      -+
>      -+void die_if_incompatible_opt4(int opt1, const char *opt1_name,
>      -+							  int opt2, const char *opt2_name,
>      -+							  int opt3, const char *opt3_name,
>      -+							  int opt4, const char *opt4_name)
>      ++void die_for_incompatible_opt4(int opt1, const char *opt1_name,
>      ++			       int opt2, const char *opt2_name,
>      ++			       int opt3, const char *opt3_name,
>      ++			       int opt4, const char *opt4_name)
>       +{
>       +	int count = 0;
>       +	const char *options[4];
>      @@ parse-options.c: void NORETURN usage_msg_opt(const char *msg,
>       +		options[count++] = opt4_name;
>       +	switch (count) {
>       +	case 4:
>      -+		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name, opt4_name);
>      ++		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
>      ++		    opt1_name, opt2_name, opt3_name, opt4_name);
>       +		break;
>       +	case 3:
>      -+		die(_("options '%s', '%s', and '%s' cannot be used together"), options[0], options[1], options[2]);
>      ++		die(_("options '%s', '%s', and '%s' cannot be used together"),
>      ++		    options[0], options[1], options[2]);
>       +		break;
>       +	case 2:
>      -+		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
>      ++		die(_("options '%s' and '%s' cannot be used together"),
>      ++		    options[0], options[1]);
>       +		break;
>       +	default:
>       +		break;
>      @@ parse-options.c: void NORETURN usage_msg_opt(const char *msg,
>       +}
>       
>        ## parse-options.h ##
>      +@@ parse-options.h: NORETURN void usage_msg_opt(const char *msg,
>      + 			    const char * const *usagestr,
>      + 			    const struct option *options);
>      + 
>      ++void die_for_incompatible_opt4(int opt1, const char *opt1_name,
>      ++			       int opt2, const char *opt2_name,
>      ++			       int opt3, const char *opt3_name,
>      ++			       int opt4, const char *opt4_name);
>      ++
>      ++
>      ++inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
>      ++				      int opt2, const char *opt2_name,
>      ++				      int opt3, const char *opt3_name)
>      ++{
>      ++	die_for_incompatible_opt4(opt1, opt1_name,
>      ++				  opt2, opt2_name,
>      ++				  opt3, opt3_name,
>      ++				  0, "");
>      ++}
>      ++
>      + /*
>      +  * Use these assertions for callbacks that expect to be called with NONEG and
>      +  * NOARG respectively, and do not otherwise handle the "unset" and "arg"
>       @@ parse-options.h: int parse_opt_tracking_mode(const struct option *, const char *, int);
>        #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
>        #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
>        
>      -+void die_if_incompatible_opt3(int opt1, const char *opt1_name,
>      -+							  int opt2, const char *opt2_name,
>      -+							  int opt3, const char *opt3_name);
>      -+
>      -+void die_if_incompatible_opt4(int opt1, const char *opt1_name,
>      -+							  int opt2, const char *opt2_name,
>      -+							  int opt3, const char *opt3_name,
>      -+							  int opt4, const char *opt4_name);
>       +
>        #endif
>       
>  2:  4c860698d69 ! 2:  078336ae418 i18n: factorize "invalid value" messages
>      @@ builtin/am.c: static int parse_opt_patchformat(const struct option *opt, const c
>        	 */
>        	else
>       -		return error(_("Invalid value for --patch-format: %s"), arg);
>      -+		return error(_("invalid value for '%s': '%s'"), "--patch-format", arg);
>      ++		return error(_("invalid value for '%s': '%s'"),
>      ++			     "--patch-format", arg);
>        	return 0;
>        }
>        
>      @@ builtin/am.c: static int parse_opt_show_current_patch(const struct option *opt,
>        		if (new_value >= ARRAY_SIZE(valid_modes))
>       -			return error(_("Invalid value for --show-current-patch: %s"), arg);
>       +			return error(_("invalid value for '%s': '%s'"),
>      -+						 "--show-current-patch", arg);
>      ++				     "--show-current-patch", arg);
>        	}
>        
>        	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
>      @@ builtin/blame.c: static int git_blame_config(const char *var, const char *value,
>       -			warning(_("invalid color '%s' in color.blame.repeatedLines"),
>       -				value);
>       +			warning(_("invalid value for '%s': '%s'"),
>      -+					"color.blame.repeatedLines", value);
>      ++				"color.blame.repeatedLines", value);
>        		return 0;
>        	}
>        	if (!strcmp(var, "color.blame.highlightrecent")) {
>      @@ builtin/blame.c: static int git_blame_config(const char *var, const char *value,
>        					    OUTPUT_SHOW_AGE_WITH_COLOR);
>        		} else {
>       -			warning(_("invalid value for blame.coloring"));
>      -+			warning(_("invalid value for '%s': '%s'"), "blame.coloring", value);
>      ++			warning(_("invalid value for '%s': '%s'"),
>      ++				"blame.coloring", value);
>        			return 0;
>        		}
>        	}
>      @@ builtin/fetch.c: static void prepare_format_display(struct ref *ref_map)
>       -		die(_("configuration fetch.output contains invalid value %s"),
>       -		    format);
>       +		die(_("invalid value for '%s': '%s'"),
>      -+			  "fetch.output", format);
>      ++		    "fetch.output", format);
>        
>        	for (rm = ref_map; rm; rm = rm->next) {
>        		if (rm->status == REF_STATUS_REJECT_SHALLOW ||
>      @@ gpg-interface.c: int git_gpg_config(const char *var, const char *value, void *cb
>        		fmt = get_format_by_name(value);
>        		if (!fmt)
>       -			return error("unsupported value for %s: %s",
>      -+			return error("invalid value for '%s': '%s'",
>      ++			return error(_("invalid value for '%s': '%s'"),
>        				     var, value);
>        		use_format = fmt;
>        		return 0;
>      @@ gpg-interface.c: int git_gpg_config(const char *var, const char *value, void *cb
>        
>        		if (ret)
>       -			return error("unsupported value for %s: %s", var,
>      -+			return error("invalid value for '%s': '%s'", var,
>      - 				     value);
>      +-				     value);
>      ++			return error(_("invalid value for '%s': '%s'"),
>      ++				     var, value);
>        		return 0;
>        	}
>      + 
>       
>        ## ls-refs.c ##
>       @@ ls-refs.c: static void ensure_config_read(void)
>      @@ ls-refs.c: static void ensure_config_read(void)
>        			/* do nothing */
>        		} else {
>       -			die(_("invalid value '%s' for lsrefs.unborn"), str);
>      -+			die(_("invalid value for '%s': '%s'"), "lsrefs.unborn", str);
>      ++			die(_("invalid value for '%s': '%s'"),
>      ++			    "lsrefs.unborn", str);
>        		}
>        	}
>        	config_read = 1;
>      @@ parallel-checkout.c: void get_parallel_checkout_configs(int *num_workers, int *t
>        	if (env_workers && *env_workers) {
>        		if (strtol_i(env_workers, 10, num_workers)) {
>       -			die("invalid value for GIT_TEST_CHECKOUT_WORKERS: '%s'",
>      +-			    env_workers);
>       +			die(_("invalid value for '%s': '%s'"),
>      -+				"GIT_TEST_CHECKOUT_WORKERS",
>      - 			    env_workers);
>      ++			    "GIT_TEST_CHECKOUT_WORKERS", env_workers);
>        		}
>        		if (*num_workers < 1)
>      + 			*num_workers = online_cpus();
>       
>        ## sequencer.c ##
>       @@ sequencer.c: static int populate_opts_cb(const char *key, const char *value, void *data)
>      @@ setup.c: static enum extension_result handle_extension(const char *var,
>        		format = hash_algo_by_name(value);
>        		if (format == GIT_HASH_UNKNOWN)
>       -			return error("invalid value for 'extensions.objectformat'");
>      -+			return error(_("invalid value for '%s': '%s'"), "extensions.objectformat", value);
>      ++			return error(_("invalid value for '%s': '%s'"),
>      ++				     "extensions.objectformat", value);
>        		data->hash_algo = format;
>        		return EXTENSION_OK;
>        	}
>  3:  376f8b56908 = 3:  d5ddd903df7 i18n: remove from i18n strings that do not hold translatable parts
>  4:  8b0057f6180 = 4:  b8e80e178ee i18n: transfer variables into placeholders in command synopsis
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-30 22:01     ` [PATCH v3 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
  2022-01-31  7:15       ` Johannes Sixt
@ 2022-01-31 10:56       ` Phillip Wood
  1 sibling, 0 replies; 41+ messages in thread
From: Phillip Wood @ 2022-01-31 10:56 UTC (permalink / raw)
  To: Jean-Noël Avila via GitGitGadget, git
  Cc: Johannes Sixt, Jean-Noël Avila

Hi Jean-Noël

On 30/01/2022 22:01, Jean-Noël Avila via GitGitGadget wrote:
> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
> 
> Find more incompatible options to factorize.
> 
> When more than two options are mutually exclusive, print the ones
> which are actually on the command line.

I think this looks good and I'd be happy to see it go in as is with the 
blank line hunk removed. I like the way it now shows all the 
incompatible options that were on the command line, not just the first 
two. Using a function to handle the messages makes the code much nicer 
to read as well. I'm not sure that making die_for_incompatible_opt3() 
really needs to be inline or that we need _for_ in the function names 
but neither does any harm.

Best Wishes

Phillip

> Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
> ---
>   builtin/commit.c                          | 35 ++++++++++-------------
>   builtin/difftool.c                        |  5 ++--
>   builtin/grep.c                            |  8 ++----
>   builtin/log.c                             |  5 ++--
>   builtin/merge-base.c                      |  6 ++--
>   parse-options.c                           | 34 ++++++++++++++++++++++
>   parse-options.h                           | 17 +++++++++++
>   t/t7500-commit-template-squash-signoff.sh |  2 +-
>   8 files changed, 80 insertions(+), 32 deletions(-)
> 
> diff --git a/builtin/commit.c b/builtin/commit.c
> index b9ed0374e30..33ca9e99c80 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -1242,8 +1242,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
>   				      struct commit *current_head,
>   				      struct wt_status *s)
>   {
> -	int f = 0;
> -
>   	argc = parse_options(argc, argv, prefix, options, usage, 0);
>   	finalize_deferred_config(s);
>   
> @@ -1251,7 +1249,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
>   		force_author = find_author_by_nickname(force_author);
>   
>   	if (force_author && renew_authorship)
> -		die(_("Using both --reset-author and --author does not make sense"));
> +		die(_("options '%s' and '%s' cannot be used together"), "--reset-author", "--author");
>   
>   	if (logfile || have_option_m || use_message)
>   		use_editor = 0;
> @@ -1268,20 +1266,16 @@ static int parse_and_validate_options(int argc, const char *argv[],
>   			die(_("You are in the middle of a rebase -- cannot amend."));
>   	}
>   	if (fixup_message && squash_message)
> -		die(_("Options --squash and --fixup cannot be used together"));
> -	if (use_message)
> -		f++;
> -	if (edit_message)
> -		f++;
> -	if (fixup_message)
> -		f++;
> -	if (logfile)
> -		f++;
> -	if (f > 1)
> -		die(_("Only one of -c/-C/-F/--fixup can be used."));
> -	if (have_option_m && (edit_message || use_message || logfile))
> -		die((_("Option -m cannot be combined with -c/-C/-F.")));
> -	if (f || have_option_m)
> +		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
> +	die_for_incompatible_opt4(!!use_message, "-C",
> +				  !!edit_message, "-c",
> +				  !!logfile, "-F",
> +				  !!fixup_message, "--fixup");
> +	die_for_incompatible_opt4(have_option_m, "-m",
> +				  !!edit_message, "-c",
> +				  !!use_message, "-C",
> +				  !!logfile, "-F");
> +	if (use_message || edit_message || logfile ||fixup_message || have_option_m)
>   		template_file = NULL;
>   	if (edit_message)
>   		use_message = edit_message;
> @@ -1306,9 +1300,10 @@ static int parse_and_validate_options(int argc, const char *argv[],
>   	if (patch_interactive)
>   		interactive = 1;
>   
> -	if (also + only + all + interactive > 1)
> -		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
> -
> +	die_for_incompatible_opt4(also, "-i/--include",
> +				  only, "-o/--only",
> +				  all, "-a/--all",
> +				  interactive, "--interactive/-p/--patch");
>   	if (fixup_message) {
>   		/*
>   		 * We limit --fixup's suboptions to only alpha characters.
> diff --git a/builtin/difftool.c b/builtin/difftool.c
> index c79fbbf67e5..faa3507369a 100644
> --- a/builtin/difftool.c
> +++ b/builtin/difftool.c
> @@ -732,8 +732,9 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
>   	} else if (dir_diff)
>   		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
>   
> -	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
> -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
> +	die_for_incompatible_opt3(use_gui_tool, "--gui",
> +				  !!difftool_cmd, "--tool",
> +				  !!extcmd, "--extcmd");
>   
>   	if (use_gui_tool)
>   		setenv("GIT_MERGETOOL_GUI", "true", 1);
> diff --git a/builtin/grep.c b/builtin/grep.c
> index 9e34a820ad4..88144f06300 100644
> --- a/builtin/grep.c
> +++ b/builtin/grep.c
> @@ -1167,11 +1167,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
>   	if (!show_in_pager && !opt.status_only)
>   		setup_pager();
>   
> -	if (!use_index && (untracked || cached))
> -		die(_("--cached or --untracked cannot be used with --no-index"));
> -
> -	if (untracked && cached)
> -		die(_("--untracked cannot be used with --cached"));
> +	die_for_incompatible_opt3(!use_index, "--no-index",
> +				  untracked, "--untracked",
> +				  cached, "--cached");
>   
>   	if (!use_index || untracked) {
>   		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
> diff --git a/builtin/log.c b/builtin/log.c
> index 4b493408cc5..970aa3483c4 100644
> --- a/builtin/log.c
> +++ b/builtin/log.c
> @@ -1978,8 +1978,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
>   	if (rev.show_notes)
>   		load_display_notes(&rev.notes_opt);
>   
> -	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
> -		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
> +	die_for_incompatible_opt3(use_stdout, "--stdout",
> +				  rev.diffopt.close_file, "--output",
> +				  !!output_directory, "--output-directory");
>   
>   	if (use_stdout) {
>   		setup_pager();
> diff --git a/builtin/merge-base.c b/builtin/merge-base.c
> index 6719ac198dc..26b84980dbd 100644
> --- a/builtin/merge-base.c
> +++ b/builtin/merge-base.c
> @@ -159,12 +159,14 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
>   		if (argc < 2)
>   			usage_with_options(merge_base_usage, options);
>   		if (show_all)
> -			die("--is-ancestor cannot be used with --all");
> +			die(_("options '%s' and '%s' cannot be used together"),
> +			    "--is-ancestor", "--all");
>   		return handle_is_ancestor(argc, argv);
>   	}
>   
>   	if (cmdmode == 'r' && show_all)
> -		die("--independent cannot be used with --all");
> +		die(_("options '%s' and '%s' cannot be used together"),
> +		    "--independent", "--all");
>   
>   	if (cmdmode == 'o')
>   		return handle_octopus(argc, argv, show_all);
> diff --git a/parse-options.c b/parse-options.c
> index a8283037be9..276e3911a74 100644
> --- a/parse-options.c
> +++ b/parse-options.c
> @@ -1079,3 +1079,37 @@ void NORETURN usage_msg_opt(const char *msg,
>   	die_message("%s\n", msg); /* The extra \n is intentional */
>   	usage_with_options(usagestr, options);
>   }
> +
> +void die_for_incompatible_opt4(int opt1, const char *opt1_name,
> +			       int opt2, const char *opt2_name,
> +			       int opt3, const char *opt3_name,
> +			       int opt4, const char *opt4_name)
> +{
> +	int count = 0;
> +	const char *options[4];
> +
> +	if (opt1)
> +		options[count++] = opt1_name;
> +	if (opt2)
> +		options[count++] = opt2_name;
> +	if (opt3)
> +		options[count++] = opt3_name;
> +	if (opt4)
> +		options[count++] = opt4_name;
> +	switch (count) {
> +	case 4:
> +		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
> +		    opt1_name, opt2_name, opt3_name, opt4_name);
> +		break;
> +	case 3:
> +		die(_("options '%s', '%s', and '%s' cannot be used together"),
> +		    options[0], options[1], options[2]);
> +		break;
> +	case 2:
> +		die(_("options '%s' and '%s' cannot be used together"),
> +		    options[0], options[1]);
> +		break;
> +	default:
> +		break;
> +	}
> +}
> diff --git a/parse-options.h b/parse-options.h
> index e22846d3b7b..68f7ae9c31a 100644
> --- a/parse-options.h
> +++ b/parse-options.h
> @@ -225,6 +225,22 @@ NORETURN void usage_msg_opt(const char *msg,
>   			    const char * const *usagestr,
>   			    const struct option *options);
>   
> +void die_for_incompatible_opt4(int opt1, const char *opt1_name,
> +			       int opt2, const char *opt2_name,
> +			       int opt3, const char *opt3_name,
> +			       int opt4, const char *opt4_name);
> +
> +
> +inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
> +				      int opt2, const char *opt2_name,
> +				      int opt3, const char *opt3_name)
> +{
> +	die_for_incompatible_opt4(opt1, opt1_name,
> +				  opt2, opt2_name,
> +				  opt3, opt3_name,
> +				  0, "");
> +}
> +
>   /*
>    * Use these assertions for callbacks that expect to be called with NONEG and
>    * NOARG respectively, and do not otherwise handle the "unset" and "arg"
> @@ -339,4 +355,5 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);
>   #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
>   #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
>   
> +
>   #endif
> diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
> index 91964653a0b..5fcaa0b4f2a 100755
> --- a/t/t7500-commit-template-squash-signoff.sh
> +++ b/t/t7500-commit-template-squash-signoff.sh
> @@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
>   '
>   
>   test_expect_success '--fixup=reword: -F give error message' '
> -	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
> +	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
>   	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
>   	test_cmp expect actual
>   '


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 4/4] i18n: transfer variables into placeholders in command synopsis
  2022-01-30 22:01     ` [PATCH v3 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
@ 2022-01-31 11:00       ` Phillip Wood
  2022-01-31 13:36         ` Jean-Noël Avila
  0 siblings, 1 reply; 41+ messages in thread
From: Phillip Wood @ 2022-01-31 11:00 UTC (permalink / raw)
  To: Jean-Noël Avila via GitGitGadget, git
  Cc: Johannes Sixt, Jean-Noël Avila

On 30/01/2022 22:01, Jean-Noël Avila via GitGitGadget wrote:
> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
> 
> This applies the style guide for documentation.

I don't really understand the title of this patch. Should 'transfer' be 
'transform'? All the changes look fine but seem to be two sorts of 
changes mixed together
  - adding '<>' around arguments where they are missing
  - converting plurals followed by '...' into singulars followed by '...'

Best Wishes

Phillip

> Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
> ---
>   builtin/fast-export.c | 2 +-
>   builtin/reflog.c      | 4 ++--
>   builtin/rev-list.c    | 2 +-
>   3 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/builtin/fast-export.c b/builtin/fast-export.c
> index 9f1c730e587..510139e9b54 100644
> --- a/builtin/fast-export.c
> +++ b/builtin/fast-export.c
> @@ -26,7 +26,7 @@
>   #include "commit-slab.h"
>   
>   static const char *fast_export_usage[] = {
> -	N_("git fast-export [rev-list-opts]"),
> +	N_("git fast-export [<rev-list-opts>]"),
>   	NULL
>   };
>   
> diff --git a/builtin/reflog.c b/builtin/reflog.c
> index ee5ee8d8cf6..343a10d371b 100644
> --- a/builtin/reflog.c
> +++ b/builtin/reflog.c
> @@ -17,10 +17,10 @@ static const char reflog_expire_usage[] =
>   N_("git reflog expire [--expire=<time>] "
>      "[--expire-unreachable=<time>] "
>      "[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] "
> -   "[--verbose] [--all] <refs>...");
> +   "[--verbose] [--all] <ref>...");
>   static const char reflog_delete_usage[] =
>   N_("git reflog delete [--rewrite] [--updateref] "
> -   "[--dry-run | -n] [--verbose] <refs>...");
> +   "[--dry-run | -n] [--verbose] <ref>...");
>   static const char reflog_exists_usage[] =
>   N_("git reflog exists <ref>");
>   
> diff --git a/builtin/rev-list.c b/builtin/rev-list.c
> index 777558e9b06..38528c7f156 100644
> --- a/builtin/rev-list.c
> +++ b/builtin/rev-list.c
> @@ -20,7 +20,7 @@
>   #include "packfile.h"
>   
>   static const char rev_list_usage[] =
> -"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
> +"git rev-list [<options>] <commit-id>... [-- <path>...]\n"
>   "  limiting output:\n"
>   "    --max-count=<n>\n"
>   "    --max-age=<epoch>\n"


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v3 4/4] i18n: transfer variables into placeholders in command synopsis
  2022-01-31 11:00       ` Phillip Wood
@ 2022-01-31 13:36         ` Jean-Noël Avila
  0 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila @ 2022-01-31 13:36 UTC (permalink / raw)
  To: phillip.wood, Jean-Noël Avila via GitGitGadget, git; +Cc: Johannes Sixt

Le 31/01/2022 à 12:00, Phillip Wood a écrit :
> On 30/01/2022 22:01, Jean-Noël Avila via GitGitGadget wrote:
>> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
>>
>> This applies the style guide for documentation.
> 
> I don't really understand the title of this patch. Should 'transfer' be 
> 'transform'? All the changes look fine but seem to be two sorts of 
> changes mixed together
>   - adding '<>' around arguments where they are missing
>   - converting plurals followed by '...' into singulars followed by '...'
> 
> Best Wishes
> 
> Phillip
> 

TBH, this patch is a remaining of some changes performed while making 
the preceding one. They are the places that were false positive from the 
grep.

Fair enough, the changes are a little broader than advertised.

As for the plural forms transformed into singular forms, the coding 
guidelines is clear about repeated parameters of the same type, (e.g. 
<file>...), but some subsets of parameters are still preserved with 
plural, such as <options>, in which case they are not "atomic" (they may 
provide several cells in argv). This is not formalized atm.

My heuristic is that when the subset is not an array of a given type, 
but may be a collection of different types, we keep the plural. Maybe 
using another syntax for these "sub-expressions", along with a link to 
where to find them would help.


JN

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v4 0/4] Factorize i18n
  2022-01-30 22:01   ` [PATCH v3 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
                       ` (4 preceding siblings ...)
  2022-01-31  7:15     ` [PATCH v3 0/4] Factorize i18n Johannes Sixt
@ 2022-01-31 22:07     ` Jean-Noël Avila via GitGitGadget
  2022-01-31 22:07       ` [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
                         ` (3 more replies)
  5 siblings, 4 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-31 22:07 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila

This is a small series of i18n factorizations. Again the idea is to:

 * reduce the number of strings to translate
 * make life easier for translators by removing constant parts of the
   strings to translate
 * uniformize the UI by using a type of message for the a given type of
   condition.

Changes since V1:

 * factorize checks of more than 2 incompatible options into dedicated
   functions which list all the incompatible options present on the command
   line

Changes since V2:

 * switch to tab size 8
 * rename die_if* to die_for*
 * make 3 arg check a call to 4 arg check
 * switch another part to die_for_incompatible_opt4

Changes since V3:

 * remove spurious blank line
 * reword last commit to better reflect the changes

Jean-Noël Avila (4):
  i18n: factorize more 'incompatible options' messages
  i18n: factorize "invalid value" messages
  i18n: remove from i18n strings that do not hold translatable parts
  i18n: fix some misformated placeholders in command synopsis

 archive.c                                 |  2 +-
 builtin/am.c                              |  8 ++++--
 builtin/bisect--helper.c                  |  6 ++--
 builtin/blame.c                           |  7 +++--
 builtin/commit.c                          | 35 ++++++++++-------------
 builtin/count-objects.c                   |  2 +-
 builtin/difftool.c                        |  5 ++--
 builtin/fast-export.c                     |  2 +-
 builtin/fetch.c                           |  4 +--
 builtin/grep.c                            |  8 ++----
 builtin/hash-object.c                     |  2 +-
 builtin/help.c                            |  4 +--
 builtin/log.c                             |  5 ++--
 builtin/merge-base.c                      |  6 ++--
 builtin/mktag.c                           |  2 +-
 builtin/mktree.c                          |  2 +-
 builtin/notes.c                           |  6 ++--
 builtin/pack-objects.c                    |  2 +-
 builtin/prune-packed.c                    |  2 +-
 builtin/pull.c                            |  6 ++--
 builtin/push.c                            |  2 +-
 builtin/rebase.c                          |  2 +-
 builtin/reflog.c                          |  6 ++--
 builtin/remote.c                          |  2 +-
 builtin/replace.c                         |  2 +-
 builtin/rev-list.c                        |  2 +-
 builtin/send-pack.c                       |  2 +-
 builtin/sparse-checkout.c                 |  8 +++---
 builtin/stripspace.c                      |  4 +--
 builtin/submodule--helper.c               |  2 +-
 builtin/update-server-info.c              |  2 +-
 diff-merges.c                             |  2 +-
 gpg-interface.c                           |  6 ++--
 ls-refs.c                                 |  3 +-
 parallel-checkout.c                       |  4 +--
 parse-options.c                           | 34 ++++++++++++++++++++++
 parse-options.h                           | 16 +++++++++++
 sequencer.c                               |  2 +-
 setup.c                                   |  3 +-
 submodule-config.c                        |  2 +-
 t/t4150-am.sh                             |  2 +-
 t/t7500-commit-template-squash-signoff.sh |  2 +-
 42 files changed, 139 insertions(+), 87 deletions(-)


base-commit: 5d01301f2b865aa8dba1654d3f447ce9d21db0b5
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1123%2Fjnavila%2Ffactorize_i18n-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1123/jnavila/factorize_i18n-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/1123

Range-diff vs v3:

 1:  aac3f9821c7 ! 1:  2eac2ef502b i18n: factorize more 'incompatible options' messages
     @@ parse-options.h: NORETURN void usage_msg_opt(const char *msg,
       /*
        * Use these assertions for callbacks that expect to be called with NONEG and
        * NOARG respectively, and do not otherwise handle the "unset" and "arg"
     -@@ parse-options.h: int parse_opt_tracking_mode(const struct option *, const char *, int);
     - #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
     - #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
     - 
     -+
     - #endif
      
       ## t/t7500-commit-template-squash-signoff.sh ##
      @@ t/t7500-commit-template-squash-signoff.sh: test_expect_success '--fixup=reword: give error with pathsec' '
 2:  078336ae418 = 2:  2d359118d8f i18n: factorize "invalid value" messages
 3:  d5ddd903df7 = 3:  cdaa576aac1 i18n: remove from i18n strings that do not hold translatable parts
 4:  b8e80e178ee ! 4:  f37b03128b2 i18n: transfer variables into placeholders in command synopsis
     @@ Metadata
      Author: Jean-Noël Avila <jn.avila@free.fr>
      
       ## Commit message ##
     -    i18n: transfer variables into placeholders in command synopsis
     +    i18n: fix some misformated placeholders in command synopsis
     +
     +     * add '<>' around arguments where missing
     +     * convert plurals into '...' forms
      
          This applies the style guide for documentation.
      
          Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
     +    Reviewed-by: Phillip Wood <phillip.wood123@gmail.com>
      
       ## builtin/fast-export.c ##
      @@

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-31 22:07     ` [PATCH v4 " Jean-Noël Avila via GitGitGadget
@ 2022-01-31 22:07       ` Jean-Noël Avila via GitGitGadget
  2022-01-31 22:41         ` Junio C Hamano
  2022-01-31 22:07       ` [PATCH v4 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-31 22:07 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Find more incompatible options to factorize.

When more than two options are mutually exclusive, print the ones
which are actually on the command line.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/commit.c                          | 35 ++++++++++-------------
 builtin/difftool.c                        |  5 ++--
 builtin/grep.c                            |  8 ++----
 builtin/log.c                             |  5 ++--
 builtin/merge-base.c                      |  6 ++--
 parse-options.c                           | 34 ++++++++++++++++++++++
 parse-options.h                           | 16 +++++++++++
 t/t7500-commit-template-squash-signoff.sh |  2 +-
 8 files changed, 79 insertions(+), 32 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index b9ed0374e30..33ca9e99c80 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1242,8 +1242,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
 				      struct commit *current_head,
 				      struct wt_status *s)
 {
-	int f = 0;
-
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
 	finalize_deferred_config(s);
 
@@ -1251,7 +1249,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
 		force_author = find_author_by_nickname(force_author);
 
 	if (force_author && renew_authorship)
-		die(_("Using both --reset-author and --author does not make sense"));
+		die(_("options '%s' and '%s' cannot be used together"), "--reset-author", "--author");
 
 	if (logfile || have_option_m || use_message)
 		use_editor = 0;
@@ -1268,20 +1266,16 @@ static int parse_and_validate_options(int argc, const char *argv[],
 			die(_("You are in the middle of a rebase -- cannot amend."));
 	}
 	if (fixup_message && squash_message)
-		die(_("Options --squash and --fixup cannot be used together"));
-	if (use_message)
-		f++;
-	if (edit_message)
-		f++;
-	if (fixup_message)
-		f++;
-	if (logfile)
-		f++;
-	if (f > 1)
-		die(_("Only one of -c/-C/-F/--fixup can be used."));
-	if (have_option_m && (edit_message || use_message || logfile))
-		die((_("Option -m cannot be combined with -c/-C/-F.")));
-	if (f || have_option_m)
+		die(_("options '%s' and '%s' cannot be used together"), "--squash", "--fixup");
+	die_for_incompatible_opt4(!!use_message, "-C",
+				  !!edit_message, "-c",
+				  !!logfile, "-F",
+				  !!fixup_message, "--fixup");
+	die_for_incompatible_opt4(have_option_m, "-m",
+				  !!edit_message, "-c",
+				  !!use_message, "-C",
+				  !!logfile, "-F");
+	if (use_message || edit_message || logfile ||fixup_message || have_option_m)
 		template_file = NULL;
 	if (edit_message)
 		use_message = edit_message;
@@ -1306,9 +1300,10 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (patch_interactive)
 		interactive = 1;
 
-	if (also + only + all + interactive > 1)
-		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
-
+	die_for_incompatible_opt4(also, "-i/--include",
+				  only, "-o/--only",
+				  all, "-a/--all",
+				  interactive, "--interactive/-p/--patch");
 	if (fixup_message) {
 		/*
 		 * We limit --fixup's suboptions to only alpha characters.
diff --git a/builtin/difftool.c b/builtin/difftool.c
index c79fbbf67e5..faa3507369a 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -732,8 +732,9 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 	} else if (dir_diff)
 		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
 
-	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
+	die_for_incompatible_opt3(use_gui_tool, "--gui",
+				  !!difftool_cmd, "--tool",
+				  !!extcmd, "--extcmd");
 
 	if (use_gui_tool)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
diff --git a/builtin/grep.c b/builtin/grep.c
index 9e34a820ad4..88144f06300 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1167,11 +1167,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	if (!show_in_pager && !opt.status_only)
 		setup_pager();
 
-	if (!use_index && (untracked || cached))
-		die(_("--cached or --untracked cannot be used with --no-index"));
-
-	if (untracked && cached)
-		die(_("--untracked cannot be used with --cached"));
+	die_for_incompatible_opt3(!use_index, "--no-index",
+				  untracked, "--untracked",
+				  cached, "--cached");
 
 	if (!use_index || untracked) {
 		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
diff --git a/builtin/log.c b/builtin/log.c
index 4b493408cc5..970aa3483c4 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1978,8 +1978,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	if (rev.show_notes)
 		load_display_notes(&rev.notes_opt);
 
-	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
+	die_for_incompatible_opt3(use_stdout, "--stdout",
+				  rev.diffopt.close_file, "--output",
+				  !!output_directory, "--output-directory");
 
 	if (use_stdout) {
 		setup_pager();
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 6719ac198dc..26b84980dbd 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -159,12 +159,14 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
 		if (argc < 2)
 			usage_with_options(merge_base_usage, options);
 		if (show_all)
-			die("--is-ancestor cannot be used with --all");
+			die(_("options '%s' and '%s' cannot be used together"),
+			    "--is-ancestor", "--all");
 		return handle_is_ancestor(argc, argv);
 	}
 
 	if (cmdmode == 'r' && show_all)
-		die("--independent cannot be used with --all");
+		die(_("options '%s' and '%s' cannot be used together"),
+		    "--independent", "--all");
 
 	if (cmdmode == 'o')
 		return handle_octopus(argc, argv, show_all);
diff --git a/parse-options.c b/parse-options.c
index a8283037be9..276e3911a74 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -1079,3 +1079,37 @@ void NORETURN usage_msg_opt(const char *msg,
 	die_message("%s\n", msg); /* The extra \n is intentional */
 	usage_with_options(usagestr, options);
 }
+
+void die_for_incompatible_opt4(int opt1, const char *opt1_name,
+			       int opt2, const char *opt2_name,
+			       int opt3, const char *opt3_name,
+			       int opt4, const char *opt4_name)
+{
+	int count = 0;
+	const char *options[4];
+
+	if (opt1)
+		options[count++] = opt1_name;
+	if (opt2)
+		options[count++] = opt2_name;
+	if (opt3)
+		options[count++] = opt3_name;
+	if (opt4)
+		options[count++] = opt4_name;
+	switch (count) {
+	case 4:
+		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
+		    opt1_name, opt2_name, opt3_name, opt4_name);
+		break;
+	case 3:
+		die(_("options '%s', '%s', and '%s' cannot be used together"),
+		    options[0], options[1], options[2]);
+		break;
+	case 2:
+		die(_("options '%s' and '%s' cannot be used together"),
+		    options[0], options[1]);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/parse-options.h b/parse-options.h
index e22846d3b7b..eb86c505470 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -225,6 +225,22 @@ NORETURN void usage_msg_opt(const char *msg,
 			    const char * const *usagestr,
 			    const struct option *options);
 
+void die_for_incompatible_opt4(int opt1, const char *opt1_name,
+			       int opt2, const char *opt2_name,
+			       int opt3, const char *opt3_name,
+			       int opt4, const char *opt4_name);
+
+
+inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
+				      int opt2, const char *opt2_name,
+				      int opt3, const char *opt3_name)
+{
+	die_for_incompatible_opt4(opt1, opt1_name,
+				  opt2, opt2_name,
+				  opt3, opt3_name,
+				  0, "");
+}
+
 /*
  * Use these assertions for callbacks that expect to be called with NONEG and
  * NOARG respectively, and do not otherwise handle the "unset" and "arg"
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 91964653a0b..5fcaa0b4f2a 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
 '
 
 test_expect_success '--fixup=reword: -F give error message' '
-	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
+	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
 	test_cmp expect actual
 '
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v4 2/4] i18n: factorize "invalid value" messages
  2022-01-31 22:07     ` [PATCH v4 " Jean-Noël Avila via GitGitGadget
  2022-01-31 22:07       ` [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
@ 2022-01-31 22:07       ` Jean-Noël Avila via GitGitGadget
  2022-01-31 22:07       ` [PATCH v4 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
  2022-01-31 22:07       ` [PATCH v4 4/4] i18n: fix some misformated placeholders in command synopsis Jean-Noël Avila via GitGitGadget
  3 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-31 22:07 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Use the same message when an invalid value is passed to a command line
option or a configuration variable.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 builtin/am.c           | 8 +++++---
 builtin/blame.c        | 7 ++++---
 builtin/fetch.c        | 4 ++--
 builtin/pack-objects.c | 2 +-
 builtin/pull.c         | 6 +++---
 builtin/push.c         | 2 +-
 builtin/send-pack.c    | 2 +-
 diff-merges.c          | 2 +-
 gpg-interface.c        | 6 +++---
 ls-refs.c              | 3 ++-
 parallel-checkout.c    | 4 ++--
 sequencer.c            | 2 +-
 setup.c                | 3 ++-
 submodule-config.c     | 2 +-
 t/t4150-am.sh          | 2 +-
 15 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index b6be1f1cb11..97dbeb8e49e 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -199,7 +199,7 @@ static int am_option_parse_empty(const struct option *opt,
 	else if (!strcmp(arg, "keep"))
 		*opt_value = KEEP_EMPTY_COMMIT;
 	else
-		return error(_("Invalid value for --empty: %s"), arg);
+		return error(_("invalid value for '%s': '%s'"), "--empty", arg);
 
 	return 0;
 }
@@ -2239,7 +2239,8 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
 	 * when you add new options
 	 */
 	else
-		return error(_("Invalid value for --patch-format: %s"), arg);
+		return error(_("invalid value for '%s': '%s'"),
+			     "--patch-format", arg);
 	return 0;
 }
 
@@ -2282,7 +2283,8 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 				break;
 		}
 		if (new_value >= ARRAY_SIZE(valid_modes))
-			return error(_("Invalid value for --show-current-patch: %s"), arg);
+			return error(_("invalid value for '%s': '%s'"),
+				     "--show-current-patch", arg);
 	}
 
 	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
diff --git a/builtin/blame.c b/builtin/blame.c
index 7fafeac4081..9c142f17a2e 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -721,8 +721,8 @@ static int git_blame_config(const char *var, const char *value, void *cb)
 	}
 	if (!strcmp(var, "color.blame.repeatedlines")) {
 		if (color_parse_mem(value, strlen(value), repeated_meta_color))
-			warning(_("invalid color '%s' in color.blame.repeatedLines"),
-				value);
+			warning(_("invalid value for '%s': '%s'"),
+				"color.blame.repeatedLines", value);
 		return 0;
 	}
 	if (!strcmp(var, "color.blame.highlightrecent")) {
@@ -739,7 +739,8 @@ static int git_blame_config(const char *var, const char *value, void *cb)
 			coloring_mode &= ~(OUTPUT_COLOR_LINE |
 					    OUTPUT_SHOW_AGE_WITH_COLOR);
 		} else {
-			warning(_("invalid value for blame.coloring"));
+			warning(_("invalid value for '%s': '%s'"),
+				"blame.coloring", value);
 			return 0;
 		}
 	}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 5f06b21f8e9..8be19bb8799 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -763,8 +763,8 @@ static void prepare_format_display(struct ref *ref_map)
 	else if (!strcasecmp(format, "compact"))
 		compact_format = 1;
 	else
-		die(_("configuration fetch.output contains invalid value %s"),
-		    format);
+		die(_("invalid value for '%s': '%s'"),
+		    "fetch.output", format);
 
 	for (rm = ref_map; rm; rm = rm->next) {
 		if (rm->status == REF_STATUS_REJECT_SHALLOW ||
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index ba2006f2212..192c3ca305e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3504,7 +3504,7 @@ static int option_parse_missing_action(const struct option *opt,
 		return 0;
 	}
 
-	die(_("invalid value for --missing"));
+	die(_("invalid value for '%s': '%s'"), "--missing", arg);
 	return 0;
 }
 
diff --git a/builtin/pull.c b/builtin/pull.c
index 100cbf9fb85..e54a0ccadc6 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -42,9 +42,9 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
 		return v;
 
 	if (fatal)
-		die(_("Invalid value for %s: %s"), key, value);
+		die(_("invalid value for '%s': '%s'"), key, value);
 	else
-		error(_("Invalid value for %s: %s"), key, value);
+		error(_("invalid value for '%s': '%s'"), key, value);
 
 	return REBASE_INVALID;
 }
@@ -318,7 +318,7 @@ static const char *config_get_ff(void)
 	if (!strcmp(value, "only"))
 		return "--ff-only";
 
-	die(_("Invalid value for pull.ff: %s"), value);
+	die(_("invalid value for '%s': '%s'"), "pull.ff", value);
 }
 
 /**
diff --git a/builtin/push.c b/builtin/push.c
index 359db90321c..cad997965a7 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -486,7 +486,7 @@ static int git_push_config(const char *k, const char *v, void *cb)
 				if (value && !strcasecmp(value, "if-asked"))
 					set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_IF_ASKED);
 				else
-					return error("Invalid value for '%s'", k);
+					return error(_("invalid value for '%s'"), k);
 			}
 		}
 	} else if (!strcmp(k, "push.recursesubmodules")) {
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 69c432ef1a6..64962be0168 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -145,7 +145,7 @@ static int send_pack_config(const char *k, const char *v, void *cb)
 				if (value && !strcasecmp(value, "if-asked"))
 					args.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
 				else
-					return error("Invalid value for '%s'", k);
+					return error(_("invalid value for '%s'"), k);
 			}
 		}
 	}
diff --git a/diff-merges.c b/diff-merges.c
index 5060ccd890b..cd6c102a0d5 100644
--- a/diff-merges.c
+++ b/diff-merges.c
@@ -67,7 +67,7 @@ static void set_diff_merges(struct rev_info *revs, const char *optarg)
 	diff_merges_setup_func_t func = func_by_opt(optarg);
 
 	if (!func)
-		die(_("unknown value for --diff-merges: %s"), optarg);
+		die(_("invalid value for '%s': '%s'"), "--diff-merges", optarg);
 
 	func(revs);
 
diff --git a/gpg-interface.c b/gpg-interface.c
index b52eb0e2e04..4e084b08f67 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -702,7 +702,7 @@ int git_gpg_config(const char *var, const char *value, void *cb)
 			return config_error_nonbool(var);
 		fmt = get_format_by_name(value);
 		if (!fmt)
-			return error("unsupported value for %s: %s",
+			return error(_("invalid value for '%s': '%s'"),
 				     var, value);
 		use_format = fmt;
 		return 0;
@@ -717,8 +717,8 @@ int git_gpg_config(const char *var, const char *value, void *cb)
 		free(trust);
 
 		if (ret)
-			return error("unsupported value for %s: %s", var,
-				     value);
+			return error(_("invalid value for '%s': '%s'"),
+				     var, value);
 		return 0;
 	}
 
diff --git a/ls-refs.c b/ls-refs.c
index 54078323dcb..98e69373c84 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -34,7 +34,8 @@ static void ensure_config_read(void)
 		} else if (!strcmp(str, "ignore")) {
 			/* do nothing */
 		} else {
-			die(_("invalid value '%s' for lsrefs.unborn"), str);
+			die(_("invalid value for '%s': '%s'"),
+			    "lsrefs.unborn", str);
 		}
 	}
 	config_read = 1;
diff --git a/parallel-checkout.c b/parallel-checkout.c
index 8dd7e7bad40..31a3d0ee1bf 100644
--- a/parallel-checkout.c
+++ b/parallel-checkout.c
@@ -39,8 +39,8 @@ void get_parallel_checkout_configs(int *num_workers, int *threshold)
 
 	if (env_workers && *env_workers) {
 		if (strtol_i(env_workers, 10, num_workers)) {
-			die("invalid value for GIT_TEST_CHECKOUT_WORKERS: '%s'",
-			    env_workers);
+			die(_("invalid value for '%s': '%s'"),
+			    "GIT_TEST_CHECKOUT_WORKERS", env_workers);
 		}
 		if (*num_workers < 1)
 			*num_workers = online_cpus();
diff --git a/sequencer.c b/sequencer.c
index 5213d16e971..683f5392eba 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2806,7 +2806,7 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
 		return error(_("invalid key: %s"), key);
 
 	if (!error_flag)
-		return error(_("invalid value for %s: %s"), key, value);
+		return error(_("invalid value for '%s': '%s'"), key, value);
 
 	return 0;
 }
diff --git a/setup.c b/setup.c
index af3b8c09abe..04ce33cdcd4 100644
--- a/setup.c
+++ b/setup.c
@@ -559,7 +559,8 @@ static enum extension_result handle_extension(const char *var,
 			return config_error_nonbool(var);
 		format = hash_algo_by_name(value);
 		if (format == GIT_HASH_UNKNOWN)
-			return error("invalid value for 'extensions.objectformat'");
+			return error(_("invalid value for '%s': '%s'"),
+				     "extensions.objectformat", value);
 		data->hash_algo = format;
 		return EXTENSION_OK;
 	}
diff --git a/submodule-config.c b/submodule-config.c
index f95344028b5..fb95a026f48 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -496,7 +496,7 @@ static int parse_config(const char *var, const char *value, void *data)
 		else if (parse_submodule_update_strategy(value,
 			 &submodule->update_strategy) < 0 ||
 			 submodule->update_strategy.type == SM_UPDATE_COMMAND)
-			die(_("invalid value for %s"), var);
+			die(_("invalid value for '%s'"), var);
 	} else if (!strcmp(item.buf, "shallow")) {
 		if (!me->overwrite && submodule->recommend_shallow != -1)
 			warn_multiple_config(me->treeish_name, submodule->name,
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 6caff0ca397..159fae8d016 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -1169,7 +1169,7 @@ test_expect_success 'invalid when passing the --empty option alone' '
 	test_when_finished "git am --abort || :" &&
 	git checkout empty-commit^ &&
 	test_must_fail git am --empty empty-commit.patch 2>err &&
-	echo "error: Invalid value for --empty: empty-commit.patch" >expected &&
+	echo "error: invalid value for '\''--empty'\'': '\''empty-commit.patch'\''" >expected &&
 	test_cmp expected err
 '
 
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v4 3/4] i18n: remove from i18n strings that do not hold translatable parts
  2022-01-31 22:07     ` [PATCH v4 " Jean-Noël Avila via GitGitGadget
  2022-01-31 22:07       ` [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
  2022-01-31 22:07       ` [PATCH v4 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
@ 2022-01-31 22:07       ` Jean-Noël Avila via GitGitGadget
  2022-01-31 22:07       ` [PATCH v4 4/4] i18n: fix some misformated placeholders in command synopsis Jean-Noël Avila via GitGitGadget
  3 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-31 22:07 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
---
 archive.c                    | 2 +-
 builtin/bisect--helper.c     | 6 +++---
 builtin/count-objects.c      | 2 +-
 builtin/hash-object.c        | 2 +-
 builtin/help.c               | 4 ++--
 builtin/mktag.c              | 2 +-
 builtin/mktree.c             | 2 +-
 builtin/notes.c              | 6 +++---
 builtin/prune-packed.c       | 2 +-
 builtin/rebase.c             | 2 +-
 builtin/reflog.c             | 2 +-
 builtin/remote.c             | 2 +-
 builtin/replace.c            | 2 +-
 builtin/sparse-checkout.c    | 8 ++++----
 builtin/stripspace.c         | 4 ++--
 builtin/submodule--helper.c  | 2 +-
 builtin/update-server-info.c | 2 +-
 17 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/archive.c b/archive.c
index d571249cf39..e29d0e00f6c 100644
--- a/archive.c
+++ b/archive.c
@@ -12,7 +12,7 @@
 
 static char const * const archive_usage[] = {
 	N_("git archive [<options>] <tree-ish> [<path>...]"),
-	N_("git archive --list"),
+	"git archive --list",
 	N_("git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"),
 	N_("git archive --remote <repo> [--exec <cmd>] --list"),
 	NULL
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 28a2e6a5750..f962dbd4303 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -22,15 +22,15 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
 
 static const char * const git_bisect_helper_usage[] = {
 	N_("git bisect--helper --bisect-reset [<commit>]"),
-	N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
+	"git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]",
 	N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
 					    " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
-	N_("git bisect--helper --bisect-next"),
+	"git bisect--helper --bisect-next",
 	N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
 	N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
 	N_("git bisect--helper --bisect-replay <filename>"),
 	N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
-	N_("git bisect--helper --bisect-visualize"),
+	"git bisect--helper --bisect-visualize",
 	N_("git bisect--helper --bisect-run <cmd>..."),
 	NULL
 };
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 3fae474f6f1..07b94195962 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -87,7 +87,7 @@ static int print_alternate(struct object_directory *odb, void *data)
 }
 
 static char const * const count_objects_usage[] = {
-	N_("git count-objects [-v] [-H | --human-readable]"),
+	"git count-objects [-v] [-H | --human-readable]",
 	NULL
 };
 
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index c7b3ad74c60..04e2442ec7c 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -81,7 +81,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
 {
 	static const char * const hash_object_usage[] = {
 		N_("git hash-object [-t <type>] [-w] [--path=<file> | --no-filters] [--stdin] [--] <file>..."),
-		N_("git hash-object  --stdin-paths"),
+		"git hash-object  --stdin-paths",
 		NULL
 	};
 	const char *type = blob_type;
diff --git a/builtin/help.c b/builtin/help.c
index d387131dd83..b4f2ad3f94e 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -77,8 +77,8 @@ static struct option builtin_help_options[] = {
 static const char * const builtin_help_usage[] = {
 	N_("git help [-a|--all] [--[no-]verbose]]\n"
 	   "         [[-i|--info] [-m|--man] [-w|--web]] [<command>]"),
-	N_("git help [-g|--guides]"),
-	N_("git help [-c|--config]"),
+	"git help [-g|--guides]",
+	"git help [-c|--config]",
 	NULL
 };
 
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 3b2dbbb37e6..c7b905c614b 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -7,7 +7,7 @@
 #include "config.h"
 
 static char const * const builtin_mktag_usage[] = {
-	N_("git mktag"),
+	"git mktag",
 	NULL
 };
 static int option_strict = 1;
diff --git a/builtin/mktree.c b/builtin/mktree.c
index ae78ca1c029..8bdaada922a 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -63,7 +63,7 @@ static void write_tree(struct object_id *oid)
 }
 
 static const char *mktree_usage[] = {
-	N_("git mktree [-z] [--missing] [--batch]"),
+	"git mktree [-z] [--missing] [--batch]",
 	NULL
 };
 
diff --git a/builtin/notes.c b/builtin/notes.c
index 05d60483e82..f99593a1853 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -32,8 +32,8 @@ static const char * const git_notes_usage[] = {
 	N_("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"),
 	N_("git notes [--ref <notes-ref>] show [<object>]"),
 	N_("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"),
-	N_("git notes merge --commit [-v | -q]"),
-	N_("git notes merge --abort [-v | -q]"),
+	"git notes merge --commit [-v | -q]",
+	"git notes merge --abort [-v | -q]",
 	N_("git notes [--ref <notes-ref>] remove [<object>...]"),
 	N_("git notes [--ref <notes-ref>] prune [-n] [-v]"),
 	N_("git notes [--ref <notes-ref>] get-ref"),
@@ -89,7 +89,7 @@ static const char * const git_notes_prune_usage[] = {
 };
 
 static const char * const git_notes_get_ref_usage[] = {
-	N_("git notes get-ref"),
+	"git notes get-ref",
 	NULL
 };
 
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index b7b9281a8ce..da3273a268b 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -3,7 +3,7 @@
 #include "prune-packed.h"
 
 static const char * const prune_packed_usage[] = {
-	N_("git prune-packed [-n | --dry-run] [-q | --quiet]"),
+	"git prune-packed [-n | --dry-run] [-q | --quiet]",
 	NULL
 };
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 36490d06c8a..64796c6a785 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -36,7 +36,7 @@ static char const * const builtin_rebase_usage[] = {
 		"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
 	N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
 		"--root [<branch>]"),
-	N_("git rebase --continue | --abort | --skip | --edit-todo"),
+	"git rebase --continue | --abort | --skip | --edit-todo",
 	NULL
 };
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index a4b1dd27e13..ee5ee8d8cf6 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -800,7 +800,7 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
  */
 
 static const char reflog_usage[] =
-N_("git reflog [ show | expire | delete | exists ]");
+"git reflog [ show | expire | delete | exists ]";
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin/remote.c b/builtin/remote.c
index 299c466116d..6f27ddc47bd 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -14,7 +14,7 @@
 #include "commit-reach.h"
 
 static const char * const builtin_remote_usage[] = {
-	N_("git remote [-v | --verbose]"),
+	"git remote [-v | --verbose]",
 	N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>"),
 	N_("git remote rename <old> <new>"),
 	N_("git remote remove <name>"),
diff --git a/builtin/replace.c b/builtin/replace.c
index 6ff1734d587..ac92337c0ec 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -22,7 +22,7 @@ static const char * const git_replace_usage[] = {
 	N_("git replace [-f] <object> <replacement>"),
 	N_("git replace [-f] --edit <object>"),
 	N_("git replace [-f] --graft <commit> [<parent>...]"),
-	N_("git replace [-f] --convert-graft-file"),
+	"git replace [-f] --convert-graft-file",
 	N_("git replace -d <object>..."),
 	N_("git replace [--format=<format>] [-l [<pattern>]]"),
 	NULL
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 679c1070368..771c9869a1c 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -43,7 +43,7 @@ static void write_patterns_to_file(FILE *fp, struct pattern_list *pl)
 }
 
 static char const * const builtin_sparse_checkout_list_usage[] = {
-	N_("git sparse-checkout list"),
+	"git sparse-checkout list",
 	NULL
 };
 
@@ -419,7 +419,7 @@ static int update_modes(int *cone_mode, int *sparse_index)
 }
 
 static char const * const builtin_sparse_checkout_init_usage[] = {
-	N_("git sparse-checkout init [--cone] [--[no-]sparse-index]"),
+	"git sparse-checkout init [--cone] [--[no-]sparse-index]",
 	NULL
 };
 
@@ -762,7 +762,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
 }
 
 static char const * const builtin_sparse_checkout_reapply_usage[] = {
-	N_("git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]"),
+	"git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]",
 	NULL
 };
 
@@ -800,7 +800,7 @@ static int sparse_checkout_reapply(int argc, const char **argv)
 }
 
 static char const * const builtin_sparse_checkout_disable_usage[] = {
-	N_("git sparse-checkout disable"),
+	"git sparse-checkout disable",
 	NULL
 };
 
diff --git a/builtin/stripspace.c b/builtin/stripspace.c
index be33eb83c1b..1e34cf2bebd 100644
--- a/builtin/stripspace.c
+++ b/builtin/stripspace.c
@@ -15,8 +15,8 @@ static void comment_lines(struct strbuf *buf)
 }
 
 static const char * const stripspace_usage[] = {
-	N_("git stripspace [-s | --strip-comments]"),
-	N_("git stripspace [-c | --comment-lines]"),
+	"git stripspace [-s | --strip-comments]",
+	"git stripspace [-c | --comment-lines]",
 	NULL
 };
 
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index c5d3fc3817f..b80aa9898ac 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2883,7 +2883,7 @@ static int module_config(int argc, const char **argv, const char *prefix)
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule--helper config <name> [<value>]"),
 		N_("git submodule--helper config --unset <name>"),
-		N_("git submodule--helper config --check-writeable"),
+		"git submodule--helper config --check-writeable",
 		NULL
 	};
 
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index 4321a344567..880fffec587 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -4,7 +4,7 @@
 #include "parse-options.h"
 
 static const char * const update_server_info_usage[] = {
-	N_("git update-server-info [--force]"),
+	"git update-server-info [--force]",
 	NULL
 };
 
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v4 4/4] i18n: fix some misformated placeholders in command synopsis
  2022-01-31 22:07     ` [PATCH v4 " Jean-Noël Avila via GitGitGadget
                         ` (2 preceding siblings ...)
  2022-01-31 22:07       ` [PATCH v4 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
@ 2022-01-31 22:07       ` Jean-Noël Avila via GitGitGadget
  3 siblings, 0 replies; 41+ messages in thread
From: Jean-Noël Avila via GitGitGadget @ 2022-01-31 22:07 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt, Phillip Wood, Jean-Noël Avila,
	Jean-Noël Avila

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>

 * add '<>' around arguments where missing
 * convert plurals into '...' forms

This applies the style guide for documentation.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
Reviewed-by: Phillip Wood <phillip.wood123@gmail.com>
---
 builtin/fast-export.c | 2 +-
 builtin/reflog.c      | 4 ++--
 builtin/rev-list.c    | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 9f1c730e587..510139e9b54 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -26,7 +26,7 @@
 #include "commit-slab.h"
 
 static const char *fast_export_usage[] = {
-	N_("git fast-export [rev-list-opts]"),
+	N_("git fast-export [<rev-list-opts>]"),
 	NULL
 };
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index ee5ee8d8cf6..343a10d371b 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -17,10 +17,10 @@ static const char reflog_expire_usage[] =
 N_("git reflog expire [--expire=<time>] "
    "[--expire-unreachable=<time>] "
    "[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] "
-   "[--verbose] [--all] <refs>...");
+   "[--verbose] [--all] <ref>...");
 static const char reflog_delete_usage[] =
 N_("git reflog delete [--rewrite] [--updateref] "
-   "[--dry-run | -n] [--verbose] <refs>...");
+   "[--dry-run | -n] [--verbose] <ref>...");
 static const char reflog_exists_usage[] =
 N_("git reflog exists <ref>");
 
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 777558e9b06..38528c7f156 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -20,7 +20,7 @@
 #include "packfile.h"
 
 static const char rev_list_usage[] =
-"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
+"git rev-list [<options>] <commit-id>... [-- <path>...]\n"
 "  limiting output:\n"
 "    --max-count=<n>\n"
 "    --max-age=<epoch>\n"
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-31 22:07       ` [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
@ 2022-01-31 22:41         ` Junio C Hamano
  2022-02-01  7:01           ` Johannes Sixt
  2022-02-02 16:05           ` Jean-Noël Avila
  0 siblings, 2 replies; 41+ messages in thread
From: Junio C Hamano @ 2022-01-31 22:41 UTC (permalink / raw)
  To: Jean-Noël Avila via GitGitGadget
  Cc: git, Johannes Sixt, Phillip Wood, Jean-Noël Avila

"Jean-Noël Avila via GitGitGadget"  <gitgitgadget@gmail.com> writes:

> +inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
> +				      int opt2, const char *opt2_name,
> +				      int opt3, const char *opt3_name)
> +{
> +	die_for_incompatible_opt4(opt1, opt1_name,
> +				  opt2, opt2_name,
> +				  opt3, opt3_name,
> +				  0, "");
> +}

I haven't seen a non-static inline function defined in a common
header files.  Does this actually work?  In my build, ld choked on
this one.

Otherwise make it "static inline"?  Or just

#define die_for_incompatible_opt3(o1,n1,o2,n2,o3,n3) \
	die_for_incompatible_opt4((o1), (n1), \
				  (o2), (n2), \
				  (o3), (n3), \
				  0, "")

perhaps?

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-31 22:41         ` Junio C Hamano
@ 2022-02-01  7:01           ` Johannes Sixt
  2022-02-01 17:58             ` Junio C Hamano
  2022-02-02 16:05           ` Jean-Noël Avila
  1 sibling, 1 reply; 41+ messages in thread
From: Johannes Sixt @ 2022-02-01  7:01 UTC (permalink / raw)
  To: Junio C Hamano, Jean-Noël Avila via GitGitGadget
  Cc: git, Phillip Wood, Jean-Noël Avila

Am 31.01.22 um 23:41 schrieb Junio C Hamano:
> "Jean-Noël Avila via GitGitGadget"  <gitgitgadget@gmail.com> writes:
> 
>> +inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
>> +				      int opt2, const char *opt2_name,
>> +				      int opt3, const char *opt3_name)
>> +{
>> +	die_for_incompatible_opt4(opt1, opt1_name,
>> +				  opt2, opt2_name,
>> +				  opt3, opt3_name,
>> +				  0, "");
>> +}
> 
> I haven't seen a non-static inline function defined in a common
> header files.  Does this actually work?  In my build, ld choked on
> this one.
> 
> Otherwise make it "static inline"?  Or just
> 
> #define die_for_incompatible_opt3(o1,n1,o2,n2,o3,n3) \
> 	die_for_incompatible_opt4((o1), (n1), \
> 				  (o2), (n2), \
> 				  (o3), (n3), \
> 				  0, "")
> 
> perhaps?

Please no macros where they are not a clear advantage. Make it a
function, either static inline, or out-of-line (the latter would be my
personal preference in this case because the function is not called in a
hot path).

-- Hannes

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages
  2022-02-01  7:01           ` Johannes Sixt
@ 2022-02-01 17:58             ` Junio C Hamano
  0 siblings, 0 replies; 41+ messages in thread
From: Junio C Hamano @ 2022-02-01 17:58 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Jean-Noël Avila via GitGitGadget, git, Phillip Wood,
	Jean-Noël Avila

Johannes Sixt <j6t@kdbg.org> writes:

>> Otherwise make it "static inline"?  Or just
>> 
>> #define die_for_incompatible_opt3(o1,n1,o2,n2,o3,n3) \
>> 	die_for_incompatible_opt4((o1), (n1), \
>> 				  (o2), (n2), \
>> 				  (o3), (n3), \
>> 				  0, "")
>> 
>> perhaps?
>
> Please no macros where they are not a clear advantage. Make it a
> function, either static inline, or out-of-line (the latter would be my
> personal preference in this case because the function is not called in a
> hot path).

In this particular case, my personal preference is actually a macro,
since 

 * there is no type safety lost

 * I find that it make it the most clear that 

   - the opt3 variant is a mere convenience wrapper, which does not
     even deserve an entry in the symbol table, of the real thing, and

   - our intention is to keep them closely in sync by not even
     giving future developers a pair of { braces }, in which they
     are tempted into writing extra code before or after calling the
     opt4 variant and make them diverge.

But it is not very strong preference.

A "static inline" wrapper would result in the same code as a macro,
and I'd be almost equally happy with it.  The code is almost already
written, and fixing it is just a matter of inserting "static " in
front.  My preference between "static inline" and macro is not
strong enough to insist on rewriting ;-)

An out-of-line wrapper has a slight disadvantage that it is not
immediately obvious that one is a mere wrapper of the other thing by
just looking at what is in the *.h file, but I am OK with it as
well.  If the original patch were written as an out-of-line wrapper,
my preference is not strong enough to insist on rewriting, either.

Thanks.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-28 22:24   ` [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
  2022-01-28 23:21     ` Johannes Sixt
@ 2022-02-01 21:01     ` Ævar Arnfjörð Bjarmason
  1 sibling, 0 replies; 41+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-02-01 21:01 UTC (permalink / raw)
  To: Jean-Noël Avila via GitGitGadget
  Cc: git, Johannes Sixt, Phillip Wood, Jean-Noël Avila


On Fri, Jan 28 2022, Jean-Noël Avila via GitGitGadget wrote:

> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
> [...]
> +void die_if_incompatible_opt3(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name)
> +{
> +	int count = 0;
> +	const char *options[3];
> +
> +	if (opt1)
> +		options[count++] = opt1_name;
> +	if (opt2)
> +		options[count++] = opt2_name;
> +	if (opt3)
> +		options[count++] = opt3_name;
> +	if (count > 2)
> +		die(_("options '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name);
> +	else if (count > 1)
> +		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
> +}
> +
> +void die_if_incompatible_opt4(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name,
> +							  int opt4, const char *opt4_name)
> +{
> +	int count = 0;
> +	const char *options[4];
> +
> +	if (opt1)
> +		options[count++] = opt1_name;
> +	if (opt2)
> +		options[count++] = opt2_name;
> +	if (opt3)
> +		options[count++] = opt3_name;
> +	if (opt4)
> +		options[count++] = opt4_name;
> +	switch (count) {
> +	case 4:
> +		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name, opt4_name);
> +		break;
> +	case 3:
> +		die(_("options '%s', '%s', and '%s' cannot be used together"), options[0], options[1], options[2]);
> +		break;
> +	case 2:
> +		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
> +		break;
> +	default:
> +		break;
> +	}
> +}
> diff --git a/parse-options.h b/parse-options.h
> index e22846d3b7b..cf393839ac4 100644
> --- a/parse-options.h
> +++ b/parse-options.h
> @@ -339,4 +339,13 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);
>  #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
>  #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
>  
> +void die_if_incompatible_opt3(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name);
> +
> +void die_if_incompatible_opt4(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name,
> +							  int opt4, const char *opt4_name);
> +
>  #endif
> diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
> index 91964653a0b..5fcaa0b4f2a 100755
> --- a/t/t7500-commit-template-squash-signoff.sh
> +++ b/t/t7500-commit-template-squash-signoff.sh
> @@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
>  '
>  
>  test_expect_success '--fixup=reword: -F give error message' '
> -	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
> +	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
>  	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
>  	test_cmp expect actual
>  '

I've really wanted (and have been meaning to find time to work on) some
expansion of what we can get from the "these are incompatible" that
OPT_CMDMODE gives us for a while.

But I think doing it like this is really going in the wrong direction,
i.e. we have no need to run all of parse_options(), callbacks and all,
and populate all the variables, only to after the fact die when we
notice both "a" and "b" were set, and those are incompatible.

I.e. to have the API work like something resembling this:
	
	diff --git a/builtin/grep.c b/builtin/grep.c
	index 75e07b5623a..80ea323f957 100644
	--- a/builtin/grep.c
	+++ b/builtin/grep.c
	@@ -849,8 +849,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
	 	struct option options[] = {
	 		OPT_BOOL(0, "cached", &cached,
	 			N_("search in index instead of in the work tree")),
	+		OPT_INCOMPATIBLE("cached", "untracked"),
	 		OPT_NEGBIT(0, "no-index", &use_index,
	 			 N_("find in contents not managed by git"), 1),
	+		OPT_INCOMPATIBLE("no-index", "untracked"),
	+		OPT_INCOMPATIBLE("no-index", "cached"),
	 		OPT_BOOL(0, "untracked", &untracked,
	 			N_("search in both tracked and untracked files")),
	 		OPT_SET_INT(0, "exclude-standard", &opt_exclude,
	@@ -1167,12 +1170,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
	 	if (!show_in_pager && !opt.status_only)
	 		setup_pager();
	 
	-	if (!use_index && (untracked || cached))
	-		die(_("--cached or --untracked cannot be used with --no-index"));
	-
	-	if (untracked && cached)
	-		die(_("--untracked cannot be used with --cached"));
	-
	 	if (!use_index || untracked) {
	 		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
	 		hit = grep_directory(&opt, &pathspec, use_exclude, use_index);
	
I.e. to have this be a new parse_opt_type. Then we'd just make note of
what's incompatible with what other stuff, and in parse_options_step()
check if the option we're currently looking at (e.g. --no-index) is
still the only one set out of a list-of-lists incompatible options.

And for i18n I really don't think we need to spend effort on detecting a
case where --foo --bar and --baz are all incompatible, and saying one
of:

    --bar is incompatible with --foo

Or:

    --bar is incompatible with --foo and --baz

Depending on whether the command-line is "--foo --bar" or "--foo --bar
--baz", let's just in both cases say:

    --bar is incompatible with --foo

Then if the user adjusts "--foo --bar --baz" to "--foo --baz" we'll just
show them a new error, using the same template:

    --baz is incompatible with --foo

I.e. doing this as we iterate options is Good Enough, it's not worth the
complexity or translator time to try to exhaustively list all
conflicting options at once.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages
  2022-01-31 22:41         ` Junio C Hamano
  2022-02-01  7:01           ` Johannes Sixt
@ 2022-02-02 16:05           ` Jean-Noël Avila
  2022-02-02 17:29             ` Johannes Sixt
  1 sibling, 1 reply; 41+ messages in thread
From: Jean-Noël Avila @ 2022-02-02 16:05 UTC (permalink / raw)
  To: Junio C Hamano, Jean-Noël Avila via GitGitGadget
  Cc: git, Johannes Sixt, Phillip Wood, Jean-Noël Avila

Le 31/01/2022 à 23:41, Junio C Hamano a écrit :
> "Jean-Noël Avila via GitGitGadget"  <gitgitgadget@gmail.com> writes:
>
>> +inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
>> +				      int opt2, const char *opt2_name,
>> +				      int opt3, const char *opt3_name)
>> +{
>> +	die_for_incompatible_opt4(opt1, opt1_name,
>> +				  opt2, opt2_name,
>> +				  opt3, opt3_name,
>> +				  0, "");
>> +}
> I haven't seen a non-static inline function defined in a common
> header files.  Does this actually work?  In my build, ld choked on
> this one.


This is quite subtle: "inline" is just a hint to the compiler but the

compiler can choose not to inline, so there must be an external symbol

to link to (which is not the case with this code).


My tests and the CI builds went smoothly, so I guess all these compilers

luckily chose to inline, but not yours.


With "static", we ensure that either it is inlined or there is a static

function (in which case, this bit of code will be duplicated across

compilation units).




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages
  2022-02-02 16:05           ` Jean-Noël Avila
@ 2022-02-02 17:29             ` Johannes Sixt
  0 siblings, 0 replies; 41+ messages in thread
From: Johannes Sixt @ 2022-02-02 17:29 UTC (permalink / raw)
  To: Jean-Noël Avila
  Cc: git, Jean-Noël Avila via GitGitGadget, Phillip Wood,
	Jean-Noël Avila, Junio C Hamano

Am 02.02.22 um 17:05 schrieb Jean-Noël Avila:
> With "static", we ensure that either it is inlined or there is a static
> function (in which case, this bit of code will be duplicated across
> compilation units).

That is the plan. Since the function is declared static, the compiler
has much more freedom to inline it because it knows that the function is
inaccessible outside the current compilation unit.

Besides, if you grep for 'inline', you will only find 'static inline'
(except in some borrowed code). static inline it is, or you pick the
macro or out-of-line solution.

-- Hannes

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2022-02-02 17:29 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-22 18:35 [PATCH 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
2022-01-22 18:35 ` [PATCH 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
2022-01-24  7:14   ` Johannes Sixt
2022-01-24 11:06     ` Phillip Wood
2022-01-25 20:52       ` Jean-Noël AVILA
2022-01-25 21:26         ` Johannes Sixt
2022-01-22 18:35 ` [PATCH 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
2022-01-24 11:09   ` Phillip Wood
2022-01-22 18:35 ` [PATCH 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
2022-01-22 18:35 ` [PATCH 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
2022-01-28 22:23 ` [PATCH v2 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
2022-01-28 22:24   ` [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
2022-01-28 23:21     ` Johannes Sixt
2022-01-28 23:58       ` Junio C Hamano
2022-01-29  8:08         ` Johannes Sixt
2022-01-29 10:41           ` Jean-Noël AVILA
2022-01-29 13:18             ` Johannes Sixt
2022-02-01 21:01     ` Ævar Arnfjörð Bjarmason
2022-01-28 22:24   ` [PATCH v2 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
2022-01-28 22:24   ` [PATCH v2 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
2022-01-28 22:24   ` [PATCH v2 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
2022-01-30 22:01   ` [PATCH v3 0/4] Factorize i18n Jean-Noël Avila via GitGitGadget
2022-01-30 22:01     ` [PATCH v3 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
2022-01-31  7:15       ` Johannes Sixt
2022-01-31 10:56       ` Phillip Wood
2022-01-30 22:01     ` [PATCH v3 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
2022-01-30 22:01     ` [PATCH v3 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
2022-01-30 22:01     ` [PATCH v3 4/4] i18n: transfer variables into placeholders in command synopsis Jean-Noël Avila via GitGitGadget
2022-01-31 11:00       ` Phillip Wood
2022-01-31 13:36         ` Jean-Noël Avila
2022-01-31  7:15     ` [PATCH v3 0/4] Factorize i18n Johannes Sixt
2022-01-31 22:07     ` [PATCH v4 " Jean-Noël Avila via GitGitGadget
2022-01-31 22:07       ` [PATCH v4 1/4] i18n: factorize more 'incompatible options' messages Jean-Noël Avila via GitGitGadget
2022-01-31 22:41         ` Junio C Hamano
2022-02-01  7:01           ` Johannes Sixt
2022-02-01 17:58             ` Junio C Hamano
2022-02-02 16:05           ` Jean-Noël Avila
2022-02-02 17:29             ` Johannes Sixt
2022-01-31 22:07       ` [PATCH v4 2/4] i18n: factorize "invalid value" messages Jean-Noël Avila via GitGitGadget
2022-01-31 22:07       ` [PATCH v4 3/4] i18n: remove from i18n strings that do not hold translatable parts Jean-Noël Avila via GitGitGadget
2022-01-31 22:07       ` [PATCH v4 4/4] i18n: fix some misformated placeholders in command synopsis Jean-Noël Avila via GitGitGadget

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).