{"thread":{"id":"41838","subject":"[PATCH v3 1/2] refs: add a new function set_worktree_head_symref","startedAt":"2016-03-27T14:37:12Z","lastAt":"2016-04-08T06:42:58Z","messageCount":8,"participants":["Kazuki Yamaguchi","Junio C Hamano","David Turner","Eric Sunshine"],"isPatch":true,"patchVersion":3,"patchTotal":2},"messages":[{"id":"281932","messageId":"cover.1459087958.git.k@rhe.jp","threadId":"41838","inReplyTo":"1458553816-29091-1-git-send-email-k@rhe.jp","subject":"[PATCH v3 0/2] update all per-worktree HEADs when renaming a branch","fromName":"Kazuki Yamaguchi","fromEmail":"k@rhe.jp","sentAt":"2016-03-27T14:37:12Z","receivedAt":"2016-03-27T14:37:12Z","isPatch":true,"sender":{"key":"k@rhe.jp","avatar":"https://avatars.githubusercontent.com/u/1033740?v=4"},"body":"Changes from v2:\n- The flags REF_COMMON_DIR and RESOLVE_REF_COMMON_DIR are removed.\n- create_symref_common_dir() is removed and instead adds narrower\n  purpose function, set_worktree_head_symref().\n\n[1/2]\nAdds a new function set_worktree_head_symref(). This takes git_dir as\nthe first argument, and updates {git_dir}/HEAD.\n\nThe new function uses hold_lock_file_for_update() directly, instead of\nthrough lock_ref_sha1_basic() which the old [v2 3/5] used.\n\n[2/2] (from [v2 4/5])\nUses the new set_worktree_head_symref(), and the\nupdate_worktrees_head_symref() function was renamed to\nreplace_each_worktree_head_symref(), to avoid confusion with\nset_worktree_head_symref() added by [1/2].\n\n\nThanks,\n\nKazuki Yamaguchi (2):\n  refs: add a new function set_worktree_head_symref\n  branch -m: update all per-worktree HEADs\n\n branch.c             | 23 +++++++++++++++++++++++\n branch.h             |  7 +++++++\n builtin/branch.c     |  3 +--\n refs.h               |  8 ++++++++\n refs/files-backend.c | 35 +++++++++++++++++++++++++++++++++++\n t/t3200-branch.sh    | 23 ++++++++++++++++++++++-\n 6 files changed, 96 insertions(+), 3 deletions(-)\n\n-- \n2.8.0.rc4.21.g05df949\n"},{"id":"281931","messageId":"39bc3c1da6daf31f2a10e592dbb5d3daadc96199.1459087958.git.k@rhe.jp","threadId":"41838","inReplyTo":"cover.1459087958.git.k@rhe.jp","subject":"[PATCH v3 1/2] refs: add a new function set_worktree_head_symref","fromName":"Kazuki Yamaguchi","fromEmail":"k@rhe.jp","sentAt":"2016-03-27T14:37:13Z","receivedAt":"2016-03-27T14:37:13Z","isPatch":true,"sender":{"key":"k@rhe.jp","avatar":"https://avatars.githubusercontent.com/u/1033740?v=4"},"body":"Add a new function set_worktree_head_symref, to update HEAD symref for\nthe specified worktree.\n\nTo update HEAD of a linked working tree,\ncreate_symref(\"worktrees/$work_tree/HEAD\", \"refs/heads/$branch\", msg)\ncould be used. However when it comes to updating HEAD of the main\nworking tree, it is unusable because it uses $GIT_DIR for\nworktree-specific symrefs (HEAD).\n\nThe new function takes git_dir (real directory) as an argument, and\nupdates HEAD of the working tree. This function will be used when\nrenaming a branch.\n\nSigned-off-by: Kazuki Yamaguchi <k@rhe.jp>\n---\n refs.h               |  8 ++++++++\n refs/files-backend.c | 35 +++++++++++++++++++++++++++++++++++\n 2 files changed, 43 insertions(+)\n\ndiff --git a/refs.h b/refs.h\nindex 2f3decb432cf..f11154cf5faf 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -306,6 +306,14 @@ extern int rename_ref(const char *oldref, const char *newref, const char *logmsg\n \n extern int create_symref(const char *refname, const char *target, const char *logmsg);\n \n+/*\n+ * Update HEAD of the specified gitdir.\n+ * Similar to create_symref(\"relative-git-dir/HEAD\", target, NULL), but this is\n+ * able to update the main working tree's HEAD wherever $GIT_DIR points to.\n+ * Return 0 if successful, non-zero otherwise.\n+ * */\n+extern int set_worktree_head_symref(const char *gitdir, const char *target);\n+\n enum action_on_err {\n \tUPDATE_REFS_MSG_ON_ERR,\n \tUPDATE_REFS_DIE_ON_ERR,\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 81f68f846b69..ec237efec35d 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -2894,6 +2894,41 @@ int create_symref(const char *refname, const char *target, const char *logmsg)\n \treturn ret;\n }\n \n+int set_worktree_head_symref(const char *gitdir, const char *target)\n+{\n+\tstatic struct lock_file head_lock;\n+\tstruct ref_lock *lock;\n+\tstruct strbuf err = STRBUF_INIT;\n+\tstruct strbuf head_path = STRBUF_INIT;\n+\tconst char *head_rel;\n+\tint ret;\n+\n+\tstrbuf_addf(&head_path, \"%s/HEAD\", absolute_path(gitdir));\n+\tif (hold_lock_file_for_update(&head_lock, head_path.buf,\n+\t\t\t\t      LOCK_NO_DEREF) < 0) {\n+\t\terror(\"%s\", err.buf);\n+\t\tstrbuf_release(&err);\n+\t\tstrbuf_release(&head_path);\n+\t\treturn -1;\n+\t}\n+\n+\t/* head_rel will be \"HEAD\" for the main tree, \"worktrees/wt/HEAD\" for\n+\t   linked trees */\n+\thead_rel = remove_leading_path(head_path.buf,\n+\t\t\t\t       absolute_path(get_git_common_dir()));\n+\t/* to make use of create_symref_locked(), initialize ref_lock */\n+\tlock = xcalloc(1, sizeof(struct ref_lock));\n+\tlock->lk = &head_lock;\n+\tlock->ref_name = xstrdup(head_rel);\n+\tlock->orig_ref_name = xstrdup(head_rel);\n+\n+\tret = create_symref_locked(lock, head_rel, target, NULL);\n+\n+\tunlock_ref(lock); /* will free lock */\n+\tstrbuf_release(&head_path);\n+\treturn ret;\n+}\n+\n int reflog_exists(const char *refname)\n {\n \tstruct stat st;\n-- \n2.8.0.rc4.21.g05df949\n"},{"id":"281933","messageId":"572722fb3051b9383d393a46c2f6d22991ab7a93.1459087958.git.k@rhe.jp","threadId":"41838","inReplyTo":"cover.1459087958.git.k@rhe.jp","subject":"[PATCH v3 2/2] branch -m: update all per-worktree HEADs","fromName":"Kazuki Yamaguchi","fromEmail":"k@rhe.jp","sentAt":"2016-03-27T14:37:14Z","receivedAt":"2016-03-27T14:37:14Z","isPatch":true,"sender":{"key":"k@rhe.jp","avatar":"https://avatars.githubusercontent.com/u/1033740?v=4"},"body":"When renaming a branch, currently only the HEAD of current working tree\nis updated, but it must update HEADs of all working trees which point at\nthe old branch.\n\nThis is the current behavior, /path/to/wt's HEAD is not updated:\n\n  % git worktree list\n  /path/to     2c3c5f2 [master]\n  /path/to/wt  2c3c5f2 [oldname]\n  % git branch -m master master2\n  % git worktree list\n  /path/to     2c3c5f2 [master2]\n  /path/to/wt  2c3c5f2 [oldname]\n  % git branch -m oldname newname\n  % git worktree list\n  /path/to     2c3c5f2 [master2]\n  /path/to/wt  0000000 [oldname]\n\nThis patch fixes this issue by updating all relevant worktree HEADs\nwhen renaming a branch.\n\nSigned-off-by: Kazuki Yamaguchi <k@rhe.jp>\n---\n branch.c          | 23 +++++++++++++++++++++++\n branch.h          |  7 +++++++\n builtin/branch.c  |  3 +--\n t/t3200-branch.sh | 23 ++++++++++++++++++++++-\n 4 files changed, 53 insertions(+), 3 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex c50ea42172ce..416244370783 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -344,3 +344,26 @@ void die_if_checked_out(const char *branch)\n \t\tdie(_(\"'%s' is already checked out at '%s'\"), branch, existing);\n \t}\n }\n+\n+int replace_each_worktree_head_symref(const char *oldref, const char *newref)\n+{\n+\tint ret = 0;\n+\tstruct worktree **worktrees = get_worktrees();\n+\tint i;\n+\n+\tfor (i = 0; worktrees[i]; i++) {\n+\t\tif (worktrees[i]->is_detached)\n+\t\t\tcontinue;\n+\t\tif (strcmp(oldref, worktrees[i]->head_ref))\n+\t\t\tcontinue;\n+\n+\t\tif (set_worktree_head_symref(worktrees[i]->git_dir, newref)) {\n+\t\t\tret = -1;\n+\t\t\terror(_(\"HEAD of working tree %s is not updated\"),\n+\t\t\t      worktrees[i]->path);\n+\t\t}\n+\t}\n+\n+\tfree_worktrees(worktrees);\n+\treturn ret;\n+}\ndiff --git a/branch.h b/branch.h\nindex 78ad4387cd32..d69163daf793 100644\n--- a/branch.h\n+++ b/branch.h\n@@ -60,4 +60,11 @@ extern int read_branch_desc(struct strbuf *, const char *branch_name);\n  */\n extern void die_if_checked_out(const char *branch);\n \n+/*\n+ * Update all per-worktree HEADs pointing at the old ref to point the new ref.\n+ * This will be used when renaming a branch. Returns 0 if successful, non-zero\n+ * otherwise.\n+ */\n+extern int replace_each_worktree_head_symref(const char *oldref, const char *newref);\n+\n #endif\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 7b45b6bd6b80..b1738313175c 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -552,8 +552,7 @@ static void rename_branch(const char *oldname, const char *newname, int force)\n \tif (recovery)\n \t\twarning(_(\"Renamed a misnamed branch '%s' away\"), oldref.buf + 11);\n \n-\t/* no need to pass logmsg here as HEAD didn't really move */\n-\tif (!strcmp(oldname, head) && create_symref(\"HEAD\", newref.buf, NULL))\n+\tif (replace_each_worktree_head_symref(oldref.buf, newref.buf))\n \t\tdie(_(\"Branch renamed to %s, but HEAD is not updated!\"), newname);\n \n \tstrbuf_addf(&oldsection, \"branch.%s\", oldref.buf + 11);\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex a89724849065..f7d438bd7d1d 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -126,7 +126,28 @@ test_expect_success 'git branch -M foo bar should fail when bar is checked out'\n test_expect_success 'git branch -M baz bam should succeed when baz is checked out' '\n \tgit checkout -b baz &&\n \tgit branch bam &&\n-\tgit branch -M baz bam\n+\tgit branch -M baz bam &&\n+\ttest $(git rev-parse --abbrev-ref HEAD) = bam\n+'\n+\n+test_expect_success 'git branch -M baz bam should succeed when baz is checked out as linked working tree' '\n+\tgit checkout master &&\n+\tgit worktree add -b baz bazdir &&\n+\tgit worktree add -f bazdir2 baz &&\n+\tgit branch -M baz bam &&\n+\ttest $(git -C bazdir rev-parse --abbrev-ref HEAD) = bam &&\n+\ttest $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam\n+'\n+\n+test_expect_success 'git branch -M baz bam should succeed within a worktree in which baz is checked out' '\n+\tgit checkout -b baz &&\n+\tgit worktree add -f bazdir3 baz &&\n+\t(\n+\t\tcd bazdir3 &&\n+\t\tgit branch -M baz bam &&\n+\t\ttest $(git rev-parse --abbrev-ref HEAD) = bam\n+\t) &&\n+\ttest $(git rev-parse --abbrev-ref HEAD) = bam\n '\n \n test_expect_success 'git branch -M master should work when master is checked out' '\n-- \n2.8.0.rc4.21.g05df949\n"},{"id":"281974","messageId":"xmqq4mbqze65.fsf@gitster.mtv.corp.google.com","threadId":"41838","inReplyTo":"39bc3c1da6daf31f2a10e592dbb5d3daadc96199.1459087958.git.k@rhe.jp","subject":"Re: [PATCH v3 1/2] refs: add a new function set_worktree_head_symref","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-03-28T17:48:50Z","receivedAt":"2016-03-28T17:48:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Kazuki Yamaguchi <k@rhe.jp> writes:\n\n> Add a new function set_worktree_head_symref, to update HEAD symref for\n> the specified worktree.\n>\n> To update HEAD of a linked working tree,\n> create_symref(\"worktrees/$work_tree/HEAD\", \"refs/heads/$branch\", msg)\n> could be used. However when it comes to updating HEAD of the main\n> working tree, it is unusable because it uses $GIT_DIR for\n> worktree-specific symrefs (HEAD).\n>\n> The new function takes git_dir (real directory) as an argument, and\n> updates HEAD of the working tree. This function will be used when\n> renaming a branch.\n>\n> Signed-off-by: Kazuki Yamaguchi <k@rhe.jp>\n> ---\n\nI suspect that this helper function should be in the common layer\n(refs.c) to be redirected to specific backend(s).\n\nDavid & Michael, what do you think?\n\n>  refs.h               |  8 ++++++++\n>  refs/files-backend.c | 35 +++++++++++++++++++++++++++++++++++\n>  2 files changed, 43 insertions(+)\n>\n> diff --git a/refs.h b/refs.h\n> index 2f3decb432cf..f11154cf5faf 100644\n> --- a/refs.h\n> +++ b/refs.h\n> @@ -306,6 +306,14 @@ extern int rename_ref(const char *oldref, const char *newref, const char *logmsg\n>  \n>  extern int create_symref(const char *refname, const char *target, const char *logmsg);\n>  \n> +/*\n> + * Update HEAD of the specified gitdir.\n> + * Similar to create_symref(\"relative-git-dir/HEAD\", target, NULL), but this is\n> + * able to update the main working tree's HEAD wherever $GIT_DIR points to.\n> + * Return 0 if successful, non-zero otherwise.\n> + * */\n> +extern int set_worktree_head_symref(const char *gitdir, const char *target);\n> +\n>  enum action_on_err {\n>  \tUPDATE_REFS_MSG_ON_ERR,\n>  \tUPDATE_REFS_DIE_ON_ERR,\n> diff --git a/refs/files-backend.c b/refs/files-backend.c\n> index 81f68f846b69..ec237efec35d 100644\n> --- a/refs/files-backend.c\n> +++ b/refs/files-backend.c\n> @@ -2894,6 +2894,41 @@ int create_symref(const char *refname, const char *target, const char *logmsg)\n>  \treturn ret;\n>  }\n>  \n> +int set_worktree_head_symref(const char *gitdir, const char *target)\n> +{\n> +\tstatic struct lock_file head_lock;\n> +\tstruct ref_lock *lock;\n> +\tstruct strbuf err = STRBUF_INIT;\n> +\tstruct strbuf head_path = STRBUF_INIT;\n> +\tconst char *head_rel;\n> +\tint ret;\n> +\n> +\tstrbuf_addf(&head_path, \"%s/HEAD\", absolute_path(gitdir));\n> +\tif (hold_lock_file_for_update(&head_lock, head_path.buf,\n> +\t\t\t\t      LOCK_NO_DEREF) < 0) {\n> +\t\terror(\"%s\", err.buf);\n> +\t\tstrbuf_release(&err);\n> +\t\tstrbuf_release(&head_path);\n> +\t\treturn -1;\n> +\t}\n> +\n> +\t/* head_rel will be \"HEAD\" for the main tree, \"worktrees/wt/HEAD\" for\n> +\t   linked trees */\n> +\thead_rel = remove_leading_path(head_path.buf,\n> +\t\t\t\t       absolute_path(get_git_common_dir()));\n> +\t/* to make use of create_symref_locked(), initialize ref_lock */\n> +\tlock = xcalloc(1, sizeof(struct ref_lock));\n> +\tlock->lk = &head_lock;\n> +\tlock->ref_name = xstrdup(head_rel);\n> +\tlock->orig_ref_name = xstrdup(head_rel);\n> +\n> +\tret = create_symref_locked(lock, head_rel, target, NULL);\n> +\n> +\tunlock_ref(lock); /* will free lock */\n> +\tstrbuf_release(&head_path);\n> +\treturn ret;\n> +}\n> +\n>  int reflog_exists(const char *refname)\n>  {\n>  \tstruct stat st;\n"},{"id":"282017","messageId":"1459218192.2976.4.camel@twopensource.com","threadId":"41838","inReplyTo":"xmqq4mbqze65.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 1/2] refs: add a new function set_worktree_head_symref","fromName":"David Turner","fromEmail":"dturner@twopensource.com","sentAt":"2016-03-29T02:23:12Z","receivedAt":"2016-03-29T02:23:12Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"On Mon, 2016-03-28 at 10:48 -0700, Junio C Hamano wrote:\n> Kazuki Yamaguchi <k@rhe.jp> writes:\n> \n> > Add a new function set_worktree_head_symref, to update HEAD symref\n> > for\n> > the specified worktree.\n> > \n> > To update HEAD of a linked working tree,\n> > create_symref(\"worktrees/$work_tree/HEAD\", \"refs/heads/$branch\",\n> > msg)\n> > could be used. However when it comes to updating HEAD of the main\n> > working tree, it is unusable because it uses $GIT_DIR for\n> > worktree-specific symrefs (HEAD).\n> > \n> > The new function takes git_dir (real directory) as an argument, and\n> > updates HEAD of the working tree. This function will be used when\n> > renaming a branch.\n> > \n> > Signed-off-by: Kazuki Yamaguchi <k@rhe.jp>\n> > ---\n> \n> I suspect that this helper function should be in the common layer\n> (refs.c) to be redirected to specific backend(s).\n> \n> David & Michael, what do you think?\n\nHEAD is a per-worktree ref, so it's always handled by the files\nbackend.  So this looks fine to me.\n\n> > +/*\n> > + * Update HEAD of the specified gitdir.\n> > + * Similar to create_symref(\"relative-git-dir/HEAD\", target,\n> > NULL), but this is\n> > + * able to update the main working tree's HEAD wherever $GIT_DIR\n> > points to.\n\n\nnit: \"able to update the main working tree's HEAD regardless of where\nGIT_DIR points to\" would be clearer.\n"},{"id":"282912","messageId":"CAPig+cQym57U-izza5_Hn0xCDcG0MHFMcWJFc==ohKnr7acFWQ@mail.gmail.com","threadId":"41838","inReplyTo":"39bc3c1da6daf31f2a10e592dbb5d3daadc96199.1459087958.git.k@rhe.jp","subject":"Re: [PATCH v3 1/2] refs: add a new function set_worktree_head_symref","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-04-07T21:20:10Z","receivedAt":"2016-04-07T21:20:10Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Mar 27, 2016 at 10:37 AM, Kazuki Yamaguchi <k@rhe.jp> wrote:\n> Add a new function set_worktree_head_symref, to update HEAD symref for\n> the specified worktree.\n>\n> To update HEAD of a linked working tree,\n> create_symref(\"worktrees/$work_tree/HEAD\", \"refs/heads/$branch\", msg)\n> could be used. However when it comes to updating HEAD of the main\n> working tree, it is unusable because it uses $GIT_DIR for\n> worktree-specific symrefs (HEAD).\n>\n> The new function takes git_dir (real directory) as an argument, and\n> updates HEAD of the working tree. This function will be used when\n> renaming a branch.\n>\n> Signed-off-by: Kazuki Yamaguchi <k@rhe.jp>\n> ---\n> diff --git a/refs/files-backend.c b/refs/files-backend.c\n> @@ -2894,6 +2894,41 @@ int create_symref(const char *refname, const char *target, const char *logmsg)\n> +int set_worktree_head_symref(const char *gitdir, const char *target)\n> +{\n> +       static struct lock_file head_lock;\n> +       struct ref_lock *lock;\n> +       struct strbuf err = STRBUF_INIT;\n> +       struct strbuf head_path = STRBUF_INIT;\n> +       const char *head_rel;\n> +       int ret;\n> +\n> +       strbuf_addf(&head_path, \"%s/HEAD\", absolute_path(gitdir));\n> +       if (hold_lock_file_for_update(&head_lock, head_path.buf,\n> +                                     LOCK_NO_DEREF) < 0) {\n> +               error(\"%s\", err.buf);\n\n'err' has not been populated at this point, so I suspect that this\nerror message is likely to be rather uninformative.\n\n> +               strbuf_release(&err);\n> +               strbuf_release(&head_path);\n> +               return -1;\n> +       }\n> +\n> +       /* head_rel will be \"HEAD\" for the main tree, \"worktrees/wt/HEAD\" for\n> +          linked trees */\n> +       head_rel = remove_leading_path(head_path.buf,\n> +                                      absolute_path(get_git_common_dir()));\n> +       /* to make use of create_symref_locked(), initialize ref_lock */\n> +       lock = xcalloc(1, sizeof(struct ref_lock));\n> +       lock->lk = &head_lock;\n> +       lock->ref_name = xstrdup(head_rel);\n> +       lock->orig_ref_name = xstrdup(head_rel);\n> +\n> +       ret = create_symref_locked(lock, head_rel, target, NULL);\n> +\n> +       unlock_ref(lock); /* will free lock */\n> +       strbuf_release(&head_path);\n> +       return ret;\n> +}\n> +\n"},{"id":"282921","messageId":"20160408063713.GA17696@chikuwa.rhe.jp","threadId":"41838","inReplyTo":"CAPig+cQym57U-izza5_Hn0xCDcG0MHFMcWJFc==ohKnr7acFWQ@mail.gmail.com","subject":"Re: [PATCH v3 1/2] refs: add a new function set_worktree_head_symref","fromName":"Kazuki Yamaguchi","fromEmail":"k@rhe.jp","sentAt":"2016-04-08T06:37:13Z","receivedAt":"2016-04-08T06:37:13Z","isPatch":true,"sender":{"key":"k@rhe.jp","avatar":"https://avatars.githubusercontent.com/u/1033740?v=4"},"body":"On Thu, Apr 07, 2016 at 05:20:10PM -0400, Eric Sunshine wrote:\n> On Sun, Mar 27, 2016 at 10:37 AM, Kazuki Yamaguchi <k@rhe.jp> wrote:\n> > Add a new function set_worktree_head_symref, to update HEAD symref for\n> > the specified worktree.\n> >\n> > To update HEAD of a linked working tree,\n> > create_symref(\"worktrees/$work_tree/HEAD\", \"refs/heads/$branch\", msg)\n> > could be used. However when it comes to updating HEAD of the main\n> > working tree, it is unusable because it uses $GIT_DIR for\n> > worktree-specific symrefs (HEAD).\n> >\n> > The new function takes git_dir (real directory) as an argument, and\n> > updates HEAD of the working tree. This function will be used when\n> > renaming a branch.\n> >\n> > Signed-off-by: Kazuki Yamaguchi <k@rhe.jp>\n> > ---\n> > diff --git a/refs/files-backend.c b/refs/files-backend.c\n> > @@ -2894,6 +2894,41 @@ int create_symref(const char *refname, const char *target, const char *logmsg)\n> > +int set_worktree_head_symref(const char *gitdir, const char *target)\n> > +{\n> > +       static struct lock_file head_lock;\n> > +       struct ref_lock *lock;\n> > +       struct strbuf err = STRBUF_INIT;\n> > +       struct strbuf head_path = STRBUF_INIT;\n> > +       const char *head_rel;\n> > +       int ret;\n> > +\n> > +       strbuf_addf(&head_path, \"%s/HEAD\", absolute_path(gitdir));\n> > +       if (hold_lock_file_for_update(&head_lock, head_path.buf,\n> > +                                     LOCK_NO_DEREF) < 0) {\n> > +               error(\"%s\", err.buf);\n> \n> 'err' has not been populated at this point, so I suspect that this\n> error message is likely to be rather uninformative.\n\nYes, unable_to_lock_message() is missing. Thank you for pointing it out.\n\n> \n> > +               strbuf_release(&err);\n> > +               strbuf_release(&head_path);\n> > +               return -1;\n> > +       }\n> > +\n> > +       /* head_rel will be \"HEAD\" for the main tree, \"worktrees/wt/HEAD\" for\n> > +          linked trees */\n> > +       head_rel = remove_leading_path(head_path.buf,\n> > +                                      absolute_path(get_git_common_dir()));\n> > +       /* to make use of create_symref_locked(), initialize ref_lock */\n> > +       lock = xcalloc(1, sizeof(struct ref_lock));\n> > +       lock->lk = &head_lock;\n> > +       lock->ref_name = xstrdup(head_rel);\n> > +       lock->orig_ref_name = xstrdup(head_rel);\n> > +\n> > +       ret = create_symref_locked(lock, head_rel, target, NULL);\n> > +\n> > +       unlock_ref(lock); /* will free lock */\n> > +       strbuf_release(&head_path);\n> > +       return ret;\n> > +}\n> > +\n"},{"id":"282922","messageId":"CAPig+cQYktE08zy3nSqxm924P0foW91RtHcapmRBy_Fwh9S_Ug@mail.gmail.com","threadId":"41838","inReplyTo":"20160408063713.GA17696@chikuwa.rhe.jp","subject":"Re: [PATCH v3 1/2] refs: add a new function set_worktree_head_symref","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2016-04-08T06:42:58Z","receivedAt":"2016-04-08T06:42:58Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 8, 2016 at 2:37 AM, Kazuki Yamaguchi <k@rhe.jp> wrote:\n> On Thu, Apr 07, 2016 at 05:20:10PM -0400, Eric Sunshine wrote:\n>> On Sun, Mar 27, 2016 at 10:37 AM, Kazuki Yamaguchi <k@rhe.jp> wrote:\n>> > +int set_worktree_head_symref(const char *gitdir, const char *target)\n>> > +{\n>> > +       static struct lock_file head_lock;\n>> > +       struct ref_lock *lock;\n>> > +       struct strbuf err = STRBUF_INIT;\n>> > +       struct strbuf head_path = STRBUF_INIT;\n>> > +       const char *head_rel;\n>> > +       int ret;\n>> > +\n>> > +       strbuf_addf(&head_path, \"%s/HEAD\", absolute_path(gitdir));\n>> > +       if (hold_lock_file_for_update(&head_lock, head_path.buf,\n>> > +                                     LOCK_NO_DEREF) < 0) {\n>> > +               error(\"%s\", err.buf);\n>>\n>> 'err' has not been populated at this point, so I suspect that this\n>> error message is likely to be rather uninformative.\n>\n> Yes, unable_to_lock_message() is missing. Thank you for pointing it out.\n\nYou're welcome. As this patch is already in Junio's \"next\" branch, if\nyou post a fix, it should be incremental atop \"ky/branch-m-worktree\",\nrather than as a re-roll of this series.\n"}]}