Now with:

 * The --type=bool etc. Ui change to env--bool.

 * I considered supporting YesPlease for gettext poison, but didn't go
   for it. Details in updated commit message.

 * "default" "case" arm fork warning on some compilers.

Ævar Arnfjörð Bjarmason (8):
  config tests: simplify include cycle test
  env--helper: new undocumented builtin wrapping git_env_*()
  config.c: refactor die_bad_number() to not call gettext() early
  t6040 test: stop using global "script" variable
  tests: make GIT_TEST_GETTEXT_POISON a boolean
  tests README: re-flow a previously changed paragraph
  tests: replace test_tristate with "git env--helper"
  tests: make GIT_TEST_FAIL_PREREQS a boolean

 .gitignore                |  1 +
 Makefile                  |  1 +
 builtin.h                 |  1 +
 builtin/env--helper.c     | 95 +++++++++++++++++++++++++++++++++++++
 ci/lib.sh                 |  2 +-
 config.c                  | 28 +++++++----
 gettext.c                 |  6 +--
 git-sh-i18n.sh            |  4 +-
 git.c                     |  1 +
 po/README                 |  2 +-
 t/README                  | 12 ++---
 t/lib-git-daemon.sh       |  7 ++-
 t/lib-git-svn.sh          | 11 ++---
 t/lib-httpd.sh            | 15 +++---
 t/t0000-basic.sh          | 10 ++--
 t/t0017-env-helper.sh     | 99 +++++++++++++++++++++++++++++++++++++++
 t/t0205-gettext-poison.sh |  7 ++-
 t/t1305-config-include.sh | 21 +++------
 t/t5512-ls-remote.sh      |  3 +-
 t/t6040-tracking-info.sh  |  6 +--
 t/t7201-co.sh             |  2 +-
 t/t9902-completion.sh     |  2 +-
 t/test-lib-functions.sh   | 58 ++++-------------------
 t/test-lib.sh             | 31 ++++++++----
 24 files changed, 298 insertions(+), 127 deletions(-)
 create mode 100644 builtin/env--helper.c
 create mode 100755 t/t0017-env-helper.sh

