do_for_each_reflog(): use a strbuf to hold logfile name
[gitweb.git] / path.c
diff --git a/path.c b/path.c
index d1fccbde7f5ba08ba9876b12e1dbabf87f44b4e9..6f2aa699ad63c2f7c65632761efbaebb7f461868 100644 (file)
--- a/path.c
+++ b/path.c
@@ -122,39 +122,43 @@ char *git_path(const char *fmt, ...)
        return cleanup_path(pathname);
 }
 
-
-/* git_mkstemp() - create tmp file honoring TMPDIR variable */
-int git_mkstemp(char *path, size_t len, const char *template)
+char *git_path_submodule(const char *path, const char *fmt, ...)
 {
-       const char *tmp;
-       size_t n;
-
-       tmp = getenv("TMPDIR");
-       if (!tmp)
-               tmp = "/tmp";
-       n = snprintf(path, len, "%s/%s", tmp, template);
-       if (len <= n) {
-               errno = ENAMETOOLONG;
-               return -1;
-       }
-       return mkstemp(path);
-}
+       char *pathname = get_pathname();
+       struct strbuf buf = STRBUF_INIT;
+       const char *git_dir;
+       va_list args;
+       unsigned len;
 
-/* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */
-int git_mkstemps(char *path, size_t len, const char *template, int suffix_len)
-{
-       const char *tmp;
-       size_t n;
-
-       tmp = getenv("TMPDIR");
-       if (!tmp)
-               tmp = "/tmp";
-       n = snprintf(path, len, "%s/%s", tmp, template);
-       if (len <= n) {
-               errno = ENAMETOOLONG;
-               return -1;
+       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");
+
+       git_dir = read_gitfile(buf.buf);
+       if (git_dir) {
+               strbuf_reset(&buf);
+               strbuf_addstr(&buf, git_dir);
        }
-       return mkstemps(path, suffix_len);
+       strbuf_addch(&buf, '/');
+
+       if (buf.len >= PATH_MAX)
+               return bad_path;
+       memcpy(pathname, buf.buf, buf.len + 1);
+
+       strbuf_release(&buf);
+       len = strlen(pathname);
+
+       va_start(args, fmt);
+       len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
+       va_end(args);
+       if (len >= PATH_MAX)
+               return bad_path;
+       return cleanup_path(pathname);
 }
 
 int validate_headref(const char *path)
@@ -237,6 +241,8 @@ char *expand_user_path(const char *path)
                size_t username_len = first_slash - username;
                if (username_len == 0) {
                        const char *home = getenv("HOME");
+                       if (!home)
+                               goto return_null;
                        strbuf_add(&user_path, home, strlen(home));
                } else {
                        struct passwd *pw = getpw_str(username, username_len);
@@ -277,7 +283,7 @@ char *expand_user_path(const char *path)
  * links.  User relative paths are also returned as they are given,
  * except DWIM suffixing.
  */
-char *enter_repo(char *path, int strict)
+const char *enter_repo(const char *path, int strict)
 {
        static char used_path[PATH_MAX];
        static char validated_path[PATH_MAX];
@@ -287,18 +293,21 @@ char *enter_repo(char *path, int strict)
 
        if (!strict) {
                static const char *suffix[] = {
-                       ".git/.git", "/.git", ".git", "", NULL,
+                       "/.git", "", ".git/.git", ".git", NULL,
                };
+               const char *gitfile;
                int len = strlen(path);
                int i;
-               while ((1 < len) && (path[len-1] == '/')) {
-                       path[len-1] = 0;
+               while ((1 < len) && (path[len-1] == '/'))
                        len--;
-               }
+
                if (PATH_MAX <= len)
                        return NULL;
-               if (path[0] == '~') {
-                       char *newpath = expand_user_path(path);
+               strncpy(used_path, path, len); used_path[len] = 0 ;
+               strcpy(validated_path, used_path);
+
+               if (used_path[0] == '~') {
+                       char *newpath = expand_user_path(used_path);
                        if (!newpath || (PATH_MAX - 10 < strlen(newpath))) {
                                free(newpath);
                                return NULL;
@@ -310,24 +319,26 @@ char *enter_repo(char *path, int strict)
                         * anyway.
                         */
                        strcpy(used_path, newpath); free(newpath);
-                       strcpy(validated_path, path);
-                       path = used_path;
                }
                else if (PATH_MAX - 10 < len)
                        return NULL;
-               else {
-                       path = strcpy(used_path, path);
-                       strcpy(validated_path, path);
-               }
-               len = strlen(path);
+               len = strlen(used_path);
                for (i = 0; suffix[i]; i++) {
-                       strcpy(path + len, suffix[i]);
-                       if (!access(path, F_OK)) {
+                       struct stat st;
+                       strcpy(used_path + len, suffix[i]);
+                       if (!stat(used_path, &st) &&
+                           (S_ISREG(st.st_mode) ||
+                           (S_ISDIR(st.st_mode) && is_git_directory(used_path)))) {
                                strcat(validated_path, suffix[i]);
                                break;
                        }
                }
-               if (!suffix[i] || chdir(path))
+               if (!suffix[i])
+                       return NULL;
+               gitfile = read_gitfile(used_path) ;
+               if (gitfile)
+                       strcpy(used_path, gitfile);
+               if (chdir(used_path))
                        return NULL;
                path = validated_path;
        }
@@ -391,7 +402,7 @@ int set_shared_perm(const char *path, int mode)
        return 0;
 }
 
-const char *make_relative_path(const char *abs, const char *base)
+const char *relative_path(const char *abs, const char *base)
 {
        static char buf[PATH_MAX + 1];
        int i = 0, j = 0;
@@ -649,3 +660,10 @@ int daemon_avoid_alias(const char *p)
                }
        }
 }
+
+int offset_1st_component(const char *path)
+{
+       if (has_dos_drive_prefix(path))
+               return 2 + is_dir_sep(path[2]);
+       return is_dir_sep(path[0]);
+}