aboutsummaryrefslogtreecommitdiffstats
path: root/path.c
diff options
context:
space:
mode:
Diffstat (limited to 'path.c')
-rw-r--r--path.c297
1 files changed, 131 insertions, 166 deletions
diff --git a/path.c b/path.c
index 044a50bad0..910756c8b3 100644
--- a/path.c
+++ b/path.c
@@ -1,11 +1,11 @@
/*
* Utilities for paths and pathnames
*/
+
#include "git-compat-util.h"
#include "abspath.h"
#include "environment.h"
#include "gettext.h"
-#include "hex.h"
#include "repository.h"
#include "strbuf.h"
#include "string-list.h"
@@ -18,7 +18,6 @@
#include "object-store-ll.h"
#include "lockfile.h"
#include "exec-cmd.h"
-#include "wrapper.h"
static int get_st_mode_bits(const char *path, int *mode)
{
@@ -29,8 +28,6 @@ static int get_st_mode_bits(const char *path, int *mode)
return 0;
}
-static char bad_path[] = "/bad-path/";
-
static struct strbuf *get_pathname(void)
{
static struct strbuf pathname_array[4] = {
@@ -60,21 +57,6 @@ static void strbuf_cleanup_path(struct strbuf *sb)
strbuf_remove(sb, 0, path - sb->buf);
}
-char *mksnpath(char *buf, size_t n, const char *fmt, ...)
-{
- va_list args;
- unsigned len;
-
- va_start(args, fmt);
- len = vsnprintf(buf, n, fmt, args);
- va_end(args);
- if (len >= n) {
- strlcpy(buf, bad_path, n);
- return buf;
- }
- return (char *)cleanup_path(buf);
-}
-
static int dir_prefix(const char *buf, const char *dir)
{
int len = strlen(dir);
@@ -381,15 +363,15 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len,
strbuf_addstr(buf, LOCK_SUFFIX);
}
-void report_linked_checkout_garbage(void)
+void report_linked_checkout_garbage(struct repository *r)
{
struct strbuf sb = STRBUF_INIT;
const struct common_dir *p;
int len;
- if (!the_repository->different_commondir)
+ if (!r->different_commondir)
return;
- strbuf_addf(&sb, "%s/", get_git_dir());
+ strbuf_addf(&sb, "%s/", r->gitdir);
len = sb.len;
for (p = common_list; p->path; p++) {
const char *path = p->path;
@@ -403,10 +385,11 @@ void report_linked_checkout_garbage(void)
strbuf_release(&sb);
}
-static void adjust_git_path(const struct repository *repo,
+static void adjust_git_path(struct repository *repo,
struct strbuf *buf, int git_dir_len)
{
const char *base = buf->buf + git_dir_len;
+
if (is_dir_file(base, "info", "grafts"))
strbuf_splice(buf, 0, buf->len,
repo->graft_file, strlen(repo->graft_file));
@@ -415,8 +398,8 @@ static void adjust_git_path(const struct repository *repo,
repo->index_file, strlen(repo->index_file));
else if (dir_prefix(base, "objects"))
replace_dir(buf, git_dir_len + 7, repo->objects->odb->path);
- else if (git_hooks_path && dir_prefix(base, "hooks"))
- replace_dir(buf, git_dir_len + 5, git_hooks_path);
+ else if (repo_settings_get_hooks_path(repo) && dir_prefix(base, "hooks"))
+ replace_dir(buf, git_dir_len + 5, repo_settings_get_hooks_path(repo));
else if (repo->different_commondir)
update_common_dir(buf, git_dir_len, repo->commondir);
}
@@ -430,12 +413,12 @@ static void strbuf_worktree_gitdir(struct strbuf *buf,
else if (!wt->id)
strbuf_addstr(buf, repo->commondir);
else
- strbuf_git_common_path(buf, repo, "worktrees/%s", wt->id);
+ repo_common_path_append(repo, buf, "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)
+static void repo_git_pathv(struct repository *repo,
+ const struct worktree *wt, struct strbuf *buf,
+ const char *fmt, va_list args)
{
int gitdir_len;
strbuf_worktree_gitdir(buf, repo, wt);
@@ -448,63 +431,38 @@ static void do_git_path(const struct repository *repo,
strbuf_cleanup_path(buf);
}
-char *repo_git_path(const struct repository *repo,
+char *repo_git_path(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);
+ repo_git_pathv(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(the_repository, NULL, buf, fmt, args);
- va_end(args);
- return buf->buf;
-}
-
-void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
+const char *repo_git_path_append(struct repository *repo,
+ struct strbuf *sb,
+ const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
- do_git_path(the_repository, NULL, sb, fmt, args);
+ repo_git_pathv(repo, NULL, sb, fmt, args);
va_end(args);
+ return sb->buf;
}
-const char *git_path(const char *fmt, ...)
-{
- struct strbuf *pathname = get_pathname();
- va_list args;
- va_start(args, fmt);
- do_git_path(the_repository, NULL, pathname, fmt, args);
- va_end(args);
- return pathname->buf;
-}
-
-char *git_pathdup(const char *fmt, ...)
+const char *repo_git_path_replace(struct repository *repo,
+ struct strbuf *sb,
+ const char *fmt, ...)
{
- struct strbuf path = STRBUF_INIT;
va_list args;
+ strbuf_reset(sb);
va_start(args, fmt);
- do_git_path(the_repository, NULL, &path, fmt, args);
+ repo_git_pathv(repo, NULL, sb, fmt, args);
va_end(args);
- return strbuf_detach(&path, NULL);
+ return sb->buf;
}
char *mkpathdup(const char *fmt, ...)
@@ -528,12 +486,17 @@ const char *mkpath(const char *fmt, ...)
return cleanup_path(pathname->buf);
}
-const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
+const char *worktree_git_path(struct repository *r,
+ const struct worktree *wt, const char *fmt, ...)
{
struct strbuf *pathname = get_pathname();
va_list args;
+
+ if (wt && wt->repo != r)
+ BUG("worktree not connected to expected repository");
+
va_start(args, fmt);
- do_git_path(the_repository, wt, pathname, fmt, args);
+ repo_git_pathv(r, wt, pathname, fmt, args);
va_end(args);
return pathname->buf;
}
@@ -555,39 +518,56 @@ char *repo_worktree_path(const struct repository *repo, const char *fmt, ...)
struct strbuf path = STRBUF_INIT;
va_list args;
+ va_start(args, fmt);
+ do_worktree_path(repo, &path, fmt, args);
+ va_end(args);
+
+ return strbuf_detach(&path, NULL);
+}
+
+const char *repo_worktree_path_append(const struct repository *repo,
+ struct strbuf *sb,
+ const char *fmt, ...)
+{
+ va_list args;
+
if (!repo->worktree)
return NULL;
va_start(args, fmt);
- do_worktree_path(repo, &path, fmt, args);
+ do_worktree_path(repo, sb, fmt, args);
va_end(args);
- return strbuf_detach(&path, NULL);
+ return sb->buf;
}
-void strbuf_repo_worktree_path(struct strbuf *sb,
- const struct repository *repo,
- const char *fmt, ...)
+const char *repo_worktree_path_replace(const struct repository *repo,
+ struct strbuf *sb,
+ const char *fmt, ...)
{
va_list args;
+ strbuf_reset(sb);
if (!repo->worktree)
- return;
+ return NULL;
va_start(args, fmt);
do_worktree_path(repo, sb, fmt, args);
va_end(args);
+
+ return sb->buf;
}
/* Returns 0 on success, negative on failure. */
-static int do_submodule_path(struct strbuf *buf, const char *path,
+static int do_submodule_path(struct repository *repo,
+ struct strbuf *buf, const char *path,
const char *fmt, va_list args)
{
struct strbuf git_submodule_common_dir = STRBUF_INIT;
struct strbuf git_submodule_dir = STRBUF_INIT;
int ret;
- ret = submodule_to_gitdir(&git_submodule_dir, path);
+ ret = submodule_to_gitdir(repo, &git_submodule_dir, path);
if (ret)
goto cleanup;
@@ -606,13 +586,14 @@ cleanup:
return ret;
}
-char *git_pathdup_submodule(const char *path, const char *fmt, ...)
+char *repo_submodule_path(struct repository *repo,
+ const char *path, const char *fmt, ...)
{
int err;
va_list args;
struct strbuf buf = STRBUF_INIT;
va_start(args, fmt);
- err = do_submodule_path(&buf, path, fmt, args);
+ err = do_submodule_path(repo, &buf, path, fmt, args);
va_end(args);
if (err) {
strbuf_release(&buf);
@@ -621,100 +602,81 @@ char *git_pathdup_submodule(const char *path, const char *fmt, ...)
return strbuf_detach(&buf, NULL);
}
-int strbuf_git_path_submodule(struct strbuf *buf, const char *path,
- const char *fmt, ...)
+const char *repo_submodule_path_append(struct repository *repo,
+ struct strbuf *buf,
+ const char *path,
+ const char *fmt, ...)
{
int err;
va_list args;
va_start(args, fmt);
- err = do_submodule_path(buf, path, fmt, args);
+ err = do_submodule_path(repo, buf, path, fmt, args);
va_end(args);
+ if (err)
+ return NULL;
+ return buf->buf;
+}
- return err;
+const char *repo_submodule_path_replace(struct repository *repo,
+ struct strbuf *buf,
+ const char *path,
+ const char *fmt, ...)
+{
+ int err;
+ va_list args;
+ strbuf_reset(buf);
+ va_start(args, fmt);
+ err = do_submodule_path(repo, buf, path, fmt, args);
+ va_end(args);
+ if (err)
+ return NULL;
+ return buf->buf;
}
-static void do_git_common_path(const struct repository *repo,
- struct strbuf *buf,
- const char *fmt,
- va_list args)
+static void repo_common_pathv(const struct repository *repo,
+ struct strbuf *sb,
+ const char *fmt,
+ va_list args)
{
- strbuf_addstr(buf, repo->commondir);
- if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
- strbuf_addch(buf, '/');
- strbuf_vaddf(buf, fmt, args);
- strbuf_cleanup_path(buf);
+ strbuf_addstr(sb, repo->commondir);
+ if (sb->len && !is_dir_sep(sb->buf[sb->len - 1]))
+ strbuf_addch(sb, '/');
+ strbuf_vaddf(sb, fmt, args);
+ strbuf_cleanup_path(sb);
}
-const char *git_common_path(const char *fmt, ...)
+char *repo_common_path(const struct repository *repo,
+ const char *fmt, ...)
{
- struct strbuf *pathname = get_pathname();
+ struct strbuf sb = STRBUF_INIT;
va_list args;
va_start(args, fmt);
- do_git_common_path(the_repository, pathname, fmt, args);
+ repo_common_pathv(repo, &sb, fmt, args);
va_end(args);
- return pathname->buf;
+ return strbuf_detach(&sb, NULL);
}
-void strbuf_git_common_path(struct strbuf *sb,
- const struct repository *repo,
- const char *fmt, ...)
+const char *repo_common_path_append(const struct repository *repo,
+ struct strbuf *sb,
+ const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
- do_git_common_path(repo, sb, fmt, args);
+ repo_common_pathv(repo, sb, fmt, args);
va_end(args);
+ return sb->buf;
}
-int validate_headref(const char *path)
+const char *repo_common_path_replace(const struct repository *repo,
+ struct strbuf *sb,
+ const char *fmt, ...)
{
- struct stat st;
- char buffer[256];
- const char *refname;
- struct object_id oid;
- int fd;
- ssize_t len;
-
- if (lstat(path, &st) < 0)
- return -1;
-
- /* Make sure it is a "refs/.." symlink */
- if (S_ISLNK(st.st_mode)) {
- len = readlink(path, buffer, sizeof(buffer)-1);
- if (len >= 5 && !memcmp("refs/", buffer, 5))
- return 0;
- return -1;
- }
-
- /*
- * Anything else, just open it and try to see if it is a symbolic ref.
- */
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -1;
- 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 (skip_prefix(buffer, "ref:", &refname)) {
- while (isspace(*refname))
- refname++;
- if (starts_with(refname, "refs/"))
- return 0;
- }
-
- /*
- * Is this a detached HEAD?
- */
- if (!get_oid_hex(buffer, &oid))
- return 0;
-
- return -1;
+ va_list args;
+ strbuf_reset(sb);
+ va_start(args, fmt);
+ repo_common_pathv(repo, sb, fmt, args);
+ va_end(args);
+ return sb->buf;
}
static struct passwd *getpw_str(const char *username, size_t len)
@@ -795,7 +757,7 @@ return_null:
* links. User relative paths are also returned as they are given,
* except DWIM suffixing.
*/
-const char *enter_repo(const char *path, int strict)
+const char *enter_repo(const char *path, unsigned flags)
{
static struct strbuf validated_path = STRBUF_INIT;
static struct strbuf used_path = STRBUF_INIT;
@@ -803,7 +765,7 @@ const char *enter_repo(const char *path, int strict)
if (!path)
return NULL;
- if (!strict) {
+ if (!(flags & ENTER_REPO_STRICT)) {
static const char *suffix[] = {
"/.git", "", ".git/.git", ".git", NULL,
};
@@ -847,6 +809,8 @@ const char *enter_repo(const char *path, int strict)
if (!suffix[i])
return NULL;
gitfile = read_gitfile(used_path.buf);
+ if (!(flags & ENTER_REPO_ANY_OWNER_OK))
+ die_upon_dubious_ownership(gitfile, NULL, used_path.buf);
if (gitfile) {
strbuf_reset(&used_path);
strbuf_addstr(&used_path, gitfile);
@@ -857,6 +821,8 @@ const char *enter_repo(const char *path, int strict)
}
else {
const char *gitfile = read_gitfile(path);
+ if (!(flags & ENTER_REPO_ANY_OWNER_OK))
+ die_upon_dubious_ownership(gitfile, NULL, path);
if (gitfile)
path = gitfile;
if (chdir(path))
@@ -872,21 +838,22 @@ const char *enter_repo(const char *path, int strict)
return NULL;
}
-static int calc_shared_perm(int mode)
+int calc_shared_perm(struct repository *repo,
+ int mode)
{
int tweak;
- if (get_shared_repository() < 0)
- tweak = -get_shared_repository();
+ if (repo_settings_get_shared_repository(repo) < 0)
+ tweak = -repo_settings_get_shared_repository(repo);
else
- tweak = get_shared_repository();
+ tweak = repo_settings_get_shared_repository(repo);
if (!(mode & S_IWUSR))
tweak &= ~0222;
if (mode & S_IXUSR)
/* Copy read bits to execute bits */
tweak |= (tweak & 0444) >> 2;
- if (get_shared_repository() < 0)
+ if (repo_settings_get_shared_repository(repo) < 0)
mode = (mode & ~0777) | tweak;
else
mode |= tweak;
@@ -894,17 +861,17 @@ static int calc_shared_perm(int mode)
return mode;
}
-
-int adjust_shared_perm(const char *path)
+int adjust_shared_perm(struct repository *repo,
+ const char *path)
{
int old_mode, new_mode;
- if (!get_shared_repository())
+ if (!repo_settings_get_shared_repository(repo))
return 0;
if (get_st_mode_bits(path, &old_mode) < 0)
return -1;
- new_mode = calc_shared_perm(old_mode);
+ new_mode = calc_shared_perm(repo, old_mode);
if (S_ISDIR(old_mode)) {
/* Copy read bits to execute bits */
new_mode |= (new_mode & 0444) >> 2;
@@ -923,7 +890,7 @@ int adjust_shared_perm(const char *path)
return 0;
}
-void safe_create_dir(const char *dir, int share)
+void safe_create_dir(struct repository *repo, const char *dir, int share)
{
if (mkdir(dir, 0777) < 0) {
if (errno != EEXIST) {
@@ -931,7 +898,7 @@ void safe_create_dir(const char *dir, int share)
exit(1);
}
}
- else if (share && adjust_shared_perm(dir))
+ else if (share && adjust_shared_perm(repo, dir))
die(_("Could not make %s writable by group"), dir);
}
@@ -1249,12 +1216,12 @@ int strbuf_normalize_path(struct strbuf *src)
*/
int longest_ancestor_length(const char *path, struct string_list *prefixes)
{
- int i, max_len = -1;
+ int max_len = -1;
if (!strcmp(path, "/"))
return -1;
- for (i = 0; i < prefixes->nr; i++) {
+ for (size_t i = 0; i < prefixes->nr; i++) {
const char *ceil = prefixes->items[i].string;
int len = strlen(ceil);
@@ -1589,7 +1556,5 @@ REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
REPO_GIT_PATH_FUNC(merge_mode, "MERGE_MODE")
REPO_GIT_PATH_FUNC(merge_head, "MERGE_HEAD")
-REPO_GIT_PATH_FUNC(merge_autostash, "MERGE_AUTOSTASH")
-REPO_GIT_PATH_FUNC(auto_merge, "AUTO_MERGE")
REPO_GIT_PATH_FUNC(fetch_head, "FETCH_HEAD")
REPO_GIT_PATH_FUNC(shallow, "shallow")