diff options
Diffstat (limited to 'path.c')
| -rw-r--r-- | path.c | 297 |
1 files changed, 131 insertions, 166 deletions
@@ -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") |
