Merge branch 'js/alias-early-config' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 10 Jul 2017 20:58:57 +0000 (13:58 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Jul 2017 20:58:58 +0000 (13:58 -0700)
The code to pick up and execute command alias definition from the
configuration used to switch to the top of the working tree and
then come back when the expanded alias was executed, which was
unnecessarilyl complex. Attempt to simplify the logic by using the
early-config mechanism that does not chdir around.

* js/alias-early-config:
alias: use the early config machinery to expand aliases
t7006: demonstrate a problem with aliases in subdirectories
t1308: relax the test verifying that empty alias values are disallowed
help: use early config when autocorrecting aliases
config: report correct line number upon error
discover_git_directory(): avoid setting invalid git_dir

1  2 
config.c
help.c
setup.c
t/t1300-repo-config.sh
diff --combined config.c
index a30056ec7e9a0cca87dea494a92a4671a19b7643,3df7515db2e70e70a97b3a29dfd77d10dc462b3d..f0511e58e2af4235201a01618134a020592cf11c
+++ b/config.c
@@@ -588,7 -588,8 +588,8 @@@ static int get_value(config_fn_t fn, vo
         */
        cf->linenr--;
        ret = fn(name->buf, value, data);
-       cf->linenr++;
+       if (ret >= 0)
+               cf->linenr++;
        return ret;
  }
  
@@@ -2621,7 -2622,7 +2622,7 @@@ int git_config_rename_section_in_file(c
        struct lock_file *lock;
        int out_fd;
        char buf[1024];
 -      FILE *config_file;
 +      FILE *config_file = NULL;
        struct stat st;
  
        if (new_name && !section_name_is_ok(new_name)) {
                }
        }
        fclose(config_file);
 +      config_file = NULL;
  commit_and_out:
        if (commit_lock_file(lock) < 0)
                ret = error_errno("could not write config file %s",
                                  config_filename);
  out:
 +      if (config_file)
 +              fclose(config_file);
        rollback_lock_file(lock);
  out_no_rollback:
        free(filename_buf);
diff --combined help.c
index db7f3d79a016881639a8c0640451afe35b011e5e,91ec8ab36f1c31ffecbd41f1d227ee9e13047951..b44c55ec2da515d12c1327f01202621738fa8653
--- 1/help.c
--- 2/help.c
+++ b/help.c
@@@ -1,7 -1,6 +1,7 @@@
  #include "cache.h"
  #include "builtin.h"
  #include "exec_cmd.h"
 +#include "run-command.h"
  #include "levenshtein.h"
  #include "help.h"
  #include "common-cmds.h"
@@@ -97,6 -96,48 +97,6 @@@ static void pretty_print_cmdnames(struc
        string_list_clear(&list, 0);
  }
  
 -static int is_executable(const char *name)
 -{
 -      struct stat st;
 -
 -      if (stat(name, &st) || /* stat, not lstat */
 -          !S_ISREG(st.st_mode))
 -              return 0;
 -
 -#if defined(GIT_WINDOWS_NATIVE)
 -      /*
 -       * On Windows there is no executable bit. The file extension
 -       * indicates whether it can be run as an executable, and Git
 -       * has special-handling to detect scripts and launch them
 -       * through the indicated script interpreter. We test for the
 -       * file extension first because virus scanners may make
 -       * it quite expensive to open many files.
 -       */
 -      if (ends_with(name, ".exe"))
 -              return S_IXUSR;
 -
 -{
 -      /*
 -       * Now that we know it does not have an executable extension,
 -       * peek into the file instead.
 -       */
 -      char buf[3] = { 0 };
 -      int n;
 -      int fd = open(name, O_RDONLY);
 -      st.st_mode &= ~S_IXUSR;
 -      if (fd >= 0) {
 -              n = read(fd, buf, 2);
 -              if (n == 2)
 -                      /* look for a she-bang */
 -                      if (!strcmp(buf, "#!"))
 -                              st.st_mode |= S_IXUSR;
 -              close(fd);
 -      }
 -}
 -#endif
 -      return st.st_mode & S_IXUSR;
 -}
 -
  static void list_commands_in_dir(struct cmdnames *cmds,
                                         const char *path,
                                         const char *prefix)
@@@ -289,7 -330,7 +289,7 @@@ const char *help_unknown_cmd(const cha
        memset(&other_cmds, 0, sizeof(other_cmds));
        memset(&aliases, 0, sizeof(aliases));
  
-       git_config(git_unknown_cmd_config, NULL);
+       read_early_config(git_unknown_cmd_config, NULL);
  
        load_command_list("git-", &main_cmds, &other_cmds);
  
  
        if (SIMILAR_ENOUGH(best_similarity)) {
                fprintf_ln(stderr,
 -                         Q_("\nDid you mean this?",
 -                            "\nDid you mean one of these?",
 +                         Q_("\nThe most similar command is",
 +                            "\nThe most similar commands are",
                           n));
  
                for (i = 0; i < n; i++)
diff --combined setup.c
index e3f7699a902aed20a83820067cf913df2f3750a9,ba3241bf026e87414d8f652c59fef0d120c92c19..2435186e448a6bf09616b0f1de1225ff2a666e48
+++ b/setup.c
@@@ -703,16 -703,11 +703,16 @@@ static const char *setup_discovered_git
  
        /* --work-tree is set without --git-dir; use discovered one */
        if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
 +              char *to_free = NULL;
 +              const char *ret;
 +
                if (offset != cwd->len && !is_absolute_path(gitdir))
 -                      gitdir = real_pathdup(gitdir, 1);
 +                      gitdir = to_free = real_pathdup(gitdir, 1);
                if (chdir(cwd->buf))
                        die_errno("Could not come back to cwd");
 -              return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
 +              ret = setup_explicit_git_dir(gitdir, cwd, nongit_ok);
 +              free(to_free);
 +              return ret;
        }
  
        /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
@@@ -753,7 -748,7 +753,7 @@@ static const char *setup_bare_git_dir(s
  
        /* --work-tree is set without --git-dir; use discovered one */
        if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
 -              const char *gitdir;
 +              static const char *gitdir;
  
                gitdir = offset == cwd->len ? "." : xmemdupz(cwd->buf, offset);
                if (chdir(cwd->buf))
@@@ -982,6 -977,7 +982,7 @@@ const char *discover_git_directory(stru
                warning("ignoring git dir '%s': %s",
                        gitdir->buf + gitdir_offset, err.buf);
                strbuf_release(&err);
+               strbuf_setlen(gitdir, gitdir_offset);
                return NULL;
        }
  
diff --combined t/t1300-repo-config.sh
index 13b7851f7c2feb87f63449d917380452e85c1f84,f664bfc67148a738be4a0ec58fc71b88344022b7..a37ef0422212eafdae4b4c0fae9e28d4a183117f
@@@ -703,6 -703,12 +703,12 @@@ test_expect_success 'invalid unit' 
        test_i18ngrep "bad numeric config value .1auto. for .aninvalid.unit. in file .git/config: invalid unit" actual
  '
  
+ test_expect_success 'line number is reported correctly' '
+       printf "[bool]\n\tvar\n" >invalid &&
+       test_must_fail git config -f invalid --path bool.var 2>actual &&
+       test_i18ngrep "line 2" actual
+ '
  test_expect_success 'invalid stdin config' '
        echo "[broken" | test_must_fail git config --list --file - >output 2>&1 &&
        test_i18ngrep "bad config line 1 in standard input" output
@@@ -1539,10 -1545,4 +1545,10 @@@ test_expect_success !MINGW '--show-orig
        test_cmp expect output
  '
  
 +test_expect_success '--local requires a repo' '
 +      # we expect 128 to ensure that we do not simply
 +      # fail to find anything and return code "1"
 +      test_expect_code 128 nongit git config --local foo.bar
 +'
 +
  test_done