summaryrefslogtreecommitdiff
path: root/path.c
diff options
context:
space:
mode:
Diffstat (limited to 'path.c')
-rw-r--r--path.c118
1 files changed, 76 insertions, 42 deletions
diff --git a/path.c b/path.c
index 2ec950b27f..4d73cc9cd2 100644
--- 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_gently(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);
@@ -336,7 +342,7 @@ char *enter_repo(char *path, int strict)
if (access("objects", X_OK) == 0 && access("refs", X_OK) == 0 &&
validate_headref("HEAD") == 0) {
- setenv(GIT_DIR_ENVIRONMENT, ".", 1);
+ set_git_dir(".");
check_repository_format();
return path;
}
@@ -391,20 +397,41 @@ 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 baselen;
- if (!base)
- return abs;
- baselen = strlen(base);
- if (prefixcmp(abs, base))
+ int i = 0, j = 0;
+
+ if (!base || !base[0])
return abs;
- if (abs[baselen] == '/')
- baselen++;
- else if (base[baselen - 1] != '/')
+ while (base[i]) {
+ if (is_dir_sep(base[i])) {
+ if (!is_dir_sep(abs[j]))
+ return abs;
+ while (is_dir_sep(base[i]))
+ i++;
+ while (is_dir_sep(abs[j]))
+ j++;
+ continue;
+ } else if (abs[j] != base[i]) {
+ return abs;
+ }
+ i++;
+ j++;
+ }
+ if (
+ /* "/foo" is a prefix of "/foo" */
+ abs[j] &&
+ /* "/foo" is not a prefix of "/foobar" */
+ !is_dir_sep(base[i-1]) && !is_dir_sep(abs[j])
+ )
return abs;
- strcpy(buf, abs + baselen);
+ while (is_dir_sep(abs[j]))
+ j++;
+ if (!abs[j])
+ strcpy(buf, ".");
+ else
+ strcpy(buf, abs + j);
return buf;
}
@@ -589,7 +616,7 @@ int daemon_avoid_alias(const char *p)
/*
* This resurrects the belts and suspenders paranoia check by HPA
* done in <435560F7.4080006@zytor.com> thread, now enter_repo()
- * does not do getcwd() based path canonicalizations.
+ * does not do getcwd() based path canonicalization.
*
* sl becomes true immediately after seeing '/' and continues to
* be true as long as dots continue after that without intervening
@@ -628,3 +655,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]);
+}