v3 fixes all the things found in v2, deletes unused stuff and adds a new patch 01/13 that renames str(n)cmp_icase to fspath(n)cmp. Interdiff diff --git a/branch.c b/branch.c index 8e323d3..a5a8dcb 100644 --- a/branch.c +++ b/branch.c @@ -338,12 +338,12 @@ void die_if_checked_out(const char *branch, int ignore_current_worktree) { const struct worktree *wt; - wt = find_shared_symref("HEAD", branch, ignore_current_worktree); - if (wt) { - skip_prefix(branch, "refs/heads/", &branch); - die(_("'%s' is already checked out at '%s'"), - branch, wt->path); - } + wt = find_shared_symref("HEAD", branch); + if (!wt || (ignore_current_worktree && wt->is_current)) + return; + skip_prefix(branch, "refs/heads/", &branch); + die(_("'%s' is already checked out at '%s'"), + branch, wt->path); } int replace_each_worktree_head_symref(const char *oldref, const char *newref) diff --git a/builtin/branch.c b/builtin/branch.c index 3a2eceb..b488c3f 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -221,7 +221,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, if (kinds == FILTER_REFS_BRANCHES) { const struct worktree *wt = - find_shared_symref("HEAD", name, 0); + find_shared_symref("HEAD", name); if (wt) { error(_("Cannot delete branch '%s' " "checked out at '%s'"), diff --git a/builtin/notes.c b/builtin/notes.c index f154a69..c65b59a 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -852,7 +852,7 @@ static int merge(int argc, const char **argv, const char *prefix) update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL, 0, UPDATE_REFS_DIE_ON_ERR); /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ - wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref(), 0); + wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref()); if (wt) die(_("A notes merge into %s is already in-progress at %s"), default_notes_ref(), wt->path); diff --git a/dir.c b/dir.c index 996653b..f04bd3b 100644 --- a/dir.c +++ b/dir.c @@ -53,13 +53,12 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir, int check_only, const struct path_simplify *simplify); static int get_dtype(struct dirent *de, const char *path, int len); -/* helper string functions with support for the ignore_case flag */ -int strcmp_icase(const char *a, const char *b) +int fspathcmp(const char *a, const char *b) { return ignore_case ? strcasecmp(a, b) : strcmp(a, b); } -int strncmp_icase(const char *a, const char *b, size_t count) +int fspathncmp(const char *a, const char *b, size_t count) { return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count); } @@ -802,12 +801,12 @@ int match_basename(const char *basename, int basenamelen, { if (prefix == patternlen) { if (patternlen == basenamelen && - !strncmp_icase(pattern, basename, basenamelen)) + !fspathncmp(pattern, basename, basenamelen)) return 1; } else if (flags & EXC_FLAG_ENDSWITH) { /* "*literal" matching against "fooliteral" */ if (patternlen - 1 <= basenamelen && - !strncmp_icase(pattern + 1, + !fspathncmp(pattern + 1, basename + basenamelen - (patternlen - 1), patternlen - 1)) return 1; @@ -844,7 +843,7 @@ int match_pathname(const char *pathname, int pathlen, */ if (pathlen < baselen + 1 || (baselen && pathname[baselen] != '/') || - strncmp_icase(pathname, base, baselen)) + fspathncmp(pathname, base, baselen)) return 0; namelen = baselen ? pathlen - baselen - 1 : pathlen; @@ -858,7 +857,7 @@ int match_pathname(const char *pathname, int pathlen, if (prefix > namelen) return 0; - if (strncmp_icase(pattern, name, prefix)) + if (fspathncmp(pattern, name, prefix)) return 0; pattern += prefix; patternlen -= prefix; diff --git a/dir.h b/dir.h index 301b737..e34d555 100644 --- a/dir.h +++ b/dir.h @@ -270,8 +270,8 @@ extern int remove_dir_recursively(struct strbuf *path, int flag); /* tries to remove the path with empty directories along it, ignores ENOENT */ extern int remove_path(const char *path); -extern int strcmp_icase(const char *a, const char *b); -extern int strncmp_icase(const char *a, const char *b, size_t count); +extern int fspathcmp(const char *a, const char *b); +extern int fspathncmp(const char *a, const char *b, size_t count); extern int fnmatch_icase(const char *pattern, const char *string, int flags); /* diff --git a/fast-import.c b/fast-import.c index 9fc7093..339cd38 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1512,7 +1512,7 @@ static int tree_content_set( t = root->tree; for (i = 0; i < t->entry_count; i++) { e = t->entries[i]; - if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) { + if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) { if (!*slash1) { if (!S_ISDIR(mode) && e->versions[1].mode == mode @@ -1602,7 +1602,7 @@ static int tree_content_remove( t = root->tree; for (i = 0; i < t->entry_count; i++) { e = t->entries[i]; - if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) { + if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) { if (*slash1 && !S_ISDIR(e->versions[1].mode)) /* * If p names a file in some subdirectory, and a @@ -1669,7 +1669,7 @@ static int tree_content_get( t = root->tree; for (i = 0; i < t->entry_count; i++) { e = t->entries[i]; - if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) { + if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) { if (!*slash1) goto found_entry; if (!S_ISDIR(e->versions[1].mode)) diff --git a/path.c b/path.c index c421d37..8fdd187 100644 --- a/path.c +++ b/path.c @@ -466,16 +466,6 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...) return pathname->buf; } -char *worktree_git_pathdup(const struct worktree *wt, const char *fmt, ...) -{ - struct strbuf path = STRBUF_INIT; - va_list args; - va_start(args, fmt); - do_git_path(wt, &path, fmt, args); - va_end(args); - return strbuf_detach(&path, NULL); -} - static void do_submodule_path(struct strbuf *buf, const char *path, const char *fmt, va_list args) { diff --git a/sha1_file.c b/sha1_file.c index d0f2aa0..ea6381b 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -301,7 +301,7 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base, return -1; } } - if (!strcmp_icase(ent->base, normalized_objdir)) { + if (!fspathcmp(ent->base, normalized_objdir)) { free(ent); return -1; } diff --git a/worktree.c b/worktree.c index 8a3d394..4817d60 100644 --- a/worktree.c +++ b/worktree.c @@ -151,14 +151,32 @@ done: return worktree; } +static void mark_current_worktree(struct worktree **worktrees) +{ + struct strbuf git_dir = STRBUF_INIT; + struct strbuf path = STRBUF_INIT; + int i; + + strbuf_addstr(&git_dir, absolute_path(get_git_dir())); + for (i = 0; worktrees[i]; i++) { + struct worktree *wt = worktrees[i]; + strbuf_addstr(&path, absolute_path(get_worktree_git_dir(wt))); + wt->is_current = !fspathcmp(git_dir.buf, path.buf); + strbuf_reset(&path); + if (wt->is_current) + break; + } + strbuf_release(&git_dir); + strbuf_release(&path); +} + struct worktree **get_worktrees(void) { struct worktree **list = NULL; - struct strbuf git_dir = STRBUF_INIT; struct strbuf path = STRBUF_INIT; DIR *dir; struct dirent *d; - int i, counter = 0, alloc = 2; + int counter = 0, alloc = 2; list = xmalloc(alloc * sizeof(struct worktree *)); @@ -184,17 +202,7 @@ struct worktree **get_worktrees(void) ALLOC_GROW(list, counter + 1, alloc); list[counter] = NULL; - strbuf_addstr(&git_dir, absolute_path(get_git_dir())); - for (i = 0; i < counter; i++) { - struct worktree *wt = list[i]; - strbuf_addstr(&path, absolute_path(get_worktree_git_dir(wt))); - wt->is_current = !strcmp_icase(git_dir.buf, path.buf); - strbuf_reset(&path); - if (wt->is_current) - break; - } - strbuf_release(&git_dir); - strbuf_release(&path); + mark_current_worktree(list); return list; } @@ -241,9 +249,14 @@ int is_worktree_being_bisected(const struct worktree *wt, return found_rebase; } +/* + * note: this function should be able to detect shared symref even if + * HEAD is temporarily detached (e.g. in the middle of rebase or + * bisect). New commands that do similar things should update this + * function as well. + */ const struct worktree *find_shared_symref(const char *symref, - const char *target, - int ignore_current_worktree) + const char *target) { const struct worktree *existing = NULL; struct strbuf path = STRBUF_INIT; @@ -258,9 +271,6 @@ const struct worktree *find_shared_symref(const char *symref, for (i = 0; worktrees[i]; i++) { struct worktree *wt = worktrees[i]; - if (ignore_current_worktree && wt->is_current) - continue; - if (wt->is_detached && !strcmp(symref, "HEAD")) { if (is_worktree_being_rebased(wt, target)) { existing = wt; diff --git a/worktree.h b/worktree.h index d4a3534..1394909 100644 --- a/worktree.h +++ b/worktree.h @@ -36,26 +36,21 @@ extern void free_worktrees(struct worktree **); /* * Check if a per-worktree symref points to a ref in the main worktree - * or any linked worktree, and return the path to the exising worktree - * if it is. Returns NULL if there is no existing ref. The result - * may be destroyed by the next call. + * or any linked worktree, and return the worktree that holds the ref, + * or NULL otherwise. The result may be destroyed by the next call. */ extern const struct worktree *find_shared_symref(const char *symref, - const char *target, - int ignore_current_worktree); + const char *target); int is_worktree_being_rebased(const struct worktree *wt, const char *target); int is_worktree_being_bisected(const struct worktree *wt, const char *target); /* - * Similar to git_path() and git_pathdup() but can produce paths for a - * specified worktree instead of current one + * Similar to git_path() but can produce paths for a specified + * worktree instead of current one */ extern const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...) __attribute__((format (printf, 2, 3))); -extern char *worktree_git_pathdup(const struct worktree *wt, - const char *fmt, ...) - __attribute__((format (printf, 2, 3))); #endif diff --git a/wt-status.c b/wt-status.c index 971e071..0032ef5 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1410,7 +1410,7 @@ void wt_status_get_state(struct wt_status_state *state, if (!stat(git_path_merge_head(), &st)) { state->merge_in_progress = 1; } else if (wt_status_check_rebase(NULL, state)) { - ; /* all set */ + ; /* all set */ } else if (!stat(git_path_cherry_pick_head(), &st) && !get_sha1("CHERRY_PICK_HEAD", sha1)) { state->cherry_pick_in_progress = 1; [01/13] dir.c: rename str(n)cmp_icase to fspath(n)cmp [02/13] path.c: add git_common_path() and strbuf_git_common_path() [03/13] worktree.c: store "id" instead of "git_dir" [04/13] worktree.c: make find_shared_symref() return struct worktree * [05/13] worktree.c: mark current worktree [06/13] path.c: refactor and add worktree_git_path() [07/13] wt-status.c: split rebase detection out of wt_status_get_state() [08/13] wt-status.c: make wt_status_check_rebase() work on any worktree [09/13] worktree.c: avoid referencing to worktrees[i] multiple times [10/13] worktree.c: check whether branch is rebased in another worktree [11/13] wt-status.c: split bisect detection out of wt_status_get_state() [12/13] worktree.c: check whether branch is bisected in another worktree [13/13] branch: do not rename a branch under bisect or rebase Total 17 files changed, 344 insertions(+), 82 deletions(-) -- Duy -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html