Merge branch 'ao/path-use-xmalloc'
authorJunio C Hamano <gitster@pobox.com>
Sat, 28 Oct 2017 01:18:39 +0000 (10:18 +0900)
committerJunio C Hamano <gitster@pobox.com>
Sat, 28 Oct 2017 01:18:40 +0000 (10:18 +0900)
A possible oom error is now caught as a fatal error, instead of
continuing and dereferencing NULL.

* ao/path-use-xmalloc:
path.c: use xmalloc() in add_to_trie()

1  2 
path.c
diff --combined path.c
index 2e09a7bce0688acccaca8b980c2c337a71885966,9d518992d843ed0c0a3a4063fa49e6a26b0a0f36..da8b655730d363dda5010bdf2d53bd76abb82931
--- 1/path.c
--- 2/path.c
+++ b/path.c
@@@ -2,14 -2,11 +2,14 @@@
   * Utilities for paths and pathnames
   */
  #include "cache.h"
 +#include "repository.h"
  #include "strbuf.h"
  #include "string-list.h"
  #include "dir.h"
  #include "worktree.h"
  #include "submodule-config.h"
 +#include "path.h"
 +#include "packfile.h"
  
  static int get_st_mode_bits(const char *path, int *mode)
  {
@@@ -34,10 -31,11 +34,10 @@@ static struct strbuf *get_pathname(void
        return sb;
  }
  
 -static char *cleanup_path(char *path)
 +static const char *cleanup_path(const char *path)
  {
        /* Clean it up */
 -      if (!memcmp(path, "./", 2)) {
 -              path += 2;
 +      if (skip_prefix(path, "./", &path)) {
                while (*path == '/')
                        path++;
        }
@@@ -46,7 -44,7 +46,7 @@@
  
  static void strbuf_cleanup_path(struct strbuf *sb)
  {
 -      char *path = cleanup_path(sb->buf);
 +      const char *path = cleanup_path(sb->buf);
        if (path > sb->buf)
                strbuf_remove(sb, 0, path - sb->buf);
  }
@@@ -63,7 -61,7 +63,7 @@@ char *mksnpath(char *buf, size_t n, con
                strlcpy(buf, bad_path, n);
                return buf;
        }
 -      return cleanup_path(buf);
 +      return (char *)cleanup_path(buf);
  }
  
  static int dir_prefix(const char *buf, const char *dir)
@@@ -192,7 -190,7 +192,7 @@@ static void *add_to_trie(struct trie *r
                 * Split this node: child will contain this node's
                 * existing children.
                 */
-               child = malloc(sizeof(*child));
+               child = xmalloc(sizeof(*child));
                memcpy(child->children, root->children, sizeof(root->children));
  
                child->len = root->len - i - 1;
@@@ -345,6 -343,8 +345,6 @@@ static void update_common_dir(struct st
  {
        char *base = buf->buf + git_dir_len;
        init_common_trie();
 -      if (!common_dir)
 -              common_dir = get_git_common_dir();
        if (trie_find(&common_trie, base, check_common, NULL) > 0)
                replace_dir(buf, git_dir_len, common_dir);
  }
@@@ -355,7 -355,7 +355,7 @@@ void report_linked_checkout_garbage(voi
        const struct common_dir *p;
        int len;
  
 -      if (!git_common_dir_env)
 +      if (!the_repository->different_commondir)
                return;
        strbuf_addf(&sb, "%s/", get_git_dir());
        len = sb.len;
        strbuf_release(&sb);
  }
  
 -static void adjust_git_path(struct strbuf *buf, int git_dir_len)
 +static void adjust_git_path(const struct repository *repo,
 +                          struct strbuf *buf, int git_dir_len)
  {
        const char *base = buf->buf + git_dir_len;
 -      if (git_graft_env && is_dir_file(base, "info", "grafts"))
 +      if (is_dir_file(base, "info", "grafts"))
                strbuf_splice(buf, 0, buf->len,
 -                            get_graft_file(), strlen(get_graft_file()));
 -      else if (git_index_env && !strcmp(base, "index"))
 +                            repo->graft_file, strlen(repo->graft_file));
 +      else if (!strcmp(base, "index"))
                strbuf_splice(buf, 0, buf->len,
 -                            get_index_file(), strlen(get_index_file()));
 -      else if (git_db_env && dir_prefix(base, "objects"))
 -              replace_dir(buf, git_dir_len + 7, get_object_directory());
 +                            repo->index_file, strlen(repo->index_file));
 +      else if (dir_prefix(base, "objects"))
 +              replace_dir(buf, git_dir_len + 7, repo->objectdir);
        else if (git_hooks_path && dir_prefix(base, "hooks"))
                replace_dir(buf, git_dir_len + 5, git_hooks_path);
 -      else if (git_common_dir_env)
 -              update_common_dir(buf, git_dir_len, NULL);
 +      else if (repo->different_commondir)
 +              update_common_dir(buf, git_dir_len, repo->commondir);
  }
  
 -static void do_git_path(const struct worktree *wt, struct strbuf *buf,
 +static void strbuf_worktree_gitdir(struct strbuf *buf,
 +                                 const struct repository *repo,
 +                                 const struct worktree *wt)
 +{
 +      if (!wt)
 +              strbuf_addstr(buf, repo->gitdir);
 +      else if (!wt->id)
 +              strbuf_addstr(buf, repo->commondir);
 +      else
 +              strbuf_git_common_path(buf, repo, "worktrees/%s", wt->id);
 +}
 +
 +static void do_git_path(const struct repository *repo,
 +                      const struct worktree *wt, struct strbuf *buf,
                        const char *fmt, va_list args)
  {
        int gitdir_len;
 -      strbuf_addstr(buf, get_worktree_git_dir(wt));
 +      strbuf_worktree_gitdir(buf, repo, wt);
        if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
                strbuf_addch(buf, '/');
        gitdir_len = buf->len;
        strbuf_vaddf(buf, fmt, args);
 -      adjust_git_path(buf, gitdir_len);
 +      if (!wt)
 +              adjust_git_path(repo, buf, gitdir_len);
        strbuf_cleanup_path(buf);
  }
  
 +char *repo_git_path(const struct repository *repo,
 +                  const char *fmt, ...)
 +{
 +      struct strbuf path = STRBUF_INIT;
 +      va_list args;
 +      va_start(args, fmt);
 +      do_git_path(repo, NULL, &path, fmt, args);
 +      va_end(args);
 +      return strbuf_detach(&path, NULL);
 +}
 +
 +void strbuf_repo_git_path(struct strbuf *sb,
 +                        const struct repository *repo,
 +                        const char *fmt, ...)
 +{
 +      va_list args;
 +      va_start(args, fmt);
 +      do_git_path(repo, NULL, sb, fmt, args);
 +      va_end(args);
 +}
 +
  char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
  {
        va_list args;
        strbuf_reset(buf);
        va_start(args, fmt);
 -      do_git_path(NULL, buf, fmt, args);
 +      do_git_path(the_repository, NULL, buf, fmt, args);
        va_end(args);
        return buf->buf;
  }
@@@ -451,7 -415,7 +451,7 @@@ void strbuf_git_path(struct strbuf *sb
  {
        va_list args;
        va_start(args, fmt);
 -      do_git_path(NULL, sb, fmt, args);
 +      do_git_path(the_repository, NULL, sb, fmt, args);
        va_end(args);
  }
  
@@@ -460,7 -424,7 +460,7 @@@ const char *git_path(const char *fmt, .
        struct strbuf *pathname = get_pathname();
        va_list args;
        va_start(args, fmt);
 -      do_git_path(NULL, pathname, fmt, args);
 +      do_git_path(the_repository, NULL, pathname, fmt, args);
        va_end(args);
        return pathname->buf;
  }
@@@ -470,7 -434,7 +470,7 @@@ char *git_pathdup(const char *fmt, ...
        struct strbuf path = STRBUF_INIT;
        va_list args;
        va_start(args, fmt);
 -      do_git_path(NULL, &path, fmt, args);
 +      do_git_path(the_repository, NULL, &path, fmt, args);
        va_end(args);
        return strbuf_detach(&path, NULL);
  }
@@@ -501,52 -465,11 +501,52 @@@ const char *worktree_git_path(const str
        struct strbuf *pathname = get_pathname();
        va_list args;
        va_start(args, fmt);
 -      do_git_path(wt, pathname, fmt, args);
 +      do_git_path(the_repository, wt, pathname, fmt, args);
        va_end(args);
        return pathname->buf;
  }
  
 +static void do_worktree_path(const struct repository *repo,
 +                           struct strbuf *buf,
 +                           const char *fmt, va_list args)
 +{
 +      strbuf_addstr(buf, repo->worktree);
 +      if(buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
 +              strbuf_addch(buf, '/');
 +
 +      strbuf_vaddf(buf, fmt, args);
 +      strbuf_cleanup_path(buf);
 +}
 +
 +char *repo_worktree_path(const struct repository *repo, const char *fmt, ...)
 +{
 +      struct strbuf path = STRBUF_INIT;
 +      va_list args;
 +
 +      if (!repo->worktree)
 +              return NULL;
 +
 +      va_start(args, fmt);
 +      do_worktree_path(repo, &path, fmt, args);
 +      va_end(args);
 +
 +      return strbuf_detach(&path, NULL);
 +}
 +
 +void strbuf_repo_worktree_path(struct strbuf *sb,
 +                             const struct repository *repo,
 +                             const char *fmt, ...)
 +{
 +      va_list args;
 +
 +      if (!repo->worktree)
 +              return;
 +
 +      va_start(args, fmt);
 +      do_worktree_path(repo, sb, fmt, args);
 +      va_end(args);
 +}
 +
  /* Returns 0 on success, negative on failure. */
  static int do_submodule_path(struct strbuf *buf, const char *path,
                             const char *fmt, va_list args)
@@@ -601,12 -524,11 +601,12 @@@ int strbuf_git_path_submodule(struct st
        return err;
  }
  
 -static void do_git_common_path(struct strbuf *buf,
 +static void do_git_common_path(const struct repository *repo,
 +                             struct strbuf *buf,
                               const char *fmt,
                               va_list args)
  {
 -      strbuf_addstr(buf, get_git_common_dir());
 +      strbuf_addstr(buf, repo->commondir);
        if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
                strbuf_addch(buf, '/');
        strbuf_vaddf(buf, fmt, args);
@@@ -618,27 -540,24 +618,27 @@@ const char *git_common_path(const char 
        struct strbuf *pathname = get_pathname();
        va_list args;
        va_start(args, fmt);
 -      do_git_common_path(pathname, fmt, args);
 +      do_git_common_path(the_repository, pathname, fmt, args);
        va_end(args);
        return pathname->buf;
  }
  
 -void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...)
 +void strbuf_git_common_path(struct strbuf *sb,
 +                          const struct repository *repo,
 +                          const char *fmt, ...)
  {
        va_list args;
        va_start(args, fmt);
 -      do_git_common_path(sb, fmt, args);
 +      do_git_common_path(repo, sb, fmt, args);
        va_end(args);
  }
  
  int validate_headref(const char *path)
  {
        struct stat st;
 -      char *buf, buffer[256];
 -      unsigned char sha1[20];
 +      char buffer[256];
 +      const char *refname;
 +      struct object_id oid;
        int fd;
        ssize_t len;
  
        len = read_in_full(fd, buffer, sizeof(buffer)-1);
        close(fd);
  
 +      if (len < 0)
 +              return -1;
 +      buffer[len] = '\0';
 +
        /*
         * Is it a symbolic ref?
         */
 -      if (len < 4)
 -              return -1;
 -      if (!memcmp("ref:", buffer, 4)) {
 -              buf = buffer + 4;
 -              len -= 4;
 -              while (len && isspace(*buf))
 -                      buf++, len--;
 -              if (len >= 5 && !memcmp("refs/", buf, 5))
 +      if (skip_prefix(buffer, "ref:", &refname)) {
 +              while (isspace(*refname))
 +                      refname++;
 +              if (starts_with(refname, "refs/"))
                        return 0;
        }
  
        /*
         * Is this a detached HEAD?
         */
 -      if (!get_sha1_hex(buffer, sha1))
 +      if (!get_oid_hex(buffer, &oid))
                return 0;
  
        return -1;
@@@ -717,7 -636,7 +717,7 @@@ char *expand_user_path(const char *path
                        if (!home)
                                goto return_null;
                        if (real_home)
 -                              strbuf_addstr(&user_path, real_path(home));
 +                              strbuf_add_real_path(&user_path, home);
                        else
                                strbuf_addstr(&user_path, home);
  #ifdef GIT_WINDOWS_NATIVE