aboutsummaryrefslogtreecommitdiffstats
path: root/refs.c
diff options
context:
space:
mode:
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c76
1 files changed, 51 insertions, 25 deletions
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)