Merge branch 'pt/xdg-config-path'
authorJunio C Hamano <gitster@pobox.com>
Mon, 11 May 2015 21:24:01 +0000 (14:24 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 11 May 2015 21:24:01 +0000 (14:24 -0700)
Code clean-up for xdg configuration path support.

* pt/xdg-config-path:
path.c: remove home_config_paths()
git-config: replace use of home_config_paths()
git-commit: replace use of home_config_paths()
credential-store.c: replace home_config_paths() with xdg_config_home()
dir.c: replace home_config_paths() with xdg_config_home()
attr.c: replace home_config_paths() with xdg_config_home()
path.c: implement xdg_config_home()

1  2 
attr.c
builtin/commit.c
builtin/config.c
cache.h
config.c
credential-store.c
dir.c
path.c
diff --cc attr.c
Simple merge
Simple merge
Simple merge
diff --cc cache.h
Simple merge
diff --cc config.c
Simple merge
Simple merge
diff --cc dir.c
Simple merge
diff --cc path.c
index 586f2c90a3c0def34016a692a14e335a46c015ed,2436301ccabaa07513fae556d6624fad4b7b4328..10f4cbf6b78607870461f21dd1cd0f7a2776bc49
--- 1/path.c
--- 2/path.c
+++ b/path.c
@@@ -61,220 -49,124 +61,192 @@@ char *mksnpath(char *buf, size_t n, con
        return cleanup_path(buf);
  }
  
 -static char *vsnpath(char *buf, size_t n, const char *fmt, va_list args)
 +static int dir_prefix(const char *buf, const char *dir)
  {
 -      const char *git_dir = get_git_dir();
 -      size_t len;
 -
 -      len = strlen(git_dir);
 -      if (n < len + 1)
 -              goto bad;
 -      memcpy(buf, git_dir, len);
 -      if (len && !is_dir_sep(git_dir[len-1]))
 -              buf[len++] = '/';
 -      len += vsnprintf(buf + len, n - len, fmt, args);
 -      if (len >= n)
 -              goto bad;
 -      return cleanup_path(buf);
 -bad:
 -      strlcpy(buf, bad_path, n);
 -      return buf;
 +      int len = strlen(dir);
 +      return !strncmp(buf, dir, len) &&
 +              (is_dir_sep(buf[len]) || buf[len] == '\0');
 +}
 +
 +/* $buf =~ m|$dir/+$file| but without regex */
 +static int is_dir_file(const char *buf, const char *dir, const char *file)
 +{
 +      int len = strlen(dir);
 +      if (strncmp(buf, dir, len) || !is_dir_sep(buf[len]))
 +              return 0;
 +      while (is_dir_sep(buf[len]))
 +              len++;
 +      return !strcmp(buf + len, file);
 +}
 +
 +static void replace_dir(struct strbuf *buf, int len, const char *newdir)
 +{
 +      int newlen = strlen(newdir);
 +      int need_sep = (buf->buf[len] && !is_dir_sep(buf->buf[len])) &&
 +              !is_dir_sep(newdir[newlen - 1]);
 +      if (need_sep)
 +              len--;   /* keep one char, to be replaced with '/'  */
 +      strbuf_splice(buf, 0, len, newdir, newlen);
 +      if (need_sep)
 +              buf->buf[newlen] = '/';
 +}
 +
 +static const char *common_list[] = {
 +      "/branches", "/hooks", "/info", "!/logs", "/lost-found",
 +      "/objects", "/refs", "/remotes", "/worktrees", "/rr-cache", "/svn",
 +      "config", "!gc.pid", "packed-refs", "shallow",
 +      NULL
 +};
 +
 +static void update_common_dir(struct strbuf *buf, int git_dir_len)
 +{
 +      char *base = buf->buf + git_dir_len;
 +      const char **p;
 +
 +      if (is_dir_file(base, "logs", "HEAD") ||
 +          is_dir_file(base, "info", "sparse-checkout"))
 +              return; /* keep this in $GIT_DIR */
 +      for (p = common_list; *p; p++) {
 +              const char *path = *p;
 +              int is_dir = 0;
 +              if (*path == '!')
 +                      path++;
 +              if (*path == '/') {
 +                      path++;
 +                      is_dir = 1;
 +              }
 +              if (is_dir && dir_prefix(base, path)) {
 +                      replace_dir(buf, git_dir_len, get_git_common_dir());
 +                      return;
 +              }
 +              if (!is_dir && !strcmp(base, path)) {
 +                      replace_dir(buf, git_dir_len, get_git_common_dir());
 +                      return;
 +              }
 +      }
 +}
 +
 +void report_linked_checkout_garbage(void)
 +{
 +      struct strbuf sb = STRBUF_INIT;
 +      const char **p;
 +      int len;
 +
 +      if (!git_common_dir_env)
 +              return;
 +      strbuf_addf(&sb, "%s/", get_git_dir());
 +      len = sb.len;
 +      for (p = common_list; *p; p++) {
 +              const char *path = *p;
 +              if (*path == '!')
 +                      continue;
 +              strbuf_setlen(&sb, len);
 +              strbuf_addstr(&sb, path);
 +              if (file_exists(sb.buf))
 +                      report_garbage("unused in linked checkout", sb.buf);
 +      }
 +      strbuf_release(&sb);
  }
  
 -char *git_snpath(char *buf, size_t n, const char *fmt, ...)
 +static void adjust_git_path(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"))
 +              strbuf_splice(buf, 0, buf->len,
 +                            get_graft_file(), strlen(get_graft_file()));
 +      else if (git_index_env && !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());
 +      else if (git_common_dir_env)
 +              update_common_dir(buf, git_dir_len);
 +}
 +
 +static void do_git_path(struct strbuf *buf, const char *fmt, va_list args)
 +{
 +      int gitdir_len;
 +      strbuf_addstr(buf, get_git_dir());
 +      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);
 +      strbuf_cleanup_path(buf);
 +}
 +
 +void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
  {
 -      char *ret;
        va_list args;
        va_start(args, fmt);
 -      ret = vsnpath(buf, n, fmt, args);
 +      do_git_path(sb, fmt, args);
        va_end(args);
 -      return ret;
  }
  
 -char *git_pathdup(const char *fmt, ...)
 +const char *git_path(const char *fmt, ...)
  {
 -      char path[PATH_MAX], *ret;
 +      struct strbuf *pathname = get_pathname();
        va_list args;
        va_start(args, fmt);
 -      ret = vsnpath(path, sizeof(path), fmt, args);
 +      do_git_path(pathname, fmt, args);
        va_end(args);
 -      return xstrdup(ret);
 +      return pathname->buf;
  }
  
 -char *mkpathdup(const char *fmt, ...)
 +char *git_pathdup(const char *fmt, ...)
  {
 -      char *path;
 -      struct strbuf sb = STRBUF_INIT;
 +      struct strbuf path = STRBUF_INIT;
        va_list args;
 -
        va_start(args, fmt);
 -      strbuf_vaddf(&sb, fmt, args);
 +      do_git_path(&path, fmt, args);
        va_end(args);
 -      path = xstrdup(cleanup_path(sb.buf));
 -
 -      strbuf_release(&sb);
 -      return path;
 +      return strbuf_detach(&path, NULL);
  }
  
 -char *mkpath(const char *fmt, ...)
 +char *mkpathdup(const char *fmt, ...)
  {
 +      struct strbuf sb = STRBUF_INIT;
        va_list args;
 -      unsigned len;
 -      char *pathname = get_pathname();
 -
        va_start(args, fmt);
 -      len = vsnprintf(pathname, PATH_MAX, fmt, args);
 +      strbuf_vaddf(&sb, fmt, args);
        va_end(args);
 -      if (len >= PATH_MAX)
 -              return bad_path;
 -      return cleanup_path(pathname);
 +      strbuf_cleanup_path(&sb);
 +      return strbuf_detach(&sb, NULL);
  }
  
 -char *git_path(const char *fmt, ...)
 +const char *mkpath(const char *fmt, ...)
  {
 -      char *pathname = get_pathname();
        va_list args;
 -      char *ret;
 -
 +      struct strbuf *pathname = get_pathname();
        va_start(args, fmt);
 -      ret = vsnpath(pathname, PATH_MAX, fmt, args);
 +      strbuf_vaddf(pathname, fmt, args);
        va_end(args);
 -      return ret;
 +      return cleanup_path(pathname->buf);
  }
  