Range-diff:
1:  c3483c37a1 = 1:  c3483c37a1 config tests: simplify include cycle test
2:  e689759f7c ! 2:  39cb96739a env--helper: new undocumented builtin wrapping 
git_env_*()
    @@ -20,9 +20,11 @@
         default value makes all the difference, and we'll be able to replace
         test_tristate() itself with that.
     
    -    The --mode-bool option will be used by subsequent patches, but not
    -    --mode-ulong. I figured it was easy enough to add it & test for it so
    -    I left it in so we'd have wrappers for both git_env_*() functions.
    +    The --type=bool option will be used by subsequent patches, but not
    +    --type=ulong. I figured it was easy enough to add it & test for it so
    +    I left it in so we'd have wrappers for both git_env_*() functions, and
    +    to have a template to make it obvious how we'd add --type=int etc. if
    +    it's needed in the future.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <ava...@gmail.com>
     
    @@ -72,74 +74,95 @@
     +#include "parse-options.h"
     +
     +static char const * const env__helper_usage[] = {
    -+  N_("git env--helper [--mode-bool | --mode-ulong] --env-variable=<VAR> 
--env-default=<DEF> [<options>]"),
    ++  N_("git env--helper --type=[bool|ulong] <options> <env-var>"),
     +  NULL
     +};
     +
    ++enum {
    ++  ENV_HELPER_TYPE_BOOL = 1,
    ++  ENV_HELPER_TYPE_ULONG
    ++} cmdmode = 0;
    ++
    ++static int option_parse_type(const struct option *opt, const char *arg,
    ++                       int unset)
    ++{
    ++  if (!strcmp(arg, "bool"))
    ++          cmdmode = ENV_HELPER_TYPE_BOOL;
    ++  else if (!strcmp(arg, "ulong"))
    ++          cmdmode = ENV_HELPER_TYPE_ULONG;
    ++  else
    ++          die(_("unrecognized --type argument, %s"), arg);
    ++
    ++  return 0;
    ++}
    ++
     +int cmd_env__helper(int argc, const char **argv, const char *prefix)
     +{
    -+  enum {
    -+          ENV_HELPER_BOOL = 1,
    -+          ENV_HELPER_ULONG,
    -+  } cmdmode = 0;
     +  int exit_code = 0;
    -+  int quiet = 0;
     +  const char *env_variable = NULL;
     +  const char *env_default = NULL;
     +  int ret;
    -+  int ret_int, tmp_int;
    -+  unsigned long ret_ulong, tmp_ulong;
    ++  int ret_int, default_int;
    ++  unsigned long ret_ulong, default_ulong;
     +  struct option opts[] = {
    -+          OPT_CMDMODE(0, "mode-bool", &cmdmode,
    -+                      N_("invoke git_env_bool(...)"), ENV_HELPER_BOOL),
    -+          OPT_CMDMODE(0, "mode-ulong", &cmdmode,
    -+                      N_("invoke git_env_ulong(...)"), ENV_HELPER_ULONG),
    -+          OPT_STRING(0, "variable", &env_variable, N_("name"),
    -+                     N_("which environment variable to ask git_env_*(...) 
about")),
    ++          OPT_CALLBACK_F(0, "type", &cmdmode, N_("type"),
    ++                         N_("value is given this type"), PARSE_OPT_NONEG,
    ++                         option_parse_type),
     +          OPT_STRING(0, "default", &env_default, N_("value"),
    -+                     N_("what default value does git_env_*(...) fall back 
on?")),
    ++                     N_("default for git_env_*(...) to fall back on")),
     +          OPT_BOOL(0, "exit-code", &exit_code,
    -+                   N_("exit code determined by truth of the git_env_*() 
function")),
    -+          OPT_BOOL(0, "quiet", &quiet,
    -+                   N_("don't print the git_env_*() return value")),
    ++                   N_("be quiet only use git_env_*() value as exit 
code")),
     +          OPT_END(),
     +  };
     +
    -+  if (parse_options(argc, argv, prefix, opts, env__helper_usage, 0))
    ++  argc = parse_options(argc, argv, prefix, opts, env__helper_usage,
    ++                       PARSE_OPT_KEEP_UNKNOWN);
    ++  if (env_default && !*env_default)
     +          usage_with_options(env__helper_usage, opts);
    -+  if (!env_variable || !env_default ||
    -+      !*env_variable || !*env_default)
    ++  if (!cmdmode)
     +          usage_with_options(env__helper_usage, opts);
    ++  if (argc != 1)
    ++          usage_with_options(env__helper_usage, opts);
    ++  env_variable = argv[0];
     +
     +  switch (cmdmode) {
    -+  case ENV_HELPER_BOOL:
    -+          tmp_int = strtol(env_default, (char **)&env_default, 10);
    -+          if (*env_default) {
    -+                  error(_("option `--default' expects a numerical value 
with `--mode-bool`"));
    -+                  usage_with_options(env__helper_usage, opts);
    ++  case ENV_HELPER_TYPE_BOOL:
    ++          if (env_default) {
    ++                  default_int = git_parse_maybe_bool(env_default);
    ++                  if (default_int == -1) {
    ++                          error(_("option `--default' expects a boolean 
value with `--type=bool`, not `%s`"),
    ++                                env_default);
    ++                          usage_with_options(env__helper_usage, opts);
    ++                  }
    ++          } else {
    ++                  default_int = 0;
     +          }
    -+          ret_int = git_env_bool(env_variable, tmp_int);
    -+          if (!quiet)
    -+                  printf("%d\n", ret_int);
    ++          ret_int = git_env_bool(env_variable, default_int);
    ++          if (!exit_code)
    ++                  puts(ret_int ? "true" : "false");
     +          ret = ret_int;
     +          break;
    -+  case ENV_HELPER_ULONG:
    -+          tmp_ulong = strtoll(env_default, (char **)&env_default, 10);
    -+          if (*env_default) {
    -+                  error(_("option `--default' expects a numerical value 
with `--mode-ulong`"));
    -+                  usage_with_options(env__helper_usage, opts);
    ++  case ENV_HELPER_TYPE_ULONG:
    ++          if (env_default) {
    ++                  if (!git_parse_ulong(env_default, &default_ulong)) {
    ++                          error(_("option `--default' expects an unsigned 
long value with `--type=ulong`, not `%s`"),
    ++                                env_default);
    ++                          usage_with_options(env__helper_usage, opts);
    ++                  }
    ++          } else {
    ++                  default_ulong = 0;
     +          }
    -+          ret_ulong = git_env_ulong(env_variable, tmp_ulong);
    -+          if (!quiet)
    ++          ret_ulong = git_env_ulong(env_variable, default_ulong);
    ++          if (!exit_code)
     +                  printf("%lu\n", ret_ulong);
     +          ret = ret_ulong;
     +          break;
    ++  default:
    ++          BUG("unknown <type> value");
    ++          break;
     +  }
     +
    -+  if (exit_code)
    -+          return !ret;
    -+
    -+  return 0;
    ++  return !ret;
     +}
     
      diff --git a/git.c b/git.c
    @@ -168,64 +191,77 @@
     +
     +test_expect_success 'env--helper usage' '
     +  test_must_fail git env--helper &&
    -+  test_must_fail git env--helper --mode-bool &&
    -+  test_must_fail git env--helper --mode-ulong &&
    -+  test_must_fail git env--helper --mode-bool --variable &&
    -+  test_must_fail git env--helper --mode-bool --variable --default &&
    -+  test_must_fail git env--helper --mode-bool --variable= --default=
    ++  test_must_fail git env--helper --type=bool &&
    ++  test_must_fail git env--helper --type=ulong &&
    ++  test_must_fail git env--helper --type=bool &&
    ++  test_must_fail git env--helper --type=bool --default &&
    ++  test_must_fail git env--helper --type=bool --default= &&
    ++  test_must_fail git env--helper --defaultxyz
     +'
     +
     +test_expect_success 'env--helper bad default values' '
    -+  test_must_fail git env--helper --mode-bool --variable=MISSING 
--default=1xyz &&
    -+  test_must_fail git env--helper --mode-ulong --variable=MISSING 
--default=1xyz
    ++  test_must_fail git env--helper --type=bool --default=1xyz MISSING &&
    ++  test_must_fail git env--helper --type=ulong --default=1xyz MISSING
     +'
     +
    -+test_expect_success 'env--helper --mode-bool' '
    -+  echo 1 >expected &&
    -+  git env--helper --mode-bool --variable=MISSING --default=1 --exit-code 
>actual &&
    ++test_expect_success 'env--helper --type=bool' '
    ++  # Test various --default bool values
    ++  echo true >expected &&
    ++  git env--helper --type=bool --default=1 MISSING >actual &&
     +  test_cmp expected actual &&
    -+
    -+  echo 0 >expected &&
    -+  test_must_fail git env--helper --mode-bool --variable=MISSING 
--default=0 --exit-code >actual &&
    ++  git env--helper --type=bool --default=yes MISSING >actual &&
     +  test_cmp expected actual &&
    -+
    -+  git env--helper --mode-bool --variable=MISSING --default=0 >actual &&
    ++  git env--helper --type=bool --default=true MISSING >actual &&
     +  test_cmp expected actual &&
    -+
    -+  >expected &&
    -+  git env--helper --mode-bool --variable=MISSING --default=1 --exit-code 
--quiet >actual &&
    ++  echo false >expected &&
    ++  test_must_fail git env--helper --type=bool --default=0 MISSING >actual 
&&
     +  test_cmp expected actual &&
    -+
    -+  EXISTS=true git env--helper --mode-bool --variable=EXISTS --default=0 
--exit-code --quiet >actual &&
    ++  test_must_fail git env--helper --type=bool --default=no MISSING >actual 
&&
    ++  test_cmp expected actual &&
    ++  test_must_fail git env--helper --type=bool --default=false MISSING 
>actual &&
     +  test_cmp expected actual &&
     +
    -+  echo 1 >expected &&
    -+  EXISTS=true git env--helper --mode-bool --variable=EXISTS --default=0 
--exit-code >actual &&
    -+  test_cmp expected actual
    ++  # No output with --exit-code
    ++  git env--helper --type=bool --default=true --exit-code MISSING 
>actual.out 2>actual.err &&
    ++  test_must_be_empty actual.out &&
    ++  test_must_be_empty actual.err &&
    ++  test_must_fail git env--helper --type=bool --default=false --exit-code 
MISSING >actual.out 2>actual.err &&
    ++  test_must_be_empty actual.out &&
    ++  test_must_be_empty actual.err &&
    ++
    ++  # Existing variable
    ++  EXISTS=true git env--helper --type=bool --default=false --exit-code 
EXISTS >actual.out 2>actual.err &&
    ++  test_must_be_empty actual.out &&
    ++  test_must_be_empty actual.err &&
    ++  test_must_fail \
    ++          env EXISTS=false \
    ++          git env--helper --type=bool --default=true --exit-code EXISTS 
>actual.out 2>actual.err &&
    ++  test_must_be_empty actual.out &&
    ++  test_must_be_empty actual.err
     +'
     +
    -+test_expect_success 'env--helper --mode-ulong' '
    ++test_expect_success 'env--helper --type=ulong' '
     +  echo 1234567890 >expected &&
    -+  git env--helper --mode-ulong --variable=MISSING --default=1234567890 
--exit-code >actual &&
    -+  test_cmp expected actual &&
    ++  git env--helper --type=ulong --default=1234567890 MISSING >actual.out 
2>actual.err &&
    ++  test_cmp expected actual.out &&
    ++  test_must_be_empty actual.err &&
     +
     +  echo 0 >expected &&
    -+  test_must_fail git env--helper --mode-ulong --variable=MISSING 
--default=0 --exit-code >actual &&
    ++  test_must_fail git env--helper --type=ulong --default=0 MISSING >actual 
&&
     +  test_cmp expected actual &&
     +
    -+  git env--helper --mode-ulong --variable=MISSING --default=0 >actual &&
    -+  test_cmp expected actual &&
    ++  git env--helper --type=ulong --default=1234567890 --exit-code MISSING 
>actual.out 2>actual.err &&
    ++  test_must_be_empty actual.out &&
    ++  test_must_be_empty actual.err &&
     +
    -+  >expected &&
    -+  git env--helper --mode-ulong --variable=MISSING --default=1234567890 
--exit-code --quiet >actual &&
    -+  test_cmp expected actual &&
    -+
    -+  EXISTS=1234567890 git env--helper --mode-ulong --variable=EXISTS 
--default=0 --exit-code --quiet >actual &&
    -+  test_cmp expected actual &&
    ++  EXISTS=1234567890 git env--helper --type=ulong --default=0 EXISTS 
--exit-code >actual.out 2>actual.err &&
    ++  test_must_be_empty actual.out &&
    ++  test_must_be_empty actual.err &&
     +
     +  echo 1234567890 >expected &&
    -+  EXISTS=1234567890 git env--helper --mode-ulong --variable=EXISTS 
--default=0 --exit-code >actual &&
    -+  test_cmp expected actual
    ++  EXISTS=1234567890 git env--helper --type=ulong --default=0 EXISTS 
>actual.out 2>actual.err &&
    ++  test_cmp expected actual.out &&
    ++  test_must_be_empty actual.err
     +'
     +
     +test_done
3:  f759d5e91e = 3:  8a88f263bf config.c: refactor die_bad_number() to not call 
gettext() early
4:  1ac798e8ce = 4:  6594a95d6e t6040 test: stop using global "script" variable
5:  d7d6e6c874 ! 5:  248c0f9d46 tests: make GIT_TEST_GETTEXT_POISON a boolean
    @@ -17,7 +17,7 @@
         the special case of GIT_TEST_GETTEXT_POISON and always emit that
         message in the C locale, lest we infinitely loop.
     
    -    As seen in the updated tests in t0016-env-helper.sh there's also a
    +    As seen in the updated tests in t0017-env-helper.sh there's also a
         caveat related to "env--helper" needing to read the config for trace2
         purposes.
     
    @@ -32,6 +32,21 @@
         change in this series won't happen again, and testing for this
         explicitly in "env--helper"'s own tests.
     
    +    This change breaks existing uses of
    +    e.g. GIT_TEST_GETTEXT_POISON=YesPlease, which we've documented in
    +    po/README and other places. As noted in [1] we might want to consider
    +    also accepting "YesPlease" in "env--helper" as a special-case.
    +
    +    But as the lack of uproar over 6cdccfce1e ("i18n: make GETTEXT_POISON
    +    a runtime option", 2018-11-08) demonstrates the audience for this
    +    option is a really narrow set of git developers, who shouldn't have
    +    much trouble modifying their test scripts, so I think it's better to
    +    deal with that minor headache now and make all the relevant GIT_TEST_*
    +    variables boolean in the same way than carry the "YesPlease"
    +    special-case forward.
    +
    +    1. 
https://public-inbox.org/git/xmqqtvckm3h8....@gitster-ct.c.googlers.com/
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <ava...@gmail.com>
     
      diff --git a/ci/lib.sh b/ci/lib.sh
    @@ -93,8 +108,8 @@
      GIT_INTERNAL_GETTEXT_SH_SCHEME=fallthrough
     -if test -n "$GIT_TEST_GETTEXT_POISON"
     +if test -n "$GIT_TEST_GETTEXT_POISON" &&
    -+      git env--helper --mode-bool --variable=GIT_TEST_GETTEXT_POISON \
    -+          --default=0 --exit-code --quiet
    ++      git env--helper --type=bool --default=0 --exit-code \
    ++          GIT_TEST_GETTEXT_POISON
      then
        GIT_INTERNAL_GETTEXT_SH_SCHEME=poison
      elif test -n "@@USE_GETTEXT_SCHEME@@"
    @@ -131,7 +146,7 @@
      --- a/t/t0017-env-helper.sh
      +++ b/t/t0017-env-helper.sh
     @@
    -   test_cmp expected actual
    +   test_must_be_empty actual.err
      '
      
     +test_expect_success 'env--helper reads config thanks to trace2' '
    @@ -146,7 +161,7 @@
     +
     +  test_must_fail \
     +          env HOME="$(pwd)/home" GIT_TEST_GETTEXT_POISON=true \
    -+          git -C cycle env--helper --mode-bool 
--variable=GIT_TEST_GETTEXT_POISON --default=0 --exit-code --quiet 2>err &&
    ++          git -C cycle env--helper --type=bool --default=0 --exit-code 
GIT_TEST_GETTEXT_POISON 2>err &&
     +  grep "# GETTEXT POISON #" err
     +'
     +
    @@ -227,7 +242,7 @@
     -  test_set_prereq C_LOCALE_OUTPUT
     -fi
     +test_lazy_prereq C_LOCALE_OUTPUT '
    -+  ! git env--helper --mode-bool --variable=GIT_TEST_GETTEXT_POISON 
--default=0 --exit-code --quiet
    ++  ! git env--helper --type=bool --default=0 --exit-code 
GIT_TEST_GETTEXT_POISON
     +'
      
      if test -z "$GIT_TEST_CHECK_CACHE_TREE"
6:  954428b3cd = 6:  c9d44aa306 tests README: re-flow a previously changed 
paragraph
7:  79b41cf01b ! 7:  b0bab6adc8 tests: replace test_tristate with "git 
env--helper"
    @@ -35,7 +35,7 @@
      
     -test_tristate GIT_TEST_GIT_DAEMON
     -if test "$GIT_TEST_GIT_DAEMON" = false
    -+if ! git env--helper --mode-bool --variable=GIT_TEST_GIT_DAEMON 
--default=1 --exit-code --quiet
    ++if ! git env--helper --type=bool --default=true --exit-code 
GIT_TEST_GIT_DAEMON
      then
        skip_all="git-daemon testing disabled (unset GIT_TEST_GIT_DAEMON to 
enable)"
        test_done
    @@ -68,7 +68,7 @@
     -  test_tristate GIT_SVN_TEST_HTTPD
     -  case $GIT_SVN_TEST_HTTPD in
     -  true)
    -+  if git env--helper --mode-bool --variable=GIT_TEST_HTTPD --default=0 
--exit-code --quiet        
    ++  if git env--helper --type=bool --default=false --exit-code 
GIT_TEST_HTTPD
     +  then
                . "$TEST_DIRECTORY"/lib-httpd.sh
                LIB_HTTPD_SVN="$loc"
    @@ -85,7 +85,7 @@
      require_svnserve () {
     -  test_tristate GIT_TEST_SVNSERVE
     -  if ! test "$GIT_TEST_SVNSERVE" = true
    -+  if ! git env--helper --mode-bool --variable=GIT_TEST_SVNSERVE 
--default=0 --exit-code --quiet
    ++  if ! git env--helper --type=bool --default=false --exit-code 
GIT_TEST_SVNSERVE
        then
                skip_all='skipping svnserve test. (set $GIT_TEST_SVNSERVE to 
enable)'
                test_done
    @@ -99,7 +99,7 @@
      
     -test_tristate GIT_TEST_HTTPD
     -if test "$GIT_TEST_HTTPD" = false
    -+if ! git env--helper --mode-bool --variable=GIT_TEST_HTTPD --default=1 
--exit-code --quiet
    ++if ! git env--helper --type=bool --default=true --exit-code GIT_TEST_HTTPD
      then
        skip_all="Network testing disabled (unset GIT_TEST_HTTPD to enable)"
        test_done
    @@ -162,7 +162,7 @@
      test_lazy_prereq GIT_DAEMON '
     -  test_tristate GIT_TEST_GIT_DAEMON &&
     -  test "$GIT_TEST_GIT_DAEMON" != false
    -+  git env--helper --mode-bool --variable=GIT_TEST_GIT_DAEMON --default=1 
--exit-code --quiet
    ++  git env--helper --type=bool --default=true --exit-code 
GIT_TEST_GIT_DAEMON
      '
      
      # This test spawns a daemon, so run it only if the user would be OK with
8:  a9aa166b66 ! 8:  d1a32debba tests: make GIT_TEST_FAIL_PREREQS a boolean
    @@ -90,6 +90,15 @@
        then
                case "$1" in
                # The "!" case is handled below with
    +@@
    + # The error/skip message should be given by $2.
    + #
    + test_skip_or_die () {
    +-  if ! git env--helper --mode-bool --variable=$1 --default=0 --exit-code 
--quiet
    ++  if ! git env--helper --type=bool --default=false --exit-code $1
    +   then
    +           skip_all=$2
    +           test_done
     
      diff --git a/t/test-lib.sh b/t/test-lib.sh
      --- a/t/test-lib.sh
    @@ -106,16 +115,14 @@
     +GIT_TEST_FAIL_PREREQS_INTERNAL=
     +if test -n "$GIT_TEST_FAIL_PREREQS"
     +then
    -+  if git env--helper --mode-bool --variable=GIT_TEST_FAIL_PREREQS \
    -+          --default=0 --exit-code --quiet
    ++  if git env--helper --type=bool --default=0 --exit-code 
GIT_TEST_FAIL_PREREQS
     +  then
     +          GIT_TEST_FAIL_PREREQS_INTERNAL=true
     +          test_set_prereq FAIL_PREREQS
     +  fi
     +else
     +  test_lazy_prereq FAIL_PREREQS '
    -+          git env--helper --mode-bool --variable=GIT_TEST_FAIL_PREREQS \
    -+                  --default=0 --exit-code --quiet
    ++          git env--helper --type=bool --default=0 --exit-code 
GIT_TEST_FAIL_PREREQS
     +  '
     +fi
     +
-- 
2.22.0.455.g172b71a6c5

Reply via email to