From 71e5473493612f74244e2fa7a257a868df98be53 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Mon, 19 Sep 2022 16:34:50 +0000 Subject: refs: unify parse_worktree_ref() and ref_type() The logic to handle worktree refs (worktrees/NAME/REF and main-worktree/REF) existed in two places: * ref_type() in refs.c * parse_worktree_ref() in worktree.c Collapse this logic together in one function parse_worktree_ref(): this avoids having to cross-check the result of parse_worktree_ref() and ref_type(). Introduce enum ref_worktree_type, which is slightly different from enum ref_type. The latter is a misleading name (one would think that 'ref_type' would have the symref option). Instead, enum ref_worktree_type only makes explicit how a refname relates to a worktree. From this point of view, HEAD and refs/bisect/abc are the same: they specify the current worktree implicitly. The files-backend must avoid packing refs/bisect/* and friends into packed-refs, so expose is_per_worktree_ref() separately. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- refs.c | 76 ++++++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 25 deletions(-) (limited to 'refs.c') diff --git a/refs.c b/refs.c index c89d558892..1491ae937e 100644 --- a/refs.c +++ b/refs.c @@ -811,7 +811,7 @@ int dwim_log(const char *str, int len, struct object_id *oid, char **log) return repo_dwim_log(the_repository, str, len, oid, log); } -static int is_per_worktree_ref(const char *refname) +int is_per_worktree_ref(const char *refname) { return starts_with(refname, "refs/worktree/") || starts_with(refname, "refs/bisect/") || @@ -827,37 +827,63 @@ static int is_pseudoref_syntax(const char *refname) return 0; } + /* + * HEAD is not a pseudoref, but it certainly uses the + * pseudoref syntax. + */ return 1; } -static int is_main_pseudoref_syntax(const char *refname) -{ - return skip_prefix(refname, "main-worktree/", &refname) && - *refname && - is_pseudoref_syntax(refname); +static int is_current_worktree_ref(const char *ref) { + return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref); } -static int is_other_pseudoref_syntax(const char *refname) +enum ref_worktree_type parse_worktree_ref(const char *maybe_worktree_ref, + const char **worktree_name, int *worktree_name_length, + const char **bare_refname) { - if (!skip_prefix(refname, "worktrees/", &refname)) - return 0; - refname = strchr(refname, '/'); - if (!refname || !refname[1]) - return 0; - return is_pseudoref_syntax(refname + 1); -} + const char *name_dummy; + int name_length_dummy; + const char *ref_dummy; -enum ref_type ref_type(const char *refname) -{ - if (is_per_worktree_ref(refname)) - return REF_TYPE_PER_WORKTREE; - if (is_pseudoref_syntax(refname)) - return REF_TYPE_PSEUDOREF; - if (is_main_pseudoref_syntax(refname)) - return REF_TYPE_MAIN_PSEUDOREF; - if (is_other_pseudoref_syntax(refname)) - return REF_TYPE_OTHER_PSEUDOREF; - return REF_TYPE_NORMAL; + if (!worktree_name) + worktree_name = &name_dummy; + if (!worktree_name_length) + worktree_name_length = &name_length_dummy; + if (!bare_refname) + bare_refname = &ref_dummy; + + if (skip_prefix(maybe_worktree_ref, "worktrees/", bare_refname)) { + const char *slash = strchr(*bare_refname, '/'); + + *worktree_name = *bare_refname; + if (!slash) { + *worktree_name_length = strlen(*worktree_name); + + /* This is an error condition, and the caller tell because the bare_refname is "" */ + *bare_refname = *worktree_name + *worktree_name_length; + return REF_WORKTREE_OTHER; + } + + *worktree_name_length = slash - *bare_refname; + *bare_refname = slash + 1; + + if (is_current_worktree_ref(*bare_refname)) + return REF_WORKTREE_OTHER; + } + + *worktree_name = NULL; + *worktree_name_length = 0; + + if (skip_prefix(maybe_worktree_ref, "main-worktree/", bare_refname) + && is_current_worktree_ref(*bare_refname)) + return REF_WORKTREE_MAIN; + + *bare_refname = maybe_worktree_ref; + if (is_current_worktree_ref(maybe_worktree_ref)) + return REF_WORKTREE_CURRENT; + + return REF_WORKTREE_SHARED; } long get_files_ref_lock_timeout_ms(void) -- cgit v1.2.3