Skip to contentSkip to conversation

Factorization of messages with similar meaning

PATCH Superseded Jean-Noël Avila via GitGitGadget 7 participants 94 messages Dec 3, 2021 – Jan 5, 2022 Page 1 of 2

lore
Share & tools
lore
#0 lore raw

cover Factorization of messages with similar meaning

This series is a meager attempt at rationalizing a small fraction of the internationalized messages. Sorry in advance for the dull task of reviewing these insipide patches.

Doing so has some positive effects:

* non-translatable constant strings are kept out of the way for translators
* messages with identical meaning are built identically
* the total number of messages to translate is decreased.

I'm inclined to even go a step further and turn these messages into #define or const strings. This would have the added benefits:

* make sure that the messages to translate are identical
* create a library of message skeletons to be picked up when new messages are needed

What do you think?

Jean-Noël Avila (10):
i18n: refactor "foo and bar are mutually exclusive"
i18n: refactor "%s, %s and %s are mutually exclusive"
i18n: turn "options are incompatible" into "are mutually exclusive"
i18n: standardize "cannot open" and "cannot read"
i18n: tag.c factorize i18n strings
i18n: factorize "--foo requires --bar" and the like
i18n: factorize "no directory given for --foo"
i18n: refactor "unrecognized %(foo) argument" strings
i18n: factorize "--foo outside a repository"
i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"

 apply.c                           |  8 ++++----
 archive.c                         |  8 ++++----
 builtin/add.c                     | 12 ++++++------
 builtin/branch.c                  |  2 +-
 builtin/checkout.c                |  8 ++++----
 builtin/clone.c                   |  2 +-
 builtin/commit.c                  |  6 +++---
 builtin/describe.c                |  2 +-
 builtin/diff-tree.c               |  2 +-
 builtin/difftool.c                |  4 ++--
 builtin/fast-export.c             |  4 ++--
 builtin/fetch.c                   |  6 +++---
 builtin/index-pack.c              |  4 ++--
 builtin/init-db.c                 |  2 +-
 builtin/log.c                     |  8 ++++----
 builtin/pack-objects.c            |  2 +-
 builtin/push.c                    |  8 ++++----
 builtin/repack.c                  |  4 ++--
 builtin/reset.c                   |  8 ++++----
 builtin/rm.c                      |  2 +-
 builtin/stash.c                   |  4 ++--
 builtin/submodule--helper.c       |  4 ++--
 builtin/tag.c                     | 10 +++++-----
 builtin/worktree.c                |  6 +++---
 diff.c                            |  2 +-
 fetch-pack.c                      |  2 +-
 git.c                             |  6 +++---
 http-fetch.c                      |  4 ++--
 range-diff.c                      |  2 +-
 ref-filter.c                      | 20 ++++++++++----------
 revision.c                        | 22 +++++++++++-----------
 t/t2026-checkout-pathspec-file.sh |  4 ++--
 t/t2072-restore-pathspec-file.sh  |  2 +-
 t/t3704-add-pathspec-file.sh      |  6 +++---
 t/t3909-stash-pathspec-file.sh    |  2 +-
 t/t5606-clone-options.sh          |  2 +-
 t/t7107-reset-pathspec-file.sh    |  2 +-
 t/t7526-commit-pathspec-file.sh   |  4 ++--
 38 files changed, 103 insertions(+), 103 deletions(-)

base-commit: 35151cf0720460a897cde9b8039af364743240e7
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1088%2Fjnavila%2Fi18n-refactor-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1088/jnavila/i18n-refactor-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1088

Signature · 1 line
gitgitgadget
#1 lore raw

PATCH 1/10 i18n: refactor "foo and bar are mutually exclusive"

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use static strings for constant parts of the sentences.

---
 builtin/checkout.c          | 2 +-
 builtin/diff-tree.c         | 2 +-
 builtin/fetch.c             | 2 +-
 builtin/init-db.c           | 2 +-
 builtin/log.c               | 4 ++--
 builtin/submodule--helper.c | 4 ++--
 builtin/worktree.c          | 2 +-
 range-diff.c                | 2 +-
 8 files changed, 10 insertions(+), 10 deletions(-)
builtin/checkout.c +1 -1
index cbf73b8c9f6..4bd8a57f190 100644
@@ -1621,7 +1621,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				cb_option, toupper(cb_option));
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
-		die(_("-p and --overlay are mutually exclusive"));
+		die(_("%s and %s are mutually exclusive"), "-p", "--overlay");
 
 	if (opts->checkout_index >= 0 || opts->checkout_worktree >= 0) {
 		if (opts->checkout_index < 0)
builtin/diff-tree.c +1 -1
index f33d30d57bf..08d5477486a 100644
@@ -152,7 +152,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
 	}
 
 	if (read_stdin && merge_base)
-		die(_("--stdin and --merge-base are mutually exclusive"));
+		die(_("%s and %s are mutually exclusive"), "--stdin", "--merge-base");
 	if (merge_base && opt->pending.nr != 2)
 		die(_("--merge-base only works with two commits"));
 
builtin/fetch.c +1 -1
index f7abbc31ff1..bec3cc7535e 100644
@@ -2012,7 +2012,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		if (deepen_relative < 0)
 			die(_("Negative depth in --deepen is not supported"));
 		if (depth)
-			die(_("--deepen and --depth are mutually exclusive"));
+			die(_("%s and %s are mutually exclusive"), "--deepen", "--depth");
 		depth = xstrfmt("%d", deepen_relative);
 	}
 	if (unshallow) {
builtin/init-db.c +1 -1
index 2167796ff2a..1439e05c93d 100644
@@ -557,7 +557,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
 
 	if (real_git_dir && is_bare_repository_cfg == 1)
-		die(_("--separate-git-dir and --bare are mutually exclusive"));
+		die(_("%s and %s are mutually exclusive"), "--separate-git-dir", "--bare");
 
 	if (real_git_dir && !is_absolute_path(real_git_dir))
 		real_git_dir = real_pathdup(real_git_dir, 1);
builtin/log.c +2 -2
index f75d87e8d7f..a2005e3c778 100644
@@ -1928,9 +1928,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		numbered = 0;
 
 	if (numbered && keep_subject)
-		die(_("-n and -k are mutually exclusive"));
+		die(_("%s and %s are mutually exclusive"), "-n", "-k");
 	if (keep_subject && subject_prefix)
-		die(_("--subject-prefix/--rfc and -k are mutually exclusive"));
+		die(_("%s and %s are mutually exclusive"), "--subject-prefix/--rfc", "-k");
 	rev.preserve_subject = keep_subject;
 
 	argc = setup_revisions(argc, argv, &rev, &s_r_opt);
builtin/submodule--helper.c +2 -2
index e630f0c730e..beedd873894 100644
@@ -1313,7 +1313,7 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 
 	if (files) {
 		if (cached)
-			die(_("--cached and --files are mutually exclusive"));
+			die(_("%s and %s are mutually exclusive"), "--cached", "--files");
 		diff_cmd = DIFF_FILES;
 	}
 
@@ -2971,7 +2971,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
 		die(_("--branch or --default required"));
 
 	if (opt_branch && opt_default)
-		die(_("--branch and --default are mutually exclusive"));
+		die(_("%s and %s are mutually exclusive"), "--branch", "--default");
 
 	if (argc != 1 || !(path = argv[0]))
 		usage_with_options(usage, options);
builtin/worktree.c +1 -1
index d22ece93e1a..9287c455594 100644
@@ -700,7 +700,7 @@ static int list(int ac, const char **av, const char *prefix)
 	if (ac)
 		usage_with_options(worktree_usage, options);
 	else if (verbose && porcelain)
-		die(_("--verbose and --porcelain are mutually exclusive"));
+		die(_("%s and %s are mutually exclusive"), "--verbose", "--porcelain");
 	else {
 		struct worktree **worktrees = get_worktrees();
 		int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
range-diff.c +1 -1
index cac89a2f4f2..bd954988e0f 100644
@@ -556,7 +556,7 @@ int show_range_diff(const char *range1, const char *range2,
 	struct string_list branch2 = STRING_LIST_INIT_DUP;
 
 	if (range_diff_opts->left_only && range_diff_opts->right_only)
-		res = error(_("--left-only and --right-only are mutually exclusive"));
+		res = error(_("%s and %s are mutually exclusive"), "--left-only", "--right-only");
 
 	if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg))
 		res = error(_("could not parse log for '%s'"), range1);
Signature · 1 line
gitgitgadget
#2 lore raw

Re: [PATCH 01/10] i18n: refactor "foo and bar are mutually exclusive"

Quoted 21 lines · Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use static strings for constant parts of the sentences.

---
 builtin/checkout.c          | 2 +-
 builtin/diff-tree.c         | 2 +-
 builtin/fetch.c             | 2 +-
 builtin/init-db.c           | 2 +-
 builtin/log.c               | 4 ++--
 builtin/submodule--helper.c | 4 ++--
 builtin/worktree.c          | 2 +-
 range-diff.c                | 2 +-
 8 files changed, 10 insertions(+), 10 deletions(-)
builtin/checkout.c +0 -0
index cbf73b8c9f6..4bd8a57f190 100644

builtin/checkout.c static int checkout_main(int argc, const char **argv, const char *prefix, · line 1624

Quoted 5 lines
builtin/checkout.c +1 -1
@@ -1621,7 +1621,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				cb_option, toupper(cb_option));
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
-		die(_("-p and --overlay are mutually exclusive"));
+		die(_("%s and %s are mutually exclusive"), "-p", "--overlay");

It's good to do all of these, but I think we should really quote the '%s' while at it. It also helps translators, who without that won't know (without jumping to the source) if %s and %s are "walking" and "chewing gum" or something like a CLI option that's quoted :)

#3 lore raw

Re: [PATCH 01/10] i18n: refactor "foo and bar are mutually exclusive"

Quoted 26 lines · On Tuesday, 7 December 2021 19:07:41 CET Ævar Arnfjörð Bjarmason wrote:
Quoted 23 lines · Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use static strings for constant parts of the sentences.

---
 builtin/checkout.c          | 2 +-
 builtin/diff-tree.c         | 2 +-
 builtin/fetch.c             | 2 +-
 builtin/init-db.c           | 2 +-
 builtin/log.c               | 4 ++--
 builtin/submodule--helper.c | 4 ++--
 builtin/worktree.c          | 2 +-
 range-diff.c                | 2 +-
 8 files changed, 10 insertions(+), 10 deletions(-)
builtin/checkout.c +0 -0
index cbf73b8c9f6..4bd8a57f190 100644
@@ -1621,7 +1621,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				cb_option, toupper(cb_option));
 
Quoted 9 lines

builtin/checkout.c static int checkout_main(int argc, const char **argv, const char *prefix, · line 1624

Quoted 3 lines
builtin/checkout.c +1 -1
 	if (opts->overlay_mode == 1 && opts->patch_mode)
-		die(_("-p and --overlay are mutually exclusive"));
+		die(_("%s and %s are mutually exclusive"), "-p", "--overlay");

It's good to do all of these, but I think we should really quote the '%s' while at it. It also helps translators, who without that won't know (without jumping to the source) if %s and %s are "walking" and "chewing gum" or something like a CLI option that's quoted :)

With other comments included, the proposition for this factorization would be:

"the options '%s' and '%s' cannot be used together"

#4 lore raw

PATCH 2/10 i18n: refactor "%s, %s and %s are mutually exclusive"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use placeholders for constant tokens.

---
 builtin/difftool.c | 2 +-
 builtin/log.c      | 2 +-
 builtin/worktree.c | 2 +-
 diff.c             | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)
builtin/difftool.c +1 -1
index 4931c108451..61ebfa9c68c 100644
@@ -739,7 +739,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 		die(_("--dir-diff is incompatible with --no-index"));
 
 	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("--gui, --tool and --extcmd are mutually exclusive"));
+		die(_("%s, %s and %s are mutually exclusive"), "--gui", "--tool", "--extcmd");
 
 	if (use_gui_tool)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
builtin/log.c +1 -1
index a2005e3c778..c39b974ea37 100644
@@ -1964,7 +1964,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		load_display_notes(&rev.notes_opt);
 
 	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("--stdout, --output, and --output-directory are mutually exclusive"));
+		die(_("%s, %s and %s are mutually exclusive"), "--stdout", "--output", "--output-directory");
 
 	if (use_stdout) {
 		setup_pager();
builtin/worktree.c +1 -1
index 9287c455594..73ee505234c 100644
@@ -504,7 +504,7 @@ static int add(int ac, const char **av, const char *prefix)
 	opts.checkout = 1;
 	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
-		die(_("-b, -B, and --detach are mutually exclusive"));
+		die(_("%s, %s and %s are mutually exclusive"), "-b", "-B", "--detach");
 	if (lock_reason && !keep_locked)
 		die(_("--reason requires --lock"));
 	if (lock_reason)
diff.c +1 -1
index 861282db1c3..342e53f1c1f 100644
@@ -4642,7 +4642,7 @@ void diff_setup_done(struct diff_options *options)
 		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
-		die(_("-G, -S and --find-object are mutually exclusive"));
+		die(_("%s, %s and %s are mutually exclusive"), "-G", "-S", "--find-object");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
 		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
Signature · 1 line
gitgitgadget
#5 lore raw

PATCH 3/10 i18n: turn "options are incompatible" into "are mutually exclusive"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 apply.c                           |  2 +-
 archive.c                         |  2 +-
 builtin/add.c                     |  8 ++++----
 builtin/branch.c                  |  2 +-
 builtin/checkout.c                |  4 ++--
 builtin/clone.c                   |  2 +-
 builtin/commit.c                  |  4 ++--
 builtin/describe.c                |  2 +-
 builtin/difftool.c                |  2 +-
 builtin/fast-export.c             |  2 +-
 builtin/index-pack.c              |  2 +-
 builtin/pack-objects.c            |  2 +-
 builtin/push.c                    |  8 ++++----
 builtin/repack.c                  |  4 ++--
 builtin/reset.c                   |  4 ++--
 builtin/stash.c                   |  2 +-
 builtin/tag.c                     |  2 +-
 revision.c                        | 22 +++++++++++-----------
 t/t2026-checkout-pathspec-file.sh |  4 ++--
 t/t2072-restore-pathspec-file.sh  |  2 +-
 t/t3704-add-pathspec-file.sh      |  6 +++---
 t/t3909-stash-pathspec-file.sh    |  2 +-
 t/t5606-clone-options.sh          |  2 +-
 t/t7107-reset-pathspec-file.sh    |  2 +-
 t/t7526-commit-pathspec-file.sh   |  4 ++--
 25 files changed, 49 insertions(+), 49 deletions(-)
apply.c +1 -1
index 43a0aebf4ee..fefec23f1ec 100644
@@ -133,7 +133,7 @@ int check_apply_state(struct apply_state *state, int force_apply)
 	int is_not_gitdir = !startup_info->have_repository;
 
 	if (state->apply_with_reject && state->threeway)
-		return error(_("--reject and --3way cannot be used together."));
+		return error(_("%s and %s are mutually exclusive"),"--reject",  "--3way");
 	if (state->threeway) {
 		if (is_not_gitdir)
 			return error(_("--3way outside a repository"));
archive.c +1 -1
index a3bbb091256..10376be7161 100644
@@ -581,7 +581,7 @@ static int parse_archive_args(int argc, const char **argv,
 	if (output)
 		die(_("Unexpected option --output"));
 	if (is_remote && args->extra_files.nr)
-		die(_("Options --add-file and --remote cannot be used together"));
+		die(_("%s and %s are mutually exclusive"), "--add-file", "--remote");
 
 	if (!base)
 		base = "";
builtin/add.c +4 -4
index ef6b619c45e..de1547b3dcd 100644
@@ -510,9 +510,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		add_interactive = 1;
 	if (add_interactive) {
 		if (show_only)
-			die(_("--dry-run is incompatible with --interactive/--patch"));
+			die(_("%s and %s are mutually exclusive"), "--dry-run", "--interactive/--patch");
 		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--interactive/--patch");
 		exit(interactive_add(argv + 1, prefix, patch_interactive));
 	}
 	if (legacy_stash_p) {
@@ -529,7 +529,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (edit_interactive) {
 		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --edit"));
+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--edit");
 		return(edit_patch(argc, argv, prefix));
 	}
 	argc--;
@@ -541,7 +541,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		addremove = 0; /* "-u" was given but not "-A" */
 
 	if (addremove && take_worktree_changes)
-		die(_("-A and -u are mutually incompatible"));
+		die(_("%s and %s are mutually exclusive"), "-A", "-u");
 
 	if (!show_only && ignore_missing)
 		die(_("Option --ignore-missing can only be used together with --dry-run"));
builtin/branch.c +1 -1
index 7a1d1eeb070..50d99fa6fd4 100644
@@ -717,7 +717,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	finalize_colopts(&colopts, -1);
 	if (filter.verbose) {
 		if (explicitly_enable_column(colopts))
-			die(_("--column and --verbose are incompatible"));
+			die(_("%s and %s are mutually exclusive"), "--column", "--verbose");
 		colopts = 0;
 	}
 
builtin/checkout.c +2 -2
index 4bd8a57f190..ca444e9c177 100644
@@ -1731,10 +1731,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
 
 		if (opts->force_detach)
-			die(_("--pathspec-from-file is incompatible with --detach"));
+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file",  "--detach");
 
 		if (opts->patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--patch");
 
 		parse_pathspec_file(&opts->pathspec, 0,
 				    0,
builtin/clone.c +1 -1
index fb377b27657..b8c3f072bae 100644
@@ -903,7 +903,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 			die(_("--bare and --origin %s options are incompatible."),
 			    option_origin);
 		if (real_git_dir)
-			die(_("--bare and --separate-git-dir are incompatible."));
+			die(_("%s and %s are mutually exclusive"), "--bare", "--separate-git-dir");
 		option_no_checkout = 1;
 	}
 
builtin/commit.c +2 -2
index 883c16256c8..cb7b9a38daa 100644
@@ -355,7 +355,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 
 	if (pathspec_from_file) {
 		if (interactive)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--interactive/--patch");
 
 		if (all)
 			die(_("--pathspec-from-file with -a does not make sense"));
@@ -1193,7 +1193,7 @@ static void finalize_deferred_config(struct wt_status *s)
 		    status_format == STATUS_FORMAT_UNSPECIFIED)
 			status_format = STATUS_FORMAT_PORCELAIN;
 		else if (status_format == STATUS_FORMAT_LONG)
-			die(_("--long and -z are incompatible"));
+			die(_("%s and %s are mutually exclusive"), "--long", "-z");
 	}
 
 	if (use_deferred_config && status_format == STATUS_FORMAT_UNSPECIFIED)
builtin/describe.c +1 -1
index e912ba50d7b..26da61a216f 100644
@@ -590,7 +590,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 	save_commit_buffer = 0;
 
 	if (longformat && abbrev == 0)
-		die(_("--long is incompatible with --abbrev=0"));
+		die(_("%s and %s are mutually exclusive"), "--long", "--abbrev=0");
 
 	if (contains) {
 		struct string_list_item *item;
builtin/difftool.c +1 -1
index 61ebfa9c68c..ab8f06c991d 100644
@@ -736,7 +736,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 		setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
 		setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
 	} else if (dir_diff)
-		die(_("--dir-diff is incompatible with --no-index"));
+		die(_("%s and %s are mutually exclusive"), "--dir-diff", "--no-index");
 
 	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
 		die(_("%s, %s and %s are mutually exclusive"), "--gui", "--tool", "--extcmd");
builtin/fast-export.c +1 -1
index 8e2caf72819..31157e966d6 100644
@@ -1269,7 +1269,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		printf("feature done\n");
 
 	if (import_filename && import_filename_if_exists)
-		die(_("Cannot pass both --import-marks and --import-marks-if-exists"));
+		die(_("%s and %s are mutually exclusive"), "--import-marks", "--import-marks-if-exists");
 	if (import_filename)
 		import_marks(import_filename, 0);
 	else if (import_filename_if_exists)
builtin/index-pack.c +1 -1
index c23d01de7dc..f9b40349f41 100644
@@ -1849,7 +1849,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (from_stdin && !startup_info->have_repository)
 		die(_("--stdin requires a git repository"));
 	if (from_stdin && hash_algo)
-		die(_("--object-format cannot be used with --stdin"));
+		die(_("%s and %s are mutually exclusive"), "--object-format", "--stdin");
 	if (!index_name && pack_name)
 		index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
 
builtin/pack-objects.c +1 -1
index 1a3dd445f83..a5e674894f0 100644
@@ -4070,7 +4070,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 		die(_("--thin cannot be used to build an indexable pack"));
 
 	if (keep_unreachable && unpack_unreachable)
-		die(_("--keep-unreachable and --unpack-unreachable are incompatible"));
+		die(_("%s and %s are mutually exclusive"), "--keep-unreachable", "--unpack-unreachable");
 	if (!rev_list_all || !rev_list_reflog || !rev_list_index)
 		unpack_unreachable_expiration = 0;
 
builtin/push.c +4 -4
index 4b026ce6c6a..ba55e07a678 100644
@@ -589,7 +589,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 	set_push_cert_flags(&flags, push_cert);
 
 	if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
-		die(_("--delete is incompatible with --all, --mirror and --tags"));
+		die(_("%s and %s are mutually exclusive"), "--delete", "--all/--mirror/--tags");
 	if (deleterefs && argc < 2)
 		die(_("--delete doesn't make sense without any refs"));
 
@@ -627,18 +627,18 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 
 	if (flags & TRANSPORT_PUSH_ALL) {
 		if (tags)
-			die(_("--all and --tags are incompatible"));
+			die(_("%s and %s are mutually exclusive"), "--all", "--tags");
 		if (argc >= 2)
 			die(_("--all can't be combined with refspecs"));
 	}
 	if (flags & TRANSPORT_PUSH_MIRROR) {
 		if (tags)
-			die(_("--mirror and --tags are incompatible"));
+			die(_("%s and %s are mutually exclusive"), "--mirror", "--tags");
 		if (argc >= 2)
 			die(_("--mirror can't be combined with refspecs"));
 	}
 	if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
-		die(_("--all and --mirror are incompatible"));
+		die(_("%s and %s are mutually exclusive"), "--all", "--mirror");
 
 	if (!is_empty_cas(&cas) && (flags & TRANSPORT_PUSH_FORCE_IF_INCLUDES))
 		cas.use_force_if_includes = 1;
builtin/repack.c +2 -2
index 0b2d1e5d82b..8e92943f871 100644
@@ -679,7 +679,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	if (keep_unreachable &&
 	    (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
-		die(_("--keep-unreachable and -A are incompatible"));
+		die(_("%s and %s are mutually exclusive"), "--keep-unreachable", "-A");
 
 	if (write_bitmaps < 0) {
 		if (!write_midx &&
@@ -710,7 +710,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	if (geometric_factor) {
 		if (pack_everything)
-			die(_("--geometric is incompatible with -A, -a"));
+			die(_("%s and %s are mutually exclusive"),"--geometric", "-A/-a");
 		init_pack_geometry(&geometry);
 		split_pack_geometry(geometry, geometric_factor);
 	}
builtin/reset.c +2 -2
index 73935953494..6e80e5c5a51 100644
@@ -328,7 +328,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--patch");
 
 		if (pathspec.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
@@ -364,7 +364,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	if (patch_mode) {
 		if (reset_type != NONE)
-			die(_("--patch is incompatible with --{hard,mixed,soft}"));
+			die(_("%s and %s are mutually exclusive"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
 		return run_add_interactive(rev, "--patch=reset", &pathspec);
 	}
builtin/stash.c +1 -1
index a0ccc8654df..080572cc608 100644
@@ -1644,7 +1644,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 
 	if (pathspec_from_file) {
 		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--patch");
 
 		if (ps.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
builtin/tag.c +1 -1
index 6fe646710d6..41941d5129f 100644
@@ -522,7 +522,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	finalize_colopts(&colopts, -1);
 	if (cmdmode == 'l' && filter.lines != -1) {
 		if (explicitly_enable_column(colopts))
-			die(_("--column and -n are incompatible"));
+			die(_("%s and %s are mutually exclusive"), "--column", "-n");
 		colopts = 0;
 	}
 	if (!sorting)
revision.c +11 -11
index 1981a0859f0..58a1a0e66c6 100644
@@ -2295,11 +2295,11 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->left_only = 1;
 	} else if (!strcmp(arg, "--right-only")) {
 		if (revs->left_only)
-			die("--right-only is incompatible with --left-only");
+			die(_("%s and %s are mutually exclusive"), "--right-only", "--left-only");
 		revs->right_only = 1;
 	} else if (!strcmp(arg, "--cherry")) {
 		if (revs->left_only)
-			die("--cherry is incompatible with --left-only");
+			die(_("%s and %s are mutually exclusive"), "--cherry", "--left-only");
 		revs->cherry_mark = 1;
 		revs->right_only = 1;
 		revs->max_parents = 1;
@@ -2308,12 +2308,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->count = 1;
 	} else if (!strcmp(arg, "--cherry-mark")) {
 		if (revs->cherry_pick)
-			die("--cherry-mark is incompatible with --cherry-pick");
+			die(_("%s and %s are mutually exclusive"), "--cherry-mark", "--cherry-pick");
 		revs->cherry_mark = 1;
 		revs->limited = 1; /* needs limit_list() */
 	} else if (!strcmp(arg, "--cherry-pick")) {
 		if (revs->cherry_mark)
-			die("--cherry-pick is incompatible with --cherry-mark");
+			die(_("%s and %s are mutually exclusive"), "--cherry-pick", "--cherry-mark");
 		revs->cherry_pick = 1;
 		revs->limited = 1;
 	} else if (!strcmp(arg, "--objects")) {
@@ -2519,7 +2519,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		return opts;
 	}
 	if (revs->graph && revs->track_linear)
-		die("--show-linear-break and --graph are incompatible");
+		die(_("%s and %s are mutually exclusive"), "--show-linear-break", "--graph");
 
 	return 1;
 }
@@ -2862,24 +2862,24 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	compile_grep_patterns(&revs->grep_filter);
 
 	if (revs->reverse && revs->reflog_info)
-		die("cannot combine --reverse with --walk-reflogs");
+		die(_("%s and %s are mutually exclusive"), "--reverse", "--walk-reflogs");
 	if (revs->reflog_info && revs->limited)
 		die("cannot combine --walk-reflogs with history-limiting options");
 	if (revs->rewrite_parents && revs->children.name)
-		die("cannot combine --parents and --children");
+		die(_("%s and %s are mutually exclusive"), "--parents", "--children");
 
 	/*
 	 * Limitations on the graph functionality
 	 */
 	if (revs->reverse && revs->graph)
-		die("cannot combine --reverse with --graph");
+		die(_("%s and %s are mutually exclusive"), "--reverse", "--graph");
 
 	if (revs->reflog_info && revs->graph)
-		die("cannot combine --walk-reflogs with --graph");
+		die(_("%s and %s are mutually exclusive"), "--walk-reflogs", "--graph");
 	if (revs->no_walk && revs->graph)
-		die("cannot combine --no-walk with --graph");
+		die(_("%s and %s are mutually exclusive"), "--no-walk", "--graph");
 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
-		die("cannot use --grep-reflog without --walk-reflogs");
+		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");
 
 	if (revs->line_level_traverse &&
 	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
t/t2026-checkout-pathspec-file.sh +2 -2
index 43d31d79485..88e00203df6 100755
@@ -148,10 +148,10 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git checkout --pathspec-from-file=list --detach 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --detach" err &&
+	test_i18ngrep -e "--pathspec-from-file and --detach are mutually exclusive" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "--pathspec-from-file and --patch are mutually exclusive" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t2072-restore-pathspec-file.sh +1 -1
index b48345bf95f..2e918daa225 100755
@@ -152,7 +152,7 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git restore --pathspec-from-file=list --patch --source=HEAD^1 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "--pathspec-from-file and --patch are mutually exclusive" err &&
 
 	test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t3704-add-pathspec-file.sh +3 -3
index 9e35c1fbca6..4e5cdabc97f 100755
@@ -137,13 +137,13 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git add --pathspec-from-file=list --interactive 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "--pathspec-from-file and --interactive/--patch are mutually exclusive" err &&
 
 	test_must_fail git add --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "--pathspec-from-file and --interactive/--patch are mutually exclusive" err &&
 
 	test_must_fail git add --pathspec-from-file=list --edit 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --edit" err &&
+	test_i18ngrep -e "--pathspec-from-file and --edit are mutually exclusive" err &&
 
 	test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t3909-stash-pathspec-file.sh +1 -1
index 55e050cfd4d..b7e6c89682b 100755
@@ -88,7 +88,7 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git stash push --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "--pathspec-from-file and --patch are mutually exclusive" err &&
 
 	test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t5606-clone-options.sh +1 -1
index d822153e4d2..dec92ff0a75 100755
@@ -54,7 +54,7 @@ test_expect_success 'disallows --bare with --separate-git-dir' '
 
 	test_must_fail git clone --bare --separate-git-dir dot-git-destiation parent clone-bare-sgd 2>err &&
 	test_debug "cat err" &&
-	test_i18ngrep -e "--bare and --separate-git-dir are incompatible" err
+	test_i18ngrep -e "--bare and --separate-git-dir are mutually exclusive" err
 
 '
 
t/t7107-reset-pathspec-file.sh +1 -1
index 15ccb14f7e2..b8a3e2e2a9d 100755
@@ -160,7 +160,7 @@ test_expect_success 'error conditions' '
 	git rm fileA.t &&
 
 	test_must_fail git reset --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "--pathspec-from-file and --patch are mutually exclusive" err &&
 
 	test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t7526-commit-pathspec-file.sh +2 -2
index 5fbe47ebcd0..8ef1c8d941c 100755
@@ -140,10 +140,10 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git commit --pathspec-from-file=list --interactive -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "--pathspec-from-file and --interactive/--patch are mutually exclusive" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --patch -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "--pathspec-from-file and --interactive/--patch are mutually exclusive" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err &&
 	test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
Signature · 1 line
gitgitgadget
#6 lore raw

PATCH 4/10 i18n: standardize "cannot open" and "cannot read"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 archive.c       | 4 ++--
 builtin/fetch.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
archive.c +2 -2
index 10376be7161..f1208beacff 100644
@@ -185,7 +185,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
 
 	buffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);
 	if (!buffer)
-		return error(_("cannot read %s"), oid_to_hex(oid));
+		return error(_("cannot read '%s'"), oid_to_hex(oid));
 	err = write_entry(args, oid, path.buf, path.len, mode, buffer, size);
 	free(buffer);
 	return err;
@@ -338,7 +338,7 @@ int write_archive_entries(struct archiver_args *args,
 
 		strbuf_reset(&content);
 		if (strbuf_read_file(&content, path, info->stat.st_size) < 0)
-			err = error_errno(_("could not read '%s'"), path);
+			err = error_errno(_("cannot read '%s'"), path);
 		else
 			err = write_entry(args, &fake_oid, path_in_archive.buf,
 					  path_in_archive.len,
builtin/fetch.c +2 -2
index bec3cc7535e..b0d63149388 100644
@@ -995,7 +995,7 @@ static int open_fetch_head(struct fetch_head *fetch_head)
 	if (write_fetch_head) {
 		fetch_head->fp = fopen(filename, "a");
 		if (!fetch_head->fp)
-			return error_errno(_("cannot open %s"), filename);
+			return error_errno(_("cannot open '%s'"), filename);
 		strbuf_init(&fetch_head->buf, 0);
 	} else {
 		fetch_head->fp = NULL;
@@ -1405,7 +1405,7 @@ static int truncate_fetch_head(void)
 	FILE *fp = fopen_for_writing(filename);
 
 	if (!fp)
-		return error_errno(_("cannot open %s"), filename);
+		return error_errno(_("cannot open '%s'"), filename);
 	fclose(fp);
 	return 0;
 }
Signature · 1 line
gitgitgadget
#7 lore raw

Re: [PATCH 04/10] i18n: standardize "cannot open" and "cannot read"

Quoted 13 lines · Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 archive.c       | 4 ++--
 builtin/fetch.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
archive.c +0 -0
index 10376be7161..f1208beacff 100644

archive.c static int write_archive_entry(const struct object_id *oid, const char *base, · line 188

Quoted 5 lines
archive.c +1 -1
@@ -185,7 +185,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
 
 	buffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);
 	if (!buffer)
-		return error(_("cannot read %s"), oid_to_hex(oid));
+		return error(_("cannot read '%s'"), oid_to_hex(oid));

Re my just-sent comment, i.e. quote things like that, but between this and the first patch there's a bunch that don't use quotes that could use them...

#8 lore raw

PATCH 5/10 i18n: tag.c factorize i18n strings

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
builtin/tag.c +4 -4
index 41941d5129f..6415d6c81a2 100644
@@ -543,13 +543,13 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
+		die(_("%s option is only allowed in list mode"), "-n");
 	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
+		die(_("%s option is only allowed in list mode"), "--contains");
 	if (filter.no_commit)
-		die(_("--no-contains option is only allowed in list mode"));
+		die(_("%s option is only allowed in list mode"), "--no-contains");
 	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		die(_("%s option is only allowed in list mode"), "--points-at");
 	if (filter.reachable_from || filter.unreachable_from)
 		die(_("--merged and --no-merged options are only allowed in list mode"));
 	if (cmdmode == 'd') {
Signature · 1 line
gitgitgadget
#9 lore raw

Re: [PATCH 05/10] i18n: tag.c factorize i18n strings

Quoted 19 lines · Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
builtin/tag.c +1 -2
index 41941d5129f..6415d6c81a2 100644
@@ -543,13 +543,13 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
+		die(_("%s option is only allowed in list mode"), "-n");
 	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));

builtin/tag.c int cmd_tag(int argc, const char **argv, const char *prefix) · line 555

Quoted 10 lines
builtin/tag.c +3 -2
+		die(_("%s option is only allowed in list mode"), "--contains");
 	if (filter.no_commit)
-		die(_("--no-contains option is only allowed in list mode"));
+		die(_("%s option is only allowed in list mode"), "--no-contains");
 	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		die(_("%s option is only allowed in list mode"), "--points-at");
 	if (filter.reachable_from || filter.unreachable_from)
 		die(_("--merged and --no-merged options are only allowed in list mode"));
 	if (cmdmode == 'd') {

Since for all of these we're asking translators to re-do some work (albeit with translation memory) this could use a bit of grammar improvement. E.g.:

_("the '%s' option is only allowed in list mode'")

I.e. "blah option is only" without a "the" is a bit odd.

But also for this & various other boilerplate in this series, I think it would be much better as say:

    const char *only_in_list = NULL;
    if (...)
        only_in_list = "-n";
    else if (...)
        only_in_list = "--contains";
    [...]
    if (only_in_list)
        die(__("the '%s' option [...]"), only_in_list);

I.e. we're buying ourselves the chance to easily get a rid of a lot of this repetition, but aren't using it. I think a series like this should probably resist some big refactorings, but things like that would be pretty easy & make the code more readable.

#10 lore raw

PATCH 6/10 i18n: factorize "--foo requires --bar" and the like

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 archive.c             | 2 +-
 builtin/add.c         | 4 ++--
 builtin/checkout.c    | 2 +-
 builtin/commit.c      | 2 +-
 builtin/fast-export.c | 2 +-
 builtin/index-pack.c  | 2 +-
 builtin/log.c         | 2 +-
 builtin/reset.c       | 4 ++--
 builtin/rm.c          | 2 +-
 builtin/stash.c       | 2 +-
 builtin/worktree.c    | 2 +-
 fetch-pack.c          | 2 +-
 http-fetch.c          | 4 ++--
 13 files changed, 16 insertions(+), 16 deletions(-)
archive.c +1 -1
index f1208beacff..0d96217b4d4 100644
@@ -577,7 +577,7 @@ static int parse_archive_args(int argc, const char **argv,
 	if (remote)
 		die(_("Unexpected option --remote"));
 	if (exec)
-		die(_("Option --exec can only be used together with --remote"));
+		die(_("%s requires %s"), "--exec", "--remote");
 	if (output)
 		die(_("Unexpected option --output"));
 	if (is_remote && args->extra_files.nr)
builtin/add.c +2 -2
index de1547b3dcd..1be22f8c287 100644
@@ -544,7 +544,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		die(_("%s and %s are mutually exclusive"), "-A", "-u");
 
 	if (!show_only && ignore_missing)
-		die(_("Option --ignore-missing can only be used together with --dry-run"));
+		die(_("%s requires %s"), "--ignore-missing", "--dry-run");
 
 	if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
 			  chmod_arg[1] != 'x' || chmod_arg[2]))
@@ -576,7 +576,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_SYMLINK_LEADING_PATH,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (require_pathspec && pathspec.nr == 0) {
builtin/checkout.c +1 -1
index ca444e9c177..825e753f607 100644
@@ -1740,7 +1740,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				    0,
 				    prefix, opts->pathspec_from_file, opts->pathspec_file_nul);
 	} else if (opts->pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	opts->pathspec.recursive = 1;
builtin/commit.c +1 -1
index cb7b9a38daa..37e8cf09bd5 100644
@@ -367,7 +367,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 				    PATHSPEC_PREFER_FULL,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (!pathspec.nr && (also || (only && !allow_empty &&
builtin/fast-export.c +1 -1
index 31157e966d6..b0302a75374 100644
@@ -1254,7 +1254,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		usage_with_options (fast_export_usage, options);
 
 	if (anonymized_seeds.cmpfn && !anonymize)
-		die(_("--anonymize-map without --anonymize does not make sense"));
+		die(_("%s requires %s"), "--anonymize-map", "--anonymize");
 
 	if (refspecs_list.nr) {
 		int i;
builtin/index-pack.c +1 -1
index f9b40349f41..ed16230fa99 100644
@@ -1845,7 +1845,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (!pack_name && !from_stdin)
 		usage(index_pack_usage);
 	if (fix_thin_pack && !from_stdin)
-		die(_("--fix-thin cannot be used without --stdin"));
+		die(_("%s requires %s"), "--fix-thin", "--stdin");
 	if (from_stdin && !startup_info->have_repository)
 		die(_("--stdin requires a git repository"));
 	if (from_stdin && hash_algo)
builtin/log.c +1 -1
index c39b974ea37..ea54576f38b 100644
@@ -2097,7 +2097,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	if (creation_factor < 0)
 		creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
 	else if (!rdiff_prev)
-		die(_("--creation-factor requires --range-diff"));
+		die(_("%s requires %s"), "--creation-factor", "--range-diff");
 
 	if (rdiff_prev) {
 		if (!cover_letter && total != 1)
builtin/reset.c +2 -2
index 6e80e5c5a51..7efa95e0529 100644
@@ -337,7 +337,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_PREFER_FULL,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
@@ -395,7 +395,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		    _(reset_type_names[reset_type]));
 
 	if (intent_to_add && reset_type != MIXED)
-		die(_("-N can only be used with --mixed"));
+		die(_("%s requires %s"), "-N", "--mixed");
 
 	/* Soft reset does not touch the index file nor the working tree
 	 * at all, but requires them in a good order.  Other resets reset
builtin/rm.c +1 -1
index 3d0967cdc11..38ac3c71252 100644
@@ -278,7 +278,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_PREFER_CWD,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (!pathspec.nr)
builtin/stash.c +1 -1
index 080572cc608..84a0a4667e6 100644
@@ -1653,7 +1653,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
builtin/worktree.c +1 -1
index 73ee505234c..c6d64dc8dfa 100644
@@ -506,7 +506,7 @@ static int add(int ac, const char **av, const char *prefix)
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
 		die(_("%s, %s and %s are mutually exclusive"), "-b", "-B", "--detach");
 	if (lock_reason && !keep_locked)
-		die(_("--reason requires --lock"));
+		die(_("%s requires %s"), "--reason", "--lock");
 	if (lock_reason)
 		opts.keep_locked = lock_reason;
 	else if (keep_locked)
fetch-pack.c +1 -1
index a9604f35a3e..0bdef8877c1 100644
@@ -296,7 +296,7 @@ static int find_common(struct fetch_negotiator *negotiator,
 	struct packet_reader reader;
 
 	if (args->stateless_rpc && multi_ack == 1)
-		die(_("--stateless-rpc requires multi_ack_detailed"));
+		die(_("%s requires %s"), "--stateless-rpc", "multi_ack_detailed");
 
 	packet_reader_init(&reader, fd[0], NULL, 0,
 			   PACKET_READ_CHOMP_NEWLINE |
http-fetch.c +2 -2
index fa642462a9e..68cbfc1979d 100644
@@ -131,7 +131,7 @@ int cmd_main(int argc, const char **argv)
 
 	if (packfile) {
 		if (!index_pack_args.nr)
-			die(_("--packfile requires --index-pack-args"));
+			die(_("%s requires %s"), "--packfile", "--index-pack-args");
 
 		fetch_single_packfile(&packfile_hash, argv[arg],
 				      index_pack_args.v);
@@ -140,7 +140,7 @@ int cmd_main(int argc, const char **argv)
 	}
 
 	if (index_pack_args.nr)
-		die(_("--index-pack-args can only be used with --packfile"));
+		die(_("%s requires %s"), "--index-pack-args", "--packfile");
 
 	if (commits_on_stdin) {
 		commits = walker_targets_stdin(&commit_id, &write_ref);
Signature · 1 line
gitgitgadget
#11 lore raw

PATCH 7/10 i18n: factorize "no directory given for --foo"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 git.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
git.c +3 -3
index 5ff21be21f3..8624730f022 100644
@@ -185,7 +185,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--git-dir")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for --git-dir\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "--git-dir");
 				usage(git_usage_string);
 			}
 			setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
@@ -213,7 +213,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--work-tree")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for --work-tree\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "--work-tree");
 				usage(git_usage_string);
 			}
 			setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
@@ -297,7 +297,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "-C")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for -C\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "-C");
 				usage(git_usage_string);
 			}
 			if ((*argv)[1][0]) {
Signature · 1 line
gitgitgadget
#12 lore raw

PATCH 8/10 i18n: refactor "unrecognized %(foo) argument" strings

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 ref-filter.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
ref-filter.c +6 -6
index 08a3f839c97..554c2ba1b17 100644
@@ -341,7 +341,7 @@ static int objectsize_atom_parser(struct ref_format *format, struct used_atom *a
 		else
 			oi.info.disk_sizep = &oi.disk_size;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(objectsize) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "objectsize", arg);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ static int subject_atom_parser(struct ref_format *format, struct used_atom *atom
 	else if (!strcmp(arg, "sanitize"))
 		atom->u.contents.option = C_SUB_SANITIZE;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(subject) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "subject", arg);
 	return 0;
 }
 
@@ -428,7 +428,7 @@ static int contents_atom_parser(struct ref_format *format, struct used_atom *ato
 		if (strtoul_ui(arg, 10, &atom->u.contents.nlines))
 			return strbuf_addf_ret(err, -1, _("positive value expected contents:lines=%s"), arg);
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(contents) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "contents", arg);
 	return 0;
 }
 
@@ -440,7 +440,7 @@ static int raw_atom_parser(struct ref_format *format, struct used_atom *atom,
 	else if (!strcmp(arg, "size"))
 		atom->u.raw_data.option = RAW_LENGTH;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(raw) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "raw", arg);
 	return 0;
 }
 
@@ -531,7 +531,7 @@ static int align_atom_parser(struct ref_format *format, struct used_atom *atom,
 		else if ((position = parse_align_position(s)) >= 0)
 			align->position = position;
 		else {
-			strbuf_addf(err, _("unrecognized %%(align) argument: %s"), s);
+			strbuf_addf(err, _("unrecognized %%(%s) argument: %s"), "align", s);
 			string_list_clear(&params, 0);
 			return -1;
 		}
@@ -557,7 +557,7 @@ static int if_atom_parser(struct ref_format *format, struct used_atom *atom,
 	} else if (skip_prefix(arg, "notequals=", &atom->u.if_then_else.str)) {
 		atom->u.if_then_else.cmp_status = COMPARE_UNEQUAL;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(if) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "if", arg);
 	return 0;
 }
 
Signature · 1 line
gitgitgadget
#13 lore raw

Re: [PATCH 08/10] i18n: refactor "unrecognized %(foo) argument" strings

Quoted 57 lines · Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 ref-filter.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
ref-filter.c +5 -5
index 08a3f839c97..554c2ba1b17 100644
@@ -341,7 +341,7 @@ static int objectsize_atom_parser(struct ref_format *format, struct used_atom *a
 		else
 			oi.info.disk_sizep = &oi.disk_size;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(objectsize) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "objectsize", arg);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ static int subject_atom_parser(struct ref_format *format, struct used_atom *atom
 	else if (!strcmp(arg, "sanitize"))
 		atom->u.contents.option = C_SUB_SANITIZE;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(subject) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "subject", arg);
 	return 0;
 }
 
@@ -428,7 +428,7 @@ static int contents_atom_parser(struct ref_format *format, struct used_atom *ato
 		if (strtoul_ui(arg, 10, &atom->u.contents.nlines))
 			return strbuf_addf_ret(err, -1, _("positive value expected contents:lines=%s"), arg);
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(contents) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "contents", arg);
 	return 0;
 }
 
@@ -440,7 +440,7 @@ static int raw_atom_parser(struct ref_format *format, struct used_atom *atom,
 	else if (!strcmp(arg, "size"))
 		atom->u.raw_data.option = RAW_LENGTH;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(raw) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "raw", arg);
 	return 0;
 }
 
@@ -531,7 +531,7 @@ static int align_atom_parser(struct ref_format *format, struct used_atom *atom,
 		else if ((position = parse_align_position(s)) >= 0)
 			align->position = position;
 		else {
-			strbuf_addf(err, _("unrecognized %%(align) argument: %s"), s);
+			strbuf_addf(err, _("unrecognized %%(%s) argument: %s"), "align", s);
 			string_list_clear(&params, 0);
 			return -1;
 		}

ref-filter.c static int if_atom_parser(struct ref_format *format, struct used_atom *atom, · line 562

Quoted 7 lines
ref-filter.c +1 -1
@@ -557,7 +557,7 @@ static int if_atom_parser(struct ref_format *format, struct used_atom *atom,
 	} else if (skip_prefix(arg, "notequals=", &atom->u.if_then_else.str)) {
 		atom->u.if_then_else.cmp_status = COMPARE_UNEQUAL;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(if) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "if", arg);
 	return 0;
 }

Maybe too big a refactoring, but doesn't the parent function here know the "name" and could just pass it along?

Or actually not pass it at all and just have all of these be say:

    return -2;

And we'd do the error one caller above this if we get a return code of -2.

#14 lore raw

PATCH 9/10 i18n: factorize "--foo outside a repository"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 apply.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
apply.c +3 -3
index fefec23f1ec..13b9abafe9d 100644
@@ -136,7 +136,7 @@ int check_apply_state(struct apply_state *state, int force_apply)
 		return error(_("%s and %s are mutually exclusive"),"--reject",  "--3way");
 	if (state->threeway) {
 		if (is_not_gitdir)
-			return error(_("--3way outside a repository"));
+			return error(_("%s outside a repository"), "--3way");
 		state->check_index = 1;
 	}
 	if (state->apply_with_reject) {
@@ -147,10 +147,10 @@ int check_apply_state(struct apply_state *state, int force_apply)
 	if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor))
 		state->apply = 0;
 	if (state->check_index && is_not_gitdir)
-		return error(_("--index outside a repository"));
+		return error(_("%s outside a repository"), "--index");
 	if (state->cached) {
 		if (is_not_gitdir)
-			return error(_("--cached outside a repository"));
+			return error(_("%s outside a repository"), "--cached");
 		state->check_index = 1;
 	}
 	if (state->ita_only && (state->check_index || is_not_gitdir))
Signature · 1 line
gitgitgadget
#15 lore raw

PATCH 10/10 i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 ref-filter.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
ref-filter.c +4 -4
index 554c2ba1b17..b515efeaa25 100644
@@ -841,7 +841,7 @@ static void if_then_else_handler(struct ref_formatting_stack **stack)
 	struct if_then_else *if_then_else = (struct if_then_else *)cur->at_end_data;
 
 	if (!if_then_else->then_atom_seen)
-		die(_("format: %%(if) atom used without a %%(then) atom"));
+		die(_("format: %%(%s) atom used without a %%(%s) atom"), "if", "then");
 
 	if (if_then_else->else_atom_seen) {
 		/*
@@ -907,7 +907,7 @@ static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	if (cur->at_end == if_then_else_handler)
 		if_then_else = (struct if_then_else *)cur->at_end_data;
 	if (!if_then_else)
-		return strbuf_addf_ret(err, -1, _("format: %%(then) atom used without an %%(if) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "then", "if");
 	if (if_then_else->then_atom_seen)
 		return strbuf_addf_ret(err, -1, _("format: %%(then) atom used more than once"));
 	if (if_then_else->else_atom_seen)
@@ -943,9 +943,9 @@ static int else_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	if (prev->at_end == if_then_else_handler)
 		if_then_else = (struct if_then_else *)prev->at_end_data;
 	if (!if_then_else)
-		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without an %%(if) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "else", "if");
 	if (!if_then_else->then_atom_seen)
-		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without a %%(then) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "else", "then");
 	if (if_then_else->else_atom_seen)
 		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used more than once"));
 	if_then_else->else_atom_seen = 1;
Signature · 1 line
gitgitgadget
#16 lore raw
In reply to Jean-Noël Avila via GitGitGadget
Quoted 10 lines · Jean-Noël Avila via GitGitGadget

This series is a meager attempt at rationalizing a small fraction of the internationalized messages. Sorry in advance for the dull task of reviewing these insipide patches.

Doing so has some positive effects:

* non-translatable constant strings are kept out of the way for translators
* messages with identical meaning are built identically
* the total number of messages to translate is decreased.

Quoted 8 lines

I'm inclined to even go a step further and turn these messages into #define or const strings. This would have the added benefits:

* make sure that the messages to translate are identical
* create a library of message skeletons to be picked up when new messages are needed

What do you think?

One slight negative of this approach is that it makes messages a bit harder to grep for. It sometimes really nice to "git jump grep" for specific messages you got to see where they're coming from.

I don't think that's a strong objection, though. If this is making the translations overall more maintainable it might be worth the tradeoff.

We could also allow GIT_VERBOSE=1 or something to print the file/line of error(), warning(), and die() messages, which solves the same problem. I think Ævar might have had some patches in that direction.

-Peff

#17 lore raw

Am 03.12.21 um 22:55 schrieb Jeff King:

Quoted 19 lines · Jean-Noël Avila via GitGitGadget
Quoted 18 lines

This series is a meager attempt at rationalizing a small fraction of the internationalized messages. Sorry in advance for the dull task of reviewing these insipide patches.

Doing so has some positive effects:

* non-translatable constant strings are kept out of the way for translators
* messages with identical meaning are built identically
* the total number of messages to translate is decreased.

I'm inclined to even go a step further and turn these messages into #define or const strings. This would have the added benefits:

* make sure that the messages to translate are identical
* create a library of message skeletons to be picked up when new messages are needed

Quoted 5 lines
Quoted 1 line

What do you think?

One slight negative of this approach is that it makes messages a bit harder to grep for. It sometimes really nice to "git jump grep" for specific messages you got to see where they're coming from.

This can be mitigated by using, for example,

  git grep -e --stdin --and -e mutually

as long as the rewrite keeps the arguments on the same line with the format strings, which it does.

Another aspect is that translators lose context. For example, "%s and %s are mutally exclusive" may have to be translated differently depending on what kind of text is substituted for %s. In this example it's probably always command line options (I haven't checked), so not an immediate problem. But something to keep in mind.

-- Hannes

#18 lore raw
Quoted 5 lines · Johannes Sixt

Another aspect is that translators lose context. For example, "%s and %s are mutally exclusive" may have to be translated differently depending on what kind of text is substituted for %s. In this example it's probably always command line options (I haven't checked), so not an immediate problem. But something to keep in mind.

Yup. I do not think we are quite ready to have two identical msgid strings to be translated into two different msgstr strings. We've briefly talked about pgettext() a few months ago, but nothing concrete came out of it, as far as I can recall.

#19 lore raw
Quoted 8 lines · On Sunday, 5 December 2021 08:31:38 CET Junio C Hamano wrote:
Quoted 5 lines · Johannes Sixt

Another aspect is that translators lose context. For example, "%s and %s are mutally exclusive" may have to be translated differently depending on what kind of text is substituted for %s. In this example it's probably always command line options (I haven't checked), so not an immediate problem. But something to keep in mind.

Quoted 6 lines

Yup. I do not think we are quite ready to have two identical msgid strings to be translated into two different msgstr strings. We've briefly talked about pgettext() a few months ago, but nothing concrete came out of it, as far as I can recall.

As a translator, I made sure that all the messages are with the same grammatical structure where the placeholders are only command line options. The same messages with placeholders are meant to convey exactly the same meaning at all their use point. We have all the control on the source code to tailor them so that one message model is only used with specific types of variables (options here). That's another reason why I was proposing to define and name them.

If needed, "%s and %s are mutually exclusive" could be turned into "options %s and %s are mutually exclusive" to make it clear that the placeholders can only hold option names.

#20 lore raw

Am 05.12.21 um 18:25 schrieb Jean-Noël AVILA:

Quoted 3 lines

If needed, "%s and %s are mutually exclusive" could be turned into "options %s and %s are mutually exclusive" to make it clear that the placeholders can only hold option names.

IMO, being less terse helps not only translators, but also users.

Regarding this particular message, personally, I am not a fan of "mutually exclusive" (sounds like it's been taken from a law text). How about "options ... are incompatible" or "... cannot be used together"?

-- Hannes

#21 lore raw
Quoted 10 lines · Johannes Sixt

Am 05.12.21 um 18:25 schrieb Jean-Noël AVILA:

Quoted 3 lines

If needed, "%s and %s are mutually exclusive" could be turned into "options %s and %s are mutually exclusive" to make it clear that the placeholders can only hold option names.

IMO, being less terse helps not only translators, but also users.

Regarding this particular message, personally, I am not a fan of "mutually exclusive" (sounds like it's been taken from a law text). How about "options ... are incompatible" or "... cannot be used together"?

Sounds good. Or perhaps "X cannot be used with Y", which may be even shorter and is still clear what it wants to say.

X and Y are incompatible.
X and Y cannot be used together.
X cannot be used with Y.

#22 lore raw
In reply to Jean-Noël Avila via GitGitGadget
Quoted 4 lines · Jean-Noël Avila via GitGitGadget

This series is a meager attempt at rationalizing a small fraction of the internationalized messages. Sorry in advance for the dull task of reviewing these insipide patches.

Quoted 8 lines

Doing so has some positive effects:

* non-translatable constant strings are kept out of the way for translators
* messages with identical meaning are built identically
* the total number of messages to translate is decreased.

I'm inclined to even go a step further and turn these messages into #define or const strings.

After looking at [01/10] that repeats the same string in many places, I would have to say that we do not want such C preprocessor macros. Having to hunt for an existing message that is close enough to what you want to say, when you are writing a new message, feels a bit too much.

I wonder if a tool that

- looks for "newly added" messages (by scanning "git diff" output)

- compares them with po/git.pot for existing msgid in a fuzzy way to locate the ones that may be candidate for a change like the changes in this series

can help developers, though.

Thanks.

#23 lore raw

v2 cover Factorization of messages with similar meaning

In reply to Jean-Noël Avila via GitGitGadget

This series is a meager attempt at rationalizing a small fraction of the internationalized messages. Sorry in advance for the dull task of reviewing these insipide patches.

Doing so has some positive effects:

* non-translatable constant strings are kept out of the way for translators
* messages with identical meaning are built identically
* the total number of messages to translate is decreased.

Changes since V1:

* took into account the comments, except for ref-filter.c where the proposed refactoring is not obvious.
* added even more strings to the "cannot be used together" crowd.

Jean-Noël Avila (11):
i18n: refactor "foo and bar are mutually exclusive"
i18n: refactor "%s, %s and %s are mutually exclusive"
i18n: turn "options are incompatible" into "cannot be used together"
i18n: standardize "cannot open" and "cannot read"
i18n: tag.c factorize i18n strings
i18n: factorize "--foo requires --bar" and the like
i18n: factorize "no directory given for --foo"
i18n: refactor "unrecognized %(foo) argument" strings
i18n: factorize "--foo outside a repository"
i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"
i18n: turn even more messages into "cannot be used together" ones

 apply.c                                   |  8 ++++----
 archive.c                                 |  8 ++++----
 builtin/add.c                             | 14 +++++++-------
 builtin/am.c                              |  4 ++--
 builtin/branch.c                          |  2 +-
 builtin/cat-file.c                        |  2 +-
 builtin/checkout.c                        | 12 ++++++------
 builtin/clone.c                           |  4 ++--
 builtin/commit.c                          | 18 ++++++++++--------
 builtin/describe.c                        |  6 +++---
 builtin/diff-tree.c                       |  2 +-
 builtin/difftool.c                        |  4 ++--
 builtin/fast-export.c                     |  4 ++--
 builtin/fetch.c                           |  8 ++++----
 builtin/index-pack.c                      |  4 ++--
 builtin/init-db.c                         |  4 ++--
 builtin/log.c                             |  8 ++++----
 builtin/ls-files.c                        |  2 +-
 builtin/merge.c                           |  4 ++--
 builtin/pack-objects.c                    |  2 +-
 builtin/push.c                            |  8 ++++----
 builtin/rebase.c                          | 10 +++++-----
 builtin/repack.c                          |  4 ++--
 builtin/reset.c                           | 10 +++++-----
 builtin/rev-list.c                        |  4 ++--
 builtin/rm.c                              |  4 ++--
 builtin/show-branch.c                     |  4 ++--
 builtin/stash.c                           |  8 ++++----
 builtin/submodule--helper.c               |  4 ++--
 builtin/tag.c                             | 13 ++++++++-----
 builtin/worktree.c                        |  6 +++---
 diff.c                                    |  8 ++++----
 fetch-pack.c                              |  2 +-
 git.c                                     |  6 +++---
 http-fetch.c                              |  4 ++--
 range-diff.c                              |  2 +-
 ref-filter.c                              | 22 +++++++++++-----------
 revision.c                                | 22 +++++++++++-----------
 t/t0001-init.sh                           |  6 +++---
 t/t2025-checkout-no-overlay.sh            |  2 +-
 t/t2026-checkout-pathspec-file.sh         |  6 +++---
 t/t2072-restore-pathspec-file.sh          |  4 ++--
 t/t3431-rebase-fork-point.sh              |  2 +-
 t/t3601-rm-pathspec-file.sh               |  2 +-
 t/t3704-add-pathspec-file.sh              |  8 ++++----
 t/t3909-stash-pathspec-file.sh            |  4 ++--
 t/t4209-log-pickaxe.sh                    | 10 +++++-----
 t/t5606-clone-options.sh                  |  4 ++--
 t/t7107-reset-pathspec-file.sh            |  4 ++--
 t/t7500-commit-template-squash-signoff.sh | 11 ++++++-----
 t/t7526-commit-pathspec-file.sh           |  8 ++++----
 51 files changed, 169 insertions(+), 163 deletions(-)

base-commit: 2ae0a9cb8298185a94e5998086f380a355dd8907
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1088%2Fjnavila%2Fi18n-refactor-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1088/jnavila/i18n-refactor-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1088

Range-diff vs v1:

1: 476eb77aff6 ! 1: 71699eaa27b i18n: refactor "foo and bar are mutually exclusive"

     @@ Metadata
       ## Commit message ##
          i18n: refactor "foo and bar are mutually exclusive"
      
     -    Use static strings for constant parts of the sentences.
     +    Use static strings for constant parts of the sentences. They are all
     +    turned into "cannot be used together".
      
          Signed-off-by: Jean-Noël Avila <[email protected]>
      
     @@ builtin/checkout.c: static int checkout_main(int argc, const char **argv, const
       
       	if (opts->overlay_mode == 1 && opts->patch_mode)
      -		die(_("-p and --overlay are mutually exclusive"));
     -+		die(_("%s and %s are mutually exclusive"), "-p", "--overlay");
     ++		die(_("options '%s' and '%s' cannot be used together"), "-p", "--overlay");
       
       	if (opts->checkout_index >= 0 || opts->checkout_worktree >= 0) {
       		if (opts->checkout_index < 0)
     @@ builtin/diff-tree.c: int cmd_diff_tree(int argc, const char **argv, const char *
       
       	if (read_stdin && merge_base)
      -		die(_("--stdin and --merge-base are mutually exclusive"));
     -+		die(_("%s and %s are mutually exclusive"), "--stdin", "--merge-base");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--stdin", "--merge-base");
       	if (merge_base && opt->pending.nr != 2)
       		die(_("--merge-base only works with two commits"));
       
     @@ builtin/diff-tree.c: int cmd_diff_tree(int argc, const char **argv, const char *
       ## builtin/fetch.c ##
      @@ builtin/fetch.c: int cmd_fetch(int argc, const char **argv, const char *prefix)
       		if (deepen_relative < 0)
     - 			die(_("Negative depth in --deepen is not supported"));
     + 			die(_("negative depth in --deepen is not supported"));
       		if (depth)
      -			die(_("--deepen and --depth are mutually exclusive"));
     -+			die(_("%s and %s are mutually exclusive"), "--deepen", "--depth");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--deepen", "--depth");
       		depth = xstrfmt("%d", deepen_relative);
       	}
       	if (unshallow) {
     + 		if (depth)
     +-			die(_("--depth and --unshallow cannot be used together"));
     ++			die(_("options '%s' and '%s' cannot be used together"), "--depth", "--unshallow");
     + 		else if (!is_repository_shallow(the_repository))
     + 			die(_("--unshallow on a complete repository does not make sense"));
     + 		else
      
       ## builtin/init-db.c ##
      @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *prefix)
     @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *pref
       
       	if (real_git_dir && is_bare_repository_cfg == 1)
      -		die(_("--separate-git-dir and --bare are mutually exclusive"));
     -+		die(_("%s and %s are mutually exclusive"), "--separate-git-dir", "--bare");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
       
       	if (real_git_dir && !is_absolute_path(real_git_dir))
       		real_git_dir = real_pathdup(real_git_dir, 1);
     @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *pre
       
       	if (numbered && keep_subject)
      -		die(_("-n and -k are mutually exclusive"));
     -+		die(_("%s and %s are mutually exclusive"), "-n", "-k");
     ++		die(_("options '%s' and '%s' cannot be used together"), "-n", "-k");
       	if (keep_subject && subject_prefix)
      -		die(_("--subject-prefix/--rfc and -k are mutually exclusive"));
     -+		die(_("%s and %s are mutually exclusive"), "--subject-prefix/--rfc", "-k");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--subject-prefix/--rfc", "-k");
       	rev.preserve_subject = keep_subject;
       
       	argc = setup_revisions(argc, argv, &rev, &s_r_opt);
     @@ builtin/submodule--helper.c: static int module_summary(int argc, const char **ar
       	if (files) {
       		if (cached)
      -			die(_("--cached and --files are mutually exclusive"));
     -+			die(_("%s and %s are mutually exclusive"), "--cached", "--files");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--cached", "--files");
       		diff_cmd = DIFF_FILES;
       	}
       
     @@ builtin/submodule--helper.c: static int module_set_branch(int argc, const char *
       
       	if (opt_branch && opt_default)
      -		die(_("--branch and --default are mutually exclusive"));
     -+		die(_("%s and %s are mutually exclusive"), "--branch", "--default");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--branch", "--default");
       
       	if (argc != 1 || !(path = argv[0]))
       		usage_with_options(usage, options);
     @@ builtin/worktree.c: static int list(int ac, const char **av, const char *prefix)
       		usage_with_options(worktree_usage, options);
       	else if (verbose && porcelain)
      -		die(_("--verbose and --porcelain are mutually exclusive"));
     -+		die(_("%s and %s are mutually exclusive"), "--verbose", "--porcelain");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--verbose", "--porcelain");
       	else {
       		struct worktree **worktrees = get_worktrees();
       		int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
     @@ range-diff.c: int show_range_diff(const char *range1, const char *range2,
       
       	if (range_diff_opts->left_only && range_diff_opts->right_only)
      -		res = error(_("--left-only and --right-only are mutually exclusive"));
     -+		res = error(_("%s and %s are mutually exclusive"), "--left-only", "--right-only");
     ++		res = error(_("options '%s' and '%s' cannot be used together"), "--left-only", "--right-only");
       
       	if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg))
       		res = error(_("could not parse log for '%s'"), range1);
     +
     + ## t/t0001-init.sh ##
     +@@ t/t0001-init.sh: test_expect_success 'init with separate gitdir' '
     + 
     + test_expect_success 'explicit bare & --separate-git-dir incompatible' '
     + 	test_must_fail git init --bare --separate-git-dir goop.git bare.git 2>err &&
     +-	test_i18ngrep "mutually exclusive" err
     ++	test_i18ngrep "cannot be used together" err
     + '
     + 
     + test_expect_success 'implicit bare & --separate-git-dir incompatible' '
     +
     + ## t/t2025-checkout-no-overlay.sh ##
     +@@ t/t2025-checkout-no-overlay.sh: test_expect_success 'checkout --no-overlay removing last file from directory' '
     + 
     + test_expect_success 'checkout -p --overlay is disallowed' '
     + 	test_must_fail git checkout -p --overlay HEAD 2>actual &&
     +-	test_i18ngrep "fatal: -p and --overlay are mutually exclusive" actual
     ++	test_i18ngrep "fatal: options .-p. and .--overlay. cannot be used together" actual
     + '
     + 
     + test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
     +
     + ## t/t4209-log-pickaxe.sh ##
     +@@ t/t4209-log-pickaxe.sh: test_expect_success 'usage' '
     + 	test_i18ngrep "switch.*requires a value" err &&
     + 
     + 	test_expect_code 128 git log -Gregex -Sstring 2>err &&
     +-	grep "mutually exclusive" err &&
     ++	grep "cannot be used together" err &&
     + 
     + 	test_expect_code 128 git log -Gregex --find-object=HEAD 2>err &&
     +-	grep "mutually exclusive" err &&
     ++	grep "cannot be used together" err &&
     + 
     + 	test_expect_code 128 git log -Sstring --find-object=HEAD 2>err &&
     +-	grep "mutually exclusive" err &&
     ++	grep "cannot be used together" err &&
     + 
     + 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
     + 	grep "mutually exclusive" err
  2:  32c7799388b !  2:  be4e8757f38 i18n: refactor "%s, %s and %s are mutually exclusive"
     @@ Metadata
       ## Commit message ##
          i18n: refactor "%s, %s and %s are mutually exclusive"
      
     -    Use placeholders for constant tokens.
     +    Use placeholders for constant tokens. The strings are turned into
     +    "cannot be used together"
      
          Signed-off-by: Jean-Noël Avila <[email protected]>
      
     @@ builtin/difftool.c: int cmd_difftool(int argc, const char **argv, const char *pr
       
       	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
      -		die(_("--gui, --tool and --extcmd are mutually exclusive"));
     -+		die(_("%s, %s and %s are mutually exclusive"), "--gui", "--tool", "--extcmd");
     ++		die(_("options '%s', '%s' and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
       
       	if (use_gui_tool)
       		setenv("GIT_MERGETOOL_GUI", "true", 1);
     @@ 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(_("--stdout, --output, and --output-directory are mutually exclusive"));
     -+		die(_("%s, %s and %s are mutually exclusive"), "--stdout", "--output", "--output-directory");
     ++		die(_("options '%s', '%s' and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
       
       	if (use_stdout) {
       		setup_pager();
     @@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix)
       	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
       	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
      -		die(_("-b, -B, and --detach are mutually exclusive"));
     -+		die(_("%s, %s and %s are mutually exclusive"), "-b", "-B", "--detach");
     ++		die(_("options '%s', '%s' and '%s' cannot be used together"), "-b", "-B", "--detach");
       	if (lock_reason && !keep_locked)
       		die(_("--reason requires --lock"));
       	if (lock_reason)
     @@ diff.c: void diff_setup_done(struct diff_options *options)
       
       	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
      -		die(_("-G, -S and --find-object are mutually exclusive"));
     -+		die(_("%s, %s and %s are mutually exclusive"), "-G", "-S", "--find-object");
     ++		die(_("options '%s', '%s' and '%s' cannot be used together"), "-G", "-S", "--find-object");
       
       	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
       		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
  3:  46e94ef3ac9 !  3:  53bad588bfc i18n: turn "options are incompatible" into "are mutually exclusive"
     @@ Metadata
      Author: Jean-Noël Avila <[email protected]>
      
       ## Commit message ##
     -    i18n: turn "options are incompatible" into "are mutually exclusive"
     +    i18n: turn "options are incompatible" into "cannot be used together"
      
          Signed-off-by: Jean-Noël Avila <[email protected]>
      
     @@ apply.c: int check_apply_state(struct apply_state *state, int force_apply)
       
       	if (state->apply_with_reject && state->threeway)
      -		return error(_("--reject and --3way cannot be used together."));
     -+		return error(_("%s and %s are mutually exclusive"),"--reject",  "--3way");
     ++		return error(_("options '%s' and '%s' cannot be used together"),"--reject",  "--3way");
       	if (state->threeway) {
       		if (is_not_gitdir)
       			return error(_("--3way outside a repository"));
     @@ archive.c: static int parse_archive_args(int argc, const char **argv,
       		die(_("Unexpected option --output"));
       	if (is_remote && args->extra_files.nr)
      -		die(_("Options --add-file and --remote cannot be used together"));
     -+		die(_("%s and %s are mutually exclusive"), "--add-file", "--remote");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--add-file", "--remote");
       
       	if (!base)
       		base = "";
     @@ builtin/add.c: int cmd_add(int argc, const char **argv, const char *prefix)
       	if (add_interactive) {
       		if (show_only)
      -			die(_("--dry-run is incompatible with --interactive/--patch"));
     -+			die(_("%s and %s are mutually exclusive"), "--dry-run", "--interactive/--patch");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
       		if (pathspec_from_file)
      -			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
     -+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--interactive/--patch");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
       		exit(interactive_add(argv + 1, prefix, patch_interactive));
       	}
       	if (legacy_stash_p) {
     @@ builtin/add.c: int cmd_add(int argc, const char **argv, const char *prefix)
       	if (edit_interactive) {
       		if (pathspec_from_file)
      -			die(_("--pathspec-from-file is incompatible with --edit"));
     -+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--edit");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--edit");
       		return(edit_patch(argc, argv, prefix));
       	}
       	argc--;
     @@ builtin/add.c: int cmd_add(int argc, const char **argv, const char *prefix)
       
       	if (addremove && take_worktree_changes)
      -		die(_("-A and -u are mutually incompatible"));
     -+		die(_("%s and %s are mutually exclusive"), "-A", "-u");
     ++		die(_("options '%s' and '%s' cannot be used together"), "-A", "-u");
       
       	if (!show_only && ignore_missing)
       		die(_("Option --ignore-missing can only be used together with --dry-run"));
     @@ builtin/branch.c: int cmd_branch(int argc, const char **argv, const char *prefix
       	if (filter.verbose) {
       		if (explicitly_enable_column(colopts))
      -			die(_("--column and --verbose are incompatible"));
     -+			die(_("%s and %s are mutually exclusive"), "--column", "--verbose");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--column", "--verbose");
       		colopts = 0;
       	}
       
     @@ builtin/checkout.c: static int checkout_main(int argc, const char **argv, const
       
       		if (opts->force_detach)
      -			die(_("--pathspec-from-file is incompatible with --detach"));
     -+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file",  "--detach");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file",  "--detach");
       
       		if (opts->patch_mode)
      -			die(_("--pathspec-from-file is incompatible with --patch"));
     -+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--patch");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
       
       		parse_pathspec_file(&opts->pathspec, 0,
       				    0,
     @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
       			    option_origin);
       		if (real_git_dir)
      -			die(_("--bare and --separate-git-dir are incompatible."));
     -+			die(_("%s and %s are mutually exclusive"), "--bare", "--separate-git-dir");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--bare", "--separate-git-dir");
       		option_no_checkout = 1;
       	}
       
     @@ builtin/commit.c: static const char *prepare_index(const char **argv, const char
       	if (pathspec_from_file) {
       		if (interactive)
      -			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
     -+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--interactive/--patch");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
       
       		if (all)
     - 			die(_("--pathspec-from-file with -a does not make sense"));
     +-			die(_("--pathspec-from-file with -a does not make sense"));
     ++			die(_("options '%s' and '%s' cannot be used together"),"--pathspec-from-file", "-a");
     + 
     + 		if (pathspec.nr)
     + 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
      @@ builtin/commit.c: static void finalize_deferred_config(struct wt_status *s)
       		    status_format == STATUS_FORMAT_UNSPECIFIED)
       			status_format = STATUS_FORMAT_PORCELAIN;
       		else if (status_format == STATUS_FORMAT_LONG)
      -			die(_("--long and -z are incompatible"));
     -+			die(_("%s and %s are mutually exclusive"), "--long", "-z");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--long", "-z");
       	}
       
       	if (use_deferred_config && status_format == STATUS_FORMAT_UNSPECIFIED)
     @@ builtin/describe.c: int cmd_describe(int argc, const char **argv, const char *pr
       
       	if (longformat && abbrev == 0)
      -		die(_("--long is incompatible with --abbrev=0"));
     -+		die(_("%s and %s are mutually exclusive"), "--long", "--abbrev=0");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--long", "--abbrev=0");
       
       	if (contains) {
       		struct string_list_item *item;
     @@ builtin/difftool.c: int cmd_difftool(int argc, const char **argv, const char *pr
       		setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
       	} else if (dir_diff)
      -		die(_("--dir-diff is incompatible with --no-index"));
     -+		die(_("%s and %s are mutually exclusive"), "--dir-diff", "--no-index");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
       
       	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
     - 		die(_("%s, %s and %s are mutually exclusive"), "--gui", "--tool", "--extcmd");
     + 		die(_("options '%s', '%s' and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
      
       ## builtin/fast-export.c ##
      @@ builtin/fast-export.c: int cmd_fast_export(int argc, const char **argv, const char *prefix)
     @@ builtin/fast-export.c: int cmd_fast_export(int argc, const char **argv, const ch
       
       	if (import_filename && import_filename_if_exists)
      -		die(_("Cannot pass both --import-marks and --import-marks-if-exists"));
     -+		die(_("%s and %s are mutually exclusive"), "--import-marks", "--import-marks-if-exists");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--import-marks", "--import-marks-if-exists");
       	if (import_filename)
       		import_marks(import_filename, 0);
       	else if (import_filename_if_exists)
     @@ builtin/index-pack.c: int cmd_index_pack(int argc, const char **argv, const char
       		die(_("--stdin requires a git repository"));
       	if (from_stdin && hash_algo)
      -		die(_("--object-format cannot be used with --stdin"));
     -+		die(_("%s and %s are mutually exclusive"), "--object-format", "--stdin");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--object-format", "--stdin");
       	if (!index_name && pack_name)
       		index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
       
      
     + ## builtin/ls-files.c ##
     +@@ builtin/ls-files.c: int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
     + 		 * would not make any sense with this option.
     + 		 */
     + 		if (show_stage || show_unmerged)
     +-			die("ls-files --with-tree is incompatible with -s or -u");
     ++			die(_("options '%s' and '%s' cannot be used together"), "ls-files --with-tree", "-s/-u");
     + 		overlay_tree_on_index(the_repository->index, with_tree, max_prefix);
     + 	}
     + 
     +
     + ## builtin/merge.c ##
     +@@ builtin/merge.c: int cmd_merge(int argc, const char **argv, const char *prefix)
     + 
     + 	if (squash) {
     + 		if (fast_forward == FF_NO)
     +-			die(_("You cannot combine --squash with --no-ff."));
     ++			die(_("options '%s' and '%s' cannot be used together"), "--squash", "--no-ff.");
     + 		if (option_commit > 0)
     +-			die(_("You cannot combine --squash with --commit."));
     ++			die(_("options '%s' and '%s' cannot be used together"), "--squash", "--commit.");
     + 		/*
     + 		 * squash can now silently disable option_commit - this is not
     + 		 * a problem as it is only overriding the default, not a user
     +
       ## builtin/pack-objects.c ##
      @@ builtin/pack-objects.c: int cmd_pack_objects(int argc, const char **argv, const char *prefix)
       		die(_("--thin cannot be used to build an indexable pack"));
       
       	if (keep_unreachable && unpack_unreachable)
      -		die(_("--keep-unreachable and --unpack-unreachable are incompatible"));
     -+		die(_("%s and %s are mutually exclusive"), "--keep-unreachable", "--unpack-unreachable");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "--unpack-unreachable");
       	if (!rev_list_all || !rev_list_reflog || !rev_list_index)
       		unpack_unreachable_expiration = 0;
       
     @@ builtin/push.c: int cmd_push(int argc, const char **argv, const char *prefix)
       
       	if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
      -		die(_("--delete is incompatible with --all, --mirror and --tags"));
     -+		die(_("%s and %s are mutually exclusive"), "--delete", "--all/--mirror/--tags");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--mirror/--tags");
       	if (deleterefs && argc < 2)
       		die(_("--delete doesn't make sense without any refs"));
       
     @@ builtin/push.c: int cmd_push(int argc, const char **argv, const char *prefix)
       	if (flags & TRANSPORT_PUSH_ALL) {
       		if (tags)
      -			die(_("--all and --tags are incompatible"));
     -+			die(_("%s and %s are mutually exclusive"), "--all", "--tags");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--all", "--tags");
       		if (argc >= 2)
       			die(_("--all can't be combined with refspecs"));
       	}
       	if (flags & TRANSPORT_PUSH_MIRROR) {
       		if (tags)
      -			die(_("--mirror and --tags are incompatible"));
     -+			die(_("%s and %s are mutually exclusive"), "--mirror", "--tags");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--mirror", "--tags");
       		if (argc >= 2)
       			die(_("--mirror can't be combined with refspecs"));
       	}
       	if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
      -		die(_("--all and --mirror are incompatible"));
     -+		die(_("%s and %s are mutually exclusive"), "--all", "--mirror");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--all", "--mirror");
       
       	if (!is_empty_cas(&cas) && (flags & TRANSPORT_PUSH_FORCE_IF_INCLUDES))
       		cas.use_force_if_includes = 1;
      
     + ## builtin/rebase.c ##
     +@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
     + 
     + 	if (keep_base) {
     + 		if (options.onto_name)
     +-			die(_("cannot combine '--keep-base' with '--onto'"));
     ++			die(_("options '%s' and '%s' cannot be used together"),"--keep-base", "--onto");
     + 		if (options.root)
     +-			die(_("cannot combine '--keep-base' with '--root'"));
     ++			die(_("options '%s' and '%s' cannot be used together"),"--keep-base", "--root");
     + 	}
     + 
     + 	if (options.root && options.fork_point > 0)
     +-		die(_("cannot combine '--root' with '--fork-point'"));
     ++		die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
     + 
     + 	if (action != ACTION_NONE && !in_progress)
     + 		die(_("No rebase in progress?"));
     +
       ## builtin/repack.c ##
      @@ builtin/repack.c: int cmd_repack(int argc, const char **argv, const char *prefix)
       
       	if (keep_unreachable &&
       	    (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
      -		die(_("--keep-unreachable and -A are incompatible"));
     -+		die(_("%s and %s are mutually exclusive"), "--keep-unreachable", "-A");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "-A");
       
       	if (write_bitmaps < 0) {
       		if (!write_midx &&
     @@ builtin/repack.c: int cmd_repack(int argc, const char **argv, const char *prefix
       	if (geometric_factor) {
       		if (pack_everything)
      -			die(_("--geometric is incompatible with -A, -a"));
     -+			die(_("%s and %s are mutually exclusive"),"--geometric", "-A/-a");
     ++			die(_("options '%s' and '%s' cannot be used together"),"--geometric", "-A/-a");
       		init_pack_geometry(&geometry);
       		split_pack_geometry(geometry, geometric_factor);
       	}
     @@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)
       	if (pathspec_from_file) {
       		if (patch_mode)
      -			die(_("--pathspec-from-file is incompatible with --patch"));
     -+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--patch");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
       
       		if (pathspec.nr)
       			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
     @@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)
       	if (patch_mode) {
       		if (reset_type != NONE)
      -			die(_("--patch is incompatible with --{hard,mixed,soft}"));
     -+			die(_("%s and %s are mutually exclusive"), "--patch", "--{hard,mixed,soft}");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
       		trace2_cmd_mode("patch-interactive");
       		return run_add_interactive(rev, "--patch=reset", &pathspec);
       	}
      
     + ## builtin/rev-list.c ##
     +@@ builtin/rev-list.c: int cmd_rev_list(int argc, const char **argv, const char *prefix)
     + 		const char *arg = argv[i];
     + 		if (skip_prefix(arg, "--missing=", &arg)) {
     + 			if (revs.exclude_promisor_objects)
     +-				die(_("cannot combine --exclude-promisor-objects and --missing"));
     ++				die(_("options '%s' and '%s' cannot be used together"),"--exclude-promisor-objects", "--missing");
     + 			if (parse_missing_action_value(arg))
     + 				break;
     + 		}
     +
     + ## builtin/show-branch.c ##
     +@@ builtin/show-branch.c: int cmd_show_branch(int ac, const char **av, const char *prefix)
     + 			 *
     + 			 * Also --all and --remotes do not make sense either.
     + 			 */
     +-			die(_("--reflog is incompatible with --all, --remotes, "
     +-			      "--independent or --merge-base"));
     ++			die(_("options '%s' and '%s' cannot be used together"), "--reflog",
     ++				"--all/--remotes/--independent/--merge-base");
     + 	}
     + 
     + 	/* If nothing is specified, show all branches by default */
     +
       ## builtin/stash.c ##
      @@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *prefix,
       
       	if (pathspec_from_file) {
       		if (patch_mode)
      -			die(_("--pathspec-from-file is incompatible with --patch"));
     -+			die(_("%s and %s are mutually exclusive"), "--pathspec-from-file", "--patch");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
     + 
     + 		if (only_staged)
     +-			die(_("--pathspec-from-file is incompatible with --staged"));
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--staged");
       
       		if (ps.nr)
       			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
     @@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)
       	if (cmdmode == 'l' && filter.lines != -1) {
       		if (explicitly_enable_column(colopts))
      -			die(_("--column and -n are incompatible"));
     -+			die(_("%s and %s are mutually exclusive"), "--column", "-n");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--column", "-n");
       		colopts = 0;
       	}
     - 	if (!sorting)
     + 	sorting = ref_sorting_options(&sorting_options);
      
       ## revision.c ##
      @@ revision.c: static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
     @@ revision.c: static int handle_revision_opt(struct rev_info *revs, int argc, cons
       	} else if (!strcmp(arg, "--right-only")) {
       		if (revs->left_only)
      -			die("--right-only is incompatible with --left-only");
     -+			die(_("%s and %s are mutually exclusive"), "--right-only", "--left-only");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--right-only", "--left-only");
       		revs->right_only = 1;
       	} else if (!strcmp(arg, "--cherry")) {
       		if (revs->left_only)
      -			die("--cherry is incompatible with --left-only");
     -+			die(_("%s and %s are mutually exclusive"), "--cherry", "--left-only");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--cherry", "--left-only");
       		revs->cherry_mark = 1;
       		revs->right_only = 1;
       		revs->max_parents = 1;
     @@ revision.c: static int handle_revision_opt(struct rev_info *revs, int argc, cons
       	} else if (!strcmp(arg, "--cherry-mark")) {
       		if (revs->cherry_pick)
      -			die("--cherry-mark is incompatible with --cherry-pick");
     -+			die(_("%s and %s are mutually exclusive"), "--cherry-mark", "--cherry-pick");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--cherry-mark", "--cherry-pick");
       		revs->cherry_mark = 1;
       		revs->limited = 1; /* needs limit_list() */
       	} else if (!strcmp(arg, "--cherry-pick")) {
       		if (revs->cherry_mark)
      -			die("--cherry-pick is incompatible with --cherry-mark");
     -+			die(_("%s and %s are mutually exclusive"), "--cherry-pick", "--cherry-mark");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--cherry-pick", "--cherry-mark");
       		revs->cherry_pick = 1;
       		revs->limited = 1;
       	} else if (!strcmp(arg, "--objects")) {
     @@ revision.c: static int handle_revision_opt(struct rev_info *revs, int argc, cons
       	}
       	if (revs->graph && revs->track_linear)
      -		die("--show-linear-break and --graph are incompatible");
     -+		die(_("%s and %s are mutually exclusive"), "--show-linear-break", "--graph");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--show-linear-break", "--graph");
       
       	return 1;
       }
     @@ revision.c: int setup_revisions(int argc, const char **argv, struct rev_info *re
       
       	if (revs->reverse && revs->reflog_info)
      -		die("cannot combine --reverse with --walk-reflogs");
     -+		die(_("%s and %s are mutually exclusive"), "--reverse", "--walk-reflogs");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--walk-reflogs");
       	if (revs->reflog_info && revs->limited)
       		die("cannot combine --walk-reflogs with history-limiting options");
       	if (revs->rewrite_parents && revs->children.name)
      -		die("cannot combine --parents and --children");
     -+		die(_("%s and %s are mutually exclusive"), "--parents", "--children");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--parents", "--children");
       
       	/*
       	 * Limitations on the graph functionality
       	 */
       	if (revs->reverse && revs->graph)
      -		die("cannot combine --reverse with --graph");
     -+		die(_("%s and %s are mutually exclusive"), "--reverse", "--graph");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--graph");
       
       	if (revs->reflog_info && revs->graph)
      -		die("cannot combine --walk-reflogs with --graph");
     -+		die(_("%s and %s are mutually exclusive"), "--walk-reflogs", "--graph");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--walk-reflogs", "--graph");
       	if (revs->no_walk && revs->graph)
      -		die("cannot combine --no-walk with --graph");
     -+		die(_("%s and %s are mutually exclusive"), "--no-walk", "--graph");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
       	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
      -		die("cannot use --grep-reflog without --walk-reflogs");
      +		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");
     @@ t/t2026-checkout-pathspec-file.sh: test_expect_success 'error conditions' '
       
       	test_must_fail git checkout --pathspec-from-file=list --detach 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --detach" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --detach are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--detach. cannot be used together" err &&
       
       	test_must_fail git checkout --pathspec-from-file=list --patch 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --patch are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
       
       	test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err &&
       	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     @@ t/t2072-restore-pathspec-file.sh: test_expect_success 'error conditions' '
       
       	test_must_fail git restore --pathspec-from-file=list --patch --source=HEAD^1 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --patch are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
       
       	test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err &&
       	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     @@ t/t3704-add-pathspec-file.sh: test_expect_success 'error conditions' '
       
       	test_must_fail git add --pathspec-from-file=list --interactive 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --interactive/--patch are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
       
       	test_must_fail git add --pathspec-from-file=list --patch 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --interactive/--patch are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
       
       	test_must_fail git add --pathspec-from-file=list --edit 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --edit" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --edit are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err &&
       
       	test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err &&
       	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     @@ t/t3909-stash-pathspec-file.sh: test_expect_success 'error conditions' '
       
       	test_must_fail git stash push --pathspec-from-file=list --patch 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --patch are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
       
       	test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
       	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     @@ t/t5606-clone-options.sh: test_expect_success 'disallows --bare with --separate-
       	test_must_fail git clone --bare --separate-git-dir dot-git-destiation parent clone-bare-sgd 2>err &&
       	test_debug "cat err" &&
      -	test_i18ngrep -e "--bare and --separate-git-dir are incompatible" err
     -+	test_i18ngrep -e "--bare and --separate-git-dir are mutually exclusive" err
     ++	test_i18ngrep -e "options .--bare. and .--separate-git-dir. cannot be used together" err
       
       '
       
     @@ t/t7107-reset-pathspec-file.sh: test_expect_success 'error conditions' '
       
       	test_must_fail git reset --pathspec-from-file=list --patch 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --patch are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
       
       	test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err &&
       	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     @@ t/t7526-commit-pathspec-file.sh: test_expect_success 'error conditions' '
       
       	test_must_fail git commit --pathspec-from-file=list --interactive -m "Commit" 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --interactive/--patch are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
       
       	test_must_fail git commit --pathspec-from-file=list --patch -m "Commit" 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
     -+	test_i18ngrep -e "--pathspec-from-file and --interactive/--patch are mutually exclusive" err &&
     ++	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
       
       	test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err &&
       	test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
  4:  d408cecc85f =  4:  88dfde62eda i18n: standardize "cannot open" and "cannot read"
  5:  b67f0e492e0 !  5:  6d89c23a248 i18n: tag.c factorize i18n strings
     @@ Commit message
          Signed-off-by: Jean-Noël Avila <[email protected]>
      
       ## builtin/tag.c ##
     +@@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)
     + 		OPT_END()
     + 	};
     + 	int ret = 0;
     ++	const char *only_in_list = NULL;
     + 
     + 	setup_ref_filter_porcelain_msg();
     + 
      @@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)
       		goto cleanup;
       	}
       	if (filter.lines != -1)
      -		die(_("-n option is only allowed in list mode"));
     -+		die(_("%s option is only allowed in list mode"), "-n");
     ++		only_in_list = "-n";
       	if (filter.with_commit)
      -		die(_("--contains option is only allowed in list mode"));
     -+		die(_("%s option is only allowed in list mode"), "--contains");
     ++		only_in_list = "--contains";
       	if (filter.no_commit)
      -		die(_("--no-contains option is only allowed in list mode"));
     -+		die(_("%s option is only allowed in list mode"), "--no-contains");
     ++		only_in_list = "--no-contains";
       	if (filter.points_at.nr)
      -		die(_("--points-at option is only allowed in list mode"));
     -+		die(_("%s option is only allowed in list mode"), "--points-at");
     ++		only_in_list = "--points-at";
     ++	if (only_in_list)
     ++		die("the '%s' option is only allowed in list mode", only_in_list);
       	if (filter.reachable_from || filter.unreachable_from)
       		die(_("--merged and --no-merged options are only allowed in list mode"));
       	if (cmdmode == 'd') {

6: 653e33f7995 ! 6: f83ed5cb799 i18n: factorize "--foo requires --bar" and the like
@@ archive.c: static int parse_archive_args(int argc, const char **argv,

## builtin/add.c ##
@@ builtin/add.c: int cmd_add(int argc, const char **argv, const char *prefix)
- die(_("%s and %s are mutually exclusive"), "-A", "-u");
+ die(_("options '%s' and '%s' cannot be used together"), "-A", "-u");

if (!show_only && ignore_missing)
- die(_("Option --ignore-missing can only be used together with --dry-run"));
@@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)
- die(_("-N can only be used with --mixed"));
+ die(_("%s requires %s"), "-N", "--mixed");

- /* Soft reset does not touch the index file nor the working tree
- * at all, but requires them in a good order. Other resets reset
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;

## builtin/rm.c ##
@@ builtin/rm.c: int cmd_rm(int argc, const char **argv, const char *prefix)
@@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *
## builtin/worktree.c ##
@@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix)
if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
- die(_("%s, %s and %s are mutually exclusive"), "-b", "-B", "--detach");
+ die(_("options '%s', '%s' and '%s' cannot be used together"), "-b", "-B", "--detach");
if (lock_reason && !keep_locked)
- die(_("--reason requires --lock"));
+ die(_("%s requires %s"), "--reason", "--lock");

  7:  4b0e1ff29cb =  7:  2b7d558f8f9 i18n: factorize "no directory given for --foo"
  8:  4c2df4522a1 !  8:  5f80ac2fa20 i18n: refactor "unrecognized %(foo) argument" strings

@@ ref-filter.c: static int raw_atom_parser(struct ref_format *format, struct used_
return 0;
}

+@@ ref-filter.c: static int oid_atom_parser(struct ref_format *format, struct used_atom *atom,
+ if (atom->u.oid.length < MINIMUM_ABBREV)
+ atom->u.oid.length = MINIMUM_ABBREV;
+ } else
+- return strbuf_addf_ret(err, -1, _("unrecognized argument '%s' in %%(%s)"), arg, atom->name);
++ return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), atom->name, arg);
+ return 0;
+ }
+
@@ ref-filter.c: static int align_atom_parser(struct ref_format *format, struct used_atom *atom,
else if ((position = parse_align_position(s)) >= 0)
align->position = position;
9: 6196bccf086 ! 9: 9dd53960c42 i18n: factorize "--foo outside a repository"
@@ Commit message

## apply.c ##
@@ apply.c: int check_apply_state(struct apply_state *state, int force_apply)
- return error(_("%s and %s are mutually exclusive"),"--reject", "--3way");
+ return error(_("options '%s' and '%s' cannot be used together"),"--reject", "--3way");
if (state->threeway) {
if (is_not_gitdir)
- return error(_("--3way outside a repository"));

 10:  7d97cbe7e9a = 10:  a575f566f2a i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"
  -:  ----------- > 11:  89066f01f32 i18n: turn even more messages into "cannot be used together" ones
Signature · 1 line
gitgitgadget
#24 lore raw

PATCH v2 1/11 i18n: refactor "foo and bar are mutually exclusive"

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use static strings for constant parts of the sentences. They are all turned into "cannot be used together".

---
 builtin/checkout.c             | 2 +-
 builtin/diff-tree.c            | 2 +-
 builtin/fetch.c                | 4 ++--
 builtin/init-db.c              | 2 +-
 builtin/log.c                  | 4 ++--
 builtin/submodule--helper.c    | 4 ++--
 builtin/worktree.c             | 2 +-
 range-diff.c                   | 2 +-
 t/t0001-init.sh                | 2 +-
 t/t2025-checkout-no-overlay.sh | 2 +-
 t/t4209-log-pickaxe.sh         | 6 +++---
 11 files changed, 16 insertions(+), 16 deletions(-)
builtin/checkout.c +1 -1
index 72beeb49aa9..79014e1cb6c 100644
@@ -1639,7 +1639,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				cb_option, toupper(cb_option));
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
-		die(_("-p and --overlay are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "-p", "--overlay");
 
 	if (opts->checkout_index >= 0 || opts->checkout_worktree >= 0) {
 		if (opts->checkout_index < 0)
builtin/diff-tree.c +1 -1
index f33d30d57bf..0e0ac1f1670 100644
@@ -152,7 +152,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
 	}
 
 	if (read_stdin && merge_base)
-		die(_("--stdin and --merge-base are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--stdin", "--merge-base");
 	if (merge_base && opt->pending.nr != 2)
 		die(_("--merge-base only works with two commits"));
 
builtin/fetch.c +2 -2
index f1fe73a3e0f..2c584c85812 100644
@@ -2028,12 +2028,12 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		if (deepen_relative < 0)
 			die(_("negative depth in --deepen is not supported"));
 		if (depth)
-			die(_("--deepen and --depth are mutually exclusive"));
+			die(_("options '%s' and '%s' cannot be used together"), "--deepen", "--depth");
 		depth = xstrfmt("%d", deepen_relative);
 	}
 	if (unshallow) {
 		if (depth)
-			die(_("--depth and --unshallow cannot be used together"));
+			die(_("options '%s' and '%s' cannot be used together"), "--depth", "--unshallow");
 		else if (!is_repository_shallow(the_repository))
 			die(_("--unshallow on a complete repository does not make sense"));
 		else
builtin/init-db.c +1 -1
index 2167796ff2a..546f9c595e7 100644
@@ -557,7 +557,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
 
 	if (real_git_dir && is_bare_repository_cfg == 1)
-		die(_("--separate-git-dir and --bare are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
 
 	if (real_git_dir && !is_absolute_path(real_git_dir))
 		real_git_dir = real_pathdup(real_git_dir, 1);
builtin/log.c +2 -2
index 93ace0dde7d..fad93ad2fc1 100644
@@ -1943,9 +1943,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		numbered = 0;
 
 	if (numbered && keep_subject)
-		die(_("-n and -k are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "-n", "-k");
 	if (keep_subject && subject_prefix)
-		die(_("--subject-prefix/--rfc and -k are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--subject-prefix/--rfc", "-k");
 	rev.preserve_subject = keep_subject;
 
 	argc = setup_revisions(argc, argv, &rev, &s_r_opt);
builtin/submodule--helper.c +2 -2
index 9b25a508e6a..c5d3fc3817f 100644
@@ -1313,7 +1313,7 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 
 	if (files) {
 		if (cached)
-			die(_("--cached and --files are mutually exclusive"));
+			die(_("options '%s' and '%s' cannot be used together"), "--cached", "--files");
 		diff_cmd = DIFF_FILES;
 	}
 
@@ -2972,7 +2972,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
 		die(_("--branch or --default required"));
 
 	if (opt_branch && opt_default)
-		die(_("--branch and --default are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--branch", "--default");
 
 	if (argc != 1 || !(path = argv[0]))
 		usage_with_options(usage, options);
builtin/worktree.c +1 -1
index a396cfdc64e..9a520485769 100644
@@ -699,7 +699,7 @@ static int list(int ac, const char **av, const char *prefix)
 	if (ac)
 		usage_with_options(worktree_usage, options);
 	else if (verbose && porcelain)
-		die(_("--verbose and --porcelain are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--verbose", "--porcelain");
 	else {
 		struct worktree **worktrees = get_worktrees();
 		int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
range-diff.c +1 -1
index cac89a2f4f2..30a4de5c2d8 100644
@@ -556,7 +556,7 @@ int show_range_diff(const char *range1, const char *range2,
 	struct string_list branch2 = STRING_LIST_INIT_DUP;
 
 	if (range_diff_opts->left_only && range_diff_opts->right_only)
-		res = error(_("--left-only and --right-only are mutually exclusive"));
+		res = error(_("options '%s' and '%s' cannot be used together"), "--left-only", "--right-only");
 
 	if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg))
 		res = error(_("could not parse log for '%s'"), range1);
t/t0001-init.sh +1 -1
index 7603ad2f82b..3235ab4d53c 100755
@@ -331,7 +331,7 @@ test_expect_success 'init with separate gitdir' '
 
 test_expect_success 'explicit bare & --separate-git-dir incompatible' '
 	test_must_fail git init --bare --separate-git-dir goop.git bare.git 2>err &&
-	test_i18ngrep "mutually exclusive" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'implicit bare & --separate-git-dir incompatible' '
t/t2025-checkout-no-overlay.sh +1 -1
index fa9e0987063..8f13341cf8e 100755
@@ -25,7 +25,7 @@ test_expect_success 'checkout --no-overlay removing last file from directory' '
 
 test_expect_success 'checkout -p --overlay is disallowed' '
 	test_must_fail git checkout -p --overlay HEAD 2>actual &&
-	test_i18ngrep "fatal: -p and --overlay are mutually exclusive" actual
+	test_i18ngrep "fatal: options .-p. and .--overlay. cannot be used together" actual
 '
 
 test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
t/t4209-log-pickaxe.sh +3 -3
index 75795d0b492..4f820f8597d 100755
@@ -63,13 +63,13 @@ test_expect_success 'usage' '
 	test_i18ngrep "switch.*requires a value" err &&
 
 	test_expect_code 128 git log -Gregex -Sstring 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log -Gregex --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log -Sstring --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
 	grep "mutually exclusive" err
Signature · 1 line
gitgitgadget
#25 lore raw

PATCH v2 2/11 i18n: refactor "%s, %s and %s are mutually exclusive"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use placeholders for constant tokens. The strings are turned into "cannot be used together"

---
 builtin/difftool.c | 2 +-
 builtin/log.c      | 2 +-
 builtin/worktree.c | 2 +-
 diff.c             | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)
builtin/difftool.c +1 -1
index 4ee40fe3a06..c2b049aafc9 100644
@@ -733,7 +733,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 		die(_("--dir-diff is incompatible with --no-index"));
 
 	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("--gui, --tool and --extcmd are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
 
 	if (use_gui_tool)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
builtin/log.c +1 -1
index fad93ad2fc1..705d58110b0 100644
@@ -1979,7 +1979,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		load_display_notes(&rev.notes_opt);
 
 	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("--stdout, --output, and --output-directory are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
 
 	if (use_stdout) {
 		setup_pager();
builtin/worktree.c +1 -1
index 9a520485769..b5ef19b2dda 100644
@@ -503,7 +503,7 @@ static int add(int ac, const char **av, const char *prefix)
 	opts.checkout = 1;
 	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
-		die(_("-b, -B, and --detach are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "-b", "-B", "--detach");
 	if (lock_reason && !keep_locked)
 		die(_("--reason requires --lock"));
 	if (lock_reason)
diff.c +1 -1
index 41076857428..8de1c49763c 100644
@@ -4642,7 +4642,7 @@ void diff_setup_done(struct diff_options *options)
 		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
-		die(_("-G, -S and --find-object are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "-G", "-S", "--find-object");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
 		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
Signature · 1 line
gitgitgadget
#26 lore raw

PATCH v2 3/11 i18n: turn "options are incompatible" into "cannot be used together"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 apply.c                           |  2 +-
 archive.c                         |  2 +-
 builtin/add.c                     |  8 ++++----
 builtin/branch.c                  |  2 +-
 builtin/checkout.c                |  4 ++--
 builtin/clone.c                   |  2 +-
 builtin/commit.c                  |  6 +++---
 builtin/describe.c                |  2 +-
 builtin/difftool.c                |  2 +-
 builtin/fast-export.c             |  2 +-
 builtin/index-pack.c              |  2 +-
 builtin/ls-files.c                |  2 +-
 builtin/merge.c                   |  4 ++--
 builtin/pack-objects.c            |  2 +-
 builtin/push.c                    |  8 ++++----
 builtin/rebase.c                  |  6 +++---
 builtin/repack.c                  |  4 ++--
 builtin/reset.c                   |  4 ++--
 builtin/rev-list.c                |  2 +-
 builtin/show-branch.c             |  4 ++--
 builtin/stash.c                   |  4 ++--
 builtin/tag.c                     |  2 +-
 revision.c                        | 22 +++++++++++-----------
 t/t2026-checkout-pathspec-file.sh |  4 ++--
 t/t2072-restore-pathspec-file.sh  |  2 +-
 t/t3704-add-pathspec-file.sh      |  6 +++---
 t/t3909-stash-pathspec-file.sh    |  2 +-
 t/t5606-clone-options.sh          |  2 +-
 t/t7107-reset-pathspec-file.sh    |  2 +-
 t/t7526-commit-pathspec-file.sh   |  4 ++--
 30 files changed, 60 insertions(+), 60 deletions(-)
apply.c +1 -1
index fed195250b6..000f2a9b1b3 100644
@@ -133,7 +133,7 @@ int check_apply_state(struct apply_state *state, int force_apply)
 	int is_not_gitdir = !startup_info->have_repository;
 
 	if (state->apply_with_reject && state->threeway)
-		return error(_("--reject and --3way cannot be used together."));
+		return error(_("options '%s' and '%s' cannot be used together"),"--reject",  "--3way");
 	if (state->threeway) {
 		if (is_not_gitdir)
 			return error(_("--3way outside a repository"));
archive.c +1 -1
index a3bbb091256..e85ba169088 100644
@@ -581,7 +581,7 @@ static int parse_archive_args(int argc, const char **argv,
 	if (output)
 		die(_("Unexpected option --output"));
 	if (is_remote && args->extra_files.nr)
-		die(_("Options --add-file and --remote cannot be used together"));
+		die(_("options '%s' and '%s' cannot be used together"), "--add-file", "--remote");
 
 	if (!base)
 		base = "";
builtin/add.c +4 -4
index a010b2c325f..4b2754345ad 100644
@@ -507,9 +507,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		add_interactive = 1;
 	if (add_interactive) {
 		if (show_only)
-			die(_("--dry-run is incompatible with --interactive/--patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
 		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
 		exit(interactive_add(argv + 1, prefix, patch_interactive));
 	}
 	if (legacy_stash_p) {
@@ -526,7 +526,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (edit_interactive) {
 		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --edit"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--edit");
 		return(edit_patch(argc, argv, prefix));
 	}
 	argc--;
@@ -538,7 +538,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		addremove = 0; /* "-u" was given but not "-A" */
 
 	if (addremove && take_worktree_changes)
-		die(_("-A and -u are mutually incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "-A", "-u");
 
 	if (!show_only && ignore_missing)
 		die(_("Option --ignore-missing can only be used together with --dry-run"));
builtin/branch.c +1 -1
index 6c8b0fcc11f..0e93865371c 100644
@@ -722,7 +722,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	finalize_colopts(&colopts, -1);
 	if (filter.verbose) {
 		if (explicitly_enable_column(colopts))
-			die(_("--column and --verbose are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--column", "--verbose");
 		colopts = 0;
 	}
 
builtin/checkout.c +2 -2
index 79014e1cb6c..2d7bfbd0f1a 100644
@@ -1749,10 +1749,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
 
 		if (opts->force_detach)
-			die(_("--pathspec-from-file is incompatible with --detach"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file",  "--detach");
 
 		if (opts->patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		parse_pathspec_file(&opts->pathspec, 0,
 				    0,
builtin/clone.c +1 -1
index fb377b27657..13bdbe14b2f 100644
@@ -903,7 +903,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 			die(_("--bare and --origin %s options are incompatible."),
 			    option_origin);
 		if (real_git_dir)
-			die(_("--bare and --separate-git-dir are incompatible."));
+			die(_("options '%s' and '%s' cannot be used together"), "--bare", "--separate-git-dir");
 		option_no_checkout = 1;
 	}
 
builtin/commit.c +3 -3
index 883c16256c8..5c1aaa42131 100644
@@ -355,10 +355,10 @@ static const char *prepare_index(const char **argv, const char *prefix,
 
 	if (pathspec_from_file) {
 		if (interactive)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
 
 		if (all)
-			die(_("--pathspec-from-file with -a does not make sense"));
+			die(_("options '%s' and '%s' cannot be used together"),"--pathspec-from-file", "-a");
 
 		if (pathspec.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
@@ -1193,7 +1193,7 @@ static void finalize_deferred_config(struct wt_status *s)
 		    status_format == STATUS_FORMAT_UNSPECIFIED)
 			status_format = STATUS_FORMAT_PORCELAIN;
 		else if (status_format == STATUS_FORMAT_LONG)
-			die(_("--long and -z are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--long", "-z");
 	}
 
 	if (use_deferred_config && status_format == STATUS_FORMAT_UNSPECIFIED)
builtin/describe.c +1 -1
index e912ba50d7b..fd5ba1fc604 100644
@@ -590,7 +590,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 	save_commit_buffer = 0;
 
 	if (longformat && abbrev == 0)
-		die(_("--long is incompatible with --abbrev=0"));
+		die(_("options '%s' and '%s' cannot be used together"), "--long", "--abbrev=0");
 
 	if (contains) {
 		struct string_list_item *item;
builtin/difftool.c +1 -1
index c2b049aafc9..f5db9bcd7b0 100644
@@ -730,7 +730,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 		setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
 		setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
 	} else if (dir_diff)
-		die(_("--dir-diff is incompatible with --no-index"));
+		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");
builtin/fast-export.c +1 -1
index 8e2caf72819..1f8fe7b3ac1 100644
@@ -1269,7 +1269,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		printf("feature done\n");
 
 	if (import_filename && import_filename_if_exists)
-		die(_("Cannot pass both --import-marks and --import-marks-if-exists"));
+		die(_("options '%s' and '%s' cannot be used together"), "--import-marks", "--import-marks-if-exists");
 	if (import_filename)
 		import_marks(import_filename, 0);
 	else if (import_filename_if_exists)
builtin/index-pack.c +1 -1
index c23d01de7dc..30ce2ac746d 100644
@@ -1849,7 +1849,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (from_stdin && !startup_info->have_repository)
 		die(_("--stdin requires a git repository"));
 	if (from_stdin && hash_algo)
-		die(_("--object-format cannot be used with --stdin"));
+		die(_("options '%s' and '%s' cannot be used together"), "--object-format", "--stdin");
 	if (!index_name && pack_name)
 		index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
 
builtin/ls-files.c +1 -1
index 031fef1bcaa..9c80cdae951 100644
@@ -767,7 +767,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		 * would not make any sense with this option.
 		 */
 		if (show_stage || show_unmerged)
-			die("ls-files --with-tree is incompatible with -s or -u");
+			die(_("options '%s' and '%s' cannot be used together"), "ls-files --with-tree", "-s/-u");
 		overlay_tree_on_index(the_repository->index, with_tree, max_prefix);
 	}
 
builtin/merge.c +2 -2
index 5f0476b0b76..6db961e9d34 100644
@@ -1396,9 +1396,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 
 	if (squash) {
 		if (fast_forward == FF_NO)
-			die(_("You cannot combine --squash with --no-ff."));
+			die(_("options '%s' and '%s' cannot be used together"), "--squash", "--no-ff.");
 		if (option_commit > 0)
-			die(_("You cannot combine --squash with --commit."));
+			die(_("options '%s' and '%s' cannot be used together"), "--squash", "--commit.");
 		/*
 		 * squash can now silently disable option_commit - this is not
 		 * a problem as it is only overriding the default, not a user
builtin/pack-objects.c +1 -1
index b36ed828d8d..ba2006f2212 100644
@@ -4070,7 +4070,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 		die(_("--thin cannot be used to build an indexable pack"));
 
 	if (keep_unreachable && unpack_unreachable)
-		die(_("--keep-unreachable and --unpack-unreachable are incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "--unpack-unreachable");
 	if (!rev_list_all || !rev_list_reflog || !rev_list_index)
 		unpack_unreachable_expiration = 0;
 
builtin/push.c +4 -4
index 4b026ce6c6a..359db90321c 100644
@@ -589,7 +589,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 	set_push_cert_flags(&flags, push_cert);
 
 	if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
-		die(_("--delete is incompatible with --all, --mirror and --tags"));
+		die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--mirror/--tags");
 	if (deleterefs && argc < 2)
 		die(_("--delete doesn't make sense without any refs"));
 
@@ -627,18 +627,18 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 
 	if (flags & TRANSPORT_PUSH_ALL) {
 		if (tags)
-			die(_("--all and --tags are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--all", "--tags");
 		if (argc >= 2)
 			die(_("--all can't be combined with refspecs"));
 	}
 	if (flags & TRANSPORT_PUSH_MIRROR) {
 		if (tags)
-			die(_("--mirror and --tags are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--mirror", "--tags");
 		if (argc >= 2)
 			die(_("--mirror can't be combined with refspecs"));
 	}
 	if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
-		die(_("--all and --mirror are incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "--all", "--mirror");
 
 	if (!is_empty_cas(&cas) && (flags & TRANSPORT_PUSH_FORCE_IF_INCLUDES))
 		cas.use_force_if_includes = 1;
builtin/rebase.c +3 -3
index 34b4744e5f3..ed326b8aecc 100644
@@ -1190,13 +1190,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
 	if (keep_base) {
 		if (options.onto_name)
-			die(_("cannot combine '--keep-base' with '--onto'"));
+			die(_("options '%s' and '%s' cannot be used together"),"--keep-base", "--onto");
 		if (options.root)
-			die(_("cannot combine '--keep-base' with '--root'"));
+			die(_("options '%s' and '%s' cannot be used together"),"--keep-base", "--root");
 	}
 
 	if (options.root && options.fork_point > 0)
-		die(_("cannot combine '--root' with '--fork-point'"));
+		die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
 
 	if (action != ACTION_NONE && !in_progress)
 		die(_("No rebase in progress?"));
builtin/repack.c +2 -2
index 9b0be6a6ab3..f13bca4719e 100644
@@ -681,7 +681,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	if (keep_unreachable &&
 	    (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
-		die(_("--keep-unreachable and -A are incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "-A");
 
 	if (write_bitmaps < 0) {
 		if (!write_midx &&
@@ -712,7 +712,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	if (geometric_factor) {
 		if (pack_everything)
-			die(_("--geometric is incompatible with -A, -a"));
+			die(_("options '%s' and '%s' cannot be used together"),"--geometric", "-A/-a");
 		init_pack_geometry(&geometry);
 		split_pack_geometry(geometry, geometric_factor);
 	}
builtin/reset.c +2 -2
index b1ff699b43a..248998fd6fa 100644
@@ -423,7 +423,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (pathspec.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
@@ -459,7 +459,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	if (patch_mode) {
 		if (reset_type != NONE)
-			die(_("--patch is incompatible with --{hard,mixed,soft}"));
+			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
 		return run_add_interactive(rev, "--patch=reset", &pathspec);
 	}
builtin/rev-list.c +1 -1
index 36cb909ebaa..de60cbdbc9d 100644
@@ -538,7 +538,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 		const char *arg = argv[i];
 		if (skip_prefix(arg, "--missing=", &arg)) {
 			if (revs.exclude_promisor_objects)
-				die(_("cannot combine --exclude-promisor-objects and --missing"));
+				die(_("options '%s' and '%s' cannot be used together"),"--exclude-promisor-objects", "--missing");
 			if (parse_missing_action_value(arg))
 				break;
 		}
builtin/show-branch.c +2 -2
index f1e8318592c..e12c5e80e3e 100644
@@ -707,8 +707,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 			 *
 			 * Also --all and --remotes do not make sense either.
 			 */
-			die(_("--reflog is incompatible with --all, --remotes, "
-			      "--independent or --merge-base"));
+			die(_("options '%s' and '%s' cannot be used together"), "--reflog",
+				"--all/--remotes/--independent/--merge-base");
 	}
 
 	/* If nothing is specified, show all branches by default */
builtin/stash.c +2 -2
index 18c812bbe03..4d793bd0b52 100644
@@ -1700,10 +1700,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 
 	if (pathspec_from_file) {
 		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (only_staged)
-			die(_("--pathspec-from-file is incompatible with --staged"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--staged");
 
 		if (ps.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
builtin/tag.c +1 -1
index 41863c5ab77..6f7cd0e3ef5 100644
@@ -522,7 +522,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	finalize_colopts(&colopts, -1);
 	if (cmdmode == 'l' && filter.lines != -1) {
 		if (explicitly_enable_column(colopts))
-			die(_("--column and -n are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--column", "-n");
 		colopts = 0;
 	}
 	sorting = ref_sorting_options(&sorting_options);
revision.c +11 -11
index 5390a479b30..fe445dd5d45 100644
@@ -2300,11 +2300,11 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->left_only = 1;
 	} else if (!strcmp(arg, "--right-only")) {
 		if (revs->left_only)
-			die("--right-only is incompatible with --left-only");
+			die(_("options '%s' and '%s' cannot be used together"), "--right-only", "--left-only");
 		revs->right_only = 1;
 	} else if (!strcmp(arg, "--cherry")) {
 		if (revs->left_only)
-			die("--cherry is incompatible with --left-only");
+			die(_("options '%s' and '%s' cannot be used together"), "--cherry", "--left-only");
 		revs->cherry_mark = 1;
 		revs->right_only = 1;
 		revs->max_parents = 1;
@@ -2313,12 +2313,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->count = 1;
 	} else if (!strcmp(arg, "--cherry-mark")) {
 		if (revs->cherry_pick)
-			die("--cherry-mark is incompatible with --cherry-pick");
+			die(_("options '%s' and '%s' cannot be used together"), "--cherry-mark", "--cherry-pick");
 		revs->cherry_mark = 1;
 		revs->limited = 1; /* needs limit_list() */
 	} else if (!strcmp(arg, "--cherry-pick")) {
 		if (revs->cherry_mark)
-			die("--cherry-pick is incompatible with --cherry-mark");
+			die(_("options '%s' and '%s' cannot be used together"), "--cherry-pick", "--cherry-mark");
 		revs->cherry_pick = 1;
 		revs->limited = 1;
 	} else if (!strcmp(arg, "--objects")) {
@@ -2524,7 +2524,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		return opts;
 	}
 	if (revs->graph && revs->track_linear)
-		die("--show-linear-break and --graph are incompatible");
+		die(_("options '%s' and '%s' cannot be used together"), "--show-linear-break", "--graph");
 
 	return 1;
 }
@@ -2867,24 +2867,24 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	compile_grep_patterns(&revs->grep_filter);
 
 	if (revs->reverse && revs->reflog_info)
-		die("cannot combine --reverse with --walk-reflogs");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--walk-reflogs");
 	if (revs->reflog_info && revs->limited)
 		die("cannot combine --walk-reflogs with history-limiting options");
 	if (revs->rewrite_parents && revs->children.name)
-		die("cannot combine --parents and --children");
+		die(_("options '%s' and '%s' cannot be used together"), "--parents", "--children");
 
 	/*
 	 * Limitations on the graph functionality
 	 */
 	if (revs->reverse && revs->graph)
-		die("cannot combine --reverse with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--graph");
 
 	if (revs->reflog_info && revs->graph)
-		die("cannot combine --walk-reflogs with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--walk-reflogs", "--graph");
 	if (revs->no_walk && revs->graph)
-		die("cannot combine --no-walk with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
-		die("cannot use --grep-reflog without --walk-reflogs");
+		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");
 
 	if (revs->line_level_traverse &&
 	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
t/t2026-checkout-pathspec-file.sh +2 -2
index 9db11f86dd6..fbe26de2f90 100755
@@ -149,10 +149,10 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git checkout --pathspec-from-file=list --detach 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --detach" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--detach. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t2072-restore-pathspec-file.sh +1 -1
index b48345bf95f..ad1fc0ed071 100755
@@ -152,7 +152,7 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git restore --pathspec-from-file=list --patch --source=HEAD^1 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t3704-add-pathspec-file.sh +3 -3
index 5d5164d1fc6..7e17ae80229 100755
@@ -138,13 +138,13 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git add --pathspec-from-file=list --interactive 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list --edit 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --edit" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t3909-stash-pathspec-file.sh +1 -1
index 55e050cfd4d..aae2b25f766 100755
@@ -88,7 +88,7 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git stash push --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t5606-clone-options.sh +1 -1
index d822153e4d2..3af3577af0b 100755
@@ -54,7 +54,7 @@ test_expect_success 'disallows --bare with --separate-git-dir' '
 
 	test_must_fail git clone --bare --separate-git-dir dot-git-destiation parent clone-bare-sgd 2>err &&
 	test_debug "cat err" &&
-	test_i18ngrep -e "--bare and --separate-git-dir are incompatible" err
+	test_i18ngrep -e "options .--bare. and .--separate-git-dir. cannot be used together" err
 
 '
 
t/t7107-reset-pathspec-file.sh +1 -1
index 15ccb14f7e2..b211fbc0a52 100755
@@ -160,7 +160,7 @@ test_expect_success 'error conditions' '
 	git rm fileA.t &&
 
 	test_must_fail git reset --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t7526-commit-pathspec-file.sh +2 -2
index dca62fc48e5..fb5857b2a13 100755
@@ -141,10 +141,10 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git commit --pathspec-from-file=list --interactive -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --patch -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err &&
 	test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
Signature · 1 line
gitgitgadget
#27 lore raw

PATCH v2 4/11 i18n: standardize "cannot open" and "cannot read"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 archive.c       | 4 ++--
 builtin/fetch.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
archive.c +2 -2
index e85ba169088..78d35467008 100644
@@ -185,7 +185,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
 
 	buffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);
 	if (!buffer)
-		return error(_("cannot read %s"), oid_to_hex(oid));
+		return error(_("cannot read '%s'"), oid_to_hex(oid));
 	err = write_entry(args, oid, path.buf, path.len, mode, buffer, size);
 	free(buffer);
 	return err;
@@ -338,7 +338,7 @@ int write_archive_entries(struct archiver_args *args,
 
 		strbuf_reset(&content);
 		if (strbuf_read_file(&content, path, info->stat.st_size) < 0)
-			err = error_errno(_("could not read '%s'"), path);
+			err = error_errno(_("cannot read '%s'"), path);
 		else
 			err = write_entry(args, &fake_oid, path_in_archive.buf,
 					  path_in_archive.len,
builtin/fetch.c +2 -2
index 2c584c85812..c0855c363fd 100644
@@ -996,7 +996,7 @@ static int open_fetch_head(struct fetch_head *fetch_head)
 	if (write_fetch_head) {
 		fetch_head->fp = fopen(filename, "a");
 		if (!fetch_head->fp)
-			return error_errno(_("cannot open %s"), filename);
+			return error_errno(_("cannot open '%s'"), filename);
 		strbuf_init(&fetch_head->buf, 0);
 	} else {
 		fetch_head->fp = NULL;
@@ -1408,7 +1408,7 @@ static int truncate_fetch_head(void)
 	FILE *fp = fopen_for_writing(filename);
 
 	if (!fp)
-		return error_errno(_("cannot open %s"), filename);
+		return error_errno(_("cannot open '%s'"), filename);
 	fclose(fp);
 	return 0;
 }
Signature · 1 line
gitgitgadget
#28 lore raw

PATCH v2 5/11 i18n: tag.c factorize i18n strings

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
builtin/tag.c +7 -4
index 6f7cd0e3ef5..a2ab2b15304 100644
@@ -483,6 +483,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 	int ret = 0;
+	const char *only_in_list = NULL;
 
 	setup_ref_filter_porcelain_msg();
 
@@ -542,13 +543,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
+		only_in_list = "-n";
 	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
+		only_in_list = "--contains";
 	if (filter.no_commit)
-		die(_("--no-contains option is only allowed in list mode"));
+		only_in_list = "--no-contains";
 	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		only_in_list = "--points-at";
+	if (only_in_list)
+		die("the '%s' option is only allowed in list mode", only_in_list);
 	if (filter.reachable_from || filter.unreachable_from)
 		die(_("--merged and --no-merged options are only allowed in list mode"));
 	if (cmdmode == 'd') {
Signature · 1 line
gitgitgadget
#29 lore raw

Re: [PATCH v2 05/11] i18n: tag.c factorize i18n strings

Quoted 29 lines · Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
builtin/tag.c +3 -2
index 6f7cd0e3ef5..a2ab2b15304 100644
@@ -483,6 +483,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 	int ret = 0;
+	const char *only_in_list = NULL;
 
 	setup_ref_filter_porcelain_msg();
 
@@ -542,13 +543,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
+		only_in_list = "-n";
 	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
+		only_in_list = "--contains";
 	if (filter.no_commit)

builtin/tag.c int cmd_tag(int argc, const char **argv, const char *prefix) · line 557

Quoted 10 lines
builtin/tag.c +4 -2
-		die(_("--no-contains option is only allowed in list mode"));
+		only_in_list = "--no-contains";
 	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		only_in_list = "--points-at";
+	if (only_in_list)
+		die("the '%s' option is only allowed in list mode", only_in_list);
 	if (filter.reachable_from || filter.unreachable_from)
 		die(_("--merged and --no-merged options are only allowed in list mode"));
 	if (cmdmode == 'd') {

The original died with the first problematic condition that was detected, so it was possible to detect a condition and die, and check a different condition in a way that may segfault when the first condition was true, because we would have called die() before making such a risky check for the second condition. In the above cascade, however, there is luckily no such dependency, so the above change is safe.

But it still changes the semantics. Given "tag -d -n 4 --with master", we would have complained about "-n", but now we will complain about the "--contains", no?

We can fix both of the above issues by making these into an if/else if/ cascade, i.e.

	if (filter.lines != -1)
		only_in_list = "-n";
	else if (filter.with_commit)
		only_in_list = "--contains";
	...
	if (only_in_list)
		die(_("the '%s' option is only allowed..."), only_in_list);

And I think you forgot to mark the message that was factored out for translation.

#30 lore raw

Re: [PATCH v2 05/11] i18n: tag.c factorize i18n strings

Quoted 65 lines · Junio C Hamano
Quoted 29 lines · Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
builtin/tag.c +3 -2
index 6f7cd0e3ef5..a2ab2b15304 100644
@@ -483,6 +483,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 	int ret = 0;
+	const char *only_in_list = NULL;
 
 	setup_ref_filter_porcelain_msg();
 
@@ -542,13 +543,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
+		only_in_list = "-n";
 	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
+		only_in_list = "--contains";
 	if (filter.no_commit)

builtin/tag.c int cmd_tag(int argc, const char **argv, const char *prefix) · line 557

Quoted 10 lines
builtin/tag.c +4 -2
-		die(_("--no-contains option is only allowed in list mode"));
+		only_in_list = "--no-contains";
 	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		only_in_list = "--points-at";
+	if (only_in_list)
+		die("the '%s' option is only allowed in list mode", only_in_list);
 	if (filter.reachable_from || filter.unreachable_from)
 		die(_("--merged and --no-merged options are only allowed in list mode"));
 	if (cmdmode == 'd') {

The original died with the first problematic condition that was detected, so it was possible to detect a condition and die, and check a different condition in a way that may segfault when the first condition was true, because we would have called die() before making such a risky check for the second condition. In the above cascade, however, there is luckily no such dependency, so the above change is safe.

But it still changes the semantics. Given "tag -d -n 4 --with master", we would have complained about "-n", but now we will complain about the "--contains", no?

We can fix both of the above issues by making these into an if/else if/ cascade, i.e.

	if (filter.lines != -1)
		only_in_list = "-n";
	else if (filter.with_commit)
		only_in_list = "--contains";
	...
	if (only_in_list)
		die(_("the '%s' option is only allowed..."), only_in_list);
Quoted 2 lines

And I think you forgot to mark the message that was factored out for translation.

Does it really matter? I.e. we've got plenty of options parsing code in various places that might complain about issues A and B with your command-line, but will only emit one of those at a time.

So if you've got A and B you'll need to play the whack-a-mole game of fixing A, only to then run into B.

It really doesn't change things from a practical POV that we'll now complain about B first, only to complain about A later.

Ideally we'd spot and emit all of the issues, as e.g. my [1] does for some unrelated code.

But until such an improvement something as trivial as minimizing the diff size (i.e. not needing "if" -> "else if") seems preferrable to slavishly maintaining compatibility with the exact sequence of errors we'd emit before.

1. https://lore.kernel.org/git/[email protected]/

#31 lore raw

Re: [PATCH v2 05/11] i18n: tag.c factorize i18n strings

Quoted 8 lines · Ævar Arnfjörð Bjarmason

Does it really matter? I.e. we've got plenty of options parsing code in various places that might complain about issues A and B with your command-line, but will only emit one of those at a time.
...
But until such an improvement something as trivial as minimizing the diff size (i.e. not needing "if" -> "else if") seems preferrable to slavishly maintaining compatibility with the exact sequence of errors we'd emit before.

The patch is already touching every other line. Making the change into a replacement of solid block into another solid block would probably make the resulting patch easier to read.

And by doing so, the submitter demonstrates to reviewers that they _care_, as such an attention to detail is a sign that the submitter thought the ramifications of changing an early die() into an assignment that keeps going.

So, yes, it does matter.

#32 lore raw

Re: [PATCH v2 05/11] i18n: tag.c factorize i18n strings

Quoted 15 lines · On Tuesday, 28 December 2021 01:16:40 CET Junio C Hamano wrote:
Quoted 8 lines · Ævar Arnfjörð Bjarmason

Does it really matter? I.e. we've got plenty of options parsing code in various places that might complain about issues A and B with your command-line, but will only emit one of those at a time.
...
But until such an improvement something as trivial as minimizing the diff size (i.e. not needing "if" -> "else if") seems preferrable to slavishly maintaining compatibility with the exact sequence of errors we'd emit before.

The patch is already touching every other line. Making the change into a replacement of solid block into another solid block would probably make the resulting patch easier to read.

Quoted 7 lines

And by doing so, the submitter demonstrates to reviewers that they _care_, as such an attention to detail is a sign that the submitter thought the ramifications of changing an early die() into an assignment that keeps going.

So, yes, it does matter.

Sorry. The developer hat was taken off ; will reroll shortly.

#33 lore raw

PATCH v2 6/11 i18n: factorize "--foo requires --bar" and the like

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 archive.c             | 2 +-
 builtin/add.c         | 4 ++--
 builtin/checkout.c    | 2 +-
 builtin/commit.c      | 2 +-
 builtin/fast-export.c | 2 +-
 builtin/index-pack.c  | 2 +-
 builtin/log.c         | 2 +-
 builtin/reset.c       | 4 ++--
 builtin/rm.c          | 2 +-
 builtin/stash.c       | 2 +-
 builtin/worktree.c    | 2 +-
 fetch-pack.c          | 2 +-
 http-fetch.c          | 4 ++--
 13 files changed, 16 insertions(+), 16 deletions(-)
archive.c +1 -1
index 78d35467008..6fd4d951bd9 100644
@@ -577,7 +577,7 @@ static int parse_archive_args(int argc, const char **argv,
 	if (remote)
 		die(_("Unexpected option --remote"));
 	if (exec)
-		die(_("Option --exec can only be used together with --remote"));
+		die(_("%s requires %s"), "--exec", "--remote");
 	if (output)
 		die(_("Unexpected option --output"));
 	if (is_remote && args->extra_files.nr)
builtin/add.c +2 -2
index 4b2754345ad..b505eca3d4d 100644
@@ -541,7 +541,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		die(_("options '%s' and '%s' cannot be used together"), "-A", "-u");
 
 	if (!show_only && ignore_missing)
-		die(_("Option --ignore-missing can only be used together with --dry-run"));
+		die(_("%s requires %s"), "--ignore-missing", "--dry-run");
 
 	if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
 			  chmod_arg[1] != 'x' || chmod_arg[2]))
@@ -573,7 +573,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_SYMLINK_LEADING_PATH,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (require_pathspec && pathspec.nr == 0) {
builtin/checkout.c +1 -1
index 2d7bfbd0f1a..d005aaad9f2 100644
@@ -1758,7 +1758,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				    0,
 				    prefix, opts->pathspec_from_file, opts->pathspec_file_nul);
 	} else if (opts->pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	opts->pathspec.recursive = 1;
builtin/commit.c +1 -1
index 5c1aaa42131..eb803a96ae3 100644
@@ -367,7 +367,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 				    PATHSPEC_PREFER_FULL,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (!pathspec.nr && (also || (only && !allow_empty &&
builtin/fast-export.c +1 -1
index 1f8fe7b3ac1..a1eba9298a4 100644
@@ -1254,7 +1254,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		usage_with_options (fast_export_usage, options);
 
 	if (anonymized_seeds.cmpfn && !anonymize)
-		die(_("--anonymize-map without --anonymize does not make sense"));
+		die(_("%s requires %s"), "--anonymize-map", "--anonymize");
 
 	if (refspecs_list.nr) {
 		int i;
builtin/index-pack.c +1 -1
index 30ce2ac746d..6845bcb41af 100644
@@ -1845,7 +1845,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (!pack_name && !from_stdin)
 		usage(index_pack_usage);
 	if (fix_thin_pack && !from_stdin)
-		die(_("--fix-thin cannot be used without --stdin"));
+		die(_("%s requires %s"), "--fix-thin", "--stdin");
 	if (from_stdin && !startup_info->have_repository)
 		die(_("--stdin requires a git repository"));
 	if (from_stdin && hash_algo)
builtin/log.c +1 -1
index 705d58110b0..8fe51bc8afb 100644
@@ -2112,7 +2112,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	if (creation_factor < 0)
 		creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
 	else if (!rdiff_prev)
-		die(_("--creation-factor requires --range-diff"));
+		die(_("%s requires %s"), "--creation-factor", "--range-diff");
 
 	if (rdiff_prev) {
 		if (!cover_letter && total != 1)
builtin/reset.c +2 -2
index 248998fd6fa..25f52ea99f6 100644
@@ -432,7 +432,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_PREFER_FULL,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
@@ -490,7 +490,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		    _(reset_type_names[reset_type]));
 
 	if (intent_to_add && reset_type != MIXED)
-		die(_("-N can only be used with --mixed"));
+		die(_("%s requires %s"), "-N", "--mixed");
 
 	prepare_repo_settings(the_repository);
 	the_repository->settings.command_requires_full_index = 0;
builtin/rm.c +1 -1
index 3d0967cdc11..38ac3c71252 100644
@@ -278,7 +278,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_PREFER_CWD,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (!pathspec.nr)
builtin/stash.c +1 -1
index 4d793bd0b52..7ad2f9aca87 100644
@@ -1712,7 +1712,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
builtin/worktree.c +1 -1
index b5ef19b2dda..bce01c8a671 100644
@@ -505,7 +505,7 @@ static int add(int ac, const char **av, const char *prefix)
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
 		die(_("options '%s', '%s' and '%s' cannot be used together"), "-b", "-B", "--detach");
 	if (lock_reason && !keep_locked)
-		die(_("--reason requires --lock"));
+		die(_("%s requires %s"), "--reason", "--lock");
 	if (lock_reason)
 		opts.keep_locked = lock_reason;
 	else if (keep_locked)
fetch-pack.c +1 -1
index 34987a2c30d..0a5dfea9377 100644
@@ -297,7 +297,7 @@ static int find_common(struct fetch_negotiator *negotiator,
 	struct packet_reader reader;
 
 	if (args->stateless_rpc && multi_ack == 1)
-		die(_("--stateless-rpc requires multi_ack_detailed"));
+		die(_("%s requires %s"), "--stateless-rpc", "multi_ack_detailed");
 
 	packet_reader_init(&reader, fd[0], NULL, 0,
 			   PACKET_READ_CHOMP_NEWLINE |
http-fetch.c +2 -2
index c7c7d391ac5..eab45d2cc07 100644
@@ -141,7 +141,7 @@ int cmd_main(int argc, const char **argv)
 
 	if (packfile) {
 		if (!index_pack_args.nr)
-			die(_("--packfile requires --index-pack-args"));
+			die(_("%s requires %s"), "--packfile", "--index-pack-args");
 
 		fetch_single_packfile(&packfile_hash, argv[arg],
 				      index_pack_args.v);
@@ -150,7 +150,7 @@ int cmd_main(int argc, const char **argv)
 	}
 
 	if (index_pack_args.nr)
-		die(_("--index-pack-args can only be used with --packfile"));
+		die(_("%s requires %s"), "--index-pack-args", "--packfile");
 
 	if (commits_on_stdin) {
 		commits = walker_targets_stdin(&commit_id, &write_ref);
Signature · 1 line
gitgitgadget
#34 lore raw

Re: [PATCH v2 06/11] i18n: factorize "--foo requires --bar" and the like

Am 28.12.21 um 00:23 schrieb Jean-Noël Avila via GitGitGadget:

Quoted 3 lines

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Two questions:

- Is "%s requires %s" already used elsewhere or is it a new translatable string? The commit message should clarify the choice.

- Do translators know that the two %s will be substituted with options (mostly)?

fetch-pack.c static int find_common(struct fetch_negotiator *negotiator, · line 300

Quoted 8 lines
fetch-pack.c +1 -1
@@ -297,7 +297,7 @@ static int find_common(struct fetch_negotiator *negotiator,
 	struct packet_reader reader;
 
 	if (args->stateless_rpc && multi_ack == 1)
-		die(_("--stateless-rpc requires multi_ack_detailed"));
+		die(_("%s requires %s"), "--stateless-rpc", "multi_ack_detailed");

Here, the second %s is not an option. I hope that does not invalidate any translation of the string.

-- Hannes

#35 lore raw

Re: [PATCH v2 06/11] i18n: factorize "--foo requires --bar" and the like

Quoted 9 lines · On Tuesday, 28 December 2021 08:01:30 CET Johannes Sixt wrote:

Am 28.12.21 um 00:23 schrieb Jean-Noël Avila via GitGitGadget:

Quoted 3 lines

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Two questions:

- Is "%s requires %s" already used elsewhere or is it a new translatable string? The commit message should clarify the choice.

%s requires %s is a new translatable string. Will update.

Quoted 3 lines

- Do translators know that the two %s will be substituted with options (mostly)?

Indeed this is not clear. So we should apply the same transformation as for "cannot be used together"

Quoted 6 lines
Quoted 6 lines
fetch-pack.c +0 -0
@@ -297,7 +297,7 @@ static int find_common(struct fetch_negotiator *negotiator,
 	struct packet_reader reader;
 
Quoted 6 lines

fetch-pack.c static int find_common(struct fetch_negotiator *negotiator, · line 300

Quoted 3 lines
fetch-pack.c +1 -1
 	if (args->stateless_rpc && multi_ack == 1)
-		die(_("--stateless-rpc requires multi_ack_detailed"));
+		die(_("%s requires %s"), "--stateless-rpc", "multi_ack_detailed");

Here, the second %s is not an option. I hope that does not invalidate any translation of the string.

True. So let's use "the option '%s' requires '%s'" instead.

Quoted 3 lines

-- Hannes

#36 lore raw

PATCH v2 7/11 i18n: factorize "no directory given for --foo"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 git.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
git.c +3 -3
index 7edafd8ecff..7e361769ff6 100644
@@ -185,7 +185,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--git-dir")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for --git-dir\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "--git-dir");
 				usage(git_usage_string);
 			}
 			setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
@@ -213,7 +213,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--work-tree")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for --work-tree\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "--work-tree");
 				usage(git_usage_string);
 			}
 			setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
@@ -297,7 +297,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "-C")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for -C\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "-C");
 				usage(git_usage_string);
 			}
 			if ((*argv)[1][0]) {
Signature · 1 line
gitgitgadget
#37 lore raw

PATCH v2 8/11 i18n: refactor "unrecognized %(foo) argument" strings

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 ref-filter.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
ref-filter.c +7 -7
index 7260fce31d0..adbcc680812 100644
@@ -341,7 +341,7 @@ static int objectsize_atom_parser(struct ref_format *format, struct used_atom *a
 		else
 			oi.info.disk_sizep = &oi.disk_size;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(objectsize) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "objectsize", arg);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ static int subject_atom_parser(struct ref_format *format, struct used_atom *atom
 	else if (!strcmp(arg, "sanitize"))
 		atom->u.contents.option = C_SUB_SANITIZE;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(subject) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "subject", arg);
 	return 0;
 }
 
@@ -428,7 +428,7 @@ static int contents_atom_parser(struct ref_format *format, struct used_atom *ato
 		if (strtoul_ui(arg, 10, &atom->u.contents.nlines))
 			return strbuf_addf_ret(err, -1, _("positive value expected contents:lines=%s"), arg);
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(contents) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "contents", arg);
 	return 0;
 }
 
@@ -440,7 +440,7 @@ static int raw_atom_parser(struct ref_format *format, struct used_atom *atom,
 	else if (!strcmp(arg, "size"))
 		atom->u.raw_data.option = RAW_LENGTH;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(raw) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "raw", arg);
 	return 0;
 }
 
@@ -459,7 +459,7 @@ static int oid_atom_parser(struct ref_format *format, struct used_atom *atom,
 		if (atom->u.oid.length < MINIMUM_ABBREV)
 			atom->u.oid.length = MINIMUM_ABBREV;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized argument '%s' in %%(%s)"), arg, atom->name);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), atom->name, arg);
 	return 0;
 }
 
@@ -531,7 +531,7 @@ static int align_atom_parser(struct ref_format *format, struct used_atom *atom,
 		else if ((position = parse_align_position(s)) >= 0)
 			align->position = position;
 		else {
-			strbuf_addf(err, _("unrecognized %%(align) argument: %s"), s);
+			strbuf_addf(err, _("unrecognized %%(%s) argument: %s"), "align", s);
 			string_list_clear(&params, 0);
 			return -1;
 		}
@@ -557,7 +557,7 @@ static int if_atom_parser(struct ref_format *format, struct used_atom *atom,
 	} else if (skip_prefix(arg, "notequals=", &atom->u.if_then_else.str)) {
 		atom->u.if_then_else.cmp_status = COMPARE_UNEQUAL;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(if) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "if", arg);
 	return 0;
 }
 
Signature · 1 line
gitgitgadget
#38 lore raw

PATCH v2 9/11 i18n: factorize "--foo outside a repository"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 apply.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
apply.c +3 -3
index 000f2a9b1b3..8fd2ac2cfca 100644
@@ -136,7 +136,7 @@ int check_apply_state(struct apply_state *state, int force_apply)
 		return error(_("options '%s' and '%s' cannot be used together"),"--reject",  "--3way");
 	if (state->threeway) {
 		if (is_not_gitdir)
-			return error(_("--3way outside a repository"));
+			return error(_("%s outside a repository"), "--3way");
 		state->check_index = 1;
 	}
 	if (state->apply_with_reject) {
@@ -147,10 +147,10 @@ int check_apply_state(struct apply_state *state, int force_apply)
 	if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor))
 		state->apply = 0;
 	if (state->check_index && is_not_gitdir)
-		return error(_("--index outside a repository"));
+		return error(_("%s outside a repository"), "--index");
 	if (state->cached) {
 		if (is_not_gitdir)
-			return error(_("--cached outside a repository"));
+			return error(_("%s outside a repository"), "--cached");
 		state->check_index = 1;
 	}
 	if (state->ita_only && (state->check_index || is_not_gitdir))
Signature · 1 line
gitgitgadget
#39 lore raw

PATCH v2 10/11 i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 ref-filter.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
ref-filter.c +4 -4
index adbcc680812..f7a2f17bfd9 100644
@@ -841,7 +841,7 @@ static void if_then_else_handler(struct ref_formatting_stack **stack)
 	struct if_then_else *if_then_else = (struct if_then_else *)cur->at_end_data;
 
 	if (!if_then_else->then_atom_seen)
-		die(_("format: %%(if) atom used without a %%(then) atom"));
+		die(_("format: %%(%s) atom used without a %%(%s) atom"), "if", "then");
 
 	if (if_then_else->else_atom_seen) {
 		/*
@@ -907,7 +907,7 @@ static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	if (cur->at_end == if_then_else_handler)
 		if_then_else = (struct if_then_else *)cur->at_end_data;
 	if (!if_then_else)
-		return strbuf_addf_ret(err, -1, _("format: %%(then) atom used without an %%(if) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "then", "if");
 	if (if_then_else->then_atom_seen)
 		return strbuf_addf_ret(err, -1, _("format: %%(then) atom used more than once"));
 	if (if_then_else->else_atom_seen)
@@ -943,9 +943,9 @@ static int else_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	if (prev->at_end == if_then_else_handler)
 		if_then_else = (struct if_then_else *)prev->at_end_data;
 	if (!if_then_else)
-		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without an %%(if) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "else", "if");
 	if (!if_then_else->then_atom_seen)
-		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without a %%(then) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "else", "then");
 	if (if_then_else->else_atom_seen)
 		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used more than once"));
 	if_then_else->else_atom_seen = 1;
Signature · 1 line
gitgitgadget
#40 lore raw

PATCH v2 11/11 i18n: turn even more messages into "cannot be used together" ones

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Even if some of these messages are not subject to gettext i18n, this helps bring a single style of message for a given error type.

---
 builtin/add.c                             |  2 +-
 builtin/am.c                              |  4 ++--
 builtin/cat-file.c                        |  2 +-
 builtin/checkout.c                        |  4 ++--
 builtin/clone.c                           |  2 +-
 builtin/commit.c                          | 10 ++++++----
 builtin/describe.c                        |  4 ++--
 builtin/init-db.c                         |  2 +-
 builtin/rebase.c                          |  4 ++--
 builtin/reset.c                           |  2 +-
 builtin/rev-list.c                        |  2 +-
 builtin/rm.c                              |  2 +-
 builtin/stash.c                           |  2 +-
 diff.c                                    |  6 +++---
 t/t0001-init.sh                           |  4 ++--
 t/t2026-checkout-pathspec-file.sh         |  2 +-
 t/t2072-restore-pathspec-file.sh          |  2 +-
 t/t3431-rebase-fork-point.sh              |  2 +-
 t/t3601-rm-pathspec-file.sh               |  2 +-
 t/t3704-add-pathspec-file.sh              |  2 +-
 t/t3909-stash-pathspec-file.sh            |  2 +-
 t/t4209-log-pickaxe.sh                    |  4 ++--
 t/t5606-clone-options.sh                  |  2 +-
 t/t7107-reset-pathspec-file.sh            |  2 +-
 t/t7500-commit-template-squash-signoff.sh | 11 ++++++-----
 t/t7526-commit-pathspec-file.sh           |  4 ++--
 26 files changed, 45 insertions(+), 42 deletions(-)
builtin/add.c +1 -1
index b505eca3d4d..ded15ca6eac 100644
@@ -566,7 +566,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, PATHSPEC_ATTR,
 				    PATHSPEC_PREFER_FULL |
builtin/am.c +2 -2
index 8677ea2348a..be0e32f69cf 100644
@@ -2230,8 +2230,8 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 	}
 
 	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
-		return error(_("--show-current-patch=%s is incompatible with "
-			       "--show-current-patch=%s"),
+		return error(_("options '--show-current-patch=%s' and '--show-current-patch=%s' "
+					   "cannot used together"),
 			     arg, valid_modes[resume->sub_mode]);
 
 	resume->mode = RESUME_SHOW_PATCH;
builtin/cat-file.c +1 -1
index 86fc03242b8..400ceaba5e8 100644
@@ -729,7 +729,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
 	}
 
 	if (force_path && batch.enabled) {
-		error("--path=<path> incompatible with --batch");
+		error("'--path=<path>' and '--batch' cannot be used together");
 		usage_with_options(cat_file_usage, options);
 	}
 
builtin/checkout.c +2 -2
index d005aaad9f2..e83684a58b9 100644
@@ -1635,7 +1635,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 	}
 
 	if ((!!opts->new_branch + !!opts->new_branch_force + !!opts->new_orphan_branch) > 1)
-		die(_("-%c, -%c and --orphan are mutually exclusive"),
+		die(_("options '-%c', '-%c' and '--orphan' cannot be used together"),
 				cb_option, toupper(cb_option));
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
@@ -1746,7 +1746,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 
 	if (opts->pathspec_from_file) {
 		if (opts->pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		if (opts->force_detach)
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file",  "--detach");
builtin/clone.c +1 -1
index 13bdbe14b2f..cc92393e4a5 100644
@@ -900,7 +900,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
 	if (option_bare) {
 		if (option_origin)
-			die(_("--bare and --origin %s options are incompatible."),
+			die(_("options '--bare' and '--origin %s' cannot be used together"),
 			    option_origin);
 		if (real_git_dir)
 			die(_("options '%s' and '%s' cannot be used together"), "--bare", "--separate-git-dir");
builtin/commit.c +6 -4
index eb803a96ae3..fa454ea9421 100644
@@ -361,7 +361,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 			die(_("options '%s' and '%s' cannot be used together"),"--pathspec-from-file", "-a");
 
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_FULL,
@@ -799,7 +799,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 
 		if (!strcmp(fixup_prefix, "amend")) {
 			if (have_option_m)
-				die(_("cannot combine -m with --fixup:%s"), fixup_message);
+				die(_("options '-m' and '--fixup:%s' cannot be used together"), fixup_message);
 			prepare_amend_commit(commit, &sb, &ctx);
 		}
 	} else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
@@ -1229,9 +1229,11 @@ static void check_fixup_reword_options(int argc, const char *argv[]) {
 			die(_("You are in the middle of a cherry-pick -- cannot reword."));
 	}
 	if (argc)
-		die(_("cannot combine reword option of --fixup with path '%s'"), *argv);
+		die(_("reword option of --fixup and path '%s' cannot be used together"), *argv);
 	if (patch_interactive || interactive || all || also || only)
-		die(_("reword option of --fixup is mutually exclusive with --patch/--interactive/--all/--include/--only"));
+		die(_("reword option of --fixup and "
+			  "--patch/--interactive/--all/--include/--only "
+			  "cannot be used together"));
 }
 
 static int parse_and_validate_options(int argc, const char *argv[],
builtin/describe.c +2 -2
index fd5ba1fc604..130b87b3a34 100644
@@ -670,9 +670,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 		}
 		describe("HEAD", 1);
 	} else if (dirty) {
-		die(_("--dirty is incompatible with commit-ishes"));
+		die(_("'%s' and commit-ishes cannot be used together"), "--dirty");
 	} else if (broken) {
-		die(_("--broken is incompatible with commit-ishes"));
+		die(_("'%s' and  commit-ishes cannot be used together"), "--broken");
 	} else {
 		while (argc-- > 0)
 			describe(*argv++, argc == 0);
builtin/init-db.c +1 -1
index 546f9c595e7..b85dffbdf5c 100644
@@ -681,7 +681,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	}
 	else {
 		if (real_git_dir)
-			die(_("--separate-git-dir incompatible with bare repository"));
+			die(_("'--separate-git-dir' and bare repository cannot be used together"));
 		if (work_tree)
 			set_git_work_tree(work_tree);
 	}
builtin/rebase.c +2 -2
index ed326b8aecc..d3ce0999786 100644
@@ -1460,8 +1460,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
 		if (i >= 0) {
 			if (is_merge(&options))
-				die(_("cannot combine apply options with "
-				      "merge options"));
+				die(_("apply options and merge options "
+					  "cannot be used together"));
 			else
 				options.type = REBASE_APPLY;
 		}
builtin/reset.c +1 -1
index 25f52ea99f6..9fba34addf4 100644
@@ -426,7 +426,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_FULL,
builtin/rev-list.c +1 -1
index de60cbdbc9d..0e3d93afed3 100644
@@ -676,7 +676,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	if (revs.count &&
 	    (revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
 	    (revs.left_right || revs.cherry_mark))
-		die(_("marked counting is incompatible with --objects"));
+		die(_("marked counting and '--objects' cannot be used together"));
 
 	save_commit_buffer = (revs.verbose_header ||
 			      revs.grep_filter.pattern_list ||
builtin/rm.c +1 -1
index 38ac3c71252..7f1cd6a33f8 100644
@@ -272,7 +272,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_CWD,
builtin/stash.c +1 -1
index 7ad2f9aca87..242be3eb7e8 100644
@@ -1706,7 +1706,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--staged");
 
 		if (ps.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&ps, 0,
 				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
diff.c +3 -3
index 8de1c49763c..ba2a886ec2c 100644
@@ -4639,16 +4639,16 @@ void diff_setup_done(struct diff_options *options)
 		options->set_default(options);
 
 	if (HAS_MULTI_BITS(options->output_format & check_mask))
-		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
+		die(_("options '--name-only', '--name-status', '--check' and '-s' cannot be used together"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
 		die(_("options '%s', '%s' and '%s' cannot be used together"), "-G", "-S", "--find-object");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
-		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
+		die(_("-G and --pickaxe-regex cannot be used together, use --pickaxe-regex with -S"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_ALL_OBJFIND_MASK))
-		die(_("--pickaxe-all and --find-object are mutually exclusive, use --pickaxe-all with -G and -S"));
+		die(_("--pickaxe-all and --find-object cannot be used together, use --pickaxe-all with -G and -S"));
 
 	/*
 	 * Most of the time we can say "there are changes"
t/t0001-init.sh +2 -2
index 3235ab4d53c..7d8bae09c25 100755
@@ -339,7 +339,7 @@ test_expect_success 'implicit bare & --separate-git-dir incompatible' '
 	mkdir -p bare.git &&
 	test_must_fail env GIT_DIR=. \
 		git -C bare.git init --separate-git-dir goop.git 2>err &&
-	test_i18ngrep "incompatible" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'bare & --separate-git-dir incompatible within worktree' '
@@ -348,7 +348,7 @@ test_expect_success 'bare & --separate-git-dir incompatible within worktree' '
 	git clone --bare . bare.git &&
 	git -C bare.git worktree add --detach ../linkwt &&
 	test_must_fail git -C linkwt init --separate-git-dir seprepo 2>err &&
-	test_i18ngrep "incompatible" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_lazy_prereq GETCWD_IGNORES_PERMS '
t/t2026-checkout-pathspec-file.sh +1 -1
index fbe26de2f90..2bd8cd74206 100755
@@ -155,7 +155,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
t/t2072-restore-pathspec-file.sh +1 -1
index ad1fc0ed071..4f7e9d47d28 100755
@@ -155,7 +155,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
t/t3431-rebase-fork-point.sh +1 -1
index 4c98d99e7e8..1d0b15380ed 100755
@@ -83,7 +83,7 @@ test_expect_success 'git rebase --fork-point with ambigous refname' '
 
 test_expect_success '--fork-point and --root both given' '
 	test_must_fail git rebase --fork-point --root 2>err &&
-	test_i18ngrep "cannot combine" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'rebase.forkPoint set to false' '
t/t3601-rm-pathspec-file.sh +1 -1
index b2a8db69afc..b6ebde4e572 100755
@@ -67,7 +67,7 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git rm --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git rm --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
t/t3704-add-pathspec-file.sh +1 -1
index 7e17ae80229..38a22efcdda 100755
@@ -147,7 +147,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git add --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
t/t3909-stash-pathspec-file.sh +1 -1
index aae2b25f766..43ddf051240 100755
@@ -91,7 +91,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
t/t4209-log-pickaxe.sh +2 -2
index 4f820f8597d..7f6bb27f141 100755
@@ -72,12 +72,12 @@ test_expect_success 'usage' '
 	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err
+	grep "cannot be used together" err
 '
 
 test_expect_success 'usage: --pickaxe-regex' '
 	test_expect_code 128 git log -Gregex --pickaxe-regex 2>err &&
-	grep "mutually exclusive" err
+	grep "cannot be used together" err
 '
 
 test_expect_success 'usage: --no-pickaxe-regex' '
t/t5606-clone-options.sh +1 -1
index 3af3577af0b..8f676d6b0c0 100755
@@ -46,7 +46,7 @@ test_expect_success 'disallows --bare with --origin' '
 
 	test_must_fail git clone -o foo --bare parent clone-bare-o 2>err &&
 	test_debug "cat err" &&
-	test_i18ngrep -e "--bare and --origin foo options are incompatible" err
+	test_i18ngrep -e "options .--bare. and .--origin foo. cannot be used together" err
 
 '
 
t/t7107-reset-pathspec-file.sh +1 -1
index b211fbc0a52..880adf79742 100755
@@ -163,7 +163,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
t/t7500-commit-template-squash-signoff.sh +6 -5
index 8dd0f988129..2da97f479fe 100755
@@ -359,14 +359,14 @@ test_expect_success '--fixup=reword: ignores staged changes' '
 
 test_expect_success '--fixup=reword: error out with -m option' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine -m with --fixup:reword" >expect &&
+	echo "fatal: options '\''-m'\'' and '\''--fixup:reword'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -m "reword commit message" 2>actual &&
 	test_cmp expect actual
 '
 
 test_expect_success '--fixup=amend: error out with -m option' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine -m with --fixup:amend" >expect &&
+	echo "fatal: options '\''-m'\'' and '\''--fixup:amend'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=amend:HEAD~ -m "amend commit message" 2>actual &&
 	test_cmp expect actual
 '
@@ -421,8 +421,9 @@ test_expect_success 'amend! commit allows empty commit msg body with --allow-emp
 
 test_fixup_reword_opt () {
 	test_expect_success "--fixup=reword: incompatible with $1" "
-		echo 'fatal: reword option of --fixup is mutually exclusive with'\
-			'--patch/--interactive/--all/--include/--only' >expect &&
+		echo 'fatal: reword option of --fixup and'\
+			'--patch/--interactive/--all/--include/--only'\
+			'cannot be used together' >expect &&
 		test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
 		test_cmp expect actual
 	"
@@ -435,7 +436,7 @@ done
 
 test_expect_success '--fixup=reword: give error with pathsec' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine reword option of --fixup with path '\''foo'\''" >expect &&
+	echo "fatal: reword option of --fixup and path '\''foo'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -- foo 2>actual &&
 	test_cmp expect actual
 '
t/t7526-commit-pathspec-file.sh +2 -2
index fb5857b2a13..b6013a1f742 100755
@@ -147,10 +147,10 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and .-a. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
Signature · 1 line
gitgitgadget
#41 lore raw

Re: [PATCH v2 11/11] i18n: turn even more messages into "cannot be used together" ones

Am 28.12.21 um 00:23 schrieb Jean-Noël Avila via GitGitGadget:

Quoted 40 lines

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Even if some of these messages are not subject to gettext i18n, this helps bring a single style of message for a given error type.

---
 builtin/add.c                             |  2 +-
 builtin/am.c                              |  4 ++--
 builtin/cat-file.c                        |  2 +-
 builtin/checkout.c                        |  4 ++--
 builtin/clone.c                           |  2 +-
 builtin/commit.c                          | 10 ++++++----
 builtin/describe.c                        |  4 ++--
 builtin/init-db.c                         |  2 +-
 builtin/rebase.c                          |  4 ++--
 builtin/reset.c                           |  2 +-
 builtin/rev-list.c                        |  2 +-
 builtin/rm.c                              |  2 +-
 builtin/stash.c                           |  2 +-
 diff.c                                    |  6 +++---
 t/t0001-init.sh                           |  4 ++--
 t/t2026-checkout-pathspec-file.sh         |  2 +-
 t/t2072-restore-pathspec-file.sh          |  2 +-
 t/t3431-rebase-fork-point.sh              |  2 +-
 t/t3601-rm-pathspec-file.sh               |  2 +-
 t/t3704-add-pathspec-file.sh              |  2 +-
 t/t3909-stash-pathspec-file.sh            |  2 +-
 t/t4209-log-pickaxe.sh                    |  4 ++--
 t/t5606-clone-options.sh                  |  2 +-
 t/t7107-reset-pathspec-file.sh            |  2 +-
 t/t7500-commit-template-squash-signoff.sh | 11 ++++++-----
 t/t7526-commit-pathspec-file.sh           |  4 ++--
 26 files changed, 45 insertions(+), 42 deletions(-)
builtin/add.c +0 -0
index b505eca3d4d..ded15ca6eac 100644

builtin/add.c int cmd_add(int argc, const char **argv, const char *prefix) · line 569

Quoted 5 lines
builtin/add.c +1 -1
@@ -566,7 +566,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));

You have not given a justification why this text does not begin with the word "option". IMO, it is not needed; as written, the text is sufficiently clear for both users and translators.

Quoted 8 lines
builtin/add.c +0 -0
 		parse_pathspec_file(&pathspec, PATHSPEC_ATTR,
 				    PATHSPEC_PREFER_FULL |
builtin/am.c +0 -0
index 8677ea2348a..be0e32f69cf 100644

builtin/am.c static int parse_opt_show_current_patch(const struct option *opt, const char *ar · line 2234

Quoted 7 lines
builtin/am.c +2 -2
@@ -2230,8 +2230,8 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 	}
 
 	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
-		return error(_("--show-current-patch=%s is incompatible with "
-			       "--show-current-patch=%s"),
+		return error(_("options '--show-current-patch=%s' and '--show-current-patch=%s' "
+					   "cannot used together"),

Missing "be".

builtin/cat-file.c int cmd_cat_file(int argc, const char **argv, const char *prefix) · line 732

Quoted 13 lines
builtin/am.c +0 -0
 			     arg, valid_modes[resume->sub_mode]);
 
 	resume->mode = RESUME_SHOW_PATCH;
builtin/cat-file.c +1 -1
index 86fc03242b8..400ceaba5e8 100644
@@ -729,7 +729,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
 	}
 
 	if (force_path && batch.enabled) {
-		error("--path=<path> incompatible with --batch");
+		error("'--path=<path>' and '--batch' cannot be used together");

Missing "options" perhaps.

Quoted 79 lines
builtin/cat-file.c +0 -0
 		usage_with_options(cat_file_usage, options);
 	}
 
builtin/checkout.c +2 -2
index d005aaad9f2..e83684a58b9 100644
@@ -1635,7 +1635,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 	}
 
 	if ((!!opts->new_branch + !!opts->new_branch_force + !!opts->new_orphan_branch) > 1)
-		die(_("-%c, -%c and --orphan are mutually exclusive"),
+		die(_("options '-%c', '-%c' and '--orphan' cannot be used together"),
 				cb_option, toupper(cb_option));
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
@@ -1746,7 +1746,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 
 	if (opts->pathspec_from_file) {
 		if (opts->pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		if (opts->force_detach)
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file",  "--detach");
builtin/clone.c +1 -1
index 13bdbe14b2f..cc92393e4a5 100644
@@ -900,7 +900,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
 	if (option_bare) {
 		if (option_origin)
-			die(_("--bare and --origin %s options are incompatible."),
+			die(_("options '--bare' and '--origin %s' cannot be used together"),
 			    option_origin);
 		if (real_git_dir)
 			die(_("options '%s' and '%s' cannot be used together"), "--bare", "--separate-git-dir");
builtin/commit.c +6 -4
index eb803a96ae3..fa454ea9421 100644
@@ -361,7 +361,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 			die(_("options '%s' and '%s' cannot be used together"),"--pathspec-from-file", "-a");
 
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_FULL,
@@ -799,7 +799,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 
 		if (!strcmp(fixup_prefix, "amend")) {
 			if (have_option_m)
-				die(_("cannot combine -m with --fixup:%s"), fixup_message);
+				die(_("options '-m' and '--fixup:%s' cannot be used together"), fixup_message);
 			prepare_amend_commit(commit, &sb, &ctx);
 		}
 	} else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
@@ -1229,9 +1229,11 @@ static void check_fixup_reword_options(int argc, const char *argv[]) {
 			die(_("You are in the middle of a cherry-pick -- cannot reword."));
 	}
 	if (argc)
-		die(_("cannot combine reword option of --fixup with path '%s'"), *argv);
+		die(_("reword option of --fixup and path '%s' cannot be used together"), *argv);
 	if (patch_interactive || interactive || all || also || only)
-		die(_("reword option of --fixup is mutually exclusive with --patch/--interactive/--all/--include/--only"));
+		die(_("reword option of --fixup and "
+			  "--patch/--interactive/--all/--include/--only "
+			  "cannot be used together"));
 }
 
 static int parse_and_validate_options(int argc, const char *argv[],
builtin/describe.c +0 -0
index fd5ba1fc604..130b87b3a34 100644

builtin/describe.c int cmd_describe(int argc, const char **argv, const char *prefix) · line 675

Quoted 8 lines
builtin/describe.c +2 -2
@@ -670,9 +670,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 		}
 		describe("HEAD", 1);
 	} else if (dirty) {
-		die(_("--dirty is incompatible with commit-ishes"));
+		die(_("'%s' and commit-ishes cannot be used together"), "--dirty");
 	} else if (broken) {
-		die(_("--broken is incompatible with commit-ishes"));
+		die(_("'%s' and  commit-ishes cannot be used together"), "--broken");

I noticed immediately that the two texts are not the same because they are not aligned, but it took me a few seconds to notice the extra blank in the second one.

builtin/init-db.c int cmd_init_db(int argc, const char **argv, const char *prefix) · line 684

Quoted 13 lines
builtin/describe.c +0 -0
 	} else {
 		while (argc-- > 0)
 			describe(*argv++, argc == 0);
builtin/init-db.c +1 -1
index 546f9c595e7..b85dffbdf5c 100644
@@ -681,7 +681,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	}
 	else {
 		if (real_git_dir)
-			die(_("--separate-git-dir incompatible with bare repository"));
+			die(_("'--separate-git-dir' and bare repository cannot be used together"));

IMO, in this case, the original text is awkward, and the transformation is worse because it really sounds like a mechanical replacement. I suggest not to do this transformation.

Quoted 261 lines
builtin/init-db.c +0 -0
 		if (work_tree)
 			set_git_work_tree(work_tree);
 	}
builtin/rebase.c +2 -2
index ed326b8aecc..d3ce0999786 100644
@@ -1460,8 +1460,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
 		if (i >= 0) {
 			if (is_merge(&options))
-				die(_("cannot combine apply options with "
-				      "merge options"));
+				die(_("apply options and merge options "
+					  "cannot be used together"));
 			else
 				options.type = REBASE_APPLY;
 		}
builtin/reset.c +1 -1
index 25f52ea99f6..9fba34addf4 100644
@@ -426,7 +426,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_FULL,
builtin/rev-list.c +1 -1
index de60cbdbc9d..0e3d93afed3 100644
@@ -676,7 +676,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	if (revs.count &&
 	    (revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
 	    (revs.left_right || revs.cherry_mark))
-		die(_("marked counting is incompatible with --objects"));
+		die(_("marked counting and '--objects' cannot be used together"));
 
 	save_commit_buffer = (revs.verbose_header ||
 			      revs.grep_filter.pattern_list ||
builtin/rm.c +1 -1
index 38ac3c71252..7f1cd6a33f8 100644
@@ -272,7 +272,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_CWD,
builtin/stash.c +1 -1
index 7ad2f9aca87..242be3eb7e8 100644
@@ -1706,7 +1706,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--staged");
 
 		if (ps.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&ps, 0,
 				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
diff.c +3 -3
index 8de1c49763c..ba2a886ec2c 100644
@@ -4639,16 +4639,16 @@ void diff_setup_done(struct diff_options *options)
 		options->set_default(options);
 
 	if (HAS_MULTI_BITS(options->output_format & check_mask))
-		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
+		die(_("options '--name-only', '--name-status', '--check' and '-s' cannot be used together"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
 		die(_("options '%s', '%s' and '%s' cannot be used together"), "-G", "-S", "--find-object");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
-		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
+		die(_("-G and --pickaxe-regex cannot be used together, use --pickaxe-regex with -S"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_ALL_OBJFIND_MASK))
-		die(_("--pickaxe-all and --find-object are mutually exclusive, use --pickaxe-all with -G and -S"));
+		die(_("--pickaxe-all and --find-object cannot be used together, use --pickaxe-all with -G and -S"));
 
 	/*
 	 * Most of the time we can say "there are changes"
t/t0001-init.sh +2 -2
index 3235ab4d53c..7d8bae09c25 100755
@@ -339,7 +339,7 @@ test_expect_success 'implicit bare & --separate-git-dir incompatible' '
 	mkdir -p bare.git &&
 	test_must_fail env GIT_DIR=. \
 		git -C bare.git init --separate-git-dir goop.git 2>err &&
-	test_i18ngrep "incompatible" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'bare & --separate-git-dir incompatible within worktree' '
@@ -348,7 +348,7 @@ test_expect_success 'bare & --separate-git-dir incompatible within worktree' '
 	git clone --bare . bare.git &&
 	git -C bare.git worktree add --detach ../linkwt &&
 	test_must_fail git -C linkwt init --separate-git-dir seprepo 2>err &&
-	test_i18ngrep "incompatible" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_lazy_prereq GETCWD_IGNORES_PERMS '
t/t2026-checkout-pathspec-file.sh +1 -1
index fbe26de2f90..2bd8cd74206 100755
@@ -155,7 +155,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
t/t2072-restore-pathspec-file.sh +1 -1
index ad1fc0ed071..4f7e9d47d28 100755
@@ -155,7 +155,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
t/t3431-rebase-fork-point.sh +1 -1
index 4c98d99e7e8..1d0b15380ed 100755
@@ -83,7 +83,7 @@ test_expect_success 'git rebase --fork-point with ambigous refname' '
 
 test_expect_success '--fork-point and --root both given' '
 	test_must_fail git rebase --fork-point --root 2>err &&
-	test_i18ngrep "cannot combine" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'rebase.forkPoint set to false' '
t/t3601-rm-pathspec-file.sh +1 -1
index b2a8db69afc..b6ebde4e572 100755
@@ -67,7 +67,7 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git rm --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git rm --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
t/t3704-add-pathspec-file.sh +1 -1
index 7e17ae80229..38a22efcdda 100755
@@ -147,7 +147,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git add --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
t/t3909-stash-pathspec-file.sh +1 -1
index aae2b25f766..43ddf051240 100755
@@ -91,7 +91,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
t/t4209-log-pickaxe.sh +2 -2
index 4f820f8597d..7f6bb27f141 100755
@@ -72,12 +72,12 @@ test_expect_success 'usage' '
 	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err
+	grep "cannot be used together" err
 '
 
 test_expect_success 'usage: --pickaxe-regex' '
 	test_expect_code 128 git log -Gregex --pickaxe-regex 2>err &&
-	grep "mutually exclusive" err
+	grep "cannot be used together" err
 '
 
 test_expect_success 'usage: --no-pickaxe-regex' '
t/t5606-clone-options.sh +1 -1
index 3af3577af0b..8f676d6b0c0 100755
@@ -46,7 +46,7 @@ test_expect_success 'disallows --bare with --origin' '
 
 	test_must_fail git clone -o foo --bare parent clone-bare-o 2>err &&
 	test_debug "cat err" &&
-	test_i18ngrep -e "--bare and --origin foo options are incompatible" err
+	test_i18ngrep -e "options .--bare. and .--origin foo. cannot be used together" err
 
 '
 
t/t7107-reset-pathspec-file.sh +1 -1
index b211fbc0a52..880adf79742 100755
@@ -163,7 +163,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
t/t7500-commit-template-squash-signoff.sh +2 -2
index 8dd0f988129..2da97f479fe 100755
@@ -359,14 +359,14 @@ test_expect_success '--fixup=reword: ignores staged changes' '
 
 test_expect_success '--fixup=reword: error out with -m option' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine -m with --fixup:reword" >expect &&
+	echo "fatal: options '\''-m'\'' and '\''--fixup:reword'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -m "reword commit message" 2>actual &&
 	test_cmp expect actual
 '
 
 test_expect_success '--fixup=amend: error out with -m option' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine -m with --fixup:amend" >expect &&
+	echo "fatal: options '\''-m'\'' and '\''--fixup:amend'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=amend:HEAD~ -m "amend commit message" 2>actual &&
 	test_cmp expect actual
 '

t/t7500-commit-template-squash-signoff.sh test_expect_success 'amend! commit allows empty commit msg body with --allow-emp · line 426

Quoted 8 lines
t/t7500-commit-template-squash-signoff.sh +3 -2
@@ -421,8 +421,9 @@ test_expect_success 'amend! commit allows empty commit msg body with --allow-emp
 
 test_fixup_reword_opt () {
 	test_expect_success "--fixup=reword: incompatible with $1" "
-		echo 'fatal: reword option of --fixup is mutually exclusive with'\
-			'--patch/--interactive/--all/--include/--only' >expect &&
+		echo 'fatal: reword option of --fixup and'\
+			'--patch/--interactive/--all/--include/--only'\
+			'cannot be used together' >expect &&

On first sight, it looked significant that there are no blanks between "and", the single-quote, and the backslash. On second thought, the backslash is just a line continuation, and the blank that is needed in the text is inserted by "echo" because it emits its three arguments, the single-quoted strings', in blank-separated form. This means that there must not be a blank after "and" and after "--only" and before the single-quotes. There could be a blank before the backslash.

Good.

Quoted 29 lines
t/t7500-commit-template-squash-signoff.sh +1 -1
 		test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
 		test_cmp expect actual
 	"
@@ -435,7 +436,7 @@ done
 
 test_expect_success '--fixup=reword: give error with pathsec' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine reword option of --fixup with path '\''foo'\''" >expect &&
+	echo "fatal: reword option of --fixup and path '\''foo'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -- foo 2>actual &&
 	test_cmp expect actual
 '
t/t7526-commit-pathspec-file.sh +2 -2
index fb5857b2a13..b6013a1f742 100755
@@ -147,10 +147,10 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and .-a. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err &&
 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
#42 lore raw

Re: [PATCH v2 11/11] i18n: turn even more messages into "cannot be used together" ones

Quoted 9 lines · On Tuesday, 28 December 2021 08:33:15 CET Johannes Sixt wrote:

Am 28.12.21 um 00:23 schrieb Jean-Noël Avila via GitGitGadget:

Quoted 8 lines

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

builtin/am.c +0 -0
index 8677ea2348a..be0e32f69cf 100644
@@ -2230,8 +2230,8 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 	}
 
Quoted 7 lines

builtin/am.c static int parse_opt_show_current_patch(const struct option *opt, const char *ar · line 2234

Quoted 5 lines
builtin/am.c +2 -2
 	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
-		return error(_("--show-current-patch=%s is incompatible with "
-			       "--show-current-patch=%s"),
+		return error(_("options '--show-current-patch=%s' and '--show-current-patch=%s' "
+					   "cannot used together"),

Missing "be".

Thanks.

Quoted 11 lines
Quoted 11 lines
builtin/am.c +0 -0
 			     arg, valid_modes[resume->sub_mode]);
 
 	resume->mode = RESUME_SHOW_PATCH;
builtin/cat-file.c +0 -0
index 86fc03242b8..400ceaba5e8 100644
@@ -729,7 +729,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
 	}
 
Quoted 6 lines

builtin/cat-file.c int cmd_cat_file(int argc, const char **argv, const char *prefix) · line 732

Quoted 3 lines
builtin/cat-file.c +1 -1
 	if (force_path && batch.enabled) {
-		error("--path=<path> incompatible with --batch");
+		error("'--path=<path>' and '--batch' cannot be used together");

Missing "options" perhaps.

Thanks.

Quoted 12 lines
Quoted 12 lines
builtin/cat-file.c +0 -0
 		usage_with_options(cat_file_usage, options);
 	}
 
builtin/describe.c +0 -1
index fd5ba1fc604..130b87b3a34 100644
@@ -670,9 +670,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 		}
 		describe("HEAD", 1);
 	} else if (dirty) {
-		die(_("--dirty is incompatible with commit-ishes"));
Quoted 8 lines

builtin/describe.c int cmd_describe(int argc, const char **argv, const char *prefix) · line 675

Quoted 4 lines
builtin/describe.c +2 -1
+		die(_("'%s' and commit-ishes cannot be used together"), "--dirty");
 	} else if (broken) {
-		die(_("--broken is incompatible with commit-ishes"));
+		die(_("'%s' and  commit-ishes cannot be used together"), "--broken");

I noticed immediately that the two texts are not the same because they are not aligned, but it took me a few seconds to notice the extra blank in the second one.

Thanks.

Quoted 10 lines
Quoted 10 lines
builtin/describe.c +0 -0
 	} else {
 		while (argc-- > 0)
 			describe(*argv++, argc == 0);
builtin/init-db.c +0 -0
index 546f9c595e7..b85dffbdf5c 100644
@@ -681,7 +681,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	}
Quoted 8 lines

builtin/init-db.c int cmd_init_db(int argc, const char **argv, const char *prefix) · line 684

Quoted 4 lines
builtin/init-db.c +1 -1
 	else {
 		if (real_git_dir)
-			die(_("--separate-git-dir incompatible with bare repository"));
+			die(_("'--separate-git-dir' and bare repository cannot be used together"));

IMO, in this case, the original text is awkward, and the transformation is worse because it really sounds like a mechanical replacement. I suggest not to do this transformation.

Agreed.

Quoted 17 lines

builtin/init-db.c int cmd_init_db(int argc, const char **argv, const char *prefix)

Quoted 8 lines
builtin/init-db.c +3 -2
 test_fixup_reword_opt () {
 	test_expect_success "--fixup=reword: incompatible with $1" "
-		echo 'fatal: reword option of --fixup is mutually exclusive with'\
-			'--patch/--interactive/--all/--include/--only' >expect &&
+		echo 'fatal: reword option of --fixup and'\
+			'--patch/--interactive/--all/--include/--only'\
+			'cannot be used together' >expect &&

On first sight, it looked significant that there are no blanks between "and", the single-quote, and the backslash. On second thought, the backslash is just a line continuation, and the blank that is needed in the text is inserted by "echo" because it emits its three arguments, the single-quoted strings', in blank-separated form. This means that there must not be a blank after "and" and after "--only" and before the single-quotes. There could be a blank before the backslash.

Quoted 1 line

Good.

That's exactly that. I struggled for quite some time when trying to split the string and the test was failing. Very counter-intuitive, even after you understand why.

Thanks for your review and spotting the mistakes. Will reroll.

As a side note, while editing all these tests in series, i could not help but notice that there are different styles of writing them.

#43 lore raw

v3 cover Factorization of messages with similar meaning

In reply to Jean-Noël Avila via GitGitGadget

This series is a meager attempt at rationalizing a small fraction of the internationalized messages. Sorry in advance for the dull task of reviewing these insipide patches.

Doing so has some positive effects:

* non-translatable constant strings are kept out of the way for translators
* messages with identical meaning are built identically
* the total number of messages to translate is decreased.

Changes since V1:

* took into account the comments, except for ref-filter.c where the proposed refactoring is not obvious.
* added even more strings to the "cannot be used together" crowd.

Jean-Noël Avila (11):
i18n: refactor "foo and bar are mutually exclusive"
i18n: refactor "%s, %s and %s are mutually exclusive"
i18n: turn "options are incompatible" into "cannot be used together"
i18n: standardize "cannot open" and "cannot read"
i18n: tag.c factorize i18n strings
i18n: factorize "--foo requires --bar" and the like
i18n: factorize "no directory given for --foo"
i18n: refactor "unrecognized %(foo) argument" strings
i18n: factorize "--foo outside a repository"
i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"
i18n: turn even more messages into "cannot be used together" ones

 apply.c                                   |  8 ++++----
 archive.c                                 |  8 ++++----
 builtin/add.c                             | 14 +++++++-------
 builtin/am.c                              |  4 ++--
 builtin/branch.c                          |  2 +-
 builtin/cat-file.c                        |  2 +-
 builtin/checkout.c                        | 12 ++++++------
 builtin/clone.c                           |  4 ++--
 builtin/commit.c                          | 18 ++++++++++--------
 builtin/describe.c                        |  6 +++---
 builtin/diff-tree.c                       |  2 +-
 builtin/difftool.c                        |  4 ++--
 builtin/fast-export.c                     |  4 ++--
 builtin/fetch.c                           |  8 ++++----
 builtin/index-pack.c                      |  4 ++--
 builtin/init-db.c                         |  2 +-
 builtin/log.c                             |  8 ++++----
 builtin/ls-files.c                        |  2 +-
 builtin/merge.c                           |  4 ++--
 builtin/pack-objects.c                    |  2 +-
 builtin/push.c                            |  8 ++++----
 builtin/rebase.c                          | 10 +++++-----
 builtin/repack.c                          |  4 ++--
 builtin/reset.c                           | 10 +++++-----
 builtin/rev-list.c                        |  4 ++--
 builtin/rm.c                              |  4 ++--
 builtin/show-branch.c                     |  4 ++--
 builtin/stash.c                           |  8 ++++----
 builtin/submodule--helper.c               |  4 ++--
 builtin/tag.c                             | 19 +++++++++++--------
 builtin/worktree.c                        |  6 +++---
 diff.c                                    |  8 ++++----
 fetch-pack.c                              |  2 +-
 git.c                                     |  6 +++---
 http-fetch.c                              |  4 ++--
 range-diff.c                              |  2 +-
 ref-filter.c                              | 22 +++++++++++-----------
 revision.c                                | 22 +++++++++++-----------
 t/t0001-init.sh                           |  2 +-
 t/t2025-checkout-no-overlay.sh            |  2 +-
 t/t2026-checkout-pathspec-file.sh         |  8 ++++----
 t/t2072-restore-pathspec-file.sh          |  6 +++---
 t/t3431-rebase-fork-point.sh              |  2 +-
 t/t3601-rm-pathspec-file.sh               |  4 ++--
 t/t3704-add-pathspec-file.sh              | 10 +++++-----
 t/t3909-stash-pathspec-file.sh            |  6 +++---
 t/t4209-log-pickaxe.sh                    | 10 +++++-----
 t/t5606-clone-options.sh                  |  4 ++--
 t/t7107-reset-pathspec-file.sh            |  6 +++---
 t/t7500-commit-template-squash-signoff.sh | 11 ++++++-----
 t/t7526-commit-pathspec-file.sh           | 10 +++++-----
 51 files changed, 176 insertions(+), 170 deletions(-)

base-commit: 2ae0a9cb8298185a94e5998086f380a355dd8907
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1088%2Fjnavila%2Fi18n-refactor-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1088/jnavila/i18n-refactor-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/1088

Range-diff vs v2:

  1:  71699eaa27b !  1:  05af90f5814 i18n: refactor "foo and bar are mutually exclusive"
     @@ t/t2025-checkout-no-overlay.sh: test_expect_success 'checkout --no-overlay remov
       '
       test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
     -
     - ## t/t4209-log-pickaxe.sh ##
     -@@ t/t4209-log-pickaxe.sh: test_expect_success 'usage' '
     - 	test_i18ngrep "switch.*requires a value" err &&
     - 
     - 	test_expect_code 128 git log -Gregex -Sstring 2>err &&
     --	grep "mutually exclusive" err &&
     -+	grep "cannot be used together" err &&
     - 
     - 	test_expect_code 128 git log -Gregex --find-object=HEAD 2>err &&
     --	grep "mutually exclusive" err &&
     -+	grep "cannot be used together" err &&
     - 
     - 	test_expect_code 128 git log -Sstring --find-object=HEAD 2>err &&
     --	grep "mutually exclusive" err &&
     -+	grep "cannot be used together" err &&
     - 
     - 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
     - 	grep "mutually exclusive" err
  2:  be4e8757f38 !  2:  4accf1629e5 i18n: refactor "%s, %s and %s are mutually exclusive"
     @@ diff.c: void diff_setup_done(struct diff_options *options)
       
       	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
       		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
     +
     + ## t/t4209-log-pickaxe.sh ##
     +@@ t/t4209-log-pickaxe.sh: test_expect_success 'usage' '
     + 	test_i18ngrep "switch.*requires a value" err &&
     + 
     + 	test_expect_code 128 git log -Gregex -Sstring 2>err &&
     +-	grep "mutually exclusive" err &&
     ++	grep "cannot be used together" err &&
     + 
     + 	test_expect_code 128 git log -Gregex --find-object=HEAD 2>err &&
     +-	grep "mutually exclusive" err &&
     ++	grep "cannot be used together" err &&
     + 
     + 	test_expect_code 128 git log -Sstring --find-object=HEAD 2>err &&
     +-	grep "mutually exclusive" err &&
     ++	grep "cannot be used together" err &&
     + 
     + 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
     + 	grep "mutually exclusive" err

3: 53bad588bfc ! 3: 486cc6c89e2 i18n: turn "options are incompatible" into "cannot be used together"
@@ t/t2072-restore-pathspec-file.sh: test_expect_success 'error conditions' '
test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err && test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&

+ ## t/t3431-rebase-fork-point.sh ##
+@@ t/t3431-rebase-fork-point.sh: test_expect_success 'git rebase --fork-point with ambigous refname' ' +
+ test_expect_success '--fork-point and --root both given' '
+ test_must_fail git rebase --fork-point --root 2>err &&
+- test_i18ngrep "cannot combine" err
++ test_i18ngrep "cannot be used together" err
+ '
+
+ test_expect_success 'rebase.forkPoint set to false' '
+
## t/t3704-add-pathspec-file.sh ##
@@ t/t3704-add-pathspec-file.sh: test_expect_success 'error conditions' '
>empty_list &&
@@ t/t7526-commit-pathspec-file.sh: test_expect_success 'error conditions' '
+ test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&

test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err &&
- test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
+- test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
++ test_i18ngrep -e "options .--pathspec-from-file. and .-a. cannot be used together" err &&
+
+ test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err &&
+ test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&

  4:  88dfde62eda =  4:  a2b42087342 i18n: standardize "cannot open" and "cannot read"
  5:  6d89c23a248 !  5:  2d83654c48a i18n: tag.c factorize i18n strings
     @@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)
       	}
       	if (filter.lines != -1)
      -		die(_("-n option is only allowed in list mode"));
     -+		only_in_list = "-n";
     - 	if (filter.with_commit)
     +-	if (filter.with_commit)
      -		die(_("--contains option is only allowed in list mode"));
     -+		only_in_list = "--contains";
     - 	if (filter.no_commit)
     +-	if (filter.no_commit)
      -		die(_("--no-contains option is only allowed in list mode"));
     -+		only_in_list = "--no-contains";
     - 	if (filter.points_at.nr)
     +-	if (filter.points_at.nr)
      -		die(_("--points-at option is only allowed in list mode"));
     ++		only_in_list = "-n";
     ++	else if (filter.with_commit)
     ++		only_in_list = "--contains";
     ++	else if (filter.no_commit)
     ++		only_in_list = "--no-contains";
     ++	else if (filter.points_at.nr)
      +		only_in_list = "--points-at";
      +	if (only_in_list)
     -+		die("the '%s' option is only allowed in list mode", only_in_list);
     ++		die(_("the '%s' option is only allowed in list mode"), only_in_list);
       	if (filter.reachable_from || filter.unreachable_from)
       		die(_("--merged and --no-merged options are only allowed in list mode"));
       	if (cmdmode == 'd') {
  6:  f83ed5cb799 !  6:  1097cc7d6d1 i18n: factorize "--foo requires --bar" and the like
     @@ Metadata
       ## Commit message ##
          i18n: factorize "--foo requires --bar" and the like
      
     +    They are all replaced by "the option '%s' requires '%s'", which is a
     +    new string but replaces 17 previous unique strings.
     +
          Signed-off-by: Jean-Noël Avila <[email protected]>
      
       ## archive.c ##
     @@ archive.c: static int parse_archive_args(int argc, const char **argv,
       		die(_("Unexpected option --remote"));
       	if (exec)
      -		die(_("Option --exec can only be used together with --remote"));
     -+		die(_("%s requires %s"), "--exec", "--remote");
     ++		die(_("the option '%s' requires '%s'"), "--exec", "--remote");
       	if (output)
       		die(_("Unexpected option --output"));
       	if (is_remote && args->extra_files.nr)
     @@ builtin/add.c: int cmd_add(int argc, const char **argv, const char *prefix)
       
       	if (!show_only && ignore_missing)
      -		die(_("Option --ignore-missing can only be used together with --dry-run"));
     -+		die(_("%s requires %s"), "--ignore-missing", "--dry-run");
     ++		die(_("the option '%s' requires '%s'"), "--ignore-missing", "--dry-run");
       
       	if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
       			  chmod_arg[1] != 'x' || chmod_arg[2]))
     @@ builtin/add.c: int cmd_add(int argc, const char **argv, const char *prefix)
       				    prefix, pathspec_from_file, pathspec_file_nul);
       	} else if (pathspec_file_nul) {
      -		die(_("--pathspec-file-nul requires --pathspec-from-file"));
     -+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
     ++		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
       	}
       
       	if (require_pathspec && pathspec.nr == 0) {
     @@ builtin/checkout.c: static int checkout_main(int argc, const char **argv, const
       				    prefix, opts->pathspec_from_file, opts->pathspec_file_nul);
       	} else if (opts->pathspec_file_nul) {
      -		die(_("--pathspec-file-nul requires --pathspec-from-file"));
     -+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
     ++		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
       	}
       
       	opts->pathspec.recursive = 1;
     @@ builtin/commit.c: static const char *prepare_index(const char **argv, const char
       				    prefix, pathspec_from_file, pathspec_file_nul);
       	} else if (pathspec_file_nul) {
      -		die(_("--pathspec-file-nul requires --pathspec-from-file"));
     -+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
     ++		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
       	}
       
       	if (!pathspec.nr && (also || (only && !allow_empty &&
     @@ builtin/fast-export.c: int cmd_fast_export(int argc, const char **argv, const ch
       
       	if (anonymized_seeds.cmpfn && !anonymize)
      -		die(_("--anonymize-map without --anonymize does not make sense"));
     -+		die(_("%s requires %s"), "--anonymize-map", "--anonymize");
     ++		die(_("the option '%s' requires '%s'"), "--anonymize-map", "--anonymize");
       
       	if (refspecs_list.nr) {
       		int i;
     @@ builtin/index-pack.c: int cmd_index_pack(int argc, const char **argv, const char
       		usage(index_pack_usage);
       	if (fix_thin_pack && !from_stdin)
      -		die(_("--fix-thin cannot be used without --stdin"));
     -+		die(_("%s requires %s"), "--fix-thin", "--stdin");
     ++		die(_("the option '%s' requires '%s'"), "--fix-thin", "--stdin");
       	if (from_stdin && !startup_info->have_repository)
       		die(_("--stdin requires a git repository"));
       	if (from_stdin && hash_algo)
     @@ builtin/log.c: int cmd_format_patch(int argc, const char **argv, const char *pre
       		creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
       	else if (!rdiff_prev)
      -		die(_("--creation-factor requires --range-diff"));
     -+		die(_("%s requires %s"), "--creation-factor", "--range-diff");
     ++		die(_("the option '%s' requires '%s'"), "--creation-factor", "--range-diff");
       
       	if (rdiff_prev) {
       		if (!cover_letter && total != 1)
     @@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)
       				    prefix, pathspec_from_file, pathspec_file_nul);
       	} else if (pathspec_file_nul) {
      -		die(_("--pathspec-file-nul requires --pathspec-from-file"));
     -+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
     ++		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
       	}
       
       	unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
     @@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)
       
       	if (intent_to_add && reset_type != MIXED)
      -		die(_("-N can only be used with --mixed"));
     -+		die(_("%s requires %s"), "-N", "--mixed");
     ++		die(_("the option '%s' requires '%s'"), "-N", "--mixed");
       
       	prepare_repo_settings(the_repository);
       	the_repository->settings.command_requires_full_index = 0;
     @@ builtin/rm.c: int cmd_rm(int argc, const char **argv, const char *prefix)
       				    prefix, pathspec_from_file, pathspec_file_nul);
       	} else if (pathspec_file_nul) {
      -		die(_("--pathspec-file-nul requires --pathspec-from-file"));
     -+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
     ++		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
       	}
       
       	if (!pathspec.nr)
     @@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *
       				    prefix, pathspec_from_file, pathspec_file_nul);
       	} else if (pathspec_file_nul) {
      -		die(_("--pathspec-file-nul requires --pathspec-from-file"));
     -+		die(_("%s requires %s"), "--pathspec-file-nul", "--pathspec-from-file");
     ++		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
       	}
       
       	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
     @@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix)
       		die(_("options '%s', '%s' and '%s' cannot be used together"), "-b", "-B", "--detach");
       	if (lock_reason && !keep_locked)
      -		die(_("--reason requires --lock"));
     -+		die(_("%s requires %s"), "--reason", "--lock");
     ++		die(_("the option '%s' requires '%s'"), "--reason", "--lock");
       	if (lock_reason)
       		opts.keep_locked = lock_reason;
       	else if (keep_locked)
     @@ fetch-pack.c: static int find_common(struct fetch_negotiator *negotiator,
       
       	if (args->stateless_rpc && multi_ack == 1)
      -		die(_("--stateless-rpc requires multi_ack_detailed"));
     -+		die(_("%s requires %s"), "--stateless-rpc", "multi_ack_detailed");
     ++		die(_("the option '%s' requires '%s'"), "--stateless-rpc", "multi_ack_detailed");
       
       	packet_reader_init(&reader, fd[0], NULL, 0,
       			   PACKET_READ_CHOMP_NEWLINE |
     @@ http-fetch.c: int cmd_main(int argc, const char **argv)
       	if (packfile) {
       		if (!index_pack_args.nr)
      -			die(_("--packfile requires --index-pack-args"));
     -+			die(_("%s requires %s"), "--packfile", "--index-pack-args");
     ++			die(_("the option '%s' requires '%s'"), "--packfile", "--index-pack-args");
       
       		fetch_single_packfile(&packfile_hash, argv[arg],
       				      index_pack_args.v);
     @@ http-fetch.c: int cmd_main(int argc, const char **argv)
       
       	if (index_pack_args.nr)
      -		die(_("--index-pack-args can only be used with --packfile"));
     -+		die(_("%s requires %s"), "--index-pack-args", "--packfile");
     ++		die(_("the option '%s' requires '%s'"), "--index-pack-args", "--packfile");
       
       	if (commits_on_stdin) {
       		commits = walker_targets_stdin(&commit_id, &write_ref);
     +
     + ## revision.c ##
     +@@ revision.c: int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
     + 	if (revs->no_walk && revs->graph)
     + 		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
     + 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
     +-		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");
     ++		die(_("the option '%s' requires '%s'"), "--grep-reflog", "--walk-reflogs");
     + 
     + 	if (revs->line_level_traverse &&
     + 	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
     +
     + ## t/t2026-checkout-pathspec-file.sh ##
     +@@ t/t2026-checkout-pathspec-file.sh: test_expect_success 'error conditions' '
     + 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     + 
     + 	test_must_fail git checkout --pathspec-file-nul 2>err &&
     +-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
     ++	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
     + '
     + 
     + test_done
     +
     + ## t/t2072-restore-pathspec-file.sh ##
     +@@ t/t2072-restore-pathspec-file.sh: test_expect_success 'error conditions' '
     + 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     + 
     + 	test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err &&
     +-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     ++	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
     + 
     + 	test_must_fail git restore --pathspec-from-file=empty_list --source=HEAD^1 2>err &&
     + 	test_i18ngrep -e "you must specify path(s) to restore" err
     +
     + ## t/t3601-rm-pathspec-file.sh ##
     +@@ t/t3601-rm-pathspec-file.sh: test_expect_success 'error conditions' '
     + 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     + 
     + 	test_must_fail git rm --pathspec-file-nul 2>err &&
     +-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     ++	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
     + 
     + 	>empty_list &&
     + 	test_must_fail git rm --pathspec-from-file=empty_list 2>err &&
     +
     + ## t/t3704-add-pathspec-file.sh ##
     +@@ t/t3704-add-pathspec-file.sh: test_expect_success 'error conditions' '
     + 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     + 
     + 	test_must_fail git add --pathspec-file-nul 2>err &&
     +-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     ++	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
     + 
     + 	# This case succeeds, but still prints to stderr
     + 	git add --pathspec-from-file=empty_list 2>err &&
     +
     + ## t/t3909-stash-pathspec-file.sh ##
     +@@ t/t3909-stash-pathspec-file.sh: test_expect_success 'error conditions' '
     + 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     + 
     + 	test_must_fail git stash push --pathspec-file-nul 2>err &&
     +-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
     ++	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
     + '
     + 
     + test_done
     +
     + ## t/t7107-reset-pathspec-file.sh ##
     +@@ t/t7107-reset-pathspec-file.sh: test_expect_success 'error conditions' '
     + 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     + 
     + 	test_must_fail git reset --pathspec-file-nul 2>err &&
     +-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     ++	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
     + 
     + 	test_must_fail git reset --soft --pathspec-from-file=list 2>err &&
     + 	test_i18ngrep -e "fatal: Cannot do soft reset with paths" err &&
     +
     + ## t/t7526-commit-pathspec-file.sh ##
     +@@ t/t7526-commit-pathspec-file.sh: test_expect_success 'error conditions' '
     + 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
     + 
     + 	test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err &&
     +-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     ++	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
     + 
     + 	test_must_fail git commit --pathspec-from-file=empty_list --include -m "Commit" 2>err &&
     + 	test_i18ngrep -e "No paths with --include/--only does not make sense." err &&
  7:  2b7d558f8f9 =  7:  4c17e08b9d3 i18n: factorize "no directory given for --foo"
  8:  5f80ac2fa20 =  8:  b75c5b1ce35 i18n: refactor "unrecognized %(foo) argument" strings
  9:  9dd53960c42 =  9:  44d715a224c i18n: factorize "--foo outside a repository"
 10:  a575f566f2a = 10:  03a880d534b i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"
 11:  89066f01f32 ! 11:  12c5da81087 i18n: turn even more messages into "cannot be used together" ones
     @@ builtin/am.c: static int parse_opt_show_current_patch(const struct option *opt,
      -		return error(_("--show-current-patch=%s is incompatible with "
      -			       "--show-current-patch=%s"),
      +		return error(_("options '--show-current-patch=%s' and '--show-current-patch=%s' "
     -+					   "cannot used together"),
     ++					   "cannot be used together"),
       			     arg, valid_modes[resume->sub_mode]);
       
       	resume->mode = RESUME_SHOW_PATCH;
     @@ builtin/cat-file.c: int cmd_cat_file(int argc, const char **argv, const char *pr
       
       	if (force_path && batch.enabled) {
      -		error("--path=<path> incompatible with --batch");
     -+		error("'--path=<path>' and '--batch' cannot be used together");
     ++		error("options '--path=<path>' and '--batch' cannot be used together");
       		usage_with_options(cat_file_usage, options);
       	}
       
     @@ builtin/describe.c: int cmd_describe(int argc, const char **argv, const char *pr
       		describe("HEAD", 1);
       	} else if (dirty) {
      -		die(_("--dirty is incompatible with commit-ishes"));
     -+		die(_("'%s' and commit-ishes cannot be used together"), "--dirty");
     ++		die(_("option '%s' and commit-ishes cannot be used together"), "--dirty");
       	} else if (broken) {
      -		die(_("--broken is incompatible with commit-ishes"));
     -+		die(_("'%s' and  commit-ishes cannot be used together"), "--broken");
     ++		die(_("option '%s' and commit-ishes cannot be used together"), "--broken");
       	} else {
       		while (argc-- > 0)
       			describe(*argv++, argc == 0);
      
     - ## builtin/init-db.c ##
     -@@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *prefix)
     - 	}
     - 	else {
     - 		if (real_git_dir)
     --			die(_("--separate-git-dir incompatible with bare repository"));
     -+			die(_("'--separate-git-dir' and bare repository cannot be used together"));
     - 		if (work_tree)
     - 			set_git_work_tree(work_tree);
     - 	}
     -
       ## builtin/rebase.c ##
      @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
       
     @@ diff.c: void diff_setup_done(struct diff_options *options)
       	/*
       	 * Most of the time we can say "there are changes"
      
     - ## t/t0001-init.sh ##
     -@@ t/t0001-init.sh: test_expect_success 'implicit bare & --separate-git-dir incompatible' '
     - 	mkdir -p bare.git &&
     - 	test_must_fail env GIT_DIR=. \
     - 		git -C bare.git init --separate-git-dir goop.git 2>err &&
     --	test_i18ngrep "incompatible" err
     -+	test_i18ngrep "cannot be used together" err
     - '
     - 
     - test_expect_success 'bare & --separate-git-dir incompatible within worktree' '
     -@@ t/t0001-init.sh: test_expect_success 'bare & --separate-git-dir incompatible within worktree' '
     - 	git clone --bare . bare.git &&
     - 	git -C bare.git worktree add --detach ../linkwt &&
     - 	test_must_fail git -C linkwt init --separate-git-dir seprepo 2>err &&
     --	test_i18ngrep "incompatible" err
     -+	test_i18ngrep "cannot be used together" err
     - '
     - 
     - test_lazy_prereq GETCWD_IGNORES_PERMS '
     -
       ## t/t2026-checkout-pathspec-file.sh ##
      @@ t/t2026-checkout-pathspec-file.sh: test_expect_success 'error conditions' '
       	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
     @@ t/t2026-checkout-pathspec-file.sh: test_expect_success 'error conditions' '
      +	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
       
       	test_must_fail git checkout --pathspec-file-nul 2>err &&
     - 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
     + 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
      
       ## t/t2072-restore-pathspec-file.sh ##
      @@ t/t2072-restore-pathspec-file.sh: test_expect_success 'error conditions' '
     @@ t/t2072-restore-pathspec-file.sh: test_expect_success 'error conditions' '
      +	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
       
       	test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err &&
     - 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     -
     - ## t/t3431-rebase-fork-point.sh ##
     -@@ t/t3431-rebase-fork-point.sh: test_expect_success 'git rebase --fork-point with ambigous refname' '
     - 
     - test_expect_success '--fork-point and --root both given' '
     - 	test_must_fail git rebase --fork-point --root 2>err &&
     --	test_i18ngrep "cannot combine" err
     -+	test_i18ngrep "cannot be used together" err
     - '
     - 
     - test_expect_success 'rebase.forkPoint set to false' '
     + 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
      
       ## t/t3601-rm-pathspec-file.sh ##
      @@ t/t3601-rm-pathspec-file.sh: test_expect_success 'error conditions' '
     @@ t/t3601-rm-pathspec-file.sh: test_expect_success 'error conditions' '
      +	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
       
       	test_must_fail git rm --pathspec-file-nul 2>err &&
     - 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     + 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
      
       ## t/t3704-add-pathspec-file.sh ##
      @@ t/t3704-add-pathspec-file.sh: test_expect_success 'error conditions' '
     @@ t/t3704-add-pathspec-file.sh: test_expect_success 'error conditions' '
      +	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
       
       	test_must_fail git add --pathspec-file-nul 2>err &&
     - 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     + 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
      
       ## t/t3909-stash-pathspec-file.sh ##
      @@ t/t3909-stash-pathspec-file.sh: test_expect_success 'error conditions' '
     @@ t/t3909-stash-pathspec-file.sh: test_expect_success 'error conditions' '
      +	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
       
       	test_must_fail git stash push --pathspec-file-nul 2>err &&
     - 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
     + 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
      
       ## t/t4209-log-pickaxe.sh ##
      @@ t/t4209-log-pickaxe.sh: test_expect_success 'usage' '
     @@ t/t7107-reset-pathspec-file.sh: test_expect_success 'error conditions' '
      +	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
       
       	test_must_fail git reset --pathspec-file-nul 2>err &&
     - 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     + 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
      
       ## t/t7500-commit-template-squash-signoff.sh ##
      @@ t/t7500-commit-template-squash-signoff.sh: test_expect_success '--fixup=reword: ignores staged changes' '
     @@ t/t7500-commit-template-squash-signoff.sh: test_expect_success 'amend! commit al
       	test_expect_success "--fixup=reword: incompatible with $1" "
      -		echo 'fatal: reword option of --fixup is mutually exclusive with'\
      -			'--patch/--interactive/--all/--include/--only' >expect &&
     -+		echo 'fatal: reword option of --fixup and'\
     -+			'--patch/--interactive/--all/--include/--only'\
     ++		echo 'fatal: reword option of --fixup and' \
     ++			'--patch/--interactive/--all/--include/--only' \
      +			'cannot be used together' >expect &&
       		test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
       		test_cmp expect actual
     @@ t/t7500-commit-template-squash-signoff.sh: done
      
       ## t/t7526-commit-pathspec-file.sh ##
      @@ t/t7526-commit-pathspec-file.sh: test_expect_success 'error conditions' '
     - 	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
     - 
     - 	test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err &&
     --	test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
     -+	test_i18ngrep -e ".--pathspec-from-file. and .-a. cannot be used together" err &&
     + 	test_i18ngrep -e "options .--pathspec-from-file. and .-a. cannot be used together" err &&
       
       	test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err &&
      -	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
      +	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
       
       	test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err &&
     - 	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
     + 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
Signature · 1 line
gitgitgadget
#44 lore raw

PATCH v3 1/11 i18n: refactor "foo and bar are mutually exclusive"

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use static strings for constant parts of the sentences. They are all turned into "cannot be used together".

---
 builtin/checkout.c             | 2 +-
 builtin/diff-tree.c            | 2 +-
 builtin/fetch.c                | 4 ++--
 builtin/init-db.c              | 2 +-
 builtin/log.c                  | 4 ++--
 builtin/submodule--helper.c    | 4 ++--
 builtin/worktree.c             | 2 +-
 range-diff.c                   | 2 +-
 t/t0001-init.sh                | 2 +-
 t/t2025-checkout-no-overlay.sh | 2 +-
 10 files changed, 13 insertions(+), 13 deletions(-)
builtin/checkout.c +1 -1
index 72beeb49aa9..79014e1cb6c 100644
@@ -1639,7 +1639,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				cb_option, toupper(cb_option));
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
-		die(_("-p and --overlay are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "-p", "--overlay");
 
 	if (opts->checkout_index >= 0 || opts->checkout_worktree >= 0) {
 		if (opts->checkout_index < 0)
builtin/diff-tree.c +1 -1
index f33d30d57bf..0e0ac1f1670 100644
@@ -152,7 +152,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
 	}
 
 	if (read_stdin && merge_base)
-		die(_("--stdin and --merge-base are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--stdin", "--merge-base");
 	if (merge_base && opt->pending.nr != 2)
 		die(_("--merge-base only works with two commits"));
 
builtin/fetch.c +2 -2
index f1fe73a3e0f..2c584c85812 100644
@@ -2028,12 +2028,12 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		if (deepen_relative < 0)
 			die(_("negative depth in --deepen is not supported"));
 		if (depth)
-			die(_("--deepen and --depth are mutually exclusive"));
+			die(_("options '%s' and '%s' cannot be used together"), "--deepen", "--depth");
 		depth = xstrfmt("%d", deepen_relative);
 	}
 	if (unshallow) {
 		if (depth)
-			die(_("--depth and --unshallow cannot be used together"));
+			die(_("options '%s' and '%s' cannot be used together"), "--depth", "--unshallow");
 		else if (!is_repository_shallow(the_repository))
 			die(_("--unshallow on a complete repository does not make sense"));
 		else
builtin/init-db.c +1 -1
index 2167796ff2a..546f9c595e7 100644
@@ -557,7 +557,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
 
 	if (real_git_dir && is_bare_repository_cfg == 1)
-		die(_("--separate-git-dir and --bare are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
 
 	if (real_git_dir && !is_absolute_path(real_git_dir))
 		real_git_dir = real_pathdup(real_git_dir, 1);
builtin/log.c +2 -2
index 93ace0dde7d..fad93ad2fc1 100644
@@ -1943,9 +1943,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		numbered = 0;
 
 	if (numbered && keep_subject)
-		die(_("-n and -k are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "-n", "-k");
 	if (keep_subject && subject_prefix)
-		die(_("--subject-prefix/--rfc and -k are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--subject-prefix/--rfc", "-k");
 	rev.preserve_subject = keep_subject;
 
 	argc = setup_revisions(argc, argv, &rev, &s_r_opt);
builtin/submodule--helper.c +2 -2
index 9b25a508e6a..c5d3fc3817f 100644
@@ -1313,7 +1313,7 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 
 	if (files) {
 		if (cached)
-			die(_("--cached and --files are mutually exclusive"));
+			die(_("options '%s' and '%s' cannot be used together"), "--cached", "--files");
 		diff_cmd = DIFF_FILES;
 	}
 
@@ -2972,7 +2972,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
 		die(_("--branch or --default required"));
 
 	if (opt_branch && opt_default)
-		die(_("--branch and --default are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--branch", "--default");
 
 	if (argc != 1 || !(path = argv[0]))
 		usage_with_options(usage, options);
builtin/worktree.c +1 -1
index a396cfdc64e..9a520485769 100644
@@ -699,7 +699,7 @@ static int list(int ac, const char **av, const char *prefix)
 	if (ac)
 		usage_with_options(worktree_usage, options);
 	else if (verbose && porcelain)
-		die(_("--verbose and --porcelain are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--verbose", "--porcelain");
 	else {
 		struct worktree **worktrees = get_worktrees();
 		int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
range-diff.c +1 -1
index cac89a2f4f2..30a4de5c2d8 100644
@@ -556,7 +556,7 @@ int show_range_diff(const char *range1, const char *range2,
 	struct string_list branch2 = STRING_LIST_INIT_DUP;
 
 	if (range_diff_opts->left_only && range_diff_opts->right_only)
-		res = error(_("--left-only and --right-only are mutually exclusive"));
+		res = error(_("options '%s' and '%s' cannot be used together"), "--left-only", "--right-only");
 
 	if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg))
 		res = error(_("could not parse log for '%s'"), range1);
t/t0001-init.sh +1 -1
index 7603ad2f82b..3235ab4d53c 100755
@@ -331,7 +331,7 @@ test_expect_success 'init with separate gitdir' '
 
 test_expect_success 'explicit bare & --separate-git-dir incompatible' '
 	test_must_fail git init --bare --separate-git-dir goop.git bare.git 2>err &&
-	test_i18ngrep "mutually exclusive" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'implicit bare & --separate-git-dir incompatible' '
t/t2025-checkout-no-overlay.sh +1 -1
index fa9e0987063..8f13341cf8e 100755
@@ -25,7 +25,7 @@ test_expect_success 'checkout --no-overlay removing last file from directory' '
 
 test_expect_success 'checkout -p --overlay is disallowed' '
 	test_must_fail git checkout -p --overlay HEAD 2>actual &&
-	test_i18ngrep "fatal: -p and --overlay are mutually exclusive" actual
+	test_i18ngrep "fatal: options .-p. and .--overlay. cannot be used together" actual
 '
 
 test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
Signature · 1 line
gitgitgadget
#45 lore raw

PATCH v3 2/11 i18n: refactor "%s, %s and %s are mutually exclusive"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use placeholders for constant tokens. The strings are turned into "cannot be used together"

---
 builtin/difftool.c     | 2 +-
 builtin/log.c          | 2 +-
 builtin/worktree.c     | 2 +-
 diff.c                 | 2 +-
 t/t4209-log-pickaxe.sh | 6 +++---
 5 files changed, 7 insertions(+), 7 deletions(-)
builtin/difftool.c +1 -1
index 4ee40fe3a06..c2b049aafc9 100644
@@ -733,7 +733,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 		die(_("--dir-diff is incompatible with --no-index"));
 
 	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("--gui, --tool and --extcmd are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
 
 	if (use_gui_tool)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
builtin/log.c +1 -1
index fad93ad2fc1..705d58110b0 100644
@@ -1979,7 +1979,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		load_display_notes(&rev.notes_opt);
 
 	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("--stdout, --output, and --output-directory are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
 
 	if (use_stdout) {
 		setup_pager();
builtin/worktree.c +1 -1
index 9a520485769..b5ef19b2dda 100644
@@ -503,7 +503,7 @@ static int add(int ac, const char **av, const char *prefix)
 	opts.checkout = 1;
 	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
-		die(_("-b, -B, and --detach are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "-b", "-B", "--detach");
 	if (lock_reason && !keep_locked)
 		die(_("--reason requires --lock"));
 	if (lock_reason)
diff.c +1 -1
index 41076857428..8de1c49763c 100644
@@ -4642,7 +4642,7 @@ void diff_setup_done(struct diff_options *options)
 		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
-		die(_("-G, -S and --find-object are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "-G", "-S", "--find-object");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
 		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
t/t4209-log-pickaxe.sh +3 -3
index 75795d0b492..4f820f8597d 100755
@@ -63,13 +63,13 @@ test_expect_success 'usage' '
 	test_i18ngrep "switch.*requires a value" err &&
 
 	test_expect_code 128 git log -Gregex -Sstring 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log -Gregex --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log -Sstring --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
 	grep "mutually exclusive" err
Signature · 1 line
gitgitgadget
#46 lore raw

Re: [PATCH v3 02/11] i18n: refactor "%s, %s and %s are mutually exclusive"

builtin/log.c int cmd_format_patch(int argc, const char **argv, const char *prefix) · line 1982

Quoted 3 lines · Jean-Noël Avila via GitGitGadget
builtin/log.c +1 -1
 	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("--stdout, --output, and --output-directory are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");

We probably want to preserve the Oxford comma here, and unify the ones that didn't use Oxford comma to use it.

#47 lore raw

Re: [PATCH v3 02/11] i18n: refactor "%s, %s and %s are mutually exclusive"

Quoted 9 lines · On Thursday, 30 December 2021 23:26:42 CET Junio C Hamano wrote:

builtin/log.c int cmd_format_patch(int argc, const char **argv, const char *prefix) · line 1982

Quoted 3 lines · Jean-Noël Avila via GitGitGadget
builtin/log.c +1 -1
 	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("--stdout, --output, and --output-directory are mutually exclusive"));
+		die(_("options '%s', '%s' and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");

We probably want to preserve the Oxford comma here, and unify the ones that didn't use Oxford comma to use it.

Oh. I wasn't even aware of this holy war (https://en.wikipedia.org/wiki/Serial_comma). It would be good to add this style specification for writing our messages and documents.

Will make another pass.

Thanks

#48 lore raw

PATCH v3 3/11 i18n: turn "options are incompatible" into "cannot be used together"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 apply.c                           |  2 +-
 archive.c                         |  2 +-
 builtin/add.c                     |  8 ++++----
 builtin/branch.c                  |  2 +-
 builtin/checkout.c                |  4 ++--
 builtin/clone.c                   |  2 +-
 builtin/commit.c                  |  6 +++---
 builtin/describe.c                |  2 +-
 builtin/difftool.c                |  2 +-
 builtin/fast-export.c             |  2 +-
 builtin/index-pack.c              |  2 +-
 builtin/ls-files.c                |  2 +-
 builtin/merge.c                   |  4 ++--
 builtin/pack-objects.c            |  2 +-
 builtin/push.c                    |  8 ++++----
 builtin/rebase.c                  |  6 +++---
 builtin/repack.c                  |  4 ++--
 builtin/reset.c                   |  4 ++--
 builtin/rev-list.c                |  2 +-
 builtin/show-branch.c             |  4 ++--
 builtin/stash.c                   |  4 ++--
 builtin/tag.c                     |  2 +-
 revision.c                        | 22 +++++++++++-----------
 t/t2026-checkout-pathspec-file.sh |  4 ++--
 t/t2072-restore-pathspec-file.sh  |  2 +-
 t/t3431-rebase-fork-point.sh      |  2 +-
 t/t3704-add-pathspec-file.sh      |  6 +++---
 t/t3909-stash-pathspec-file.sh    |  2 +-
 t/t5606-clone-options.sh          |  2 +-
 t/t7107-reset-pathspec-file.sh    |  2 +-
 t/t7526-commit-pathspec-file.sh   |  6 +++---
 31 files changed, 62 insertions(+), 62 deletions(-)
apply.c +1 -1
index fed195250b6..000f2a9b1b3 100644
@@ -133,7 +133,7 @@ int check_apply_state(struct apply_state *state, int force_apply)
 	int is_not_gitdir = !startup_info->have_repository;
 
 	if (state->apply_with_reject && state->threeway)
-		return error(_("--reject and --3way cannot be used together."));
+		return error(_("options '%s' and '%s' cannot be used together"),"--reject",  "--3way");
 	if (state->threeway) {
 		if (is_not_gitdir)
 			return error(_("--3way outside a repository"));
archive.c +1 -1
index a3bbb091256..e85ba169088 100644
@@ -581,7 +581,7 @@ static int parse_archive_args(int argc, const char **argv,
 	if (output)
 		die(_("Unexpected option --output"));
 	if (is_remote && args->extra_files.nr)
-		die(_("Options --add-file and --remote cannot be used together"));
+		die(_("options '%s' and '%s' cannot be used together"), "--add-file", "--remote");
 
 	if (!base)
 		base = "";
builtin/add.c +4 -4
index a010b2c325f..4b2754345ad 100644
@@ -507,9 +507,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		add_interactive = 1;
 	if (add_interactive) {
 		if (show_only)
-			die(_("--dry-run is incompatible with --interactive/--patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
 		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
 		exit(interactive_add(argv + 1, prefix, patch_interactive));
 	}
 	if (legacy_stash_p) {
@@ -526,7 +526,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (edit_interactive) {
 		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --edit"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--edit");
 		return(edit_patch(argc, argv, prefix));
 	}
 	argc--;
@@ -538,7 +538,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		addremove = 0; /* "-u" was given but not "-A" */
 
 	if (addremove && take_worktree_changes)
-		die(_("-A and -u are mutually incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "-A", "-u");
 
 	if (!show_only && ignore_missing)
 		die(_("Option --ignore-missing can only be used together with --dry-run"));
builtin/branch.c +1 -1
index 6c8b0fcc11f..0e93865371c 100644
@@ -722,7 +722,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	finalize_colopts(&colopts, -1);
 	if (filter.verbose) {
 		if (explicitly_enable_column(colopts))
-			die(_("--column and --verbose are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--column", "--verbose");
 		colopts = 0;
 	}
 
builtin/checkout.c +2 -2
index 79014e1cb6c..2d7bfbd0f1a 100644
@@ -1749,10 +1749,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
 
 		if (opts->force_detach)
-			die(_("--pathspec-from-file is incompatible with --detach"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file",  "--detach");
 
 		if (opts->patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		parse_pathspec_file(&opts->pathspec, 0,
 				    0,
builtin/clone.c +1 -1
index fb377b27657..13bdbe14b2f 100644
@@ -903,7 +903,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 			die(_("--bare and --origin %s options are incompatible."),
 			    option_origin);
 		if (real_git_dir)
-			die(_("--bare and --separate-git-dir are incompatible."));
+			die(_("options '%s' and '%s' cannot be used together"), "--bare", "--separate-git-dir");
 		option_no_checkout = 1;
 	}
 
builtin/commit.c +3 -3
index 883c16256c8..5c1aaa42131 100644
@@ -355,10 +355,10 @@ static const char *prepare_index(const char **argv, const char *prefix,
 
 	if (pathspec_from_file) {
 		if (interactive)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
 
 		if (all)
-			die(_("--pathspec-from-file with -a does not make sense"));
+			die(_("options '%s' and '%s' cannot be used together"),"--pathspec-from-file", "-a");
 
 		if (pathspec.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
@@ -1193,7 +1193,7 @@ static void finalize_deferred_config(struct wt_status *s)
 		    status_format == STATUS_FORMAT_UNSPECIFIED)
 			status_format = STATUS_FORMAT_PORCELAIN;
 		else if (status_format == STATUS_FORMAT_LONG)
-			die(_("--long and -z are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--long", "-z");
 	}
 
 	if (use_deferred_config && status_format == STATUS_FORMAT_UNSPECIFIED)
builtin/describe.c +1 -1
index e912ba50d7b..fd5ba1fc604 100644
@@ -590,7 +590,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 	save_commit_buffer = 0;
 
 	if (longformat && abbrev == 0)
-		die(_("--long is incompatible with --abbrev=0"));
+		die(_("options '%s' and '%s' cannot be used together"), "--long", "--abbrev=0");
 
 	if (contains) {
 		struct string_list_item *item;
builtin/difftool.c +1 -1
index c2b049aafc9..f5db9bcd7b0 100644
@@ -730,7 +730,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 		setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
 		setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
 	} else if (dir_diff)
-		die(_("--dir-diff is incompatible with --no-index"));
+		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");
builtin/fast-export.c +1 -1
index 8e2caf72819..1f8fe7b3ac1 100644
@@ -1269,7 +1269,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		printf("feature done\n");
 
 	if (import_filename && import_filename_if_exists)
-		die(_("Cannot pass both --import-marks and --import-marks-if-exists"));
+		die(_("options '%s' and '%s' cannot be used together"), "--import-marks", "--import-marks-if-exists");
 	if (import_filename)
 		import_marks(import_filename, 0);
 	else if (import_filename_if_exists)
builtin/index-pack.c +1 -1
index c23d01de7dc..30ce2ac746d 100644
@@ -1849,7 +1849,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (from_stdin && !startup_info->have_repository)
 		die(_("--stdin requires a git repository"));
 	if (from_stdin && hash_algo)
-		die(_("--object-format cannot be used with --stdin"));
+		die(_("options '%s' and '%s' cannot be used together"), "--object-format", "--stdin");
 	if (!index_name && pack_name)
 		index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
 
builtin/ls-files.c +1 -1
index 031fef1bcaa..9c80cdae951 100644
@@ -767,7 +767,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		 * would not make any sense with this option.
 		 */
 		if (show_stage || show_unmerged)
-			die("ls-files --with-tree is incompatible with -s or -u");
+			die(_("options '%s' and '%s' cannot be used together"), "ls-files --with-tree", "-s/-u");
 		overlay_tree_on_index(the_repository->index, with_tree, max_prefix);
 	}
 
builtin/merge.c +2 -2
index 5f0476b0b76..6db961e9d34 100644
@@ -1396,9 +1396,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 
 	if (squash) {
 		if (fast_forward == FF_NO)
-			die(_("You cannot combine --squash with --no-ff."));
+			die(_("options '%s' and '%s' cannot be used together"), "--squash", "--no-ff.");
 		if (option_commit > 0)
-			die(_("You cannot combine --squash with --commit."));
+			die(_("options '%s' and '%s' cannot be used together"), "--squash", "--commit.");
 		/*
 		 * squash can now silently disable option_commit - this is not
 		 * a problem as it is only overriding the default, not a user
builtin/pack-objects.c +1 -1
index b36ed828d8d..ba2006f2212 100644
@@ -4070,7 +4070,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 		die(_("--thin cannot be used to build an indexable pack"));
 
 	if (keep_unreachable && unpack_unreachable)
-		die(_("--keep-unreachable and --unpack-unreachable are incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "--unpack-unreachable");
 	if (!rev_list_all || !rev_list_reflog || !rev_list_index)
 		unpack_unreachable_expiration = 0;
 
builtin/push.c +4 -4
index 4b026ce6c6a..359db90321c 100644
@@ -589,7 +589,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 	set_push_cert_flags(&flags, push_cert);
 
 	if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
-		die(_("--delete is incompatible with --all, --mirror and --tags"));
+		die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--mirror/--tags");
 	if (deleterefs && argc < 2)
 		die(_("--delete doesn't make sense without any refs"));
 
@@ -627,18 +627,18 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 
 	if (flags & TRANSPORT_PUSH_ALL) {
 		if (tags)
-			die(_("--all and --tags are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--all", "--tags");
 		if (argc >= 2)
 			die(_("--all can't be combined with refspecs"));
 	}
 	if (flags & TRANSPORT_PUSH_MIRROR) {
 		if (tags)
-			die(_("--mirror and --tags are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--mirror", "--tags");
 		if (argc >= 2)
 			die(_("--mirror can't be combined with refspecs"));
 	}
 	if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
-		die(_("--all and --mirror are incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "--all", "--mirror");
 
 	if (!is_empty_cas(&cas) && (flags & TRANSPORT_PUSH_FORCE_IF_INCLUDES))
 		cas.use_force_if_includes = 1;
builtin/rebase.c +3 -3
index 34b4744e5f3..ed326b8aecc 100644
@@ -1190,13 +1190,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
 	if (keep_base) {
 		if (options.onto_name)
-			die(_("cannot combine '--keep-base' with '--onto'"));
+			die(_("options '%s' and '%s' cannot be used together"),"--keep-base", "--onto");
 		if (options.root)
-			die(_("cannot combine '--keep-base' with '--root'"));
+			die(_("options '%s' and '%s' cannot be used together"),"--keep-base", "--root");
 	}
 
 	if (options.root && options.fork_point > 0)
-		die(_("cannot combine '--root' with '--fork-point'"));
+		die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
 
 	if (action != ACTION_NONE && !in_progress)
 		die(_("No rebase in progress?"));
builtin/repack.c +2 -2
index 9b0be6a6ab3..f13bca4719e 100644
@@ -681,7 +681,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	if (keep_unreachable &&
 	    (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
-		die(_("--keep-unreachable and -A are incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "-A");
 
 	if (write_bitmaps < 0) {
 		if (!write_midx &&
@@ -712,7 +712,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	if (geometric_factor) {
 		if (pack_everything)
-			die(_("--geometric is incompatible with -A, -a"));
+			die(_("options '%s' and '%s' cannot be used together"),"--geometric", "-A/-a");
 		init_pack_geometry(&geometry);
 		split_pack_geometry(geometry, geometric_factor);
 	}
builtin/reset.c +2 -2
index b1ff699b43a..248998fd6fa 100644
@@ -423,7 +423,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (pathspec.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
@@ -459,7 +459,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	if (patch_mode) {
 		if (reset_type != NONE)
-			die(_("--patch is incompatible with --{hard,mixed,soft}"));
+			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
 		return run_add_interactive(rev, "--patch=reset", &pathspec);
 	}
builtin/rev-list.c +1 -1
index 36cb909ebaa..de60cbdbc9d 100644
@@ -538,7 +538,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 		const char *arg = argv[i];
 		if (skip_prefix(arg, "--missing=", &arg)) {
 			if (revs.exclude_promisor_objects)
-				die(_("cannot combine --exclude-promisor-objects and --missing"));
+				die(_("options '%s' and '%s' cannot be used together"),"--exclude-promisor-objects", "--missing");
 			if (parse_missing_action_value(arg))
 				break;
 		}
builtin/show-branch.c +2 -2
index f1e8318592c..e12c5e80e3e 100644
@@ -707,8 +707,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 			 *
 			 * Also --all and --remotes do not make sense either.
 			 */
-			die(_("--reflog is incompatible with --all, --remotes, "
-			      "--independent or --merge-base"));
+			die(_("options '%s' and '%s' cannot be used together"), "--reflog",
+				"--all/--remotes/--independent/--merge-base");
 	}
 
 	/* If nothing is specified, show all branches by default */
builtin/stash.c +2 -2
index 18c812bbe03..4d793bd0b52 100644
@@ -1700,10 +1700,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 
 	if (pathspec_from_file) {
 		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (only_staged)
-			die(_("--pathspec-from-file is incompatible with --staged"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--staged");
 
 		if (ps.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
builtin/tag.c +1 -1
index 41863c5ab77..6f7cd0e3ef5 100644
@@ -522,7 +522,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	finalize_colopts(&colopts, -1);
 	if (cmdmode == 'l' && filter.lines != -1) {
 		if (explicitly_enable_column(colopts))
-			die(_("--column and -n are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--column", "-n");
 		colopts = 0;
 	}
 	sorting = ref_sorting_options(&sorting_options);
revision.c +11 -11
index 5390a479b30..fe445dd5d45 100644
@@ -2300,11 +2300,11 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->left_only = 1;
 	} else if (!strcmp(arg, "--right-only")) {
 		if (revs->left_only)
-			die("--right-only is incompatible with --left-only");
+			die(_("options '%s' and '%s' cannot be used together"), "--right-only", "--left-only");
 		revs->right_only = 1;
 	} else if (!strcmp(arg, "--cherry")) {
 		if (revs->left_only)
-			die("--cherry is incompatible with --left-only");
+			die(_("options '%s' and '%s' cannot be used together"), "--cherry", "--left-only");
 		revs->cherry_mark = 1;
 		revs->right_only = 1;
 		revs->max_parents = 1;
@@ -2313,12 +2313,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->count = 1;
 	} else if (!strcmp(arg, "--cherry-mark")) {
 		if (revs->cherry_pick)
-			die("--cherry-mark is incompatible with --cherry-pick");
+			die(_("options '%s' and '%s' cannot be used together"), "--cherry-mark", "--cherry-pick");
 		revs->cherry_mark = 1;
 		revs->limited = 1; /* needs limit_list() */
 	} else if (!strcmp(arg, "--cherry-pick")) {
 		if (revs->cherry_mark)
-			die("--cherry-pick is incompatible with --cherry-mark");
+			die(_("options '%s' and '%s' cannot be used together"), "--cherry-pick", "--cherry-mark");
 		revs->cherry_pick = 1;
 		revs->limited = 1;
 	} else if (!strcmp(arg, "--objects")) {
@@ -2524,7 +2524,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		return opts;
 	}
 	if (revs->graph && revs->track_linear)
-		die("--show-linear-break and --graph are incompatible");
+		die(_("options '%s' and '%s' cannot be used together"), "--show-linear-break", "--graph");
 
 	return 1;
 }
@@ -2867,24 +2867,24 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	compile_grep_patterns(&revs->grep_filter);
 
 	if (revs->reverse && revs->reflog_info)
-		die("cannot combine --reverse with --walk-reflogs");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--walk-reflogs");
 	if (revs->reflog_info && revs->limited)
 		die("cannot combine --walk-reflogs with history-limiting options");
 	if (revs->rewrite_parents && revs->children.name)
-		die("cannot combine --parents and --children");
+		die(_("options '%s' and '%s' cannot be used together"), "--parents", "--children");
 
 	/*
 	 * Limitations on the graph functionality
 	 */
 	if (revs->reverse && revs->graph)
-		die("cannot combine --reverse with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--graph");
 
 	if (revs->reflog_info && revs->graph)
-		die("cannot combine --walk-reflogs with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--walk-reflogs", "--graph");
 	if (revs->no_walk && revs->graph)
-		die("cannot combine --no-walk with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
-		die("cannot use --grep-reflog without --walk-reflogs");
+		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");
 
 	if (revs->line_level_traverse &&
 	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
t/t2026-checkout-pathspec-file.sh +2 -2
index 9db11f86dd6..fbe26de2f90 100755
@@ -149,10 +149,10 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git checkout --pathspec-from-file=list --detach 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --detach" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--detach. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t2072-restore-pathspec-file.sh +1 -1
index b48345bf95f..ad1fc0ed071 100755
@@ -152,7 +152,7 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git restore --pathspec-from-file=list --patch --source=HEAD^1 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t3431-rebase-fork-point.sh +1 -1
index 4c98d99e7e8..1d0b15380ed 100755
@@ -83,7 +83,7 @@ test_expect_success 'git rebase --fork-point with ambigous refname' '
 
 test_expect_success '--fork-point and --root both given' '
 	test_must_fail git rebase --fork-point --root 2>err &&
-	test_i18ngrep "cannot combine" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'rebase.forkPoint set to false' '
t/t3704-add-pathspec-file.sh +3 -3
index 5d5164d1fc6..7e17ae80229 100755
@@ -138,13 +138,13 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git add --pathspec-from-file=list --interactive 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list --edit 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --edit" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t3909-stash-pathspec-file.sh +1 -1
index 55e050cfd4d..aae2b25f766 100755
@@ -88,7 +88,7 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git stash push --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t5606-clone-options.sh +1 -1
index d822153e4d2..3af3577af0b 100755
@@ -54,7 +54,7 @@ test_expect_success 'disallows --bare with --separate-git-dir' '
 
 	test_must_fail git clone --bare --separate-git-dir dot-git-destiation parent clone-bare-sgd 2>err &&
 	test_debug "cat err" &&
-	test_i18ngrep -e "--bare and --separate-git-dir are incompatible" err
+	test_i18ngrep -e "options .--bare. and .--separate-git-dir. cannot be used together" err
 
 '
 
t/t7107-reset-pathspec-file.sh +1 -1
index 15ccb14f7e2..b211fbc0a52 100755
@@ -160,7 +160,7 @@ test_expect_success 'error conditions' '
 	git rm fileA.t &&
 
 	test_must_fail git reset --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t7526-commit-pathspec-file.sh +3 -3
index dca62fc48e5..574cf30285c 100755
@@ -141,13 +141,13 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git commit --pathspec-from-file=list --interactive -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --patch -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .-a. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
Signature · 1 line
gitgitgadget
#49 lore raw

Re: [PATCH v3 03/11] i18n: turn "options are incompatible" into "cannot be used together"

Am 29.12.21 um 19:54 schrieb Jean-Noël Avila via GitGitGadget:

Quoted 18 lines
revision.c +3 -3
@@ -2867,24 +2867,24 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	compile_grep_patterns(&revs->grep_filter);
 
 	if (revs->reverse && revs->reflog_info)
-		die("cannot combine --reverse with --walk-reflogs");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--walk-reflogs");
 	if (revs->reflog_info && revs->limited)
 		die("cannot combine --walk-reflogs with history-limiting options");
 	if (revs->rewrite_parents && revs->children.name)
-		die("cannot combine --parents and --children");
+		die(_("options '%s' and '%s' cannot be used together"), "--parents", "--children");
 
 	/*
 	 * Limitations on the graph functionality
 	 */
 	if (revs->reverse && revs->graph)
-		die("cannot combine --reverse with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--graph");

revision.c int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s · line 2887

Quoted 10 lines
revision.c +3 -3
 
 	if (revs->reflog_info && revs->graph)
-		die("cannot combine --walk-reflogs with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--walk-reflogs", "--graph");
 	if (revs->no_walk && revs->graph)
-		die("cannot combine --no-walk with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
-		die("cannot use --grep-reflog without --walk-reflogs");
+		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");

This last transformation does not fit the topic of this patch. It should go into patch 6/11, I think.

revision.c int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s · line 2890

Quoted 3 lines
revision.c +0 -0
 	if (revs->line_level_traverse &&
 	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))

-- Hannes

#50 lore raw

Re: [PATCH v3 03/11] i18n: turn "options are incompatible" into "cannot be used together"

Quoted 20 lines · On Wednesday, 29 December 2021 20:36:59 CET Johannes Sixt wrote:

Am 29.12.21 um 19:54 schrieb Jean-Noël Avila via GitGitGadget:

Quoted 19 lines
revision.c +3 -3
@@ -2867,24 +2867,24 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	compile_grep_patterns(&revs->grep_filter);
 
 	if (revs->reverse && revs->reflog_info)
-		die("cannot combine --reverse with --walk-reflogs");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--walk-reflogs");
 	if (revs->reflog_info && revs->limited)
 		die("cannot combine --walk-reflogs with history-limiting options");
 	if (revs->rewrite_parents && revs->children.name)
-		die("cannot combine --parents and --children");
+		die(_("options '%s' and '%s' cannot be used together"), "--parents", "--children");
 
 	/*
 	 * Limitations on the graph functionality
 	 */
 	if (revs->reverse && revs->graph)
-		die("cannot combine --reverse with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--graph");
 
Quoted 13 lines

revision.c int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s · line 2887

Quoted 9 lines
revision.c +3 -3
 	if (revs->reflog_info && revs->graph)
-		die("cannot combine --walk-reflogs with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--walk-reflogs", "--graph");
 	if (revs->no_walk && revs->graph)
-		die("cannot combine --no-walk with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
-		die("cannot use --grep-reflog without --walk-reflogs");
+		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");

This last transformation does not fit the topic of this patch. It should go into patch 6/11, I think.

True! Will reroll after checking again.

JN

#51 lore raw

Re: [PATCH v3 03/11] i18n: turn "options are incompatible" into "cannot be used together"

Quoted 9 lines · Jean-Noël AVILA
Quoted 7 lines

revision.c int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s · line 2887

Quoted 3 lines
revision.c +1 -1
 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
-		die("cannot use --grep-reflog without --walk-reflogs");
+		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");

This last transformation does not fit the topic of this patch. It should go into patch 6/11, I think.

True! Will reroll after checking again.

Also, it lacks single-quote-pair around %s's; intended?

#52 lore raw

PATCH v3 4/11 i18n: standardize "cannot open" and "cannot read"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 archive.c       | 4 ++--
 builtin/fetch.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
archive.c +2 -2
index e85ba169088..78d35467008 100644
@@ -185,7 +185,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
 
 	buffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);
 	if (!buffer)
-		return error(_("cannot read %s"), oid_to_hex(oid));
+		return error(_("cannot read '%s'"), oid_to_hex(oid));
 	err = write_entry(args, oid, path.buf, path.len, mode, buffer, size);
 	free(buffer);
 	return err;
@@ -338,7 +338,7 @@ int write_archive_entries(struct archiver_args *args,
 
 		strbuf_reset(&content);
 		if (strbuf_read_file(&content, path, info->stat.st_size) < 0)
-			err = error_errno(_("could not read '%s'"), path);
+			err = error_errno(_("cannot read '%s'"), path);
 		else
 			err = write_entry(args, &fake_oid, path_in_archive.buf,
 					  path_in_archive.len,
builtin/fetch.c +2 -2
index 2c584c85812..c0855c363fd 100644
@@ -996,7 +996,7 @@ static int open_fetch_head(struct fetch_head *fetch_head)
 	if (write_fetch_head) {
 		fetch_head->fp = fopen(filename, "a");
 		if (!fetch_head->fp)
-			return error_errno(_("cannot open %s"), filename);
+			return error_errno(_("cannot open '%s'"), filename);
 		strbuf_init(&fetch_head->buf, 0);
 	} else {
 		fetch_head->fp = NULL;
@@ -1408,7 +1408,7 @@ static int truncate_fetch_head(void)
 	FILE *fp = fopen_for_writing(filename);
 
 	if (!fp)
-		return error_errno(_("cannot open %s"), filename);
+		return error_errno(_("cannot open '%s'"), filename);
 	fclose(fp);
 	return 0;
 }
Signature · 1 line
gitgitgadget
#53 lore raw

PATCH v3 5/11 i18n: tag.c factorize i18n strings

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
builtin/tag.c +10 -7
index 6f7cd0e3ef5..c8fcb552ef1 100644
@@ -483,6 +483,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 	int ret = 0;
+	const char *only_in_list = NULL;
 
 	setup_ref_filter_porcelain_msg();
 
@@ -542,13 +543,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
-	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
-	if (filter.no_commit)
-		die(_("--no-contains option is only allowed in list mode"));
-	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		only_in_list = "-n";
+	else if (filter.with_commit)
+		only_in_list = "--contains";
+	else if (filter.no_commit)
+		only_in_list = "--no-contains";
+	else if (filter.points_at.nr)
+		only_in_list = "--points-at";
+	if (only_in_list)
+		die(_("the '%s' option is only allowed in list mode"), only_in_list);
 	if (filter.reachable_from || filter.unreachable_from)
 		die(_("--merged and --no-merged options are only allowed in list mode"));
 	if (cmdmode == 'd') {
Signature · 1 line
gitgitgadget
#54 lore raw

Re: [PATCH v3 05/11] i18n: tag.c factorize i18n strings

Am 29.12.21 um 19:55 schrieb Jean-Noël Avila via GitGitGadget:

Quoted 31 lines

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
builtin/tag.c +2 -7
index 6f7cd0e3ef5..c8fcb552ef1 100644
@@ -483,6 +483,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 	int ret = 0;
+	const char *only_in_list = NULL;
 
 	setup_ref_filter_porcelain_msg();
 
@@ -542,13 +543,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
-	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
-	if (filter.no_commit)
-		die(_("--no-contains option is only allowed in list mode"));
-	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		only_in_list = "-n";

builtin/tag.c int cmd_tag(int argc, const char **argv, const char *prefix) · line 556

Quoted 10 lines
builtin/tag.c +8 -0
+	else if (filter.with_commit)
+		only_in_list = "--contains";
+	else if (filter.no_commit)
+		only_in_list = "--no-contains";
+	else if (filter.points_at.nr)
+		only_in_list = "--points-at";
+	if (only_in_list)
+		die(_("the '%s' option is only allowed in list mode"), only_in_list);
 	if (filter.reachable_from || filter.unreachable_from)
 		die(_("--merged and --no-merged options are only allowed in list mode"));

Shouldn't these two be changed as well?

Quoted 1 line
builtin/tag.c +0 -0
 	if (cmdmode == 'd') {
#55 lore raw

PATCH v3 6/11 i18n: factorize "--foo requires --bar" and the like

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

They are all replaced by "the option '%s' requires '%s'", which is a new string but replaces 17 previous unique strings.

---
 archive.c                         | 2 +-
 builtin/add.c                     | 4 ++--
 builtin/checkout.c                | 2 +-
 builtin/commit.c                  | 2 +-
 builtin/fast-export.c             | 2 +-
 builtin/index-pack.c              | 2 +-
 builtin/log.c                     | 2 +-
 builtin/reset.c                   | 4 ++--
 builtin/rm.c                      | 2 +-
 builtin/stash.c                   | 2 +-
 builtin/worktree.c                | 2 +-
 fetch-pack.c                      | 2 +-
 http-fetch.c                      | 4 ++--
 revision.c                        | 2 +-
 t/t2026-checkout-pathspec-file.sh | 2 +-
 t/t2072-restore-pathspec-file.sh  | 2 +-
 t/t3601-rm-pathspec-file.sh       | 2 +-
 t/t3704-add-pathspec-file.sh      | 2 +-
 t/t3909-stash-pathspec-file.sh    | 2 +-
 t/t7107-reset-pathspec-file.sh    | 2 +-
 t/t7526-commit-pathspec-file.sh   | 2 +-
 21 files changed, 24 insertions(+), 24 deletions(-)
archive.c +1 -1
index 78d35467008..d571249cf39 100644
@@ -577,7 +577,7 @@ static int parse_archive_args(int argc, const char **argv,
 	if (remote)
 		die(_("Unexpected option --remote"));
 	if (exec)
-		die(_("Option --exec can only be used together with --remote"));
+		die(_("the option '%s' requires '%s'"), "--exec", "--remote");
 	if (output)
 		die(_("Unexpected option --output"));
 	if (is_remote && args->extra_files.nr)
builtin/add.c +2 -2
index 4b2754345ad..067ec53d69f 100644
@@ -541,7 +541,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		die(_("options '%s' and '%s' cannot be used together"), "-A", "-u");
 
 	if (!show_only && ignore_missing)
-		die(_("Option --ignore-missing can only be used together with --dry-run"));
+		die(_("the option '%s' requires '%s'"), "--ignore-missing", "--dry-run");
 
 	if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
 			  chmod_arg[1] != 'x' || chmod_arg[2]))
@@ -573,7 +573,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_SYMLINK_LEADING_PATH,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (require_pathspec && pathspec.nr == 0) {
builtin/checkout.c +1 -1
index 2d7bfbd0f1a..bc219317ff2 100644
@@ -1758,7 +1758,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				    0,
 				    prefix, opts->pathspec_from_file, opts->pathspec_file_nul);
 	} else if (opts->pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	opts->pathspec.recursive = 1;
builtin/commit.c +1 -1
index 5c1aaa42131..91f685c5e71 100644
@@ -367,7 +367,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 				    PATHSPEC_PREFER_FULL,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (!pathspec.nr && (also || (only && !allow_empty &&
builtin/fast-export.c +1 -1
index 1f8fe7b3ac1..f4d9aa1e8d1 100644
@@ -1254,7 +1254,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		usage_with_options (fast_export_usage, options);
 
 	if (anonymized_seeds.cmpfn && !anonymize)
-		die(_("--anonymize-map without --anonymize does not make sense"));
+		die(_("the option '%s' requires '%s'"), "--anonymize-map", "--anonymize");
 
 	if (refspecs_list.nr) {
 		int i;
builtin/index-pack.c +1 -1
index 30ce2ac746d..3c2e6aee3cc 100644
@@ -1845,7 +1845,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (!pack_name && !from_stdin)
 		usage(index_pack_usage);
 	if (fix_thin_pack && !from_stdin)
-		die(_("--fix-thin cannot be used without --stdin"));
+		die(_("the option '%s' requires '%s'"), "--fix-thin", "--stdin");
 	if (from_stdin && !startup_info->have_repository)
 		die(_("--stdin requires a git repository"));
 	if (from_stdin && hash_algo)
builtin/log.c +1 -1
index 705d58110b0..f88d03863a3 100644
@@ -2112,7 +2112,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	if (creation_factor < 0)
 		creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
 	else if (!rdiff_prev)
-		die(_("--creation-factor requires --range-diff"));
+		die(_("the option '%s' requires '%s'"), "--creation-factor", "--range-diff");
 
 	if (rdiff_prev) {
 		if (!cover_letter && total != 1)
builtin/reset.c +2 -2
index 248998fd6fa..4779e70dfbe 100644
@@ -432,7 +432,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_PREFER_FULL,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
@@ -490,7 +490,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		    _(reset_type_names[reset_type]));
 
 	if (intent_to_add && reset_type != MIXED)
-		die(_("-N can only be used with --mixed"));
+		die(_("the option '%s' requires '%s'"), "-N", "--mixed");
 
 	prepare_repo_settings(the_repository);
 	the_repository->settings.command_requires_full_index = 0;
builtin/rm.c +1 -1
index 3d0967cdc11..cfdf24cf49a 100644
@@ -278,7 +278,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_PREFER_CWD,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (!pathspec.nr)
builtin/stash.c +1 -1
index 4d793bd0b52..3e3743fd5a3 100644
@@ -1712,7 +1712,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
builtin/worktree.c +1 -1
index b5ef19b2dda..d00078720d1 100644
@@ -505,7 +505,7 @@ static int add(int ac, const char **av, const char *prefix)
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
 		die(_("options '%s', '%s' and '%s' cannot be used together"), "-b", "-B", "--detach");
 	if (lock_reason && !keep_locked)
-		die(_("--reason requires --lock"));
+		die(_("the option '%s' requires '%s'"), "--reason", "--lock");
 	if (lock_reason)
 		opts.keep_locked = lock_reason;
 	else if (keep_locked)
fetch-pack.c +1 -1
index 34987a2c30d..dd6ec449f2d 100644
@@ -297,7 +297,7 @@ static int find_common(struct fetch_negotiator *negotiator,
 	struct packet_reader reader;
 
 	if (args->stateless_rpc && multi_ack == 1)
-		die(_("--stateless-rpc requires multi_ack_detailed"));
+		die(_("the option '%s' requires '%s'"), "--stateless-rpc", "multi_ack_detailed");
 
 	packet_reader_init(&reader, fd[0], NULL, 0,
 			   PACKET_READ_CHOMP_NEWLINE |
http-fetch.c +2 -2
index c7c7d391ac5..58b394cd47f 100644
@@ -141,7 +141,7 @@ int cmd_main(int argc, const char **argv)
 
 	if (packfile) {
 		if (!index_pack_args.nr)
-			die(_("--packfile requires --index-pack-args"));
+			die(_("the option '%s' requires '%s'"), "--packfile", "--index-pack-args");
 
 		fetch_single_packfile(&packfile_hash, argv[arg],
 				      index_pack_args.v);
@@ -150,7 +150,7 @@ int cmd_main(int argc, const char **argv)
 	}
 
 	if (index_pack_args.nr)
-		die(_("--index-pack-args can only be used with --packfile"));
+		die(_("the option '%s' requires '%s'"), "--index-pack-args", "--packfile");
 
 	if (commits_on_stdin) {
 		commits = walker_targets_stdin(&commit_id, &write_ref);
revision.c +1 -1
index fe445dd5d45..13ccc6829f1 100644
@@ -2884,7 +2884,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	if (revs->no_walk && revs->graph)
 		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
-		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");
+		die(_("the option '%s' requires '%s'"), "--grep-reflog", "--walk-reflogs");
 
 	if (revs->line_level_traverse &&
 	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
t/t2026-checkout-pathspec-file.sh +1 -1
index fbe26de2f90..9e6b17e2d23 100755
@@ -158,7 +158,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git checkout --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
 '
 
 test_done
t/t2072-restore-pathspec-file.sh +1 -1
index ad1fc0ed071..af67ca7d52b 100755
@@ -158,7 +158,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	test_must_fail git restore --pathspec-from-file=empty_list --source=HEAD^1 2>err &&
 	test_i18ngrep -e "you must specify path(s) to restore" err
t/t3601-rm-pathspec-file.sh +1 -1
index b2a8db69afc..bbed67f8ef5 100755
@@ -70,7 +70,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git rm --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	>empty_list &&
 	test_must_fail git rm --pathspec-from-file=empty_list 2>err &&
t/t3704-add-pathspec-file.sh +1 -1
index 7e17ae80229..47ad96bf661 100755
@@ -150,7 +150,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git add --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	# This case succeeds, but still prints to stderr
 	git add --pathspec-from-file=empty_list 2>err &&
t/t3909-stash-pathspec-file.sh +1 -1
index aae2b25f766..fde4625cfcb 100755
@@ -94,7 +94,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git stash push --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
 '
 
 test_done
t/t7107-reset-pathspec-file.sh +1 -1
index b211fbc0a52..f753e3229e2 100755
@@ -166,7 +166,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git reset --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	test_must_fail git reset --soft --pathspec-from-file=list 2>err &&
 	test_i18ngrep -e "fatal: Cannot do soft reset with paths" err &&
t/t7526-commit-pathspec-file.sh +1 -1
index 574cf30285c..ea69e3a6ad1 100755
@@ -153,7 +153,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	test_must_fail git commit --pathspec-from-file=empty_list --include -m "Commit" 2>err &&
 	test_i18ngrep -e "No paths with --include/--only does not make sense." err &&
Signature · 1 line
gitgitgadget
#56 lore raw

PATCH v3 7/11 i18n: factorize "no directory given for --foo"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 git.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
git.c +3 -3
index 7edafd8ecff..7e361769ff6 100644
@@ -185,7 +185,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--git-dir")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for --git-dir\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "--git-dir");
 				usage(git_usage_string);
 			}
 			setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
@@ -213,7 +213,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--work-tree")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for --work-tree\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "--work-tree");
 				usage(git_usage_string);
 			}
 			setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
@@ -297,7 +297,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "-C")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for -C\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "-C");
 				usage(git_usage_string);
 			}
 			if ((*argv)[1][0]) {
Signature · 1 line
gitgitgadget
#57 lore raw

Re: [PATCH v3 07/11] i18n: factorize "no directory given for --foo"

git.c static int handle_options(const char ***argv, int *argc, int *envchanged) · line 191

Quoted 7 lines · Jean-Noël Avila via GitGitGadget
git.c +1 -1
 		} else if (!strcmp(cmd, "--git-dir")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for --git-dir\n" ));
+				fprintf(stderr, _("no directory given for %s\n" ), "--git-dir");
 				usage(git_usage_string);
 			}
 			setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);

None of the originals of these three uses it, but I wonder if we want a single-quote-pair around %s.

#58 lore raw

PATCH v3 8/11 i18n: refactor "unrecognized %(foo) argument" strings

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 ref-filter.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
ref-filter.c +7 -7
index 7260fce31d0..adbcc680812 100644
@@ -341,7 +341,7 @@ static int objectsize_atom_parser(struct ref_format *format, struct used_atom *a
 		else
 			oi.info.disk_sizep = &oi.disk_size;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(objectsize) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "objectsize", arg);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ static int subject_atom_parser(struct ref_format *format, struct used_atom *atom
 	else if (!strcmp(arg, "sanitize"))
 		atom->u.contents.option = C_SUB_SANITIZE;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(subject) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "subject", arg);
 	return 0;
 }
 
@@ -428,7 +428,7 @@ static int contents_atom_parser(struct ref_format *format, struct used_atom *ato
 		if (strtoul_ui(arg, 10, &atom->u.contents.nlines))
 			return strbuf_addf_ret(err, -1, _("positive value expected contents:lines=%s"), arg);
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(contents) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "contents", arg);
 	return 0;
 }
 
@@ -440,7 +440,7 @@ static int raw_atom_parser(struct ref_format *format, struct used_atom *atom,
 	else if (!strcmp(arg, "size"))
 		atom->u.raw_data.option = RAW_LENGTH;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(raw) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "raw", arg);
 	return 0;
 }
 
@@ -459,7 +459,7 @@ static int oid_atom_parser(struct ref_format *format, struct used_atom *atom,
 		if (atom->u.oid.length < MINIMUM_ABBREV)
 			atom->u.oid.length = MINIMUM_ABBREV;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized argument '%s' in %%(%s)"), arg, atom->name);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), atom->name, arg);
 	return 0;
 }
 
@@ -531,7 +531,7 @@ static int align_atom_parser(struct ref_format *format, struct used_atom *atom,
 		else if ((position = parse_align_position(s)) >= 0)
 			align->position = position;
 		else {
-			strbuf_addf(err, _("unrecognized %%(align) argument: %s"), s);
+			strbuf_addf(err, _("unrecognized %%(%s) argument: %s"), "align", s);
 			string_list_clear(&params, 0);
 			return -1;
 		}
@@ -557,7 +557,7 @@ static int if_atom_parser(struct ref_format *format, struct used_atom *atom,
 	} else if (skip_prefix(arg, "notequals=", &atom->u.if_then_else.str)) {
 		atom->u.if_then_else.cmp_status = COMPARE_UNEQUAL;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(if) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "if", arg);
 	return 0;
 }
 
Signature · 1 line
gitgitgadget
#59 lore raw

PATCH v3 9/11 i18n: factorize "--foo outside a repository"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 apply.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
apply.c +3 -3
index 000f2a9b1b3..8fd2ac2cfca 100644
@@ -136,7 +136,7 @@ int check_apply_state(struct apply_state *state, int force_apply)
 		return error(_("options '%s' and '%s' cannot be used together"),"--reject",  "--3way");
 	if (state->threeway) {
 		if (is_not_gitdir)
-			return error(_("--3way outside a repository"));
+			return error(_("%s outside a repository"), "--3way");
 		state->check_index = 1;
 	}
 	if (state->apply_with_reject) {
@@ -147,10 +147,10 @@ int check_apply_state(struct apply_state *state, int force_apply)
 	if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor))
 		state->apply = 0;
 	if (state->check_index && is_not_gitdir)
-		return error(_("--index outside a repository"));
+		return error(_("%s outside a repository"), "--index");
 	if (state->cached) {
 		if (is_not_gitdir)
-			return error(_("--cached outside a repository"));
+			return error(_("%s outside a repository"), "--cached");
 		state->check_index = 1;
 	}
 	if (state->ita_only && (state->check_index || is_not_gitdir))
Signature · 1 line
gitgitgadget
#60 lore raw

PATCH v3 10/11 i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 ref-filter.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
ref-filter.c +4 -4
index adbcc680812..f7a2f17bfd9 100644
@@ -841,7 +841,7 @@ static void if_then_else_handler(struct ref_formatting_stack **stack)
 	struct if_then_else *if_then_else = (struct if_then_else *)cur->at_end_data;
 
 	if (!if_then_else->then_atom_seen)
-		die(_("format: %%(if) atom used without a %%(then) atom"));
+		die(_("format: %%(%s) atom used without a %%(%s) atom"), "if", "then");
 
 	if (if_then_else->else_atom_seen) {
 		/*
@@ -907,7 +907,7 @@ static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	if (cur->at_end == if_then_else_handler)
 		if_then_else = (struct if_then_else *)cur->at_end_data;
 	if (!if_then_else)
-		return strbuf_addf_ret(err, -1, _("format: %%(then) atom used without an %%(if) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "then", "if");
 	if (if_then_else->then_atom_seen)
 		return strbuf_addf_ret(err, -1, _("format: %%(then) atom used more than once"));
 	if (if_then_else->else_atom_seen)
@@ -943,9 +943,9 @@ static int else_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	if (prev->at_end == if_then_else_handler)
 		if_then_else = (struct if_then_else *)prev->at_end_data;
 	if (!if_then_else)
-		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without an %%(if) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "else", "if");
 	if (!if_then_else->then_atom_seen)
-		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without a %%(then) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "else", "then");
 	if (if_then_else->else_atom_seen)
 		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used more than once"));
 	if_then_else->else_atom_seen = 1;
Signature · 1 line
gitgitgadget
#61 lore raw

PATCH v3 11/11 i18n: turn even more messages into "cannot be used together" ones

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Even if some of these messages are not subject to gettext i18n, this helps bring a single style of message for a given error type.

---
 builtin/add.c                             |  2 +-
 builtin/am.c                              |  4 ++--
 builtin/cat-file.c                        |  2 +-
 builtin/checkout.c                        |  4 ++--
 builtin/clone.c                           |  2 +-
 builtin/commit.c                          | 10 ++++++----
 builtin/describe.c                        |  4 ++--
 builtin/rebase.c                          |  4 ++--
 builtin/reset.c                           |  2 +-
 builtin/rev-list.c                        |  2 +-
 builtin/rm.c                              |  2 +-
 builtin/stash.c                           |  2 +-
 diff.c                                    |  6 +++---
 t/t2026-checkout-pathspec-file.sh         |  2 +-
 t/t2072-restore-pathspec-file.sh          |  2 +-
 t/t3601-rm-pathspec-file.sh               |  2 +-
 t/t3704-add-pathspec-file.sh              |  2 +-
 t/t3909-stash-pathspec-file.sh            |  2 +-
 t/t4209-log-pickaxe.sh                    |  4 ++--
 t/t5606-clone-options.sh                  |  2 +-
 t/t7107-reset-pathspec-file.sh            |  2 +-
 t/t7500-commit-template-squash-signoff.sh | 11 ++++++-----
 t/t7526-commit-pathspec-file.sh           |  2 +-
 23 files changed, 40 insertions(+), 37 deletions(-)
builtin/add.c +1 -1
index 067ec53d69f..dcaa3b5f395 100644
@@ -566,7 +566,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, PATHSPEC_ATTR,
 				    PATHSPEC_PREFER_FULL |
builtin/am.c +2 -2
index 8677ea2348a..c9665866651 100644
@@ -2230,8 +2230,8 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 	}
 
 	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
-		return error(_("--show-current-patch=%s is incompatible with "
-			       "--show-current-patch=%s"),
+		return error(_("options '--show-current-patch=%s' and '--show-current-patch=%s' "
+					   "cannot be used together"),
 			     arg, valid_modes[resume->sub_mode]);
 
 	resume->mode = RESUME_SHOW_PATCH;
builtin/cat-file.c +1 -1
index 86fc03242b8..d94050e6c18 100644
@@ -729,7 +729,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
 	}
 
 	if (force_path && batch.enabled) {
-		error("--path=<path> incompatible with --batch");
+		error("options '--path=<path>' and '--batch' cannot be used together");
 		usage_with_options(cat_file_usage, options);
 	}
 
builtin/checkout.c +2 -2
index bc219317ff2..cfb2de5da89 100644
@@ -1635,7 +1635,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 	}
 
 	if ((!!opts->new_branch + !!opts->new_branch_force + !!opts->new_orphan_branch) > 1)
-		die(_("-%c, -%c and --orphan are mutually exclusive"),
+		die(_("options '-%c', '-%c' and '--orphan' cannot be used together"),
 				cb_option, toupper(cb_option));
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
@@ -1746,7 +1746,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 
 	if (opts->pathspec_from_file) {
 		if (opts->pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		if (opts->force_detach)
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file",  "--detach");
builtin/clone.c +1 -1
index 13bdbe14b2f..cc92393e4a5 100644
@@ -900,7 +900,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
 	if (option_bare) {
 		if (option_origin)
-			die(_("--bare and --origin %s options are incompatible."),
+			die(_("options '--bare' and '--origin %s' cannot be used together"),
 			    option_origin);
 		if (real_git_dir)
 			die(_("options '%s' and '%s' cannot be used together"), "--bare", "--separate-git-dir");
builtin/commit.c +6 -4
index 91f685c5e71..bab7a7a298c 100644
@@ -361,7 +361,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 			die(_("options '%s' and '%s' cannot be used together"),"--pathspec-from-file", "-a");
 
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_FULL,
@@ -799,7 +799,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 
 		if (!strcmp(fixup_prefix, "amend")) {
 			if (have_option_m)
-				die(_("cannot combine -m with --fixup:%s"), fixup_message);
+				die(_("options '-m' and '--fixup:%s' cannot be used together"), fixup_message);
 			prepare_amend_commit(commit, &sb, &ctx);
 		}
 	} else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
@@ -1229,9 +1229,11 @@ static void check_fixup_reword_options(int argc, const char *argv[]) {
 			die(_("You are in the middle of a cherry-pick -- cannot reword."));
 	}
 	if (argc)
-		die(_("cannot combine reword option of --fixup with path '%s'"), *argv);
+		die(_("reword option of --fixup and path '%s' cannot be used together"), *argv);
 	if (patch_interactive || interactive || all || also || only)
-		die(_("reword option of --fixup is mutually exclusive with --patch/--interactive/--all/--include/--only"));
+		die(_("reword option of --fixup and "
+			  "--patch/--interactive/--all/--include/--only "
+			  "cannot be used together"));
 }
 
 static int parse_and_validate_options(int argc, const char *argv[],
builtin/describe.c +2 -2
index fd5ba1fc604..42159cd26bd 100644
@@ -670,9 +670,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 		}
 		describe("HEAD", 1);
 	} else if (dirty) {
-		die(_("--dirty is incompatible with commit-ishes"));
+		die(_("option '%s' and commit-ishes cannot be used together"), "--dirty");
 	} else if (broken) {
-		die(_("--broken is incompatible with commit-ishes"));
+		die(_("option '%s' and commit-ishes cannot be used together"), "--broken");
 	} else {
 		while (argc-- > 0)
 			describe(*argv++, argc == 0);
builtin/rebase.c +2 -2
index ed326b8aecc..d3ce0999786 100644
@@ -1460,8 +1460,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
 		if (i >= 0) {
 			if (is_merge(&options))
-				die(_("cannot combine apply options with "
-				      "merge options"));
+				die(_("apply options and merge options "
+					  "cannot be used together"));
 			else
 				options.type = REBASE_APPLY;
 		}
builtin/reset.c +1 -1
index 4779e70dfbe..2db1012cbb1 100644
@@ -426,7 +426,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_FULL,
builtin/rev-list.c +1 -1
index de60cbdbc9d..0e3d93afed3 100644
@@ -676,7 +676,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	if (revs.count &&
 	    (revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
 	    (revs.left_right || revs.cherry_mark))
-		die(_("marked counting is incompatible with --objects"));
+		die(_("marked counting and '--objects' cannot be used together"));
 
 	save_commit_buffer = (revs.verbose_header ||
 			      revs.grep_filter.pattern_list ||
builtin/rm.c +1 -1
index cfdf24cf49a..fdfe76dd742 100644
@@ -272,7 +272,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_CWD,
builtin/stash.c +1 -1
index 3e3743fd5a3..5afa48ef989 100644
@@ -1706,7 +1706,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--staged");
 
 		if (ps.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
 
 		parse_pathspec_file(&ps, 0,
 				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
diff.c +3 -3
index 8de1c49763c..ba2a886ec2c 100644
@@ -4639,16 +4639,16 @@ void diff_setup_done(struct diff_options *options)
 		options->set_default(options);
 
 	if (HAS_MULTI_BITS(options->output_format & check_mask))
-		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
+		die(_("options '--name-only', '--name-status', '--check' and '-s' cannot be used together"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
 		die(_("options '%s', '%s' and '%s' cannot be used together"), "-G", "-S", "--find-object");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
-		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
+		die(_("-G and --pickaxe-regex cannot be used together, use --pickaxe-regex with -S"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_ALL_OBJFIND_MASK))
-		die(_("--pickaxe-all and --find-object are mutually exclusive, use --pickaxe-all with -G and -S"));
+		die(_("--pickaxe-all and --find-object cannot be used together, use --pickaxe-all with -G and -S"));
 
 	/*
 	 * Most of the time we can say "there are changes"
t/t2026-checkout-pathspec-file.sh +1 -1
index 9e6b17e2d23..9c651aefbca 100755
@@ -155,7 +155,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
t/t2072-restore-pathspec-file.sh +1 -1
index af67ca7d52b..c22669b39f9 100755
@@ -155,7 +155,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
t/t3601-rm-pathspec-file.sh +1 -1
index bbed67f8ef5..a2a0c820fe3 100755
@@ -67,7 +67,7 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git rm --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git rm --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
t/t3704-add-pathspec-file.sh +1 -1
index 47ad96bf661..4e6b5177c93 100755
@@ -147,7 +147,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git add --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
t/t3909-stash-pathspec-file.sh +1 -1
index fde4625cfcb..dead9f18d93 100755
@@ -91,7 +91,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
t/t4209-log-pickaxe.sh +2 -2
index 4f820f8597d..7f6bb27f141 100755
@@ -72,12 +72,12 @@ test_expect_success 'usage' '
 	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err
+	grep "cannot be used together" err
 '
 
 test_expect_success 'usage: --pickaxe-regex' '
 	test_expect_code 128 git log -Gregex --pickaxe-regex 2>err &&
-	grep "mutually exclusive" err
+	grep "cannot be used together" err
 '
 
 test_expect_success 'usage: --no-pickaxe-regex' '
t/t5606-clone-options.sh +1 -1
index 3af3577af0b..8f676d6b0c0 100755
@@ -46,7 +46,7 @@ test_expect_success 'disallows --bare with --origin' '
 
 	test_must_fail git clone -o foo --bare parent clone-bare-o 2>err &&
 	test_debug "cat err" &&
-	test_i18ngrep -e "--bare and --origin foo options are incompatible" err
+	test_i18ngrep -e "options .--bare. and .--origin foo. cannot be used together" err
 
 '
 
t/t7107-reset-pathspec-file.sh +1 -1
index f753e3229e2..523efbecde1 100755
@@ -163,7 +163,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
t/t7500-commit-template-squash-signoff.sh +6 -5
index 8dd0f988129..653c0954753 100755
@@ -359,14 +359,14 @@ test_expect_success '--fixup=reword: ignores staged changes' '
 
 test_expect_success '--fixup=reword: error out with -m option' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine -m with --fixup:reword" >expect &&
+	echo "fatal: options '\''-m'\'' and '\''--fixup:reword'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -m "reword commit message" 2>actual &&
 	test_cmp expect actual
 '
 
 test_expect_success '--fixup=amend: error out with -m option' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine -m with --fixup:amend" >expect &&
+	echo "fatal: options '\''-m'\'' and '\''--fixup:amend'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=amend:HEAD~ -m "amend commit message" 2>actual &&
 	test_cmp expect actual
 '
@@ -421,8 +421,9 @@ test_expect_success 'amend! commit allows empty commit msg body with --allow-emp
 
 test_fixup_reword_opt () {
 	test_expect_success "--fixup=reword: incompatible with $1" "
-		echo 'fatal: reword option of --fixup is mutually exclusive with'\
-			'--patch/--interactive/--all/--include/--only' >expect &&
+		echo 'fatal: reword option of --fixup and' \
+			'--patch/--interactive/--all/--include/--only' \
+			'cannot be used together' >expect &&
 		test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
 		test_cmp expect actual
 	"
@@ -435,7 +436,7 @@ done
 
 test_expect_success '--fixup=reword: give error with pathsec' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine reword option of --fixup with path '\''foo'\''" >expect &&
+	echo "fatal: reword option of --fixup and path '\''foo'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -- foo 2>actual &&
 	test_cmp expect actual
 '
t/t7526-commit-pathspec-file.sh +1 -1
index ea69e3a6ad1..ad011bb9f15 100755
@@ -150,7 +150,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .-a. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
Signature · 1 line
gitgitgadget
#62 lore raw

Re: [PATCH v3 11/11] i18n: turn even more messages into "cannot be used together" ones

Quoted 4 lines · Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Even if some of these messages are not subject to gettext i18n, this helps bring a single style of message for a given error type.

Makes sense, but ...

builtin/add.c int cmd_add(int argc, const char **argv, const char *prefix) · line 569

Quoted 11 lines
builtin/add.c +1 -1
index 067ec53d69f..dcaa3b5f395 100644
@@ -566,7 +566,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));

Don't we want the literal --pathspec-from-file outside the format string to prevent it from l10n? Or have all the changes in this series to turn _("use '--concrete-option-name' in message") into _("use '%s' in message") with '--concrete-option-name' as an argument done only to reduce the number of distinct format strings?

I just skimmed the rest of the patch but the above comment seems to apply to all the hunks.

Thanks.

#63 lore raw

Re: [PATCH v3 11/11] i18n: turn even more messages into "cannot be used together" ones

Quoted 7 lines · On Thursday, 30 December 2021 23:36:45 CET Junio C Hamano wrote:
Quoted 4 lines · Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Even if some of these messages are not subject to gettext i18n, this helps bring a single style of message for a given error type.

Quoted 7 lines

Makes sense, but ...

builtin/add.c int cmd_add(int argc, const char **argv, const char

Quoted 6 lines
builtin/add.c +0 -0
index 067ec53d69f..dcaa3b5f395 100644
@@ -566,7 +566,7 @@ int cmd_add(int argc, const char **argv, const char 

*prefix)

Quoted 4 lines

builtin/add.c int cmd_add(int argc, const char **argv, const char *prefix)

Quoted 4 lines
builtin/add.c +0 -1
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible 

with pathspec arguments"));

Quoted 1 line

builtin/add.c int cmd_add(int argc, const char **argv, const char · line 568

Quoted 1 line
builtin/add.c +1 -0
+			die(_("'--pathspec-from-file' and pathspec 

arguments cannot be used together"));

Quoted 7 lines

Don't we want the literal --pathspec-from-file outside the format string to prevent it from l10n? Or have all the changes in this series to turn _("use '--concrete-option-name' in message") into _("use '%s' in message") with '--concrete-option-name' as an argument done only to reduce the number of distinct format strings?

Quoted 5 lines

I just skimmed the rest of the patch but the above comment seems to apply to all the hunks.

Thanks.

The idea was to apply the '%s' shifting only to strings that can be factorized,
in order to curb the number of translatable strings.

Anyway, swiching from

    die(_("use '--concrete-option-name' in message")) 

into

    die(_("use option '%s' in message"), "--concrete-option-name")

in a more generic way fits perfectly in the spirit I had for this series.

On the other hand, the patch list is already quite large and this logic won't be extended to every other candidate strings that are not already changed here. That may be the object of another series.

JN

#64 lore raw

Re: [PATCH v3 11/11] i18n: turn even more messages into "cannot be used together" ones

Quoted 9 lines · Jean-Noël AVILA
Quoted 5 lines

Don't we want the literal --pathspec-from-file outside the format string to prevent it from l10n? Or have all the changes in this series to turn _("use '--concrete-option-name' in message") into _("use '%s' in message") with '--concrete-option-name' as an argument done only to reduce the number of distinct format strings?

The idea was to apply the '%s' shifting only to strings that can be factorized,
in order to curb the number of translatable strings.

OK, that's fine.

Quoted 9 lines

Anyway, swiching from

    die(_("use '--concrete-option-name' in message")) 

into

    die(_("use option '%s' in message"), "--concrete-option-name")

in a more generic way fits perfectly in the spirit I had for this series.

Yes, but I do not mind leaving it outside the scope of this immediate series and see a separate topic to clean them up once the dust from this series settles.

Quoted 3 lines

On the other hand, the patch list is already quite large and this logic won't be extended to every other candidate strings that are not already changed here. That may be the object of another series.

Yup.

Thanks.

#65 lore raw

v4 cover Factorization of messages with similar meaning

In reply to Jean-Noël Avila via GitGitGadget

This series is a meager attempt at rationalizing a small fraction of the internationalized messages. Sorry in advance for the dull task of reviewing these insipide patches.

Doing so has some positive effects:

* non-translatable constant strings are kept out of the way for translators
* messages with identical meaning are built identically
* the total number of messages to translate is decreased.

Changes since V1:

* took into account the comments, except for ref-filter.c where the proposed refactoring is not obvious.
* added even more strings to the "cannot be used together" crowd.

Changes since V2:

* fixed change of behaviour in tag.c
* reverted sam changes as per Johannes Sixt comments

Changes since V3:

* apply Oxford comma where needed
* switch all options to " '%s' " style where i18n is applied.

Jean-Noël Avila (11):
i18n: refactor "foo and bar are mutually exclusive"
i18n: refactor "%s, %s and %s are mutually exclusive"
i18n: turn "options are incompatible" into "cannot be used together"
i18n: standardize "cannot open" and "cannot read"
i18n: tag.c factorize i18n strings
i18n: factorize "--foo requires --bar" and the like
i18n: factorize "no directory given for --foo"
i18n: refactor "unrecognized %(foo) argument" strings
i18n: factorize "--foo outside a repository"
i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"
i18n: turn even more messages into "cannot be used together" ones

 apply.c                                   |  8 ++++----
 archive.c                                 |  8 ++++----
 builtin/add.c                             | 14 +++++++-------
 builtin/am.c                              |  6 +++---
 builtin/branch.c                          |  2 +-
 builtin/cat-file.c                        |  2 +-
 builtin/checkout.c                        | 18 +++++++++---------
 builtin/clone.c                           |  6 +++---
 builtin/commit.c                          | 17 +++++++++--------
 builtin/describe.c                        |  6 +++---
 builtin/diff-tree.c                       |  2 +-
 builtin/difftool.c                        |  4 ++--
 builtin/fast-export.c                     |  4 ++--
 builtin/fetch.c                           |  8 ++++----
 builtin/index-pack.c                      |  4 ++--
 builtin/init-db.c                         |  2 +-
 builtin/log.c                             |  8 ++++----
 builtin/ls-files.c                        |  2 +-
 builtin/merge.c                           |  4 ++--
 builtin/pack-objects.c                    |  2 +-
 builtin/push.c                            |  8 ++++----
 builtin/rebase.c                          | 10 +++++-----
 builtin/repack.c                          |  4 ++--
 builtin/reset.c                           | 10 +++++-----
 builtin/rev-list.c                        |  4 ++--
 builtin/rm.c                              |  4 ++--
 builtin/show-branch.c                     |  4 ++--
 builtin/stash.c                           |  8 ++++----
 builtin/submodule--helper.c               |  4 ++--
 builtin/tag.c                             | 23 +++++++++++++----------
 builtin/worktree.c                        |  6 +++---
 diff.c                                    | 12 ++++++++----
 fetch-pack.c                              |  2 +-
 git.c                                     |  6 +++---
 http-fetch.c                              |  4 ++--
 range-diff.c                              |  2 +-
 ref-filter.c                              | 22 +++++++++++-----------
 revision.c                                | 22 +++++++++++-----------
 t/t0001-init.sh                           |  2 +-
 t/t2025-checkout-no-overlay.sh            |  2 +-
 t/t2026-checkout-pathspec-file.sh         |  8 ++++----
 t/t2072-restore-pathspec-file.sh          |  6 +++---
 t/t3431-rebase-fork-point.sh              |  2 +-
 t/t3601-rm-pathspec-file.sh               |  4 ++--
 t/t3704-add-pathspec-file.sh              | 10 +++++-----
 t/t3909-stash-pathspec-file.sh            |  6 +++---
 t/t4209-log-pickaxe.sh                    | 10 +++++-----
 t/t5606-clone-options.sh                  |  4 ++--
 t/t7107-reset-pathspec-file.sh            |  6 +++---
 t/t7500-commit-template-squash-signoff.sh | 11 ++++++-----
 t/t7526-commit-pathspec-file.sh           | 10 +++++-----
 51 files changed, 186 insertions(+), 177 deletions(-)

base-commit: 2ae0a9cb8298185a94e5998086f380a355dd8907
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1088%2Fjnavila%2Fi18n-refactor-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1088/jnavila/i18n-refactor-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/1088

Range-diff vs v3:

  1:  05af90f5814 =  1:  05af90f5814 i18n: refactor "foo and bar are mutually exclusive"
  2:  4accf1629e5 !  2:  e307ea9b998 i18n: refactor "%s, %s and %s are mutually exclusive"
     @@ builtin/difftool.c: int cmd_difftool(int argc, const char **argv, const char *pr
       
       	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
      -		die(_("--gui, --tool and --extcmd are mutually exclusive"));
     -+		die(_("options '%s', '%s' and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
     ++		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
       
       	if (use_gui_tool)
       		setenv("GIT_MERGETOOL_GUI", "true", 1);
     @@ 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(_("--stdout, --output, and --output-directory are mutually exclusive"));
     -+		die(_("options '%s', '%s' and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
     ++		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
       
       	if (use_stdout) {
       		setup_pager();
     @@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix)
       	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
       	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
      -		die(_("-b, -B, and --detach are mutually exclusive"));
     -+		die(_("options '%s', '%s' and '%s' cannot be used together"), "-b", "-B", "--detach");
     ++		die(_("options '%s', '%s', and '%s' cannot be used together"),"-b", "-B", "--detach");
       	if (lock_reason && !keep_locked)
       		die(_("--reason requires --lock"));
       	if (lock_reason)
     @@ diff.c: void diff_setup_done(struct diff_options *options)
       
       	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
      -		die(_("-G, -S and --find-object are mutually exclusive"));
     -+		die(_("options '%s', '%s' and '%s' cannot be used together"), "-G", "-S", "--find-object");
     ++		die(_("options '%s', '%s', and '%s' cannot be used together"), "-G", "-S", "--find-object");
       
       	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
       		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
  3:  486cc6c89e2 !  3:  d5bfa26e992 i18n: turn "options are incompatible" into "cannot be used together"
     @@ apply.c: int check_apply_state(struct apply_state *state, int force_apply)
       
       	if (state->apply_with_reject && state->threeway)
      -		return error(_("--reject and --3way cannot be used together."));
     -+		return error(_("options '%s' and '%s' cannot be used together"),"--reject",  "--3way");
     ++		return error(_("options '%s' and '%s' cannot be used together"), "--reject",  "--3way");
       	if (state->threeway) {
       		if (is_not_gitdir)
       			return error(_("--3way outside a repository"));
     @@ builtin/branch.c: int cmd_branch(int argc, const char **argv, const char *prefix
       
      
       ## builtin/checkout.c ##
     +@@ builtin/checkout.c: static int checkout_paths(const struct checkout_opts *opts,
     + 		die(_("'%s' cannot be used with updating paths"), "--detach");
     + 
     + 	if (opts->merge && opts->patch_mode)
     +-		die(_("'%s' cannot be used with %s"), "--merge", "--patch");
     ++		die(_("options '%s' and '%s' cannot be used together"), "--merge", "--patch");
     + 
     + 	if (opts->ignore_unmerged && opts->merge)
     +-		die(_("'%s' cannot be used with %s"),
     ++		die(_("options '%s' and '%s' cannot be used together"),
     + 		    opts->ignore_unmerged_opt, "-m");
     + 
     + 	if (opts->new_branch)
      @@ builtin/checkout.c: static int checkout_main(int argc, const char **argv, const char *prefix,
       			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
       
       		if (opts->force_detach)
      -			die(_("--pathspec-from-file is incompatible with --detach"));
     -+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file",  "--detach");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--detach");
       
       		if (opts->patch_mode)
      -			die(_("--pathspec-from-file is incompatible with --patch"));
     @@ builtin/commit.c: static const char *prepare_index(const char **argv, const char
       
       		if (all)
      -			die(_("--pathspec-from-file with -a does not make sense"));
     -+			die(_("options '%s' and '%s' cannot be used together"),"--pathspec-from-file", "-a");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "-a");
       
       		if (pathspec.nr)
       			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
     @@ builtin/difftool.c: int cmd_difftool(int argc, const char **argv, const char *pr
      +		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(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
      
       ## builtin/fast-export.c ##
      @@ builtin/fast-export.c: int cmd_fast_export(int argc, const char **argv, const char *prefix)
     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
       	if (keep_base) {
       		if (options.onto_name)
      -			die(_("cannot combine '--keep-base' with '--onto'"));
     -+			die(_("options '%s' and '%s' cannot be used together"),"--keep-base", "--onto");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--keep-base", "--onto");
       		if (options.root)
      -			die(_("cannot combine '--keep-base' with '--root'"));
     -+			die(_("options '%s' and '%s' cannot be used together"),"--keep-base", "--root");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--keep-base", "--root");
       	}
       
       	if (options.root && options.fork_point > 0)
     @@ builtin/repack.c: int cmd_repack(int argc, const char **argv, const char *prefix
       	if (geometric_factor) {
       		if (pack_everything)
      -			die(_("--geometric is incompatible with -A, -a"));
     -+			die(_("options '%s' and '%s' cannot be used together"),"--geometric", "-A/-a");
     ++			die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a");
       		init_pack_geometry(&geometry);
       		split_pack_geometry(geometry, geometric_factor);
       	}
     @@ builtin/rev-list.c: int cmd_rev_list(int argc, const char **argv, const char *pr
       		if (skip_prefix(arg, "--missing=", &arg)) {
       			if (revs.exclude_promisor_objects)
      -				die(_("cannot combine --exclude-promisor-objects and --missing"));
     -+				die(_("options '%s' and '%s' cannot be used together"),"--exclude-promisor-objects", "--missing");
     ++				die(_("options '%s' and '%s' cannot be used together"), "--exclude-promisor-objects", "--missing");
       			if (parse_missing_action_value(arg))
       				break;
       		}
     @@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)
       		colopts = 0;
       	}
       	sorting = ref_sorting_options(&sorting_options);
     +@@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)
     + 
     + 	if (msg.given || msgfile) {
     + 		if (msg.given && msgfile)
     +-			die(_("only one -F or -m option is allowed."));
     ++			die(_("options '%s' and '%s' cannot be used together"), "-F", "-m");
     + 		if (msg.given)
     + 			strbuf_addbuf(&buf, &(msg.buf));
     + 		else {
      
       ## revision.c ##
      @@ revision.c: static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
     @@ revision.c: int setup_revisions(int argc, const char **argv, struct rev_info *re
      -		die("cannot combine --no-walk with --graph");
      +		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
       	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
     --		die("cannot use --grep-reflog without --walk-reflogs");
     -+		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");
     + 		die("cannot use --grep-reflog without --walk-reflogs");
       
     - 	if (revs->line_level_traverse &&
     - 	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
      
       ## t/t2026-checkout-pathspec-file.sh ##
      @@ t/t2026-checkout-pathspec-file.sh: test_expect_success 'error conditions' '
  4:  a2b42087342 =  4:  51c53f01dd8 i18n: standardize "cannot open" and "cannot read"
  5:  2d83654c48a !  5:  a9d8a50d666 i18n: tag.c factorize i18n strings
     @@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)
      +	if (only_in_list)
      +		die(_("the '%s' option is only allowed in list mode"), only_in_list);
       	if (filter.reachable_from || filter.unreachable_from)
     - 		die(_("--merged and --no-merged options are only allowed in list mode"));
     +-		die(_("--merged and --no-merged options are only allowed in list mode"));
     ++		die(_("'--merged' and '--no-merged' options are only allowed in list mode"));
       	if (cmdmode == 'd') {
     + 		ret = delete_tags(argv);
     + 		goto cleanup;
  6:  1097cc7d6d1 !  6:  969946274aa i18n: factorize "--foo requires --bar" and the like
     @@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *
       ## builtin/worktree.c ##
      @@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix)
       	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
     - 		die(_("options '%s', '%s' and '%s' cannot be used together"), "-b", "-B", "--detach");
     + 		die(_("options '%s', '%s', and '%s' cannot be used together"),"-b", "-B", "--detach");
       	if (lock_reason && !keep_locked)
      -		die(_("--reason requires --lock"));
      +		die(_("the option '%s' requires '%s'"), "--reason", "--lock");
     @@ revision.c: int setup_revisions(int argc, const char **argv, struct rev_info *re
       	if (revs->no_walk && revs->graph)
       		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
       	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
     --		die(_("%s requires %s"), "--grep-reflog", "--walk-reflogs");
     +-		die("cannot use --grep-reflog without --walk-reflogs");
      +		die(_("the option '%s' requires '%s'"), "--grep-reflog", "--walk-reflogs");
       
       	if (revs->line_level_traverse &&
  7:  4c17e08b9d3 !  7:  052dc06beeb i18n: factorize "no directory given for --foo"
     @@ git.c: static int handle_options(const char ***argv, int *argc, int *envchanged)
       		} else if (!strcmp(cmd, "--git-dir")) {
       			if (*argc < 2) {
      -				fprintf(stderr, _("no directory given for --git-dir\n" ));
     -+				fprintf(stderr, _("no directory given for %s\n" ), "--git-dir");
     ++				fprintf(stderr, _("no directory given for '%s' option\n" ), "--git-dir");
       				usage(git_usage_string);
       			}
       			setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
     @@ git.c: static int handle_options(const char ***argv, int *argc, int *envchanged)
       		} else if (!strcmp(cmd, "--work-tree")) {
       			if (*argc < 2) {
      -				fprintf(stderr, _("no directory given for --work-tree\n" ));
     -+				fprintf(stderr, _("no directory given for %s\n" ), "--work-tree");
     ++				fprintf(stderr, _("no directory given for '%s' option\n" ), "--work-tree");
       				usage(git_usage_string);
       			}
       			setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
     @@ git.c: static int handle_options(const char ***argv, int *argc, int *envchanged)
       		} else if (!strcmp(cmd, "-C")) {
       			if (*argc < 2) {
      -				fprintf(stderr, _("no directory given for -C\n" ));
     -+				fprintf(stderr, _("no directory given for %s\n" ), "-C");
     ++				fprintf(stderr, _("no directory given for '%s' option\n" ), "-C");
       				usage(git_usage_string);
       			}
       			if ((*argv)[1][0]) {
  8:  b75c5b1ce35 =  8:  59e1e8aa1b4 i18n: refactor "unrecognized %(foo) argument" strings
  9:  44d715a224c !  9:  39e375c68ab i18n: factorize "--foo outside a repository"
     @@ Commit message
      
       ## apply.c ##
      @@ apply.c: int check_apply_state(struct apply_state *state, int force_apply)
     - 		return error(_("options '%s' and '%s' cannot be used together"),"--reject",  "--3way");
     + 		return error(_("options '%s' and '%s' cannot be used together"), "--reject",  "--3way");
       	if (state->threeway) {
       		if (is_not_gitdir)
      -			return error(_("--3way outside a repository"));
     -+			return error(_("%s outside a repository"), "--3way");
     ++			return error(_("'%s' outside a repository"), "--3way");
       		state->check_index = 1;
       	}
       	if (state->apply_with_reject) {
     @@ apply.c: int check_apply_state(struct apply_state *state, int force_apply)
       		state->apply = 0;
       	if (state->check_index && is_not_gitdir)
      -		return error(_("--index outside a repository"));
     -+		return error(_("%s outside a repository"), "--index");
     ++		return error(_("'%s' outside a repository"), "--index");
       	if (state->cached) {
       		if (is_not_gitdir)
      -			return error(_("--cached outside a repository"));
     -+			return error(_("%s outside a repository"), "--cached");
     ++			return error(_("'%s' outside a repository"), "--cached");
       		state->check_index = 1;
       	}
       	if (state->ita_only && (state->check_index || is_not_gitdir))
 10:  03a880d534b = 10:  c6161bc3f1a i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"
 11:  12c5da81087 ! 11:  4fab0db3cc4 i18n: turn even more messages into "cannot be used together" ones
     @@ builtin/add.c: int cmd_add(int argc, const char **argv, const char *prefix)
       	if (pathspec_from_file) {
       		if (pathspec.nr)
      -			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
     -+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
     ++			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
       
       		parse_pathspec_file(&pathspec, PATHSPEC_ATTR,
       				    PATHSPEC_PREFER_FULL |
     @@ builtin/am.c: static int parse_opt_show_current_patch(const struct option *opt,
       	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
      -		return error(_("--show-current-patch=%s is incompatible with "
      -			       "--show-current-patch=%s"),
     -+		return error(_("options '--show-current-patch=%s' and '--show-current-patch=%s' "
     +-			     arg, valid_modes[resume->sub_mode]);
     ++		return error(_("options '%s=%s' and '%s=%s' "
      +					   "cannot be used together"),
     - 			     arg, valid_modes[resume->sub_mode]);
     ++					 "--show-current-patch", "--show-current-patch", arg, valid_modes[resume->sub_mode]);
       
       	resume->mode = RESUME_SHOW_PATCH;
     + 	resume->sub_mode = new_value;
      
       ## builtin/cat-file.c ##
      @@ builtin/cat-file.c: int cmd_cat_file(int argc, const char **argv, const char *prefix)
     @@ builtin/checkout.c: static int checkout_main(int argc, const char **argv, const
       
       	if ((!!opts->new_branch + !!opts->new_branch_force + !!opts->new_orphan_branch) > 1)
      -		die(_("-%c, -%c and --orphan are mutually exclusive"),
     -+		die(_("options '-%c', '-%c' and '--orphan' cannot be used together"),
     - 				cb_option, toupper(cb_option));
     +-				cb_option, toupper(cb_option));
     ++		die(_("options '-%c', '-%c', and '%s' cannot be used together"),
     ++			cb_option, toupper(cb_option), "--orphan");
       
       	if (opts->overlay_mode == 1 && opts->patch_mode)
     + 		die(_("options '%s' and '%s' cannot be used together"), "-p", "--overlay");
      @@ builtin/checkout.c: static int checkout_main(int argc, const char **argv, const char *prefix,
       
       	if (opts->pathspec_from_file) {
       		if (opts->pathspec.nr)
      -			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
     -+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
     ++			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
       
       		if (opts->force_detach)
     - 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file",  "--detach");
     + 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--detach");
      
       ## builtin/clone.c ##
      @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
     @@ builtin/clone.c: int cmd_clone(int argc, const char **argv, const char *prefix)
       	if (option_bare) {
       		if (option_origin)
      -			die(_("--bare and --origin %s options are incompatible."),
     -+			die(_("options '--bare' and '--origin %s' cannot be used together"),
     - 			    option_origin);
     +-			    option_origin);
     ++			die(_("options '%s' and '%s %s' cannot be used together"),
     ++			    "--bare", "--origin", option_origin);
       		if (real_git_dir)
       			die(_("options '%s' and '%s' cannot be used together"), "--bare", "--separate-git-dir");
     + 		option_no_checkout = 1;
      
       ## builtin/commit.c ##
      @@ builtin/commit.c: static const char *prepare_index(const char **argv, const char *prefix,
     - 			die(_("options '%s' and '%s' cannot be used together"),"--pathspec-from-file", "-a");
     + 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "-a");
       
       		if (pathspec.nr)
      -			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
     -+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
     ++			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
       
       		parse_pathspec_file(&pathspec, 0,
       				    PATHSPEC_PREFER_FULL,
     @@ builtin/commit.c: static int prepare_to_commit(const char *index_file, const cha
       		if (!strcmp(fixup_prefix, "amend")) {
       			if (have_option_m)
      -				die(_("cannot combine -m with --fixup:%s"), fixup_message);
     -+				die(_("options '-m' and '--fixup:%s' cannot be used together"), fixup_message);
     ++				die(_("options '%s' and '%s:%s' cannot be used together"), "-m", "--fixup", fixup_message);
       			prepare_amend_commit(commit, &sb, &ctx);
       		}
       	} else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
     @@ builtin/commit.c: static void check_fixup_reword_options(int argc, const char *a
       	}
       	if (argc)
      -		die(_("cannot combine reword option of --fixup with path '%s'"), *argv);
     -+		die(_("reword option of --fixup and path '%s' cannot be used together"), *argv);
     ++		die(_("reword option of '%s' and path '%s' cannot be used together"), "--fixup", *argv);
       	if (patch_interactive || interactive || all || also || only)
      -		die(_("reword option of --fixup is mutually exclusive with --patch/--interactive/--all/--include/--only"));
     -+		die(_("reword option of --fixup and "
     -+			  "--patch/--interactive/--all/--include/--only "
     -+			  "cannot be used together"));
     ++		die(_("reword option of '%s' and '%s' cannot be used together"),
     ++			"--fixup", "--patch/--interactive/--all/--include/--only");
       }
       
       static int parse_and_validate_options(int argc, const char *argv[],
     @@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)
       
       		if (pathspec.nr)
      -			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
     -+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
     ++			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
       
       		parse_pathspec_file(&pathspec, 0,
       				    PATHSPEC_PREFER_FULL,
     @@ builtin/rev-list.c: int cmd_rev_list(int argc, const char **argv, const char *pr
       	    (revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
       	    (revs.left_right || revs.cherry_mark))
      -		die(_("marked counting is incompatible with --objects"));
     -+		die(_("marked counting and '--objects' cannot be used together"));
     ++		die(_("marked counting and '%s' cannot be used together"), "--objects");
       
       	save_commit_buffer = (revs.verbose_header ||
       			      revs.grep_filter.pattern_list ||
     @@ builtin/rm.c: int cmd_rm(int argc, const char **argv, const char *prefix)
       	if (pathspec_from_file) {
       		if (pathspec.nr)
      -			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
     -+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
     ++			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
       
       		parse_pathspec_file(&pathspec, 0,
       				    PATHSPEC_PREFER_CWD,
     @@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *
       
       		if (ps.nr)
      -			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
     -+			die(_("'--pathspec-from-file' and pathspec arguments cannot be used together"));
     ++			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
       
       		parse_pathspec_file(&ps, 0,
       				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
     @@ diff.c: void diff_setup_done(struct diff_options *options)
       
       	if (HAS_MULTI_BITS(options->output_format & check_mask))
      -		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
     -+		die(_("options '--name-only', '--name-status', '--check' and '-s' cannot be used together"));
     ++		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
     ++			"--name-only", "--name-status", "--check", "-s");
       
       	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
     - 		die(_("options '%s', '%s' and '%s' cannot be used together"), "-G", "-S", "--find-object");
     +-		die(_("options '%s', '%s', and '%s' cannot be used together"), "-G", "-S", "--find-object");
     ++		die(_("options '%s', '%s', and '%s' cannot be used together"),
     ++			"-G", "-S", "--find-object");
       
       	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
      -		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
     -+		die(_("-G and --pickaxe-regex cannot be used together, use --pickaxe-regex with -S"));
     ++		die(_("options '%s' and '%s' cannot be used together, use '%s' with '%s'"),
     ++			"-G", "--pickaxe-regex", "--pickaxe-regex", "-S");
       
       	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_ALL_OBJFIND_MASK))
      -		die(_("--pickaxe-all and --find-object are mutually exclusive, use --pickaxe-all with -G and -S"));
     -+		die(_("--pickaxe-all and --find-object cannot be used together, use --pickaxe-all with -G and -S"));
     ++		die(_("options '%s' and '%s' cannot be used together, use '%s' with '%s' and '%s'"),
     ++			"--pickaxe-all", "--find-object", "--pickaxe-all", "-G", "-S");
       
       	/*
       	 * Most of the time we can say "there are changes"
     @@ t/t7500-commit-template-squash-signoff.sh: test_expect_success 'amend! commit al
       	test_expect_success "--fixup=reword: incompatible with $1" "
      -		echo 'fatal: reword option of --fixup is mutually exclusive with'\
      -			'--patch/--interactive/--all/--include/--only' >expect &&
     -+		echo 'fatal: reword option of --fixup and' \
     -+			'--patch/--interactive/--all/--include/--only' \
     ++		echo 'fatal: reword option of '\''--fixup'\'' and' \
     ++			''\''--patch/--interactive/--all/--include/--only'\' \
      +			'cannot be used together' >expect &&
       		test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
       		test_cmp expect actual
     @@ t/t7500-commit-template-squash-signoff.sh: done
       test_expect_success '--fixup=reword: give error with pathsec' '
       	commit_for_rebase_autosquash_setup &&
      -	echo "fatal: cannot combine reword option of --fixup with path '\''foo'\''" >expect &&
     -+	echo "fatal: reword option of --fixup and path '\''foo'\'' cannot be used together" >expect &&
     ++	echo "fatal: reword option of '\''--fixup'\'' and path '\''foo'\'' cannot be used together" >expect &&
       	test_must_fail git commit --fixup=reword:HEAD~ -- foo 2>actual &&
       	test_cmp expect actual
       '
Signature · 1 line
gitgitgadget
#66 lore raw

PATCH v4 1/11 i18n: refactor "foo and bar are mutually exclusive"

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use static strings for constant parts of the sentences. They are all turned into "cannot be used together".

---
 builtin/checkout.c             | 2 +-
 builtin/diff-tree.c            | 2 +-
 builtin/fetch.c                | 4 ++--
 builtin/init-db.c              | 2 +-
 builtin/log.c                  | 4 ++--
 builtin/submodule--helper.c    | 4 ++--
 builtin/worktree.c             | 2 +-
 range-diff.c                   | 2 +-
 t/t0001-init.sh                | 2 +-
 t/t2025-checkout-no-overlay.sh | 2 +-
 10 files changed, 13 insertions(+), 13 deletions(-)
builtin/checkout.c +1 -1
index 72beeb49aa9..79014e1cb6c 100644
@@ -1639,7 +1639,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				cb_option, toupper(cb_option));
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
-		die(_("-p and --overlay are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "-p", "--overlay");
 
 	if (opts->checkout_index >= 0 || opts->checkout_worktree >= 0) {
 		if (opts->checkout_index < 0)
builtin/diff-tree.c +1 -1
index f33d30d57bf..0e0ac1f1670 100644
@@ -152,7 +152,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
 	}
 
 	if (read_stdin && merge_base)
-		die(_("--stdin and --merge-base are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--stdin", "--merge-base");
 	if (merge_base && opt->pending.nr != 2)
 		die(_("--merge-base only works with two commits"));
 
builtin/fetch.c +2 -2
index f1fe73a3e0f..2c584c85812 100644
@@ -2028,12 +2028,12 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		if (deepen_relative < 0)
 			die(_("negative depth in --deepen is not supported"));
 		if (depth)
-			die(_("--deepen and --depth are mutually exclusive"));
+			die(_("options '%s' and '%s' cannot be used together"), "--deepen", "--depth");
 		depth = xstrfmt("%d", deepen_relative);
 	}
 	if (unshallow) {
 		if (depth)
-			die(_("--depth and --unshallow cannot be used together"));
+			die(_("options '%s' and '%s' cannot be used together"), "--depth", "--unshallow");
 		else if (!is_repository_shallow(the_repository))
 			die(_("--unshallow on a complete repository does not make sense"));
 		else
builtin/init-db.c +1 -1
index 2167796ff2a..546f9c595e7 100644
@@ -557,7 +557,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
 
 	if (real_git_dir && is_bare_repository_cfg == 1)
-		die(_("--separate-git-dir and --bare are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
 
 	if (real_git_dir && !is_absolute_path(real_git_dir))
 		real_git_dir = real_pathdup(real_git_dir, 1);
builtin/log.c +2 -2
index 93ace0dde7d..fad93ad2fc1 100644
@@ -1943,9 +1943,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		numbered = 0;
 
 	if (numbered && keep_subject)
-		die(_("-n and -k are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "-n", "-k");
 	if (keep_subject && subject_prefix)
-		die(_("--subject-prefix/--rfc and -k are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--subject-prefix/--rfc", "-k");
 	rev.preserve_subject = keep_subject;
 
 	argc = setup_revisions(argc, argv, &rev, &s_r_opt);
builtin/submodule--helper.c +2 -2
index 9b25a508e6a..c5d3fc3817f 100644
@@ -1313,7 +1313,7 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 
 	if (files) {
 		if (cached)
-			die(_("--cached and --files are mutually exclusive"));
+			die(_("options '%s' and '%s' cannot be used together"), "--cached", "--files");
 		diff_cmd = DIFF_FILES;
 	}
 
@@ -2972,7 +2972,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
 		die(_("--branch or --default required"));
 
 	if (opt_branch && opt_default)
-		die(_("--branch and --default are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--branch", "--default");
 
 	if (argc != 1 || !(path = argv[0]))
 		usage_with_options(usage, options);
builtin/worktree.c +1 -1
index a396cfdc64e..9a520485769 100644
@@ -699,7 +699,7 @@ static int list(int ac, const char **av, const char *prefix)
 	if (ac)
 		usage_with_options(worktree_usage, options);
 	else if (verbose && porcelain)
-		die(_("--verbose and --porcelain are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--verbose", "--porcelain");
 	else {
 		struct worktree **worktrees = get_worktrees();
 		int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
range-diff.c +1 -1
index cac89a2f4f2..30a4de5c2d8 100644
@@ -556,7 +556,7 @@ int show_range_diff(const char *range1, const char *range2,
 	struct string_list branch2 = STRING_LIST_INIT_DUP;
 
 	if (range_diff_opts->left_only && range_diff_opts->right_only)
-		res = error(_("--left-only and --right-only are mutually exclusive"));
+		res = error(_("options '%s' and '%s' cannot be used together"), "--left-only", "--right-only");
 
 	if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg))
 		res = error(_("could not parse log for '%s'"), range1);
t/t0001-init.sh +1 -1
index 7603ad2f82b..3235ab4d53c 100755
@@ -331,7 +331,7 @@ test_expect_success 'init with separate gitdir' '
 
 test_expect_success 'explicit bare & --separate-git-dir incompatible' '
 	test_must_fail git init --bare --separate-git-dir goop.git bare.git 2>err &&
-	test_i18ngrep "mutually exclusive" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'implicit bare & --separate-git-dir incompatible' '
t/t2025-checkout-no-overlay.sh +1 -1
index fa9e0987063..8f13341cf8e 100755
@@ -25,7 +25,7 @@ test_expect_success 'checkout --no-overlay removing last file from directory' '
 
 test_expect_success 'checkout -p --overlay is disallowed' '
 	test_must_fail git checkout -p --overlay HEAD 2>actual &&
-	test_i18ngrep "fatal: -p and --overlay are mutually exclusive" actual
+	test_i18ngrep "fatal: options .-p. and .--overlay. cannot be used together" actual
 '
 
 test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
Signature · 1 line
gitgitgadget
#67 lore raw

PATCH v4 2/11 i18n: refactor "%s, %s and %s are mutually exclusive"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use placeholders for constant tokens. The strings are turned into "cannot be used together"

---
 builtin/difftool.c     | 2 +-
 builtin/log.c          | 2 +-
 builtin/worktree.c     | 2 +-
 diff.c                 | 2 +-
 t/t4209-log-pickaxe.sh | 6 +++---
 5 files changed, 7 insertions(+), 7 deletions(-)
builtin/difftool.c +1 -1
index 4ee40fe3a06..5beadc07ccd 100644
@@ -733,7 +733,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 		die(_("--dir-diff is incompatible with --no-index"));
 
 	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("--gui, --tool and --extcmd are mutually exclusive"));
+		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
 
 	if (use_gui_tool)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
builtin/log.c +1 -1
index fad93ad2fc1..74b41db1cee 100644
@@ -1979,7 +1979,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		load_display_notes(&rev.notes_opt);
 
 	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("--stdout, --output, and --output-directory are mutually exclusive"));
+		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
 
 	if (use_stdout) {
 		setup_pager();
builtin/worktree.c +1 -1
index 9a520485769..27b60732a22 100644
@@ -503,7 +503,7 @@ static int add(int ac, const char **av, const char *prefix)
 	opts.checkout = 1;
 	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
-		die(_("-b, -B, and --detach are mutually exclusive"));
+		die(_("options '%s', '%s', and '%s' cannot be used together"),"-b", "-B", "--detach");
 	if (lock_reason && !keep_locked)
 		die(_("--reason requires --lock"));
 	if (lock_reason)
diff.c +1 -1
index 41076857428..02ce779e43a 100644
@@ -4642,7 +4642,7 @@ void diff_setup_done(struct diff_options *options)
 		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
-		die(_("-G, -S and --find-object are mutually exclusive"));
+		die(_("options '%s', '%s', and '%s' cannot be used together"), "-G", "-S", "--find-object");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
 		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
t/t4209-log-pickaxe.sh +3 -3
index 75795d0b492..4f820f8597d 100755
@@ -63,13 +63,13 @@ test_expect_success 'usage' '
 	test_i18ngrep "switch.*requires a value" err &&
 
 	test_expect_code 128 git log -Gregex -Sstring 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log -Gregex --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log -Sstring --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
 	grep "mutually exclusive" err
Signature · 1 line
gitgitgadget
#68 lore raw

Re: [PATCH v4 02/11] i18n: refactor "%s, %s and %s are mutually exclusive"

Am 02.01.22 um 18:15 schrieb Jean-Noël Avila via GitGitGadget:

builtin/worktree.c static int add(int ac, const char **av, const char *prefix) · line 506

Quoted 10 lines
builtin/worktree.c +1 -1
index 9a520485769..27b60732a22 100644
@@ -503,7 +503,7 @@ static int add(int ac, const char **av, const char *prefix)
 	opts.checkout = 1;
 	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
-		die(_("-b, -B, and --detach are mutually exclusive"));
+		die(_("options '%s', '%s', and '%s' cannot be used together"),"-b", "-B", "--detach");

As the range-diff in the coverletter shows, you fixed the missing blank after the comma in a lot of cases. This one slipped through. Not worth a re-roll on its own, IMO.

-- Hannes

#69 lore raw

PATCH v4 3/11 i18n: turn "options are incompatible" into "cannot be used together"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 apply.c                           |  2 +-
 archive.c                         |  2 +-
 builtin/add.c                     |  8 ++++----
 builtin/branch.c                  |  2 +-
 builtin/checkout.c                |  8 ++++----
 builtin/clone.c                   |  2 +-
 builtin/commit.c                  |  6 +++---
 builtin/describe.c                |  2 +-
 builtin/difftool.c                |  2 +-
 builtin/fast-export.c             |  2 +-
 builtin/index-pack.c              |  2 +-
 builtin/ls-files.c                |  2 +-
 builtin/merge.c                   |  4 ++--
 builtin/pack-objects.c            |  2 +-
 builtin/push.c                    |  8 ++++----
 builtin/rebase.c                  |  6 +++---
 builtin/repack.c                  |  4 ++--
 builtin/reset.c                   |  4 ++--
 builtin/rev-list.c                |  2 +-
 builtin/show-branch.c             |  4 ++--
 builtin/stash.c                   |  4 ++--
 builtin/tag.c                     |  4 ++--
 revision.c                        | 20 ++++++++++----------
 t/t2026-checkout-pathspec-file.sh |  4 ++--
 t/t2072-restore-pathspec-file.sh  |  2 +-
 t/t3431-rebase-fork-point.sh      |  2 +-
 t/t3704-add-pathspec-file.sh      |  6 +++---
 t/t3909-stash-pathspec-file.sh    |  2 +-
 t/t5606-clone-options.sh          |  2 +-
 t/t7107-reset-pathspec-file.sh    |  2 +-
 t/t7526-commit-pathspec-file.sh   |  6 +++---
 31 files changed, 64 insertions(+), 64 deletions(-)
apply.c +1 -1
index fed195250b6..609814e9708 100644
@@ -133,7 +133,7 @@ int check_apply_state(struct apply_state *state, int force_apply)
 	int is_not_gitdir = !startup_info->have_repository;
 
 	if (state->apply_with_reject && state->threeway)
-		return error(_("--reject and --3way cannot be used together."));
+		return error(_("options '%s' and '%s' cannot be used together"), "--reject",  "--3way");
 	if (state->threeway) {
 		if (is_not_gitdir)
 			return error(_("--3way outside a repository"));
archive.c +1 -1
index a3bbb091256..e85ba169088 100644
@@ -581,7 +581,7 @@ static int parse_archive_args(int argc, const char **argv,
 	if (output)
 		die(_("Unexpected option --output"));
 	if (is_remote && args->extra_files.nr)
-		die(_("Options --add-file and --remote cannot be used together"));
+		die(_("options '%s' and '%s' cannot be used together"), "--add-file", "--remote");
 
 	if (!base)
 		base = "";
builtin/add.c +4 -4
index a010b2c325f..4b2754345ad 100644
@@ -507,9 +507,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		add_interactive = 1;
 	if (add_interactive) {
 		if (show_only)
-			die(_("--dry-run is incompatible with --interactive/--patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
 		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
 		exit(interactive_add(argv + 1, prefix, patch_interactive));
 	}
 	if (legacy_stash_p) {
@@ -526,7 +526,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (edit_interactive) {
 		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --edit"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--edit");
 		return(edit_patch(argc, argv, prefix));
 	}
 	argc--;
@@ -538,7 +538,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		addremove = 0; /* "-u" was given but not "-A" */
 
 	if (addremove && take_worktree_changes)
-		die(_("-A and -u are mutually incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "-A", "-u");
 
 	if (!show_only && ignore_missing)
 		die(_("Option --ignore-missing can only be used together with --dry-run"));
builtin/branch.c +1 -1
index 6c8b0fcc11f..0e93865371c 100644
@@ -722,7 +722,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	finalize_colopts(&colopts, -1);
 	if (filter.verbose) {
 		if (explicitly_enable_column(colopts))
-			die(_("--column and --verbose are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--column", "--verbose");
 		colopts = 0;
 	}
 
builtin/checkout.c +4 -4
index 79014e1cb6c..73f5a6fbfa1 100644
@@ -464,10 +464,10 @@ static int checkout_paths(const struct checkout_opts *opts,
 		die(_("'%s' cannot be used with updating paths"), "--detach");
 
 	if (opts->merge && opts->patch_mode)
-		die(_("'%s' cannot be used with %s"), "--merge", "--patch");
+		die(_("options '%s' and '%s' cannot be used together"), "--merge", "--patch");
 
 	if (opts->ignore_unmerged && opts->merge)
-		die(_("'%s' cannot be used with %s"),
+		die(_("options '%s' and '%s' cannot be used together"),
 		    opts->ignore_unmerged_opt, "-m");
 
 	if (opts->new_branch)
@@ -1749,10 +1749,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
 
 		if (opts->force_detach)
-			die(_("--pathspec-from-file is incompatible with --detach"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--detach");
 
 		if (opts->patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		parse_pathspec_file(&opts->pathspec, 0,
 				    0,
builtin/clone.c +1 -1
index fb377b27657..13bdbe14b2f 100644
@@ -903,7 +903,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 			die(_("--bare and --origin %s options are incompatible."),
 			    option_origin);
 		if (real_git_dir)
-			die(_("--bare and --separate-git-dir are incompatible."));
+			die(_("options '%s' and '%s' cannot be used together"), "--bare", "--separate-git-dir");
 		option_no_checkout = 1;
 	}
 
builtin/commit.c +3 -3
index 883c16256c8..067c795ca4b 100644
@@ -355,10 +355,10 @@ static const char *prepare_index(const char **argv, const char *prefix,
 
 	if (pathspec_from_file) {
 		if (interactive)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
 
 		if (all)
-			die(_("--pathspec-from-file with -a does not make sense"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "-a");
 
 		if (pathspec.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
@@ -1193,7 +1193,7 @@ static void finalize_deferred_config(struct wt_status *s)
 		    status_format == STATUS_FORMAT_UNSPECIFIED)
 			status_format = STATUS_FORMAT_PORCELAIN;
 		else if (status_format == STATUS_FORMAT_LONG)
-			die(_("--long and -z are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--long", "-z");
 	}
 
 	if (use_deferred_config && status_format == STATUS_FORMAT_UNSPECIFIED)
builtin/describe.c +1 -1
index e912ba50d7b..fd5ba1fc604 100644
@@ -590,7 +590,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 	save_commit_buffer = 0;
 
 	if (longformat && abbrev == 0)
-		die(_("--long is incompatible with --abbrev=0"));
+		die(_("options '%s' and '%s' cannot be used together"), "--long", "--abbrev=0");
 
 	if (contains) {
 		struct string_list_item *item;
builtin/difftool.c +1 -1
index 5beadc07ccd..c79fbbf67e5 100644
@@ -730,7 +730,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 		setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
 		setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
 	} else if (dir_diff)
-		die(_("--dir-diff is incompatible with --no-index"));
+		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");
builtin/fast-export.c +1 -1
index 8e2caf72819..1f8fe7b3ac1 100644
@@ -1269,7 +1269,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		printf("feature done\n");
 
 	if (import_filename && import_filename_if_exists)
-		die(_("Cannot pass both --import-marks and --import-marks-if-exists"));
+		die(_("options '%s' and '%s' cannot be used together"), "--import-marks", "--import-marks-if-exists");
 	if (import_filename)
 		import_marks(import_filename, 0);
 	else if (import_filename_if_exists)
builtin/index-pack.c +1 -1
index c23d01de7dc..30ce2ac746d 100644
@@ -1849,7 +1849,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (from_stdin && !startup_info->have_repository)
 		die(_("--stdin requires a git repository"));
 	if (from_stdin && hash_algo)
-		die(_("--object-format cannot be used with --stdin"));
+		die(_("options '%s' and '%s' cannot be used together"), "--object-format", "--stdin");
 	if (!index_name && pack_name)
 		index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
 
builtin/ls-files.c +1 -1
index 031fef1bcaa..9c80cdae951 100644
@@ -767,7 +767,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		 * would not make any sense with this option.
 		 */
 		if (show_stage || show_unmerged)
-			die("ls-files --with-tree is incompatible with -s or -u");
+			die(_("options '%s' and '%s' cannot be used together"), "ls-files --with-tree", "-s/-u");
 		overlay_tree_on_index(the_repository->index, with_tree, max_prefix);
 	}
 
builtin/merge.c +2 -2
index 5f0476b0b76..6db961e9d34 100644
@@ -1396,9 +1396,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 
 	if (squash) {
 		if (fast_forward == FF_NO)
-			die(_("You cannot combine --squash with --no-ff."));
+			die(_("options '%s' and '%s' cannot be used together"), "--squash", "--no-ff.");
 		if (option_commit > 0)
-			die(_("You cannot combine --squash with --commit."));
+			die(_("options '%s' and '%s' cannot be used together"), "--squash", "--commit.");
 		/*
 		 * squash can now silently disable option_commit - this is not
 		 * a problem as it is only overriding the default, not a user
builtin/pack-objects.c +1 -1
index b36ed828d8d..ba2006f2212 100644
@@ -4070,7 +4070,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 		die(_("--thin cannot be used to build an indexable pack"));
 
 	if (keep_unreachable && unpack_unreachable)
-		die(_("--keep-unreachable and --unpack-unreachable are incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "--unpack-unreachable");
 	if (!rev_list_all || !rev_list_reflog || !rev_list_index)
 		unpack_unreachable_expiration = 0;
 
builtin/push.c +4 -4
index 4b026ce6c6a..359db90321c 100644
@@ -589,7 +589,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 	set_push_cert_flags(&flags, push_cert);
 
 	if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
-		die(_("--delete is incompatible with --all, --mirror and --tags"));
+		die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--mirror/--tags");
 	if (deleterefs && argc < 2)
 		die(_("--delete doesn't make sense without any refs"));
 
@@ -627,18 +627,18 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 
 	if (flags & TRANSPORT_PUSH_ALL) {
 		if (tags)
-			die(_("--all and --tags are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--all", "--tags");
 		if (argc >= 2)
 			die(_("--all can't be combined with refspecs"));
 	}
 	if (flags & TRANSPORT_PUSH_MIRROR) {
 		if (tags)
-			die(_("--mirror and --tags are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--mirror", "--tags");
 		if (argc >= 2)
 			die(_("--mirror can't be combined with refspecs"));
 	}
 	if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
-		die(_("--all and --mirror are incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "--all", "--mirror");
 
 	if (!is_empty_cas(&cas) && (flags & TRANSPORT_PUSH_FORCE_IF_INCLUDES))
 		cas.use_force_if_includes = 1;
builtin/rebase.c +3 -3
index 34b4744e5f3..16e6053b14a 100644
@@ -1190,13 +1190,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
 	if (keep_base) {
 		if (options.onto_name)
-			die(_("cannot combine '--keep-base' with '--onto'"));
+			die(_("options '%s' and '%s' cannot be used together"), "--keep-base", "--onto");
 		if (options.root)
-			die(_("cannot combine '--keep-base' with '--root'"));
+			die(_("options '%s' and '%s' cannot be used together"), "--keep-base", "--root");
 	}
 
 	if (options.root && options.fork_point > 0)
-		die(_("cannot combine '--root' with '--fork-point'"));
+		die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
 
 	if (action != ACTION_NONE && !in_progress)
 		die(_("No rebase in progress?"));
builtin/repack.c +2 -2
index 9b0be6a6ab3..b7b54781bd2 100644
@@ -681,7 +681,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	if (keep_unreachable &&
 	    (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
-		die(_("--keep-unreachable and -A are incompatible"));
+		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "-A");
 
 	if (write_bitmaps < 0) {
 		if (!write_midx &&
@@ -712,7 +712,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	if (geometric_factor) {
 		if (pack_everything)
-			die(_("--geometric is incompatible with -A, -a"));
+			die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a");
 		init_pack_geometry(&geometry);
 		split_pack_geometry(geometry, geometric_factor);
 	}
builtin/reset.c +2 -2
index b1ff699b43a..248998fd6fa 100644
@@ -423,7 +423,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (pathspec.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
@@ -459,7 +459,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	if (patch_mode) {
 		if (reset_type != NONE)
-			die(_("--patch is incompatible with --{hard,mixed,soft}"));
+			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
 		return run_add_interactive(rev, "--patch=reset", &pathspec);
 	}
builtin/rev-list.c +1 -1
index 36cb909ebaa..c1a3b0b3591 100644
@@ -538,7 +538,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 		const char *arg = argv[i];
 		if (skip_prefix(arg, "--missing=", &arg)) {
 			if (revs.exclude_promisor_objects)
-				die(_("cannot combine --exclude-promisor-objects and --missing"));
+				die(_("options '%s' and '%s' cannot be used together"), "--exclude-promisor-objects", "--missing");
 			if (parse_missing_action_value(arg))
 				break;
 		}
builtin/show-branch.c +2 -2
index f1e8318592c..e12c5e80e3e 100644
@@ -707,8 +707,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 			 *
 			 * Also --all and --remotes do not make sense either.
 			 */
-			die(_("--reflog is incompatible with --all, --remotes, "
-			      "--independent or --merge-base"));
+			die(_("options '%s' and '%s' cannot be used together"), "--reflog",
+				"--all/--remotes/--independent/--merge-base");
 	}
 
 	/* If nothing is specified, show all branches by default */
builtin/stash.c +2 -2
index 18c812bbe03..4d793bd0b52 100644
@@ -1700,10 +1700,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 
 	if (pathspec_from_file) {
 		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (only_staged)
-			die(_("--pathspec-from-file is incompatible with --staged"));
+			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--staged");
 
 		if (ps.nr)
 			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
builtin/tag.c +2 -2
index 41863c5ab77..dfdcfd37956 100644
@@ -522,7 +522,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	finalize_colopts(&colopts, -1);
 	if (cmdmode == 'l' && filter.lines != -1) {
 		if (explicitly_enable_column(colopts))
-			die(_("--column and -n are incompatible"));
+			die(_("options '%s' and '%s' cannot be used together"), "--column", "-n");
 		colopts = 0;
 	}
 	sorting = ref_sorting_options(&sorting_options);
@@ -564,7 +564,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 
 	if (msg.given || msgfile) {
 		if (msg.given && msgfile)
-			die(_("only one -F or -m option is allowed."));
+			die(_("options '%s' and '%s' cannot be used together"), "-F", "-m");
 		if (msg.given)
 			strbuf_addbuf(&buf, &(msg.buf));
 		else {
revision.c +10 -10
index 5390a479b30..d28b63a3253 100644
@@ -2300,11 +2300,11 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->left_only = 1;
 	} else if (!strcmp(arg, "--right-only")) {
 		if (revs->left_only)
-			die("--right-only is incompatible with --left-only");
+			die(_("options '%s' and '%s' cannot be used together"), "--right-only", "--left-only");
 		revs->right_only = 1;
 	} else if (!strcmp(arg, "--cherry")) {
 		if (revs->left_only)
-			die("--cherry is incompatible with --left-only");
+			die(_("options '%s' and '%s' cannot be used together"), "--cherry", "--left-only");
 		revs->cherry_mark = 1;
 		revs->right_only = 1;
 		revs->max_parents = 1;
@@ -2313,12 +2313,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->count = 1;
 	} else if (!strcmp(arg, "--cherry-mark")) {
 		if (revs->cherry_pick)
-			die("--cherry-mark is incompatible with --cherry-pick");
+			die(_("options '%s' and '%s' cannot be used together"), "--cherry-mark", "--cherry-pick");
 		revs->cherry_mark = 1;
 		revs->limited = 1; /* needs limit_list() */
 	} else if (!strcmp(arg, "--cherry-pick")) {
 		if (revs->cherry_mark)
-			die("--cherry-pick is incompatible with --cherry-mark");
+			die(_("options '%s' and '%s' cannot be used together"), "--cherry-pick", "--cherry-mark");
 		revs->cherry_pick = 1;
 		revs->limited = 1;
 	} else if (!strcmp(arg, "--objects")) {
@@ -2524,7 +2524,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		return opts;
 	}
 	if (revs->graph && revs->track_linear)
-		die("--show-linear-break and --graph are incompatible");
+		die(_("options '%s' and '%s' cannot be used together"), "--show-linear-break", "--graph");
 
 	return 1;
 }
@@ -2867,22 +2867,22 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	compile_grep_patterns(&revs->grep_filter);
 
 	if (revs->reverse && revs->reflog_info)
-		die("cannot combine --reverse with --walk-reflogs");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--walk-reflogs");
 	if (revs->reflog_info && revs->limited)
 		die("cannot combine --walk-reflogs with history-limiting options");
 	if (revs->rewrite_parents && revs->children.name)
-		die("cannot combine --parents and --children");
+		die(_("options '%s' and '%s' cannot be used together"), "--parents", "--children");
 
 	/*
 	 * Limitations on the graph functionality
 	 */
 	if (revs->reverse && revs->graph)
-		die("cannot combine --reverse with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--graph");
 
 	if (revs->reflog_info && revs->graph)
-		die("cannot combine --walk-reflogs with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--walk-reflogs", "--graph");
 	if (revs->no_walk && revs->graph)
-		die("cannot combine --no-walk with --graph");
+		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
 		die("cannot use --grep-reflog without --walk-reflogs");
 
t/t2026-checkout-pathspec-file.sh +2 -2
index 9db11f86dd6..fbe26de2f90 100755
@@ -149,10 +149,10 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git checkout --pathspec-from-file=list --detach 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --detach" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--detach. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t2072-restore-pathspec-file.sh +1 -1
index b48345bf95f..ad1fc0ed071 100755
@@ -152,7 +152,7 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git restore --pathspec-from-file=list --patch --source=HEAD^1 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t3431-rebase-fork-point.sh +1 -1
index 4c98d99e7e8..1d0b15380ed 100755
@@ -83,7 +83,7 @@ test_expect_success 'git rebase --fork-point with ambigous refname' '
 
 test_expect_success '--fork-point and --root both given' '
 	test_must_fail git rebase --fork-point --root 2>err &&
-	test_i18ngrep "cannot combine" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'rebase.forkPoint set to false' '
t/t3704-add-pathspec-file.sh +3 -3
index 5d5164d1fc6..7e17ae80229 100755
@@ -138,13 +138,13 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git add --pathspec-from-file=list --interactive 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list --edit 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --edit" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t3909-stash-pathspec-file.sh +1 -1
index 55e050cfd4d..aae2b25f766 100755
@@ -88,7 +88,7 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git stash push --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t5606-clone-options.sh +1 -1
index d822153e4d2..3af3577af0b 100755
@@ -54,7 +54,7 @@ test_expect_success 'disallows --bare with --separate-git-dir' '
 
 	test_must_fail git clone --bare --separate-git-dir dot-git-destiation parent clone-bare-sgd 2>err &&
 	test_debug "cat err" &&
-	test_i18ngrep -e "--bare and --separate-git-dir are incompatible" err
+	test_i18ngrep -e "options .--bare. and .--separate-git-dir. cannot be used together" err
 
 '
 
t/t7107-reset-pathspec-file.sh +1 -1
index 15ccb14f7e2..b211fbc0a52 100755
@@ -160,7 +160,7 @@ test_expect_success 'error conditions' '
 	git rm fileA.t &&
 
 	test_must_fail git reset --pathspec-from-file=list --patch 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
t/t7526-commit-pathspec-file.sh +3 -3
index dca62fc48e5..574cf30285c 100755
@@ -141,13 +141,13 @@ test_expect_success 'error conditions' '
 	>empty_list &&
 
 	test_must_fail git commit --pathspec-from-file=list --interactive -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --patch -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err &&
+	test_i18ngrep -e "options .--pathspec-from-file. and .-a. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err &&
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
Signature · 1 line
gitgitgadget
#70 lore raw

PATCH v4 4/11 i18n: standardize "cannot open" and "cannot read"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 archive.c       | 4 ++--
 builtin/fetch.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
archive.c +2 -2
index e85ba169088..78d35467008 100644
@@ -185,7 +185,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
 
 	buffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);
 	if (!buffer)
-		return error(_("cannot read %s"), oid_to_hex(oid));
+		return error(_("cannot read '%s'"), oid_to_hex(oid));
 	err = write_entry(args, oid, path.buf, path.len, mode, buffer, size);
 	free(buffer);
 	return err;
@@ -338,7 +338,7 @@ int write_archive_entries(struct archiver_args *args,
 
 		strbuf_reset(&content);
 		if (strbuf_read_file(&content, path, info->stat.st_size) < 0)
-			err = error_errno(_("could not read '%s'"), path);
+			err = error_errno(_("cannot read '%s'"), path);
 		else
 			err = write_entry(args, &fake_oid, path_in_archive.buf,
 					  path_in_archive.len,
builtin/fetch.c +2 -2
index 2c584c85812..c0855c363fd 100644
@@ -996,7 +996,7 @@ static int open_fetch_head(struct fetch_head *fetch_head)
 	if (write_fetch_head) {
 		fetch_head->fp = fopen(filename, "a");
 		if (!fetch_head->fp)
-			return error_errno(_("cannot open %s"), filename);
+			return error_errno(_("cannot open '%s'"), filename);
 		strbuf_init(&fetch_head->buf, 0);
 	} else {
 		fetch_head->fp = NULL;
@@ -1408,7 +1408,7 @@ static int truncate_fetch_head(void)
 	FILE *fp = fopen_for_writing(filename);
 
 	if (!fp)
-		return error_errno(_("cannot open %s"), filename);
+		return error_errno(_("cannot open '%s'"), filename);
 	fclose(fp);
 	return 0;
 }
Signature · 1 line
gitgitgadget
#71 lore raw

PATCH v4 5/11 i18n: tag.c factorize i18n strings

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)
builtin/tag.c +11 -8
index dfdcfd37956..82e09c1b83d 100644
@@ -483,6 +483,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 	int ret = 0;
+	const char *only_in_list = NULL;
 
 	setup_ref_filter_porcelain_msg();
 
@@ -542,15 +543,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
-	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
-	if (filter.no_commit)
-		die(_("--no-contains option is only allowed in list mode"));
-	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		only_in_list = "-n";
+	else if (filter.with_commit)
+		only_in_list = "--contains";
+	else if (filter.no_commit)
+		only_in_list = "--no-contains";
+	else if (filter.points_at.nr)
+		only_in_list = "--points-at";
+	if (only_in_list)
+		die(_("the '%s' option is only allowed in list mode"), only_in_list);
 	if (filter.reachable_from || filter.unreachable_from)
-		die(_("--merged and --no-merged options are only allowed in list mode"));
+		die(_("'--merged' and '--no-merged' options are only allowed in list mode"));
 	if (cmdmode == 'd') {
 		ret = delete_tags(argv);
 		goto cleanup;
Signature · 1 line
gitgitgadget
#72 lore raw

Re: [PATCH v4 05/11] i18n: tag.c factorize i18n strings

Am 02.01.22 um 18:15 schrieb Jean-Noël Avila via GitGitGadget:

Quoted 32 lines

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)
builtin/tag.c +3 -7
index dfdcfd37956..82e09c1b83d 100644
@@ -483,6 +483,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 	int ret = 0;
+	const char *only_in_list = NULL;
 
 	setup_ref_filter_porcelain_msg();
 
@@ -542,15 +543,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
-	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
-	if (filter.no_commit)
-		die(_("--no-contains option is only allowed in list mode"));
-	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		only_in_list = "-n";
+	else if (filter.with_commit)

builtin/tag.c int cmd_tag(int argc, const char **argv, const char *prefix) · line 556

Quoted 10 lines
builtin/tag.c +8 -1
+		only_in_list = "--contains";
+	else if (filter.no_commit)
+		only_in_list = "--no-contains";
+	else if (filter.points_at.nr)
+		only_in_list = "--points-at";
+	if (only_in_list)
+		die(_("the '%s' option is only allowed in list mode"), only_in_list);
 	if (filter.reachable_from || filter.unreachable_from)
-		die(_("--merged and --no-merged options are only allowed in list mode"));
+		die(_("'--merged' and '--no-merged' options are only allowed in list mode"));

What I meant in my earlier reply was: Shouldn't --merged and --no-merged be handled like the other options that require list mode?

	else if (filter.reachable_from)
		only_in_list = "--merged";
	else if (filter.unreachable_from)
		only_in_list = "--no-merged";
Quoted 3 lines
builtin/tag.c +0 -0
 	if (cmdmode == 'd') {
 		ret = delete_tags(argv);
 		goto cleanup;
#73 lore raw

Re: [PATCH v4 05/11] i18n: tag.c factorize i18n strings

Quoted 47 lines · On Sunday, 2 January 2022 18:37:02 CET René Scharfe wrote:

Am 02.01.22 um 18:15 schrieb Jean-Noël Avila via GitGitGadget:

Quoted 32 lines

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 builtin/tag.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)
builtin/tag.c +3 -7
index dfdcfd37956..82e09c1b83d 100644
@@ -483,6 +483,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 	int ret = 0;
+	const char *only_in_list = NULL;
 
 	setup_ref_filter_porcelain_msg();
 
@@ -542,15 +543,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
-	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
-	if (filter.no_commit)
-		die(_("--no-contains option is only allowed in list mode"));
-	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
+		only_in_list = "-n";
+	else if (filter.with_commit)

builtin/tag.c int cmd_tag(int argc, const char **argv, const char *prefix) · line 556

Quoted 10 lines
builtin/tag.c +8 -1
+		only_in_list = "--contains";
+	else if (filter.no_commit)
+		only_in_list = "--no-contains";
+	else if (filter.points_at.nr)
+		only_in_list = "--points-at";
+	if (only_in_list)
+		die(_("the '%s' option is only allowed in list mode"), only_in_list);
 	if (filter.reachable_from || filter.unreachable_from)
-		die(_("--merged and --no-merged options are only allowed in list mode"));
+		die(_("'--merged' and '--no-merged' options are only allowed in list mode"));

What I meant in my earlier reply was: Shouldn't --merged and --no-merged be handled like the other options that require list mode?

Quoted 5 lines
	else if (filter.reachable_from)
		only_in_list = "--merged";
	else if (filter.unreachable_from)
		only_in_list = "--no-merged";

Oh. That's neat! Sorry for having missed that.

#74 lore raw

PATCH v4 6/11 i18n: factorize "--foo requires --bar" and the like

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

They are all replaced by "the option '%s' requires '%s'", which is a new string but replaces 17 previous unique strings.

---
 archive.c                         | 2 +-
 builtin/add.c                     | 4 ++--
 builtin/checkout.c                | 2 +-
 builtin/commit.c                  | 2 +-
 builtin/fast-export.c             | 2 +-
 builtin/index-pack.c              | 2 +-
 builtin/log.c                     | 2 +-
 builtin/reset.c                   | 4 ++--
 builtin/rm.c                      | 2 +-
 builtin/stash.c                   | 2 +-
 builtin/worktree.c                | 2 +-
 fetch-pack.c                      | 2 +-
 http-fetch.c                      | 4 ++--
 revision.c                        | 2 +-
 t/t2026-checkout-pathspec-file.sh | 2 +-
 t/t2072-restore-pathspec-file.sh  | 2 +-
 t/t3601-rm-pathspec-file.sh       | 2 +-
 t/t3704-add-pathspec-file.sh      | 2 +-
 t/t3909-stash-pathspec-file.sh    | 2 +-
 t/t7107-reset-pathspec-file.sh    | 2 +-
 t/t7526-commit-pathspec-file.sh   | 2 +-
 21 files changed, 24 insertions(+), 24 deletions(-)
archive.c +1 -1
index 78d35467008..d571249cf39 100644
@@ -577,7 +577,7 @@ static int parse_archive_args(int argc, const char **argv,
 	if (remote)
 		die(_("Unexpected option --remote"));
 	if (exec)
-		die(_("Option --exec can only be used together with --remote"));
+		die(_("the option '%s' requires '%s'"), "--exec", "--remote");
 	if (output)
 		die(_("Unexpected option --output"));
 	if (is_remote && args->extra_files.nr)
builtin/add.c +2 -2
index 4b2754345ad..067ec53d69f 100644
@@ -541,7 +541,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		die(_("options '%s' and '%s' cannot be used together"), "-A", "-u");
 
 	if (!show_only && ignore_missing)
-		die(_("Option --ignore-missing can only be used together with --dry-run"));
+		die(_("the option '%s' requires '%s'"), "--ignore-missing", "--dry-run");
 
 	if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
 			  chmod_arg[1] != 'x' || chmod_arg[2]))
@@ -573,7 +573,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_SYMLINK_LEADING_PATH,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (require_pathspec && pathspec.nr == 0) {
builtin/checkout.c +1 -1
index 73f5a6fbfa1..af5fa8228eb 100644
@@ -1758,7 +1758,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				    0,
 				    prefix, opts->pathspec_from_file, opts->pathspec_file_nul);
 	} else if (opts->pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	opts->pathspec.recursive = 1;
builtin/commit.c +1 -1
index 067c795ca4b..49e7477747f 100644
@@ -367,7 +367,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 				    PATHSPEC_PREFER_FULL,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (!pathspec.nr && (also || (only && !allow_empty &&
builtin/fast-export.c +1 -1
index 1f8fe7b3ac1..f4d9aa1e8d1 100644
@@ -1254,7 +1254,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		usage_with_options (fast_export_usage, options);
 
 	if (anonymized_seeds.cmpfn && !anonymize)
-		die(_("--anonymize-map without --anonymize does not make sense"));
+		die(_("the option '%s' requires '%s'"), "--anonymize-map", "--anonymize");
 
 	if (refspecs_list.nr) {
 		int i;
builtin/index-pack.c +1 -1
index 30ce2ac746d..3c2e6aee3cc 100644
@@ -1845,7 +1845,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	if (!pack_name && !from_stdin)
 		usage(index_pack_usage);
 	if (fix_thin_pack && !from_stdin)
-		die(_("--fix-thin cannot be used without --stdin"));
+		die(_("the option '%s' requires '%s'"), "--fix-thin", "--stdin");
 	if (from_stdin && !startup_info->have_repository)
 		die(_("--stdin requires a git repository"));
 	if (from_stdin && hash_algo)
builtin/log.c +1 -1
index 74b41db1cee..ded042f3e01 100644
@@ -2112,7 +2112,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	if (creation_factor < 0)
 		creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
 	else if (!rdiff_prev)
-		die(_("--creation-factor requires --range-diff"));
+		die(_("the option '%s' requires '%s'"), "--creation-factor", "--range-diff");
 
 	if (rdiff_prev) {
 		if (!cover_letter && total != 1)
builtin/reset.c +2 -2
index 248998fd6fa..4779e70dfbe 100644
@@ -432,7 +432,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_PREFER_FULL,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
@@ -490,7 +490,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		    _(reset_type_names[reset_type]));
 
 	if (intent_to_add && reset_type != MIXED)
-		die(_("-N can only be used with --mixed"));
+		die(_("the option '%s' requires '%s'"), "-N", "--mixed");
 
 	prepare_repo_settings(the_repository);
 	the_repository->settings.command_requires_full_index = 0;
builtin/rm.c +1 -1
index 3d0967cdc11..cfdf24cf49a 100644
@@ -278,7 +278,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 				    PATHSPEC_PREFER_CWD,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	if (!pathspec.nr)
builtin/stash.c +1 -1
index 4d793bd0b52..3e3743fd5a3 100644
@@ -1712,7 +1712,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
 				    prefix, pathspec_from_file, pathspec_file_nul);
 	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
+		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
 	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
builtin/worktree.c +1 -1
index 27b60732a22..78e146bd3cd 100644
@@ -505,7 +505,7 @@ static int add(int ac, const char **av, const char *prefix)
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
 		die(_("options '%s', '%s', and '%s' cannot be used together"),"-b", "-B", "--detach");
 	if (lock_reason && !keep_locked)
-		die(_("--reason requires --lock"));
+		die(_("the option '%s' requires '%s'"), "--reason", "--lock");
 	if (lock_reason)
 		opts.keep_locked = lock_reason;
 	else if (keep_locked)
fetch-pack.c +1 -1
index 34987a2c30d..dd6ec449f2d 100644
@@ -297,7 +297,7 @@ static int find_common(struct fetch_negotiator *negotiator,
 	struct packet_reader reader;
 
 	if (args->stateless_rpc && multi_ack == 1)
-		die(_("--stateless-rpc requires multi_ack_detailed"));
+		die(_("the option '%s' requires '%s'"), "--stateless-rpc", "multi_ack_detailed");
 
 	packet_reader_init(&reader, fd[0], NULL, 0,
 			   PACKET_READ_CHOMP_NEWLINE |
http-fetch.c +2 -2
index c7c7d391ac5..58b394cd47f 100644
@@ -141,7 +141,7 @@ int cmd_main(int argc, const char **argv)
 
 	if (packfile) {
 		if (!index_pack_args.nr)
-			die(_("--packfile requires --index-pack-args"));
+			die(_("the option '%s' requires '%s'"), "--packfile", "--index-pack-args");
 
 		fetch_single_packfile(&packfile_hash, argv[arg],
 				      index_pack_args.v);
@@ -150,7 +150,7 @@ int cmd_main(int argc, const char **argv)
 	}
 
 	if (index_pack_args.nr)
-		die(_("--index-pack-args can only be used with --packfile"));
+		die(_("the option '%s' requires '%s'"), "--index-pack-args", "--packfile");
 
 	if (commits_on_stdin) {
 		commits = walker_targets_stdin(&commit_id, &write_ref);
revision.c +1 -1
index d28b63a3253..13ccc6829f1 100644
@@ -2884,7 +2884,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	if (revs->no_walk && revs->graph)
 		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
 	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
-		die("cannot use --grep-reflog without --walk-reflogs");
+		die(_("the option '%s' requires '%s'"), "--grep-reflog", "--walk-reflogs");
 
 	if (revs->line_level_traverse &&
 	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
t/t2026-checkout-pathspec-file.sh +1 -1
index fbe26de2f90..9e6b17e2d23 100755
@@ -158,7 +158,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git checkout --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
 '
 
 test_done
t/t2072-restore-pathspec-file.sh +1 -1
index ad1fc0ed071..af67ca7d52b 100755
@@ -158,7 +158,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	test_must_fail git restore --pathspec-from-file=empty_list --source=HEAD^1 2>err &&
 	test_i18ngrep -e "you must specify path(s) to restore" err
t/t3601-rm-pathspec-file.sh +1 -1
index b2a8db69afc..bbed67f8ef5 100755
@@ -70,7 +70,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git rm --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	>empty_list &&
 	test_must_fail git rm --pathspec-from-file=empty_list 2>err &&
t/t3704-add-pathspec-file.sh +1 -1
index 7e17ae80229..47ad96bf661 100755
@@ -150,7 +150,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git add --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	# This case succeeds, but still prints to stderr
 	git add --pathspec-from-file=empty_list 2>err &&
t/t3909-stash-pathspec-file.sh +1 -1
index aae2b25f766..fde4625cfcb 100755
@@ -94,7 +94,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git stash push --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
 '
 
 test_done
t/t7107-reset-pathspec-file.sh +1 -1
index b211fbc0a52..f753e3229e2 100755
@@ -166,7 +166,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git reset --pathspec-file-nul 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	test_must_fail git reset --soft --pathspec-from-file=list 2>err &&
 	test_i18ngrep -e "fatal: Cannot do soft reset with paths" err &&
t/t7526-commit-pathspec-file.sh +1 -1
index 574cf30285c..ea69e3a6ad1 100755
@@ -153,7 +153,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
 
 	test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err &&
-	test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
+	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
 
 	test_must_fail git commit --pathspec-from-file=empty_list --include -m "Commit" 2>err &&
 	test_i18ngrep -e "No paths with --include/--only does not make sense." err &&
Signature · 1 line
gitgitgadget
#75 lore raw

PATCH v4 7/11 i18n: factorize "no directory given for --foo"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 git.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
git.c +3 -3
index 7edafd8ecff..edda922ce6d 100644
@@ -185,7 +185,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--git-dir")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for --git-dir\n" ));
+				fprintf(stderr, _("no directory given for '%s' option\n" ), "--git-dir");
 				usage(git_usage_string);
 			}
 			setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
@@ -213,7 +213,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--work-tree")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for --work-tree\n" ));
+				fprintf(stderr, _("no directory given for '%s' option\n" ), "--work-tree");
 				usage(git_usage_string);
 			}
 			setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
@@ -297,7 +297,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "-C")) {
 			if (*argc < 2) {
-				fprintf(stderr, _("no directory given for -C\n" ));
+				fprintf(stderr, _("no directory given for '%s' option\n" ), "-C");
 				usage(git_usage_string);
 			}
 			if ((*argv)[1][0]) {
Signature · 1 line
gitgitgadget
#76 lore raw

PATCH v4 8/11 i18n: refactor "unrecognized %(foo) argument" strings

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 ref-filter.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
ref-filter.c +7 -7
index 7260fce31d0..adbcc680812 100644
@@ -341,7 +341,7 @@ static int objectsize_atom_parser(struct ref_format *format, struct used_atom *a
 		else
 			oi.info.disk_sizep = &oi.disk_size;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(objectsize) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "objectsize", arg);
 	return 0;
 }
 
@@ -374,7 +374,7 @@ static int subject_atom_parser(struct ref_format *format, struct used_atom *atom
 	else if (!strcmp(arg, "sanitize"))
 		atom->u.contents.option = C_SUB_SANITIZE;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(subject) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "subject", arg);
 	return 0;
 }
 
@@ -428,7 +428,7 @@ static int contents_atom_parser(struct ref_format *format, struct used_atom *ato
 		if (strtoul_ui(arg, 10, &atom->u.contents.nlines))
 			return strbuf_addf_ret(err, -1, _("positive value expected contents:lines=%s"), arg);
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(contents) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "contents", arg);
 	return 0;
 }
 
@@ -440,7 +440,7 @@ static int raw_atom_parser(struct ref_format *format, struct used_atom *atom,
 	else if (!strcmp(arg, "size"))
 		atom->u.raw_data.option = RAW_LENGTH;
 	else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(raw) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "raw", arg);
 	return 0;
 }
 
@@ -459,7 +459,7 @@ static int oid_atom_parser(struct ref_format *format, struct used_atom *atom,
 		if (atom->u.oid.length < MINIMUM_ABBREV)
 			atom->u.oid.length = MINIMUM_ABBREV;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized argument '%s' in %%(%s)"), arg, atom->name);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), atom->name, arg);
 	return 0;
 }
 
@@ -531,7 +531,7 @@ static int align_atom_parser(struct ref_format *format, struct used_atom *atom,
 		else if ((position = parse_align_position(s)) >= 0)
 			align->position = position;
 		else {
-			strbuf_addf(err, _("unrecognized %%(align) argument: %s"), s);
+			strbuf_addf(err, _("unrecognized %%(%s) argument: %s"), "align", s);
 			string_list_clear(&params, 0);
 			return -1;
 		}
@@ -557,7 +557,7 @@ static int if_atom_parser(struct ref_format *format, struct used_atom *atom,
 	} else if (skip_prefix(arg, "notequals=", &atom->u.if_then_else.str)) {
 		atom->u.if_then_else.cmp_status = COMPARE_UNEQUAL;
 	} else
-		return strbuf_addf_ret(err, -1, _("unrecognized %%(if) argument: %s"), arg);
+		return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), "if", arg);
 	return 0;
 }
 
Signature · 1 line
gitgitgadget
#77 lore raw

PATCH v4 9/11 i18n: factorize "--foo outside a repository"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 apply.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
apply.c +3 -3
index 609814e9708..b86f8d201a9 100644
@@ -136,7 +136,7 @@ int check_apply_state(struct apply_state *state, int force_apply)
 		return error(_("options '%s' and '%s' cannot be used together"), "--reject",  "--3way");
 	if (state->threeway) {
 		if (is_not_gitdir)
-			return error(_("--3way outside a repository"));
+			return error(_("'%s' outside a repository"), "--3way");
 		state->check_index = 1;
 	}
 	if (state->apply_with_reject) {
@@ -147,10 +147,10 @@ int check_apply_state(struct apply_state *state, int force_apply)
 	if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor))
 		state->apply = 0;
 	if (state->check_index && is_not_gitdir)
-		return error(_("--index outside a repository"));
+		return error(_("'%s' outside a repository"), "--index");
 	if (state->cached) {
 		if (is_not_gitdir)
-			return error(_("--cached outside a repository"));
+			return error(_("'%s' outside a repository"), "--cached");
 		state->check_index = 1;
 	}
 	if (state->ita_only && (state->check_index || is_not_gitdir))
Signature · 1 line
gitgitgadget
#78 lore raw

PATCH v4 10/11 i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

---
 ref-filter.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
ref-filter.c +4 -4
index adbcc680812..f7a2f17bfd9 100644
@@ -841,7 +841,7 @@ static void if_then_else_handler(struct ref_formatting_stack **stack)
 	struct if_then_else *if_then_else = (struct if_then_else *)cur->at_end_data;
 
 	if (!if_then_else->then_atom_seen)
-		die(_("format: %%(if) atom used without a %%(then) atom"));
+		die(_("format: %%(%s) atom used without a %%(%s) atom"), "if", "then");
 
 	if (if_then_else->else_atom_seen) {
 		/*
@@ -907,7 +907,7 @@ static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	if (cur->at_end == if_then_else_handler)
 		if_then_else = (struct if_then_else *)cur->at_end_data;
 	if (!if_then_else)
-		return strbuf_addf_ret(err, -1, _("format: %%(then) atom used without an %%(if) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "then", "if");
 	if (if_then_else->then_atom_seen)
 		return strbuf_addf_ret(err, -1, _("format: %%(then) atom used more than once"));
 	if (if_then_else->else_atom_seen)
@@ -943,9 +943,9 @@ static int else_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
 	if (prev->at_end == if_then_else_handler)
 		if_then_else = (struct if_then_else *)prev->at_end_data;
 	if (!if_then_else)
-		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without an %%(if) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "else", "if");
 	if (!if_then_else->then_atom_seen)
-		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without a %%(then) atom"));
+		return strbuf_addf_ret(err, -1, _("format: %%(%s) atom used without a %%(%s) atom"), "else", "then");
 	if (if_then_else->else_atom_seen)
 		return strbuf_addf_ret(err, -1, _("format: %%(else) atom used more than once"));
 	if_then_else->else_atom_seen = 1;
Signature · 1 line
gitgitgadget
#79 lore raw

PATCH v4 11/11 i18n: turn even more messages into "cannot be used together" ones

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Even if some of these messages are not subject to gettext i18n, this helps bring a single style of message for a given error type.

---
 builtin/add.c                             |  2 +-
 builtin/am.c                              |  6 +++---
 builtin/cat-file.c                        |  2 +-
 builtin/checkout.c                        |  6 +++---
 builtin/clone.c                           |  4 ++--
 builtin/commit.c                          |  9 +++++----
 builtin/describe.c                        |  4 ++--
 builtin/rebase.c                          |  4 ++--
 builtin/reset.c                           |  2 +-
 builtin/rev-list.c                        |  2 +-
 builtin/rm.c                              |  2 +-
 builtin/stash.c                           |  2 +-
 diff.c                                    | 12 ++++++++----
 t/t2026-checkout-pathspec-file.sh         |  2 +-
 t/t2072-restore-pathspec-file.sh          |  2 +-
 t/t3601-rm-pathspec-file.sh               |  2 +-
 t/t3704-add-pathspec-file.sh              |  2 +-
 t/t3909-stash-pathspec-file.sh            |  2 +-
 t/t4209-log-pickaxe.sh                    |  4 ++--
 t/t5606-clone-options.sh                  |  2 +-
 t/t7107-reset-pathspec-file.sh            |  2 +-
 t/t7500-commit-template-squash-signoff.sh | 11 ++++++-----
 t/t7526-commit-pathspec-file.sh           |  2 +-
 23 files changed, 47 insertions(+), 41 deletions(-)
builtin/add.c +1 -1
index 067ec53d69f..84dff3e7969 100644
@@ -566,7 +566,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
 
 		parse_pathspec_file(&pathspec, PATHSPEC_ATTR,
 				    PATHSPEC_PREFER_FULL |
builtin/am.c +3 -3
index 8677ea2348a..68a190dd9f5 100644
@@ -2230,9 +2230,9 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
 	}
 
 	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
-		return error(_("--show-current-patch=%s is incompatible with "
-			       "--show-current-patch=%s"),
-			     arg, valid_modes[resume->sub_mode]);
+		return error(_("options '%s=%s' and '%s=%s' "
+					   "cannot be used together"),
+					 "--show-current-patch", "--show-current-patch", arg, valid_modes[resume->sub_mode]);
 
 	resume->mode = RESUME_SHOW_PATCH;
 	resume->sub_mode = new_value;
builtin/cat-file.c +1 -1
index 86fc03242b8..d94050e6c18 100644
@@ -729,7 +729,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
 	}
 
 	if (force_path && batch.enabled) {
-		error("--path=<path> incompatible with --batch");
+		error("options '--path=<path>' and '--batch' cannot be used together");
 		usage_with_options(cat_file_usage, options);
 	}
 
builtin/checkout.c +3 -3
index af5fa8228eb..eb3a69c2120 100644
@@ -1635,8 +1635,8 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 	}
 
 	if ((!!opts->new_branch + !!opts->new_branch_force + !!opts->new_orphan_branch) > 1)
-		die(_("-%c, -%c and --orphan are mutually exclusive"),
-				cb_option, toupper(cb_option));
+		die(_("options '-%c', '-%c', and '%s' cannot be used together"),
+			cb_option, toupper(cb_option), "--orphan");
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
 		die(_("options '%s' and '%s' cannot be used together"), "-p", "--overlay");
@@ -1746,7 +1746,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 
 	if (opts->pathspec_from_file) {
 		if (opts->pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
 
 		if (opts->force_detach)
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--detach");
builtin/clone.c +2 -2
index 13bdbe14b2f..8b79666e3a7 100644
@@ -900,8 +900,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
 	if (option_bare) {
 		if (option_origin)
-			die(_("--bare and --origin %s options are incompatible."),
-			    option_origin);
+			die(_("options '%s' and '%s %s' cannot be used together"),
+			    "--bare", "--origin", option_origin);
 		if (real_git_dir)
 			die(_("options '%s' and '%s' cannot be used together"), "--bare", "--separate-git-dir");
 		option_no_checkout = 1;
builtin/commit.c +5 -4
index 49e7477747f..b9ed0374e30 100644
@@ -361,7 +361,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "-a");
 
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_FULL,
@@ -799,7 +799,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 
 		if (!strcmp(fixup_prefix, "amend")) {
 			if (have_option_m)
-				die(_("cannot combine -m with --fixup:%s"), fixup_message);
+				die(_("options '%s' and '%s:%s' cannot be used together"), "-m", "--fixup", fixup_message);
 			prepare_amend_commit(commit, &sb, &ctx);
 		}
 	} else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
@@ -1229,9 +1229,10 @@ static void check_fixup_reword_options(int argc, const char *argv[]) {
 			die(_("You are in the middle of a cherry-pick -- cannot reword."));
 	}
 	if (argc)
-		die(_("cannot combine reword option of --fixup with path '%s'"), *argv);
+		die(_("reword option of '%s' and path '%s' cannot be used together"), "--fixup", *argv);
 	if (patch_interactive || interactive || all || also || only)
-		die(_("reword option of --fixup is mutually exclusive with --patch/--interactive/--all/--include/--only"));
+		die(_("reword option of '%s' and '%s' cannot be used together"),
+			"--fixup", "--patch/--interactive/--all/--include/--only");
 }
 
 static int parse_and_validate_options(int argc, const char *argv[],
builtin/describe.c +2 -2
index fd5ba1fc604..42159cd26bd 100644
@@ -670,9 +670,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 		}
 		describe("HEAD", 1);
 	} else if (dirty) {
-		die(_("--dirty is incompatible with commit-ishes"));
+		die(_("option '%s' and commit-ishes cannot be used together"), "--dirty");
 	} else if (broken) {
-		die(_("--broken is incompatible with commit-ishes"));
+		die(_("option '%s' and commit-ishes cannot be used together"), "--broken");
 	} else {
 		while (argc-- > 0)
 			describe(*argv++, argc == 0);
builtin/rebase.c +2 -2
index 16e6053b14a..36490d06c8a 100644
@@ -1460,8 +1460,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
 		if (i >= 0) {
 			if (is_merge(&options))
-				die(_("cannot combine apply options with "
-				      "merge options"));
+				die(_("apply options and merge options "
+					  "cannot be used together"));
 			else
 				options.type = REBASE_APPLY;
 		}
builtin/reset.c +1 -1
index 4779e70dfbe..b97745ee94e 100644
@@ -426,7 +426,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--patch");
 
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_FULL,
builtin/rev-list.c +1 -1
index c1a3b0b3591..777558e9b06 100644
@@ -676,7 +676,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	if (revs.count &&
 	    (revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
 	    (revs.left_right || revs.cherry_mark))
-		die(_("marked counting is incompatible with --objects"));
+		die(_("marked counting and '%s' cannot be used together"), "--objects");
 
 	save_commit_buffer = (revs.verbose_header ||
 			      revs.grep_filter.pattern_list ||
builtin/rm.c +1 -1
index cfdf24cf49a..127a6f0220c 100644
@@ -272,7 +272,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
 	if (pathspec_from_file) {
 		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
 
 		parse_pathspec_file(&pathspec, 0,
 				    PATHSPEC_PREFER_CWD,
builtin/stash.c +1 -1
index 3e3743fd5a3..7b1876b3e31 100644
@@ -1706,7 +1706,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 			die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--staged");
 
 		if (ps.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
+			die(_("'%s' and pathspec arguments cannot be used together"), "--pathspec-from-file");
 
 		parse_pathspec_file(&ps, 0,
 				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
diff.c +8 -4
index 02ce779e43a..da5fc81a543 100644
@@ -4639,16 +4639,20 @@ void diff_setup_done(struct diff_options *options)
 		options->set_default(options);
 
 	if (HAS_MULTI_BITS(options->output_format & check_mask))
-		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
+		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
+			"--name-only", "--name-status", "--check", "-s");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
-		die(_("options '%s', '%s', and '%s' cannot be used together"), "-G", "-S", "--find-object");
+		die(_("options '%s', '%s', and '%s' cannot be used together"),
+			"-G", "-S", "--find-object");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
-		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
+		die(_("options '%s' and '%s' cannot be used together, use '%s' with '%s'"),
+			"-G", "--pickaxe-regex", "--pickaxe-regex", "-S");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_ALL_OBJFIND_MASK))
-		die(_("--pickaxe-all and --find-object are mutually exclusive, use --pickaxe-all with -G and -S"));
+		die(_("options '%s' and '%s' cannot be used together, use '%s' with '%s' and '%s'"),
+			"--pickaxe-all", "--find-object", "--pickaxe-all", "-G", "-S");
 
 	/*
 	 * Most of the time we can say "there are changes"
t/t2026-checkout-pathspec-file.sh +1 -1
index 9e6b17e2d23..9c651aefbca 100755
@@ -155,7 +155,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git checkout --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
t/t2072-restore-pathspec-file.sh +1 -1
index af67ca7d52b..c22669b39f9 100755
@@ -155,7 +155,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
t/t3601-rm-pathspec-file.sh +1 -1
index bbed67f8ef5..a2a0c820fe3 100755
@@ -67,7 +67,7 @@ test_expect_success 'error conditions' '
 	echo fileA.t >list &&
 
 	test_must_fail git rm --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git rm --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
t/t3704-add-pathspec-file.sh +1 -1
index 47ad96bf661..4e6b5177c93 100755
@@ -147,7 +147,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err &&
 
 	test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git add --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
t/t3909-stash-pathspec-file.sh +1 -1
index fde4625cfcb..dead9f18d93 100755
@@ -91,7 +91,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git stash push --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err
t/t4209-log-pickaxe.sh +2 -2
index 4f820f8597d..7f6bb27f141 100755
@@ -72,12 +72,12 @@ test_expect_success 'usage' '
 	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err
+	grep "cannot be used together" err
 '
 
 test_expect_success 'usage: --pickaxe-regex' '
 	test_expect_code 128 git log -Gregex --pickaxe-regex 2>err &&
-	grep "mutually exclusive" err
+	grep "cannot be used together" err
 '
 
 test_expect_success 'usage: --no-pickaxe-regex' '
t/t5606-clone-options.sh +1 -1
index 3af3577af0b..8f676d6b0c0 100755
@@ -46,7 +46,7 @@ test_expect_success 'disallows --bare with --origin' '
 
 	test_must_fail git clone -o foo --bare parent clone-bare-o 2>err &&
 	test_debug "cat err" &&
-	test_i18ngrep -e "--bare and --origin foo options are incompatible" err
+	test_i18ngrep -e "options .--bare. and .--origin foo. cannot be used together" err
 
 '
 
t/t7107-reset-pathspec-file.sh +1 -1
index f753e3229e2..523efbecde1 100755
@@ -163,7 +163,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git reset --pathspec-file-nul 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
t/t7500-commit-template-squash-signoff.sh +6 -5
index 8dd0f988129..91964653a0b 100755
@@ -359,14 +359,14 @@ test_expect_success '--fixup=reword: ignores staged changes' '
 
 test_expect_success '--fixup=reword: error out with -m option' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine -m with --fixup:reword" >expect &&
+	echo "fatal: options '\''-m'\'' and '\''--fixup:reword'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -m "reword commit message" 2>actual &&
 	test_cmp expect actual
 '
 
 test_expect_success '--fixup=amend: error out with -m option' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine -m with --fixup:amend" >expect &&
+	echo "fatal: options '\''-m'\'' and '\''--fixup:amend'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=amend:HEAD~ -m "amend commit message" 2>actual &&
 	test_cmp expect actual
 '
@@ -421,8 +421,9 @@ test_expect_success 'amend! commit allows empty commit msg body with --allow-emp
 
 test_fixup_reword_opt () {
 	test_expect_success "--fixup=reword: incompatible with $1" "
-		echo 'fatal: reword option of --fixup is mutually exclusive with'\
-			'--patch/--interactive/--all/--include/--only' >expect &&
+		echo 'fatal: reword option of '\''--fixup'\'' and' \
+			''\''--patch/--interactive/--all/--include/--only'\' \
+			'cannot be used together' >expect &&
 		test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
 		test_cmp expect actual
 	"
@@ -435,7 +436,7 @@ done
 
 test_expect_success '--fixup=reword: give error with pathsec' '
 	commit_for_rebase_autosquash_setup &&
-	echo "fatal: cannot combine reword option of --fixup with path '\''foo'\''" >expect &&
+	echo "fatal: reword option of '\''--fixup'\'' and path '\''foo'\'' cannot be used together" >expect &&
 	test_must_fail git commit --fixup=reword:HEAD~ -- foo 2>actual &&
 	test_cmp expect actual
 '
t/t7526-commit-pathspec-file.sh +1 -1
index ea69e3a6ad1..ad011bb9f15 100755
@@ -150,7 +150,7 @@ test_expect_success 'error conditions' '
 	test_i18ngrep -e "options .--pathspec-from-file. and .-a. cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err &&
-	test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
+	test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err &&
 
 	test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err &&
 	test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err &&
Signature · 1 line
gitgitgadget
#80 lore raw

v5 cover Factorization of messages with similar meaning

In reply to Jean-Noël Avila via GitGitGadget

This series is a meager attempt at rationalizing a small fraction of the internationalized messages. Sorry in advance for the dull task of reviewing these insipide patches.

Doing so has some positive effects:

* non-translatable constant strings are kept out of the way for translators
* messages with identical meaning are built identically
* the total number of messages to translate is decreased.

Changes since V1:

* took into account the comments, except for ref-filter.c where the proposed refactoring is not obvious.
* added even more strings to the "cannot be used together" crowd.

Changes since V2:

* fixed change of behaviour in tag.c
* reverted sam changes as per Johannes Sixt comments

Changes since V3:

* apply Oxford comma where needed
* switch all options to " '%s' " style where i18n is applied.

Changes since V4:

* Apply changes by René on tag.c
* cosmetic changes

Jean-Noël Avila (11):
i18n: refactor "foo and bar are mutually exclusive"
i18n: refactor "%s, %s and %s are mutually exclusive"
i18n: turn "options are incompatible" into "cannot be used together"
i18n: standardize "cannot open" and "cannot read"
i18n: tag.c factorize i18n strings
i18n: factorize "--foo requires --bar" and the like
i18n: factorize "no directory given for --foo"
i18n: refactor "unrecognized %(foo) argument" strings
i18n: factorize "--foo outside a repository"
i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"
i18n: turn even more messages into "cannot be used together" ones

 apply.c                                   |  8 +++----
 archive.c                                 |  8 +++----
 builtin/add.c                             | 14 ++++++------
 builtin/am.c                              |  6 ++---
 builtin/branch.c                          |  2 +-
 builtin/cat-file.c                        |  2 +-
 builtin/checkout.c                        | 18 +++++++--------
 builtin/clone.c                           |  6 ++---
 builtin/commit.c                          | 17 +++++++-------
 builtin/describe.c                        |  6 ++---
 builtin/diff-tree.c                       |  2 +-
 builtin/difftool.c                        |  4 ++--
 builtin/fast-export.c                     |  4 ++--
 builtin/fetch.c                           |  8 +++----
 builtin/index-pack.c                      |  4 ++--
 builtin/init-db.c                         |  2 +-
 builtin/log.c                             |  8 +++----
 builtin/ls-files.c                        |  2 +-
 builtin/merge.c                           |  4 ++--
 builtin/pack-objects.c                    |  2 +-
 builtin/push.c                            |  8 +++----
 builtin/rebase.c                          | 10 ++++-----
 builtin/repack.c                          |  4 ++--
 builtin/reset.c                           | 10 ++++-----
 builtin/rev-list.c                        |  4 ++--
 builtin/rm.c                              |  4 ++--
 builtin/show-branch.c                     |  4 ++--
 builtin/stash.c                           |  8 +++----
 builtin/submodule--helper.c               |  4 ++--
 builtin/tag.c                             | 27 ++++++++++++++---------
 builtin/worktree.c                        |  6 ++---
 diff.c                                    | 12 ++++++----
 fetch-pack.c                              |  2 +-
 git.c                                     |  6 ++---
 http-fetch.c                              |  4 ++--
 range-diff.c                              |  2 +-
 ref-filter.c                              | 22 +++++++++---------
 revision.c                                | 22 +++++++++---------
 t/t0001-init.sh                           |  2 +-
 t/t2025-checkout-no-overlay.sh            |  2 +-
 t/t2026-checkout-pathspec-file.sh         |  8 +++----
 t/t2072-restore-pathspec-file.sh          |  6 ++---
 t/t3431-rebase-fork-point.sh              |  2 +-
 t/t3601-rm-pathspec-file.sh               |  4 ++--
 t/t3704-add-pathspec-file.sh              | 10 ++++-----
 t/t3909-stash-pathspec-file.sh            |  6 ++---
 t/t4209-log-pickaxe.sh                    | 10 ++++-----
 t/t5606-clone-options.sh                  |  4 ++--
 t/t7107-reset-pathspec-file.sh            |  6 ++---
 t/t7500-commit-template-squash-signoff.sh | 11 ++++-----
 t/t7526-commit-pathspec-file.sh           | 10 ++++-----
 51 files changed, 189 insertions(+), 178 deletions(-)

base-commit: 2ae0a9cb8298185a94e5998086f380a355dd8907
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1088%2Fjnavila%2Fi18n-refactor-v5
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1088/jnavila/i18n-refactor-v5
Pull-Request: https://github.com/gitgitgadget/git/pull/1088

Range-diff vs v4:

  1:  05af90f5814 =  1:  05af90f5814 i18n: refactor "foo and bar are mutually exclusive"
  2:  e307ea9b998 !  2:  f6a5332d310 i18n: refactor "%s, %s and %s are mutually exclusive"
     @@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix)
       	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
       	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
      -		die(_("-b, -B, and --detach are mutually exclusive"));
     -+		die(_("options '%s', '%s', and '%s' cannot be used together"),"-b", "-B", "--detach");
     ++		die(_("options '%s', '%s', and '%s' cannot be used together"), "-b", "-B", "--detach");
       	if (lock_reason && !keep_locked)
       		die(_("--reason requires --lock"));
       	if (lock_reason)
  3:  d5bfa26e992 !  3:  80390ce08ed i18n: turn "options are incompatible" into "cannot be used together"
     @@ apply.c: int check_apply_state(struct apply_state *state, int force_apply)
       
       	if (state->apply_with_reject && state->threeway)
      -		return error(_("--reject and --3way cannot be used together."));
     -+		return error(_("options '%s' and '%s' cannot be used together"), "--reject",  "--3way");
     ++		return error(_("options '%s' and '%s' cannot be used together"), "--reject", "--3way");
       	if (state->threeway) {
       		if (is_not_gitdir)
       			return error(_("--3way outside a repository"));
  4:  51c53f01dd8 =  4:  49e41dc136f i18n: standardize "cannot open" and "cannot read"
  5:  a9d8a50d666 !  5:  ad58bc8d8a9 i18n: tag.c factorize i18n strings
     @@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)
      -		die(_("--no-contains option is only allowed in list mode"));
      -	if (filter.points_at.nr)
      -		die(_("--points-at option is only allowed in list mode"));
     +-	if (filter.reachable_from || filter.unreachable_from)
     +-		die(_("--merged and --no-merged options are only allowed in list mode"));
      +		only_in_list = "-n";
      +	else if (filter.with_commit)
      +		only_in_list = "--contains";
     @@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)
      +		only_in_list = "--no-contains";
      +	else if (filter.points_at.nr)
      +		only_in_list = "--points-at";
     ++	else if (filter.reachable_from)
     ++		only_in_list = "--merged";
     ++	else if  (filter.unreachable_from)
     ++		only_in_list = "--no-merged";
      +	if (only_in_list)
      +		die(_("the '%s' option is only allowed in list mode"), only_in_list);
     - 	if (filter.reachable_from || filter.unreachable_from)
     --		die(_("--merged and --no-merged options are only allowed in list mode"));
     -+		die(_("'--merged' and '--no-merged' options are only allowed in list mode"));
       	if (cmdmode == 'd') {
       		ret = delete_tags(argv);
       		goto cleanup;
  6:  969946274aa !  6:  fd27beb3f2b i18n: factorize "--foo requires --bar" and the like
     @@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *
       ## builtin/worktree.c ##
      @@ builtin/worktree.c: static int add(int ac, const char **av, const char *prefix)
       	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
     - 		die(_("options '%s', '%s', and '%s' cannot be used together"),"-b", "-B", "--detach");
     + 		die(_("options '%s', '%s', and '%s' cannot be used together"), "-b", "-B", "--detach");
       	if (lock_reason && !keep_locked)
      -		die(_("--reason requires --lock"));
      +		die(_("the option '%s' requires '%s'"), "--reason", "--lock");
  7:  052dc06beeb =  7:  08f5471aeaa i18n: factorize "no directory given for --foo"
  8:  59e1e8aa1b4 =  8:  437aadbc2c9 i18n: refactor "unrecognized %(foo) argument" strings
  9:  39e375c68ab !  9:  7d97ee5dd18 i18n: factorize "--foo outside a repository"

@@ Commit message

## apply.c ##
@@ apply.c: int check_apply_state(struct apply_state *state, int force_apply)
- return error(_("options '%s' and '%s' cannot be used together"), "--reject", "--3way");
+ return error(_("options '%s' and '%s' cannot be used together"), "--reject", "--3way");
if (state->threeway) {
if (is_not_gitdir)
- return error(_("--3way outside a repository"));

 10:  c6161bc3f1a = 10:  226c105559c i18n: ref-filter: factorize "%(foo) atom used without %(bar) atom"
 11:  4fab0db3cc4 = 11:  8bcc814ba00 i18n: turn even more messages into "cannot be used together" ones
Signature · 1 line
gitgitgadget
#81 lore raw

PATCH v5 1/11 i18n: refactor "foo and bar are mutually exclusive"

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use static strings for constant parts of the sentences. They are all turned into "cannot be used together".

---
 builtin/checkout.c             | 2 +-
 builtin/diff-tree.c            | 2 +-
 builtin/fetch.c                | 4 ++--
 builtin/init-db.c              | 2 +-
 builtin/log.c                  | 4 ++--
 builtin/submodule--helper.c    | 4 ++--
 builtin/worktree.c             | 2 +-
 range-diff.c                   | 2 +-
 t/t0001-init.sh                | 2 +-
 t/t2025-checkout-no-overlay.sh | 2 +-
 10 files changed, 13 insertions(+), 13 deletions(-)
builtin/checkout.c +1 -1
index 72beeb49aa9..79014e1cb6c 100644
@@ -1639,7 +1639,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 				cb_option, toupper(cb_option));
 
 	if (opts->overlay_mode == 1 && opts->patch_mode)
-		die(_("-p and --overlay are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "-p", "--overlay");
 
 	if (opts->checkout_index >= 0 || opts->checkout_worktree >= 0) {
 		if (opts->checkout_index < 0)
builtin/diff-tree.c +1 -1
index f33d30d57bf..0e0ac1f1670 100644
@@ -152,7 +152,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
 	}
 
 	if (read_stdin && merge_base)
-		die(_("--stdin and --merge-base are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--stdin", "--merge-base");
 	if (merge_base && opt->pending.nr != 2)
 		die(_("--merge-base only works with two commits"));
 
builtin/fetch.c +2 -2
index f1fe73a3e0f..2c584c85812 100644
@@ -2028,12 +2028,12 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		if (deepen_relative < 0)
 			die(_("negative depth in --deepen is not supported"));
 		if (depth)
-			die(_("--deepen and --depth are mutually exclusive"));
+			die(_("options '%s' and '%s' cannot be used together"), "--deepen", "--depth");
 		depth = xstrfmt("%d", deepen_relative);
 	}
 	if (unshallow) {
 		if (depth)
-			die(_("--depth and --unshallow cannot be used together"));
+			die(_("options '%s' and '%s' cannot be used together"), "--depth", "--unshallow");
 		else if (!is_repository_shallow(the_repository))
 			die(_("--unshallow on a complete repository does not make sense"));
 		else
builtin/init-db.c +1 -1
index 2167796ff2a..546f9c595e7 100644
@@ -557,7 +557,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
 
 	if (real_git_dir && is_bare_repository_cfg == 1)
-		die(_("--separate-git-dir and --bare are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
 
 	if (real_git_dir && !is_absolute_path(real_git_dir))
 		real_git_dir = real_pathdup(real_git_dir, 1);
builtin/log.c +2 -2
index 93ace0dde7d..fad93ad2fc1 100644
@@ -1943,9 +1943,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		numbered = 0;
 
 	if (numbered && keep_subject)
-		die(_("-n and -k are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "-n", "-k");
 	if (keep_subject && subject_prefix)
-		die(_("--subject-prefix/--rfc and -k are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--subject-prefix/--rfc", "-k");
 	rev.preserve_subject = keep_subject;
 
 	argc = setup_revisions(argc, argv, &rev, &s_r_opt);
builtin/submodule--helper.c +2 -2
index 9b25a508e6a..c5d3fc3817f 100644
@@ -1313,7 +1313,7 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 
 	if (files) {
 		if (cached)
-			die(_("--cached and --files are mutually exclusive"));
+			die(_("options '%s' and '%s' cannot be used together"), "--cached", "--files");
 		diff_cmd = DIFF_FILES;
 	}
 
@@ -2972,7 +2972,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
 		die(_("--branch or --default required"));
 
 	if (opt_branch && opt_default)
-		die(_("--branch and --default are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--branch", "--default");
 
 	if (argc != 1 || !(path = argv[0]))
 		usage_with_options(usage, options);
builtin/worktree.c +1 -1
index a396cfdc64e..9a520485769 100644
@@ -699,7 +699,7 @@ static int list(int ac, const char **av, const char *prefix)
 	if (ac)
 		usage_with_options(worktree_usage, options);
 	else if (verbose && porcelain)
-		die(_("--verbose and --porcelain are mutually exclusive"));
+		die(_("options '%s' and '%s' cannot be used together"), "--verbose", "--porcelain");
 	else {
 		struct worktree **worktrees = get_worktrees();
 		int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
range-diff.c +1 -1
index cac89a2f4f2..30a4de5c2d8 100644
@@ -556,7 +556,7 @@ int show_range_diff(const char *range1, const char *range2,
 	struct string_list branch2 = STRING_LIST_INIT_DUP;
 
 	if (range_diff_opts->left_only && range_diff_opts->right_only)
-		res = error(_("--left-only and --right-only are mutually exclusive"));
+		res = error(_("options '%s' and '%s' cannot be used together"), "--left-only", "--right-only");
 
 	if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg))
 		res = error(_("could not parse log for '%s'"), range1);
t/t0001-init.sh +1 -1
index 7603ad2f82b..3235ab4d53c 100755
@@ -331,7 +331,7 @@ test_expect_success 'init with separate gitdir' '
 
 test_expect_success 'explicit bare & --separate-git-dir incompatible' '
 	test_must_fail git init --bare --separate-git-dir goop.git bare.git 2>err &&
-	test_i18ngrep "mutually exclusive" err
+	test_i18ngrep "cannot be used together" err
 '
 
 test_expect_success 'implicit bare & --separate-git-dir incompatible' '
t/t2025-checkout-no-overlay.sh +1 -1
index fa9e0987063..8f13341cf8e 100755
@@ -25,7 +25,7 @@ test_expect_success 'checkout --no-overlay removing last file from directory' '
 
 test_expect_success 'checkout -p --overlay is disallowed' '
 	test_must_fail git checkout -p --overlay HEAD 2>actual &&
-	test_i18ngrep "fatal: -p and --overlay are mutually exclusive" actual
+	test_i18ngrep "fatal: options .-p. and .--overlay. cannot be used together" actual
 '
 
 test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
Signature · 1 line
gitgitgadget
#82 lore raw

PATCH v5 2/11 i18n: refactor "%s, %s and %s are mutually exclusive"

In reply to Jean-Noël Avila via GitGitGadget

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email protected]>

Use placeholders for constant tokens. The strings are turned into "cannot be used together"

---
 builtin/difftool.c     | 2 +-
 builtin/log.c          | 2 +-
 builtin/worktree.c     | 2 +-
 diff.c                 | 2 +-
 t/t4209-log-pickaxe.sh | 6 +++---
 5 files changed, 7 insertions(+), 7 deletions(-)
builtin/difftool.c +1 -1
index 4ee40fe3a06..5beadc07ccd 100644
@@ -733,7 +733,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 		die(_("--dir-diff is incompatible with --no-index"));
 
 	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("--gui, --tool and --extcmd are mutually exclusive"));
+		die(_("options '%s', '%s', and '%s' cannot be used together"), "--gui", "--tool", "--extcmd");
 
 	if (use_gui_tool)
 		setenv("GIT_MERGETOOL_GUI", "true", 1);
builtin/log.c +1 -1
index fad93ad2fc1..74b41db1cee 100644
@@ -1979,7 +1979,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		load_display_notes(&rev.notes_opt);
 
 	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
-		die(_("--stdout, --output, and --output-directory are mutually exclusive"));
+		die(_("options '%s', '%s', and '%s' cannot be used together"), "--stdout", "--output", "--output-directory");
 
 	if (use_stdout) {
 		setup_pager();
builtin/worktree.c +1 -1
index 9a520485769..ec1c59ba53c 100644
@@ -503,7 +503,7 @@ static int add(int ac, const char **av, const char *prefix)
 	opts.checkout = 1;
 	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
 	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
-		die(_("-b, -B, and --detach are mutually exclusive"));
+		die(_("options '%s', '%s', and '%s' cannot be used together"), "-b", "-B", "--detach");
 	if (lock_reason && !keep_locked)
 		die(_("--reason requires --lock"));
 	if (lock_reason)
diff.c +1 -1
index 41076857428..02ce779e43a 100644
@@ -4642,7 +4642,7 @@ void diff_setup_done(struct diff_options *options)
 		die(_("--name-only, --name-status, --check and -s are mutually exclusive"));
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
-		die(_("-G, -S and --find-object are mutually exclusive"));
+		die(_("options '%s', '%s', and '%s' cannot be used together"), "-G", "-S", "--find-object");
 
 	if (HAS_MULTI_BITS(options->pickaxe_opts & DIFF_PICKAXE_KINDS_G_REGEX_MASK))
 		die(_("-G and --pickaxe-regex are mutually exclusive, use --pickaxe-regex with -S"));
t/t4209-log-pickaxe.sh +3 -3
index 75795d0b492..4f820f8597d 100755
@@ -63,13 +63,13 @@ test_expect_success 'usage' '
 	test_i18ngrep "switch.*requires a value" err &&
 
 	test_expect_code 128 git log -Gregex -Sstring 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log -Gregex --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log -Sstring --find-object=HEAD 2>err &&
-	grep "mutually exclusive" err &&
+	grep "cannot be used together" err &&
 
 	test_expect_code 128 git log --pickaxe-all --find-object=HEAD 2>err &&
 	grep "mutually exclusive" err
Signature · 1 line
gitgitgadget