Merge branch 'rs/strbuf-add-real-path' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 28 Mar 2017 20:52:19 +0000 (13:52 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 28 Mar 2017 20:52:19 +0000 (13:52 -0700)
An helper function to make it easier to append the result from
real_path() to a strbuf has been added.

* rs/strbuf-add-real-path:
strbuf: add strbuf_add_real_path()
cocci: use ALLOC_ARRAY

1  2 
setup.c
strbuf.h
worktree.c
diff --combined setup.c
index 6b48cb91ff2bdde1d02b2696b5b38a64cc663161,5af64ad530a30d21fb939cbf3c5dd941489a24f0..8f64fbdfb28fc2e487cfdba76561e5b3a25766f0
+++ b/setup.c
@@@ -254,12 -254,10 +254,12 @@@ int get_common_dir_noenv(struct strbuf 
                if (!is_absolute_path(data.buf))
                        strbuf_addf(&path, "%s/", gitdir);
                strbuf_addbuf(&path, &data);
-               strbuf_addstr(sb, real_path(path.buf));
+               strbuf_add_real_path(sb, path.buf);
                ret = 1;
 -      } else
 +      } else {
                strbuf_addstr(sb, gitdir);
 +      }
 +
        strbuf_release(&data);
        strbuf_release(&path);
        return ret;
@@@ -486,30 -484,6 +486,30 @@@ int verify_repository_format(const stru
        return 0;
  }
  
 +void read_gitfile_error_die(int error_code, const char *path, const char *dir)
 +{
 +      switch (error_code) {
 +      case READ_GITFILE_ERR_STAT_FAILED:
 +      case READ_GITFILE_ERR_NOT_A_FILE:
 +              /* non-fatal; follow return path */
 +              break;
 +      case READ_GITFILE_ERR_OPEN_FAILED:
 +              die_errno("Error opening '%s'", path);
 +      case READ_GITFILE_ERR_TOO_LARGE:
 +              die("Too large to be a .git file: '%s'", path);
 +      case READ_GITFILE_ERR_READ_FAILED:
 +              die("Error reading %s", path);
 +      case READ_GITFILE_ERR_INVALID_FORMAT:
 +              die("Invalid gitfile format: %s", path);
 +      case READ_GITFILE_ERR_NO_PATH:
 +              die("No path in gitfile: %s", path);
 +      case READ_GITFILE_ERR_NOT_A_REPO:
 +              die("Not a git repository: %s", dir);
 +      default:
 +              die("BUG: unknown error code");
 +      }
 +}
 +
  /*
   * Try to read the location of the git directory from the .git file,
   * return path to git directory if found.
@@@ -583,8 -557,28 +583,8 @@@ const char *read_gitfile_gently(const c
  cleanup_return:
        if (return_error_code)
                *return_error_code = error_code;
 -      else if (error_code) {
 -              switch (error_code) {
 -              case READ_GITFILE_ERR_STAT_FAILED:
 -              case READ_GITFILE_ERR_NOT_A_FILE:
 -                      /* non-fatal; follow return path */
 -                      break;
 -              case READ_GITFILE_ERR_OPEN_FAILED:
 -                      die_errno("Error opening '%s'", path);
 -              case READ_GITFILE_ERR_TOO_LARGE:
 -                      die("Too large to be a .git file: '%s'", path);
 -              case READ_GITFILE_ERR_READ_FAILED:
 -                      die("Error reading %s", path);
 -              case READ_GITFILE_ERR_INVALID_FORMAT:
 -                      die("Invalid gitfile format: %s", path);
 -              case READ_GITFILE_ERR_NO_PATH:
 -                      die("No path in gitfile: %s", path);
 -              case READ_GITFILE_ERR_NOT_A_REPO:
 -                      die("Not a git repository: %s", dir);
 -              default:
 -                      assert(0);
 -              }
 -      }
 +      else if (error_code)
 +              read_gitfile_error_die(error_code, path, dir);
  
        free(buf);
        return error_code ? NULL : path;
@@@ -698,7 -692,7 +698,7 @@@ 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) {
                if (offset != cwd->len && !is_absolute_path(gitdir))
 -                      gitdir = xstrdup(real_path(gitdir));
 +                      gitdir = 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);
@@@ -806,12 -800,11 +806,12 @@@ static int canonicalize_ceiling_entry(s
                /* Keep entry but do not canonicalize it */
                return 1;
        } else {
 -              const char *real_path = real_path_if_valid(ceil);
 -              if (!real_path)
 +              char *real_path = real_pathdup(ceil, 0);
 +              if (!real_path) {
                        return 0;
 +              }
                free(item->string);
 -              item->string = xstrdup(real_path);
 +              item->string = real_path;
                return 1;
        }
  }
