refs: add a new function set_worktree_head_symref
Add a new function set_worktree_head_symref, to update HEAD symref for the specified worktree. To update HEAD of a linked working tree, create_symref("worktrees/$work_tree/HEAD", "refs/heads/$branch", msg) could be used. However when it comes to updating HEAD of the main working tree, it is unusable because it uses $GIT_DIR for worktree-specific symrefs (HEAD). The new function takes git_dir (real directory) as an argument, and updates HEAD of the working tree. This function will be used when renaming a branch. Signed-off-by: Kazuki Yamaguchi <k@rhe.jp> Acked-by: David Turner <dturner@twopensource.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Kazuki Yamaguchi committed
Mar 27, 2016 at 23:37 UTC
2233066e778e32dfab0471ea2ad8d1c7a94b7e39
2 files changed
+44
refs.h
+9
@@ -306,6 +306,15 @@ extern int rename_ref(const char *oldref, const char *newref, const char *logmsg
306
307
extern int create_symref(const char *refname, const char *target, const char *logmsg);
308
309
+/*
310
+ * Update HEAD of the specified gitdir.
311
+ * Similar to create_symref("relative-git-dir/HEAD", target, NULL), but
312
+ * this can update the main working tree's HEAD regardless of where
313
+ * $GIT_DIR points to.
314
+ * Return 0 if successful, non-zero otherwise.
315
+ * */
316
+extern int set_worktree_head_symref(const char *gitdir, const char *target);
317
+
318
enum action_on_err {
319
UPDATE_REFS_MSG_ON_ERR,
320
UPDATE_REFS_DIE_ON_ERR,
refs/files-backend.c
+35
@@ -2894,6 +2894,41 @@ int create_symref(const char *refname, const char *target, const char *logmsg)
2894
return ret;
2895
}
2896
2897
+int set_worktree_head_symref(const char *gitdir, const char *target)
2898
+{
2899
+ static struct lock_file head_lock;
2900
+ struct ref_lock *lock;
2901
+ struct strbuf err = STRBUF_INIT;
2902
+ struct strbuf head_path = STRBUF_INIT;
2903
+ const char *head_rel;
2904
+ int ret;
2905
+
2906
+ strbuf_addf(&head_path, "%s/HEAD", absolute_path(gitdir));
2907
+ if (hold_lock_file_for_update(&head_lock, head_path.buf,
2908
+ LOCK_NO_DEREF) < 0) {
2909
+ error("%s", err.buf);
2910
+ strbuf_release(&err);
2911
+ strbuf_release(&head_path);
2912
+ return -1;
2913
+ }
2914
+
2915
+ /* head_rel will be "HEAD" for the main tree, "worktrees/wt/HEAD" for
2916
+ linked trees */
2917
+ head_rel = remove_leading_path(head_path.buf,
2918
+ absolute_path(get_git_common_dir()));
2919
+ /* to make use of create_symref_locked(), initialize ref_lock */
2920
+ lock = xcalloc(1, sizeof(struct ref_lock));
2921
+ lock->lk = &head_lock;
2922
+ lock->ref_name = xstrdup(head_rel);
2923
+ lock->orig_ref_name = xstrdup(head_rel);
2924
+
2925
+ ret = create_symref_locked(lock, head_rel, target, NULL);
2926
+
2927
+ unlock_ref(lock); /* will free lock */
2928
+ strbuf_release(&head_path);
2929
+ return ret;
2930
+}
2931
+
2932
int reflog_exists(const char *refname)
2933
{
2934
struct stat st;