From: Junio C Hamano Date: Fri, 10 Mar 2017 21:24:23 +0000 (-0800) Subject: Merge branch 'rs/strbuf-add-real-path' X-Git-Tag: v2.13.0-rc0~143 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/fc32293502e86be2cabbe5e8e5863a2b657207b8?ds=inline;hp=-c Merge branch 'rs/strbuf-add-real-path' An helper function to make it easier to append the result from real_path() to a strbuf has been added. * rs/strbuf-add-real-path: strbuf: add strbuf_add_real_path() cocci: use ALLOC_ARRAY --- fc32293502e86be2cabbe5e8e5863a2b657207b8 diff --combined setup.c index 967f289f1e,5af64ad530..f14cbcd338 --- a/setup.c +++ b/setup.c @@@ -254,12 -254,10 +254,12 @@@ int get_common_dir_noenv(struct strbuf if (!is_absolute_path(data.buf)) strbuf_addf(&path, "%s/", gitdir); strbuf_addbuf(&path, &data); - strbuf_addstr(sb, real_path(path.buf)); + strbuf_add_real_path(sb, path.buf); ret = 1; - } else + } else { strbuf_addstr(sb, gitdir); + } + strbuf_release(&data); strbuf_release(&path); return ret; @@@ -486,30 -484,6 +486,30 @@@ int verify_repository_format(const stru return 0; } +void read_gitfile_error_die(int error_code, const char *path, const char *dir) +{ + switch (error_code) { + case READ_GITFILE_ERR_STAT_FAILED: + case READ_GITFILE_ERR_NOT_A_FILE: + /* non-fatal; follow return path */ + break; + case READ_GITFILE_ERR_OPEN_FAILED: + die_errno("Error opening '%s'", path); + case READ_GITFILE_ERR_TOO_LARGE: + die("Too large to be a .git file: '%s'", path); + case READ_GITFILE_ERR_READ_FAILED: + die("Error reading %s", path); + case READ_GITFILE_ERR_INVALID_FORMAT: + die("Invalid gitfile format: %s", path); + case READ_GITFILE_ERR_NO_PATH: + die("No path in gitfile: %s", path); + case READ_GITFILE_ERR_NOT_A_REPO: + die("Not a git repository: %s", dir); + default: + die("BUG: unknown error code"); + } +} + /* * Try to read the location of the git directory from the .git file, * return path to git directory if found. @@@ -583,8 -557,28 +583,8 @@@ const char *read_gitfile_gently(const c cleanup_return: if (return_error_code) *return_error_code = error_code; - else if (error_code) { - switch (error_code) { - case READ_GITFILE_ERR_STAT_FAILED: - case READ_GITFILE_ERR_NOT_A_FILE: - /* non-fatal; follow return path */ - break; - case READ_GITFILE_ERR_OPEN_FAILED: - die_errno("Error opening '%s'", path); - case READ_GITFILE_ERR_TOO_LARGE: - die("Too large to be a .git file: '%s'", path); - case READ_GITFILE_ERR_READ_FAILED: - die("Error reading %s", path); - case READ_GITFILE_ERR_INVALID_FORMAT: - die("Invalid gitfile format: %s", path); - case READ_GITFILE_ERR_NO_PATH: - die("No path in gitfile: %s", path); - case READ_GITFILE_ERR_NOT_A_REPO: - die("Not a git repository: %s", dir); - default: - assert(0); - } - } + else if (error_code) + read_gitfile_error_die(error_code, path, dir); free(buf); return error_code ? NULL : path; @@@ -698,7 -692,7 +698,7 @@@ static const char *setup_discovered_git /* --work-tree is set without --git-dir; use discovered one */ if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { if (offset != cwd->len && !is_absolute_path(gitdir)) - gitdir = xstrdup(real_path(gitdir)); + gitdir = real_pathdup(gitdir); if (chdir(cwd->buf)) die_errno("Could not come back to cwd"); return setup_explicit_git_dir(gitdir, cwd, nongit_ok); @@@ -806,12 -800,11 +806,12 @@@ static int canonicalize_ceiling_entry(s /* Keep entry but do not canonicalize it */ return 1; } else { - const char *real_path = real_path_if_valid(ceil); - if (!real_path) + char *real_path = real_pathdup(ceil); + if (!real_path) { return 0; + } free(item->string); - item->string = xstrdup(real_path); + item->string = real_path; return 1; } } @@@ -1021,11 -1014,11 +1021,11 @@@ const char *setup_git_directory(void return setup_git_directory_gently(NULL); } -const char *resolve_gitdir(const char *suspect) +const char *resolve_gitdir_gently(const char *suspect, int *return_error_code) { if (is_git_directory(suspect)) return suspect; - return read_gitfile(suspect); + return read_gitfile_gently(suspect, return_error_code); } /* if any standard file descriptor is missing open it to /dev/null */ diff --combined strbuf.h index cf1b5409e7,ab12d3916c..cf8e4bf532 --- a/strbuf.h +++ b/strbuf.h @@@ -109,7 -109,9 +109,7 @@@ extern void strbuf_attach(struct strbu */ static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) { - struct strbuf tmp = *a; - *a = *b; - *b = tmp; + SWAP(*a, *b); } @@@ -441,6 -443,20 +441,20 @@@ extern int strbuf_getcwd(struct strbuf */ extern void strbuf_add_absolute_path(struct strbuf *sb, const char *path); + /** + * Canonize `path` (make it absolute, resolve symlinks, remove extra + * slashes) and append it to `sb`. Die with an informative error + * message if there is a problem. + * + * The directory part of `path` (i.e., everything up to the last + * dir_sep) must denote a valid, existing directory, but the last + * component need not exist. + * + * Callers that don't mind links should use the more lightweight + * strbuf_add_absolute_path() instead. + */ + extern void strbuf_add_real_path(struct strbuf *sb, const char *path); + /** * Normalize in-place the path contained in the strbuf. See diff --combined worktree.c index d633761575,b43160c003..d7b911aac7 --- a/worktree.c +++ b/worktree.c @@@ -145,7 -145,7 +145,7 @@@ done static void mark_current_worktree(struct worktree **worktrees) { - char *git_dir = xstrdup(absolute_path(get_git_dir())); + char *git_dir = absolute_pathdup(get_git_dir()); int i; for (i = 0; worktrees[i]; i++) { @@@ -175,7 -175,7 +175,7 @@@ struct worktree **get_worktrees(unsigne struct dirent *d; int counter = 0, alloc = 2; - list = xmalloc(alloc * sizeof(struct worktree *)); + ALLOC_ARRAY(list, alloc); list[counter++] = get_main_worktree(); @@@ -255,7 -255,7 +255,7 @@@ struct worktree *find_worktree(struct w return wt; arg = prefix_filename(prefix, strlen(prefix), arg); - path = xstrdup(real_path(arg)); + path = real_pathdup(arg); for (; *list; list++) if (!fspathcmp(path, real_path((*list)->path))) break; @@@ -380,53 -380,3 +380,53 @@@ const struct worktree *find_shared_symr return existing; } + +int submodule_uses_worktrees(const char *path) +{ + char *submodule_gitdir; + struct strbuf sb = STRBUF_INIT; + DIR *dir; + struct dirent *d; + int ret = 0; + struct repository_format format; + + submodule_gitdir = git_pathdup_submodule(path, "%s", ""); + if (!submodule_gitdir) + return 0; + + /* The env would be set for the superproject. */ + get_common_dir_noenv(&sb, submodule_gitdir); + + /* + * The check below is only known to be good for repository format + * version 0 at the time of writing this code. + */ + strbuf_addstr(&sb, "/config"); + read_repository_format(&format, sb.buf); + if (format.version != 0) { + strbuf_release(&sb); + return 1; + } + + /* Replace config by worktrees. */ + strbuf_setlen(&sb, sb.len - strlen("config")); + strbuf_addstr(&sb, "worktrees"); + + /* See if there is any file inside the worktrees directory. */ + dir = opendir(sb.buf); + strbuf_release(&sb); + free(submodule_gitdir); + + if (!dir) + return 0; + + while ((d = readdir(dir)) != NULL) { + if (is_dot_or_dotdot(d->d_name)) + continue; + + ret = 1; + break; + } + closedir(dir); + return ret; +}