@@@ -1021,11 -1014,11 +1021,11 @@@ const char *setup_git_directory(void
        return setup_git_directory_gently(NULL);
  }
  
 -const char *resolve_gitdir(const char *suspect)
 +const char *resolve_gitdir_gently(const char *suspect, int *return_error_code)
  {
        if (is_git_directory(suspect))
                return suspect;
 -      return read_gitfile(suspect);
 +      return read_gitfile_gently(suspect, return_error_code);
  }
  
  /* if any standard file descriptor is missing open it to /dev/null */
diff --combined strbuf.h
index cf1b5409e7c39eba4981a0a23e8250249a9202f1,ab12d3916ce051248e2945ff01a47110c2459fe0..cf8e4bf532a63cf5133dcdf011968e9ac8b24d39
+++ b/strbuf.h
@@@ -109,7 -109,9 +109,7 @@@ extern void strbuf_attach(struct strbu
   */
  static inline void strbuf_swap(struct strbuf *a, struct strbuf *b)
  {
 -      struct strbuf tmp = *a;
 -      *a = *b;
 -      *b = tmp;
 +      SWAP(*a, *b);
  }
  
  
@@@ -441,6 -443,20 +441,20 @@@ extern int strbuf_getcwd(struct strbuf 
   */
  extern void strbuf_add_absolute_path(struct strbuf *sb, const char *path);
  
+ /**
+  * Canonize `path` (make it absolute, resolve symlinks, remove extra
+  * slashes) and append it to `sb`.  Die with an informative error
+  * message if there is a problem.
+  *
+  * The directory part of `path` (i.e., everything up to the last
+  * dir_sep) must denote a valid, existing directory, but the last
+  * component need not exist.
+  *
+  * Callers that don't mind links should use the more lightweight
+  * strbuf_add_absolute_path() instead.
+  */
+ extern void strbuf_add_real_path(struct strbuf *sb, const char *path);
  
  /**
   * Normalize in-place the path contained in the strbuf. See
diff --combined worktree.c
index 0486e31ad4a5f5ee02813d06bf9a48e48e3667cb,b43160c0031a95426249ab0730096112d0bcb1df..fa7bc67a50a6d52116b0ca994b473668998f1c3f
@@@ -145,7 -145,7 +145,7 @@@ done
  
  static void mark_current_worktree(struct worktree **worktrees)
  {
 -      char *git_dir = xstrdup(absolute_path(get_git_dir()));
 +      char *git_dir = absolute_pathdup(get_git_dir());
        int i;
  
        for (i = 0; worktrees[i]; i++) {
@@@ -175,7 -175,7 +175,7 @@@ struct worktree **get_worktrees(unsigne
        struct dirent *d;
        int counter = 0, alloc = 2;
  
-       list = xmalloc(alloc * sizeof(struct worktree *));
+       ALLOC_ARRAY(list, alloc);
  
        list[counter++] = get_main_worktree();
  
@@@ -255,7 -255,7 +255,7 @@@ struct worktree *find_worktree(struct w
                return wt;
  
        arg = prefix_filename(prefix, strlen(prefix), arg);
 -      path = xstrdup(real_path(arg));
 +      path = real_pathdup(arg, 1);
        for (; *list; list++)
                if (!fspathcmp(path, real_path((*list)->path)))
                        break;
@@@ -380,53 -380,3 +380,53 @@@ const struct worktree *find_shared_symr
  
        return existing;
  }
 +
 +int submodule_uses_worktrees(const char *path)
 +{
 +      char *submodule_gitdir;
 +      struct strbuf sb = STRBUF_INIT;
 +      DIR *dir;
 +      struct dirent *d;
 +      int ret = 0;
 +      struct repository_format format;
 +
 +      submodule_gitdir = git_pathdup_submodule(path, "%s", "");
 +      if (!submodule_gitdir)
 +              return 0;
 +
 +      /* The env would be set for the superproject. */
 +      get_common_dir_noenv(&sb, submodule_gitdir);
 +
 +      /*
 +       * The check below is only known to be good for repository format
 +       * version 0 at the time of writing this code.
 +       */
 +      strbuf_addstr(&sb, "/config");
 +      read_repository_format(&format, sb.buf);
 +      if (format.version != 0) {
 +              strbuf_release(&sb);
 +              return 1;
 +      }
 +
 +      /* Replace config by worktrees. */
 +      strbuf_setlen(&sb, sb.len - strlen("config"));
 +      strbuf_addstr(&sb, "worktrees");
 +
 +      /* See if there is any file inside the worktrees directory. */
 +      dir = opendir(sb.buf);
 +      strbuf_release(&sb);
 +      free(submodule_gitdir);
 +
 +      if (!dir)
 +              return 0;
 +
 +      while ((d = readdir(dir)) != NULL) {
 +              if (is_dot_or_dotdot(d->d_name))
 +                      continue;
 +
 +              ret = 1;
 +              break;
 +      }
 +      closedir(dir);
 +      return ret;
 +}