- void home_config_paths(char **global, char **xdg, char *file)
- {
-       char *xdg_home = getenv("XDG_CONFIG_HOME");
-       char *home = getenv("HOME");
-       char *to_free = NULL;
-       if (!home) {
-               if (global)
-                       *global = NULL;
-       } else {
-               if (!xdg_home) {
-                       to_free = mkpathdup("%s/.config", home);
-                       xdg_home = to_free;
-               }
-               if (global)
-                       *global = mkpathdup("%s/.gitconfig", home);
-       }
-       if (xdg) {
-               if (!xdg_home)
-                       *xdg = NULL;
-               else
-                       *xdg = mkpathdup("%s/git/%s", xdg_home, file);
-       }
-       free(to_free);
- }
 -char *git_path_submodule(const char *path, const char *fmt, ...)
 +const char *git_path_submodule(const char *path, const char *fmt, ...)
  {
 -      char *pathname = get_pathname();
 -      struct strbuf buf = STRBUF_INIT;
 +      struct strbuf *buf = get_pathname();
        const char *git_dir;
        va_list args;
 -      unsigned len;
 -
 -      len = strlen(path);
 -      if (len > PATH_MAX-100)
 -              return bad_path;
  
 -      strbuf_addstr(&buf, path);
 -      if (len && path[len-1] != '/')
 -              strbuf_addch(&buf, '/');
 -      strbuf_addstr(&buf, ".git");
 +      strbuf_addstr(buf, path);
 +      if (buf->len && buf->buf[buf->len - 1] != '/')
 +              strbuf_addch(buf, '/');
 +      strbuf_addstr(buf, ".git");
  
 -      git_dir = read_gitfile(buf.buf);
 +      git_dir = read_gitfile(buf->buf);
        if (git_dir) {
 -              strbuf_reset(&buf);
 -              strbuf_addstr(&buf, git_dir);
 +              strbuf_reset(buf);
 +              strbuf_addstr(buf, git_dir);
        }
 -      strbuf_addch(&buf, '/');
 -
 -      if (buf.len >= PATH_MAX)
 -              return bad_path;
 -      memcpy(pathname, buf.buf, buf.len + 1);
 -
 -      strbuf_release(&buf);
 -      len = strlen(pathname);
 +      strbuf_addch(buf, '/');
  
        va_start(args, fmt);
 -      len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
 +      strbuf_vaddf(buf, fmt, args);
        va_end(args);
 -      if (len >= PATH_MAX)
 -              return bad_path;
 -      return cleanup_path(pathname);
 +      strbuf_cleanup_path(buf);
 +      return buf->buf;
  }
  
  int validate_headref(const char *path)