Merge branch 'sg/setup-doc-update'
authorJunio C Hamano <gitster@pobox.com>
Tue, 19 Dec 2017 19:33:58 +0000 (11:33 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 19 Dec 2017 19:33:58 +0000 (11:33 -0800)
Comment update.

* sg/setup-doc-update:
setup.c: fix comment about order of .git directory discovery

1  2 
setup.c
diff --combined setup.c
index 50c6b2ab11fa3579a17079c16a4fb7241df9b875,caab366104ef93acea53d1d81932a2a2255a2714..8cc34186ce1f918ce5a9c8fc22ea81b7c645ff17
+++ b/setup.c
@@@ -1,6 -1,4 +1,6 @@@
  #include "cache.h"
 +#include "repository.h"
 +#include "config.h"
  #include "dir.h"
  #include "string-list.h"
  
@@@ -136,30 -134,21 +136,30 @@@ int path_inside_repo(const char *prefix
  
  int check_filename(const char *prefix, const char *arg)
  {
 -      const char *name;
 +      char *to_free = NULL;
        struct stat st;
  
 -      if (starts_with(arg, ":/")) {
 -              if (arg[2] == '\0') /* ":/" is root dir, always exists */
 +      if (skip_prefix(arg, ":/", &arg)) {
 +              if (!*arg) /* ":/" is root dir, always exists */
                        return 1;
 -              name = arg + 2;
 -      } else if (prefix)
 -              name = prefix_filename(prefix, strlen(prefix), arg);
 -      else
 -              name = arg;
 -      if (!lstat(name, &st))
 +              prefix = NULL;
 +      } else if (skip_prefix(arg, ":!", &arg) ||
 +                 skip_prefix(arg, ":^", &arg)) {
 +              if (!*arg) /* excluding everything is silly, but allowed */
 +                      return 1;
 +      }
 +
 +      if (prefix)
 +              arg = to_free = prefix_filename(prefix, arg);
 +
 +      if (!lstat(arg, &st)) {
 +              free(to_free);
                return 1; /* file exists */
 -      if (errno == ENOENT || errno == ENOTDIR)
 +      }
 +      if (is_missing_file_error(errno)) {
 +              free(to_free);
                return 0; /* file does not exist */
 +      }
        die_errno("failed to stat '%s'", arg);
  }
  
@@@ -187,24 -176,6 +187,24 @@@ static void NORETURN die_verify_filenam
  
  }
  
 +/*
 + * Check for arguments that don't resolve as actual files,
 + * but which look sufficiently like pathspecs that we'll consider
 + * them such for the purposes of rev/pathspec DWIM parsing.
 + */
 +static int looks_like_pathspec(const char *arg)
 +{
 +      /* anything with a wildcard character */
 +      if (!no_wildcard(arg))
 +              return 1;
 +
 +      /* long-form pathspec magic */
 +      if (starts_with(arg, ":("))
 +              return 1;
 +
 +      return 0;
 +}
 +
  /*
   * Verify a filename that we got as an argument for a pathspec
   * entry. Note that a filename that begins with "-" never verifies
@@@ -230,8 -201,8 +230,8 @@@ void verify_filename(const char *prefix
                     int diagnose_misspelt_rev)
  {
        if (*arg == '-')
 -              die("bad flag '%s' used after filename", arg);
 -      if (check_filename(prefix, arg) || !no_wildcard(arg))
 +              die("option '%s' must come before non-option arguments", arg);
 +      if (looks_like_pathspec(arg) || check_filename(prefix, arg))
                return;
        die_verify_filename(prefix, arg, diagnose_misspelt_rev);
  }
@@@ -312,9 -283,7 +312,9 @@@ int is_git_directory(const char *suspec
        size_t len;
  
        /* Check worktree-related signatures */
 -      strbuf_addf(&path, "%s/HEAD", suspect);
 +      strbuf_addstr(&path, suspect);
 +      strbuf_complete(&path, '/');
 +      strbuf_addstr(&path, "HEAD");
        if (validate_headref(path.buf))
                goto done;
  
@@@ -434,15 -403,16 +434,15 @@@ static int check_repo_format(const cha
        return 0;
  }
  
 -static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
 +static int check_repository_format_gently(const char *gitdir, struct repository_format *candidate, int *nongit_ok)
  {
        struct strbuf sb = STRBUF_INIT;
        struct strbuf err = STRBUF_INIT;
 -      struct repository_format candidate;
        int has_common;
  
        has_common = get_common_dir(&sb, gitdir);
        strbuf_addstr(&sb, "/config");
 -      read_repository_format(&candidate, sb.buf);
 +      read_repository_format(candidate, sb.buf);
        strbuf_release(&sb);
  
        /*
         * we treat a missing config as a silent "ok", even when nongit_ok
         * is unset.
         */
 -      if (candidate.version < 0)
 +      if (candidate->version < 0)
                return 0;
  
 -      if (verify_repository_format(&candidate, &err) < 0) {
 +      if (verify_repository_format(candidate, &err) < 0) {
                if (nongit_ok) {
                        warning("%s", err.buf);
                        strbuf_release(&err);
                die("%s", err.buf);
        }
  
 -      repository_format_precious_objects = candidate.precious_objects;
 -      string_list_clear(&candidate.unknown_extensions, 0);
 +      repository_format_precious_objects = candidate->precious_objects;
 +      string_list_clear(&candidate->unknown_extensions, 0);
        if (!has_common) {
 -              if (candidate.is_bare != -1) {
 -                      is_bare_repository_cfg = candidate.is_bare;
 +              if (candidate->is_bare != -1) {
 +                      is_bare_repository_cfg = candidate->is_bare;
                        if (is_bare_repository_cfg == 1)
                                inside_work_tree = -1;
                }
 -              if (candidate.work_tree) {
 +              if (candidate->work_tree) {
                        free(git_work_tree_cfg);
 -                      git_work_tree_cfg = candidate.work_tree;
 +                      git_work_tree_cfg = candidate->work_tree;
                        inside_work_tree = -1;
                }
        } else {
 -              free(candidate.work_tree);
 +              free(candidate->work_tree);
        }
  
        return 0;
@@@ -488,7 -458,6 +488,7 @@@ int read_repository_format(struct repos
        memset(format, 0, sizeof(*format));
        format->version = -1;
        format->is_bare = -1;
 +      format->hash_algo = GIT_HASH_SHA1;
        string_list_init(&format->unknown_extensions, 1);
        git_config_from_file(check_repo_format, path, format);
        return format->version;
@@@ -543,8 -512,7 +543,8 @@@ void read_gitfile_error_die(int error_c
  
  /*
   * Try to read the location of the git directory from the .git file,
 - * return path to git directory if found.
 + * return path to git directory if found. The return value comes from
 + * a shared buffer.
   *
   * On failure, if return_error_code is not NULL, return_error_code
   * will be set to an error code and NULL will be returned. If
@@@ -563,7 -531,6 +563,7 @@@ const char *read_gitfile_gently(const c
        ssize_t len;
  
        if (stat(path, &st)) {
 +              /* NEEDSWORK: discern between ENOENT vs other errors */
                error_code = READ_GITFILE_ERR_STAT_FAILED;
                goto cleanup_return;
        }
@@@ -625,7 -592,6 +625,7 @@@ cleanup_return
  
  static const char *setup_explicit_git_dir(const char *gitdirenv,
                                          struct strbuf *cwd,
 +                                        struct repository_format *repo_fmt,
                                          int *nongit_ok)
  {
        const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
                die("Not a git repository: '%s'", gitdirenv);
        }
  
 -      if (check_repository_format_gently(gitdirenv, nongit_ok)) {
 +      if (check_repository_format_gently(gitdirenv, repo_fmt, nongit_ok)) {
                free(gitfile);
                return NULL;
        }
  
  static const char *setup_discovered_git_dir(const char *gitdir,
                                            struct strbuf *cwd, int offset,
 +                                          struct repository_format *repo_fmt,
                                            int *nongit_ok)
  {
 -      if (check_repository_format_gently(gitdir, nongit_ok))
 +      if (check_repository_format_gently(gitdir, repo_fmt, nongit_ok))
                return NULL;
  
        /* --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, repo_fmt, nongit_ok);
 +              free(to_free);
 +              return ret;
        }
  
        /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
        if (offset == cwd->len)
                return NULL;
  
 -      /* Make "offset" point to past the '/', and add a '/' at the end */
 -      offset++;
 +      /* Make "offset" point past the '/' (already the case for root dirs) */
 +      if (offset != offset_1st_component(cwd->buf))
 +              offset++;
 +      /* Add a '/' at the end */
        strbuf_addch(cwd, '/');
        return cwd->buf + offset;
  }
  
  /* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */
  static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,
 +                                    struct repository_format *repo_fmt,
                                      int *nongit_ok)
  {
        int root_len;
  
 -      if (check_repository_format_gently(".", nongit_ok))
 +      if (check_repository_format_gently(".", repo_fmt, nongit_ok))
                return NULL;
  
        setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
  
        /* --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))
                        die_errno("Could not come back to cwd");
 -              return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
 +              return setup_explicit_git_dir(gitdir, cwd, repo_fmt, nongit_ok);
        }
  
        inside_git_dir = 1;
@@@ -859,51 -816,50 +859,51 @@@ static int canonicalize_ceiling_entry(s
        }
  }
  
 +enum discovery_result {
 +      GIT_DIR_NONE = 0,
 +      GIT_DIR_EXPLICIT,
 +      GIT_DIR_DISCOVERED,
 +      GIT_DIR_BARE,
 +      /* these are errors */
 +      GIT_DIR_HIT_CEILING = -1,
 +      GIT_DIR_HIT_MOUNT_POINT = -2,
 +      GIT_DIR_INVALID_GITFILE = -3
 +};
 +
  /*
   * We cannot decide in this function whether we are in the work tree or
   * not, since the config can only be read _after_ this function was called.
 + *
 + * Also, we avoid changing any global state (such as the current working
 + * directory) to allow early callers.
 + *
 + * The directory where the search should start needs to be passed in via the
 + * `dir` parameter; upon return, the `dir` buffer will contain the path of
 + * the directory where the search ended, and `gitdir` will contain the path of
 + * the discovered .git/ directory, if any. If `gitdir` is not absolute, it
 + * is relative to `dir` (i.e. *not* necessarily the cwd).
   */
 -static const char *setup_git_directory_gently_1(int *nongit_ok)
 +static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
 +                                                        struct strbuf *gitdir,
 +                                                        int die_on_error)
  {
        const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
        struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
 -      static struct strbuf cwd = STRBUF_INIT;
 -      const char *gitdirenv, *ret;
 -      char *gitfile;
 -      int offset, offset_parent, ceil_offset = -1;
 +      const char *gitdirenv;
 +      int ceil_offset = -1, min_offset = has_dos_drive_prefix(dir->buf) ? 3 : 1;
        dev_t current_device = 0;
        int one_filesystem = 1;
  
 -      /*
 -       * We may have read an incomplete configuration before
 -       * setting-up the git directory. If so, clear the cache so
 -       * that the next queries to the configuration reload complete
 -       * configuration (including the per-repo config file that we
 -       * ignored previously).
 -       */
 -      git_config_clear();
 -
 -      /*
 -       * Let's assume that we are in a git repository.
 -       * If it turns out later that we are somewhere else, the value will be
 -       * updated accordingly.
 -       */
 -      if (nongit_ok)
 -              *nongit_ok = 0;
 -
 -      if (strbuf_getcwd(&cwd))
 -              die_errno(_("Unable to read current working directory"));
 -      offset = cwd.len;
 -
        /*
         * If GIT_DIR is set explicitly, we're not going
         * to do any discovery, but we still do repository
         * validation.
         */
        gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
 -      if (gitdirenv)
 -              return setup_explicit_git_dir(gitdirenv, &cwd, nongit_ok);
 +      if (gitdirenv) {
 +              strbuf_addstr(gitdir, gitdirenv);
 +              return GIT_DIR_EXPLICIT;
 +      }
  
        if (env_ceiling_dirs) {
                int empty_entry_found = 0;
                string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
                filter_string_list(&ceiling_dirs, 0,
                                   canonicalize_ceiling_entry, &empty_entry_found);
 -              ceil_offset = longest_ancestor_length(cwd.buf, &ceiling_dirs);
 +              ceil_offset = longest_ancestor_length(dir->buf, &ceiling_dirs);
                string_list_clear(&ceiling_dirs, 0);
        }
  
 -      if (ceil_offset < 0 && has_dos_drive_prefix(cwd.buf))
 -              ceil_offset = 1;
 +      if (ceil_offset < 0)
 +              ceil_offset = min_offset - 2;
  
        /*
 -       * Test in the following order (relative to the cwd):
 +       * Test in the following order (relative to the dir):
         * - .git (file containing "gitdir: <path>")
         * - .git/
         * - ./ (bare)
         * - ../.git
         * - ../.git/
         * - ../ (bare)
-        * - ../../.git/
+        * - ../../.git
         *   etc.
         */
        one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0);
        if (one_filesystem)
 -              current_device = get_device_or_die(".", NULL, 0);
 +              current_device = get_device_or_die(dir->buf, NULL, 0);
        for (;;) {
 -              gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT);
 -              if (gitfile)
 -                      gitdirenv = gitfile = xstrdup(gitfile);
 -              else {
 -                      if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
 -                              gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT;
 +              int offset = dir->len, error_code = 0;
 +
 +              if (offset > min_offset)
 +                      strbuf_addch(dir, '/');
 +              strbuf_addstr(dir, DEFAULT_GIT_DIR_ENVIRONMENT);
 +              gitdirenv = read_gitfile_gently(dir->buf, die_on_error ?
 +                                              NULL : &error_code);
 +              if (!gitdirenv) {
 +                      if (die_on_error ||
 +                          error_code == READ_GITFILE_ERR_NOT_A_FILE) {
 +                              /* NEEDSWORK: fail if .git is not file nor dir */
 +                              if (is_git_directory(dir->buf))
 +                                      gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT;
 +                      } else if (error_code != READ_GITFILE_ERR_STAT_FAILED)
 +                              return GIT_DIR_INVALID_GITFILE;
                }
 -
 +              strbuf_setlen(dir, offset);
                if (gitdirenv) {
 -                      ret = setup_discovered_git_dir(gitdirenv,
 -                                                     &cwd, offset,
 -                                                     nongit_ok);
 -                      free(gitfile);
 -                      return ret;
 +                      strbuf_addstr(gitdir, gitdirenv);
 +                      return GIT_DIR_DISCOVERED;
                }
 -              free(gitfile);
  
 -              if (is_git_directory("."))
 -                      return setup_bare_git_dir(&cwd, offset, nongit_ok);
 -
 -              offset_parent = offset;
 -              while (--offset_parent > ceil_offset && cwd.buf[offset_parent] != '/');
 -              if (offset_parent <= ceil_offset)
 -                      return setup_nongit(cwd.buf, nongit_ok);
 -              if (one_filesystem) {
 -                      dev_t parent_device = get_device_or_die("..", cwd.buf,
 -                                                              offset);
 -                      if (parent_device != current_device) {
 -                              if (nongit_ok) {
 -                                      if (chdir(cwd.buf))
 -                                              die_errno(_("Cannot come back to cwd"));
 -                                      *nongit_ok = 1;
 -                                      return NULL;
 -                              }
 -                              strbuf_setlen(&cwd, offset);
 -                              die(_("Not a git repository (or any parent up to mount point %s)\n"
 -                              "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)."),
 -                                  cwd.buf);
 -                      }
 +              if (is_git_directory(dir->buf)) {
 +                      strbuf_addstr(gitdir, ".");
 +                      return GIT_DIR_BARE;
                }
 -              if (chdir("..")) {
 -                      strbuf_setlen(&cwd, offset);
 -                      die_errno(_("Cannot change to '%s/..'"), cwd.buf);
 -              }
 -              offset = offset_parent;
 +
 +              if (offset <= min_offset)
 +                      return GIT_DIR_HIT_CEILING;
 +
 +              while (--offset > ceil_offset && !is_dir_sep(dir->buf[offset]))
 +                      ; /* continue */
 +              if (offset <= ceil_offset)
 +                      return GIT_DIR_HIT_CEILING;
 +
 +              strbuf_setlen(dir, offset > min_offset ?  offset : min_offset);
 +              if (one_filesystem &&
 +                  current_device != get_device_or_die(dir->buf, NULL, offset))
 +                      return GIT_DIR_HIT_MOUNT_POINT;
        }
  }
  
 +int discover_git_directory(struct strbuf *commondir,
 +                         struct strbuf *gitdir)
 +{
 +      struct strbuf dir = STRBUF_INIT, err = STRBUF_INIT;
 +      size_t gitdir_offset = gitdir->len, cwd_len;
 +      size_t commondir_offset = commondir->len;
 +      struct repository_format candidate;
 +
 +      if (strbuf_getcwd(&dir))
 +              return -1;
 +
 +      cwd_len = dir.len;
 +      if (setup_git_directory_gently_1(&dir, gitdir, 0) <= 0) {
 +              strbuf_release(&dir);
 +              return -1;
 +      }
 +
 +      /*
 +       * The returned gitdir is relative to dir, and if dir does not reflect
 +       * the current working directory, we simply make the gitdir absolute.
 +       */
 +      if (dir.len < cwd_len && !is_absolute_path(gitdir->buf + gitdir_offset)) {
 +              /* Avoid a trailing "/." */
 +              if (!strcmp(".", gitdir->buf + gitdir_offset))
 +                      strbuf_setlen(gitdir, gitdir_offset);
 +              else
 +                      strbuf_addch(&dir, '/');
 +              strbuf_insert(gitdir, gitdir_offset, dir.buf, dir.len);
 +      }
 +
 +      get_common_dir(commondir, gitdir->buf + gitdir_offset);
 +
 +      strbuf_reset(&dir);
 +      strbuf_addf(&dir, "%s/config", commondir->buf + commondir_offset);
 +      read_repository_format(&candidate, dir.buf);
 +      strbuf_release(&dir);
 +
 +      if (verify_repository_format(&candidate, &err) < 0) {
 +              warning("ignoring git dir '%s': %s",
 +                      gitdir->buf + gitdir_offset, err.buf);
 +              strbuf_release(&err);
 +              strbuf_setlen(commondir, commondir_offset);
 +              strbuf_setlen(gitdir, gitdir_offset);
 +              return -1;
 +      }
 +
 +      return 0;
 +}
 +
  const char *setup_git_directory_gently(int *nongit_ok)
  {
 +      static struct strbuf cwd = STRBUF_INIT;
 +      struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
        const char *prefix;
 +      struct repository_format repo_fmt;
 +
 +      /*
 +       * We may have read an incomplete configuration before
 +       * setting-up the git directory. If so, clear the cache so
 +       * that the next queries to the configuration reload complete
 +       * configuration (including the per-repo config file that we
 +       * ignored previously).
 +       */
 +      git_config_clear();
 +
 +      /*
 +       * Let's assume that we are in a git repository.
 +       * If it turns out later that we are somewhere else, the value will be
 +       * updated accordingly.
 +       */
 +      if (nongit_ok)
 +              *nongit_ok = 0;
 +
 +      if (strbuf_getcwd(&cwd))
 +              die_errno(_("Unable to read current working directory"));
 +      strbuf_addbuf(&dir, &cwd);
 +
 +      switch (setup_git_directory_gently_1(&dir, &gitdir, 1)) {
 +      case GIT_DIR_NONE:
 +              prefix = NULL;
 +              break;
 +      case GIT_DIR_EXPLICIT:
 +              prefix = setup_explicit_git_dir(gitdir.buf, &cwd, &repo_fmt, nongit_ok);
 +              break;
 +      case GIT_DIR_DISCOVERED:
 +              if (dir.len < cwd.len && chdir(dir.buf))
 +                      die(_("Cannot change to '%s'"), dir.buf);
 +              prefix = setup_discovered_git_dir(gitdir.buf, &cwd, dir.len,
 +                                                &repo_fmt, nongit_ok);
 +              break;
 +      case GIT_DIR_BARE:
 +              if (dir.len < cwd.len && chdir(dir.buf))
 +                      die(_("Cannot change to '%s'"), dir.buf);
 +              prefix = setup_bare_git_dir(&cwd, dir.len, &repo_fmt, nongit_ok);
 +              break;
 +      case GIT_DIR_HIT_CEILING:
 +              prefix = setup_nongit(cwd.buf, nongit_ok);
 +              break;
 +      case GIT_DIR_HIT_MOUNT_POINT:
 +              if (nongit_ok) {
 +                      *nongit_ok = 1;
 +                      strbuf_release(&cwd);
 +                      strbuf_release(&dir);
 +                      return NULL;
 +              }
 +              die(_("Not a git repository (or any parent up to mount point %s)\n"
 +                    "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)."),
 +                  dir.buf);
 +      default:
 +              die("BUG: unhandled setup_git_directory_1() result");
 +      }
  
 -      prefix = setup_git_directory_gently_1(nongit_ok);
        if (prefix)
                setenv(GIT_PREFIX_ENVIRONMENT, prefix, 1);
        else
        startup_info->have_repository = !nongit_ok || !*nongit_ok;
        startup_info->prefix = prefix;
  
 +      /*
 +       * Not all paths through the setup code will call 'set_git_dir()' (which
 +       * directly sets up the environment) so in order to guarantee that the
 +       * environment is in a consistent state after setup, explicitly setup
 +       * the environment if we have a repository.
 +       *
 +       * NEEDSWORK: currently we allow bogus GIT_DIR values to be set in some
 +       * code paths so we also need to explicitly setup the environment if
 +       * the user has set GIT_DIR.  It may be beneficial to disallow bogus
 +       * GIT_DIR values at some point in the future.
 +       */
 +      if (startup_info->have_repository || getenv(GIT_DIR_ENVIRONMENT)) {
 +              if (!the_repository->gitdir) {
 +                      const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
 +                      if (!gitdir)
 +                              gitdir = DEFAULT_GIT_DIR_ENVIRONMENT;
 +                      repo_set_gitdir(the_repository, gitdir);
 +                      setup_git_env();
 +              }
 +              if (startup_info->have_repository)
 +                      repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
 +      }
 +
 +      strbuf_release(&dir);
 +      strbuf_release(&gitdir);
 +
        return prefix;
  }
  
@@@ -1177,8 -1006,7 +1177,8 @@@ int git_config_perm(const char *var, co
  
  void check_repository_format(void)
  {
 -      check_repository_format_gently(get_git_dir(), NULL);
 +      struct repository_format repo_fmt;
 +      check_repository_format_gently(get_git_dir(), &repo_fmt, NULL);
        startup_info->have_repository = 1;
  }