git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 1/4] i18n: factorize more 'incompatible options' messages

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Feb 1, 2022, 21:01 UTC
Message-ID
<220201.86a6fa9tmr.gmgdl@evledraar.gmail.com>
In-Reply-To
<844e01391e1198960072844536d736f51573cac6.1643408644.git.gitgitgadget@gmail.com>
On Fri, Jan 28 2022, Jean-Noël Avila via GitGitGadget wrote:
Show 82 quoted lines
> From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <jn.avila@free.fr>
> [...]
> +void die_if_incompatible_opt3(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name)
> +{
> +	int count = 0;
> +	const char *options[3];
> +
> +	if (opt1)
> +		options[count++] = opt1_name;
> +	if (opt2)
> +		options[count++] = opt2_name;
> +	if (opt3)
> +		options[count++] = opt3_name;
> +	if (count > 2)
> +		die(_("options '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name);
> +	else if (count > 1)
> +		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
> +}
> +
> +void die_if_incompatible_opt4(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name,
> +							  int opt4, const char *opt4_name)
> +{
> +	int count = 0;
> +	const char *options[4];
> +
> +	if (opt1)
> +		options[count++] = opt1_name;
> +	if (opt2)
> +		options[count++] = opt2_name;
> +	if (opt3)
> +		options[count++] = opt3_name;
> +	if (opt4)
> +		options[count++] = opt4_name;
> +	switch (count) {
> +	case 4:
> +		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"), opt1_name, opt2_name, opt3_name, opt4_name);
> +		break;
> +	case 3:
> +		die(_("options '%s', '%s', and '%s' cannot be used together"), options[0], options[1], options[2]);
> +		break;
> +	case 2:
> +		die(_("options '%s' and '%s' cannot be used together"), options[0], options[1]);
> +		break;
> +	default:
> +		break;
> +	}
> +}
> diff --git a/parse-options.h b/parse-options.h
> index e22846d3b7b..cf393839ac4 100644
> --- a/parse-options.h
> +++ b/parse-options.h
> @@ -339,4 +339,13 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);
>  #define OPT_PATHSPEC_FILE_NUL(v)  OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
>  #define OPT_AUTOSTASH(v) OPT_BOOL(0, "autostash", v, N_("automatically stash/stash pop before and after"))
>  
> +void die_if_incompatible_opt3(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name);
> +
> +void die_if_incompatible_opt4(int opt1, const char *opt1_name,
> +							  int opt2, const char *opt2_name,
> +							  int opt3, const char *opt3_name,
> +							  int opt4, const char *opt4_name);
> +
>  #endif
> diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
> index 91964653a0b..5fcaa0b4f2a 100755
> --- a/t/t7500-commit-template-squash-signoff.sh
> +++ b/t/t7500-commit-template-squash-signoff.sh
> @@ -442,7 +442,7 @@ test_expect_success '--fixup=reword: give error with pathsec' '
>  '
>  
>  test_expect_success '--fixup=reword: -F give error message' '
> -	echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
> +	echo "fatal: options '\''-F'\'' and '\''--fixup'\'' cannot be used together" >expect &&
>  	test_must_fail git commit --fixup=reword:HEAD~ -F msg  2>actual &&
>  	test_cmp expect actual
>  '

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

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

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

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

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

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

    --bar is incompatible with --foo

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

    --baz is incompatible with --foo

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

Previous: Johannes SixtNext: Jean-Noël Avila via GitGitGadget
Message 18 of 41 in “Factorize i18n”
  1. 0/4 Factorize i18nJean-Noël Avila via GitGitGadget, Jan 22, 2022
  2. 1/4 i18n: factorize more 'incompatible options' messagesJean-Noël Avila via GitGitGadget, Jan 22, 2022
  3. Johannes SixtJan 24, 2022
  4. Phillip WoodJan 24, 2022
  5. Jean-Noël AVILAJan 25, 2022
  6. Johannes SixtJan 25, 2022
  7. 2/4 i18n: factorize "invalid value" messagesJean-Noël Avila via GitGitGadget, Jan 22, 2022
  8. Phillip WoodJan 24, 2022
  9. 4/4 i18n: transfer variables into placeholders in command synopsisJean-Noël Avila via GitGitGadget, Jan 22, 2022
  10. 3/4 i18n: remove from i18n strings that do not hold translatable partsJean-Noël Avila via GitGitGadget, Jan 22, 2022
  11. 0/4 Factorize i18nJean-Noël Avila via GitGitGadget, Jan 28, 2022
  12. 1/4 i18n: factorize more 'incompatible options' messagesJean-Noël Avila via GitGitGadget, Jan 28, 2022
  13. Johannes SixtJan 28, 2022
  14. Junio C HamanoJan 28, 2022
  15. Johannes SixtJan 29, 2022
  16. Jean-Noël AVILAJan 29, 2022
  17. Johannes SixtJan 29, 2022
  18. Ævar Arnfjörð BjarmasonFeb 1, 2022
  19. 2/4 i18n: factorize "invalid value" messagesJean-Noël Avila via GitGitGadget, Jan 28, 2022
  20. 3/4 i18n: remove from i18n strings that do not hold translatable partsJean-Noël Avila via GitGitGadget, Jan 28, 2022
  21. 4/4 i18n: transfer variables into placeholders in command synopsisJean-Noël Avila via GitGitGadget, Jan 28, 2022
  22. 0/4 Factorize i18nJean-Noël Avila via GitGitGadget, Jan 30, 2022
  23. 1/4 i18n: factorize more 'incompatible options' messagesJean-Noël Avila via GitGitGadget, Jan 30, 2022
  24. Johannes SixtJan 31, 2022
  25. Phillip WoodJan 31, 2022
  26. 2/4 i18n: factorize "invalid value" messagesJean-Noël Avila via GitGitGadget, Jan 30, 2022
  27. 4/4 i18n: transfer variables into placeholders in command synopsisJean-Noël Avila via GitGitGadget, Jan 30, 2022
  28. Phillip WoodJan 31, 2022
  29. Jean-Noël AvilaJan 31, 2022
  30. 3/4 i18n: remove from i18n strings that do not hold translatable partsJean-Noël Avila via GitGitGadget, Jan 30, 2022
  31. Johannes SixtJan 31, 2022
  32. 0/4 Factorize i18nJean-Noël Avila via GitGitGadget, Jan 31, 2022
  33. 1/4 i18n: factorize more 'incompatible options' messagesJean-Noël Avila via GitGitGadget, Jan 31, 2022
  34. Junio C HamanoJan 31, 2022
  35. Johannes SixtFeb 1, 2022
  36. Junio C HamanoFeb 1, 2022
  37. Jean-Noël AvilaFeb 2, 2022
  38. Johannes SixtFeb 2, 2022
  39. 2/4 i18n: factorize "invalid value" messagesJean-Noël Avila via GitGitGadget, Jan 31, 2022
  40. 3/4 i18n: remove from i18n strings that do not hold translatable partsJean-Noël Avila via GitGitGadget, Jan 31, 2022
  41. 4/4 i18n: fix some misformated placeholders in command synopsisJean-Noël Avila via GitGitGadget, Jan 31, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.