{"thread":{"id":"54058","subject":"[PATCH 0/4] Handle FETCH_HEAD generically","startedAt":"2020-08-17T15:40:21Z","lastAt":"2020-08-19T21:09:52Z","messageCount":12,"participants":["Han-Wen Nienhuys via GitGitGadget","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"403825","messageId":"pull.705.git.1597678796.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":null,"subject":"[PATCH 0/4] Handle FETCH_HEAD generically","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-17T15:39:52Z","receivedAt":"2020-08-17T15:40:21Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"This moves the FETCH_HEAD handling into refs.c as discussed in \nhttps://public-inbox.org/git/xmqq5z9pav01.fsf@gitster.c.googlers.com/\n\nHan-Wen Nienhuys (4):\n  Split off reading loose ref data in separate function\n  refs: fix comment about submodule ref_stores\n  refs: move gitdir into base ref_store\n  refs: read FETCH_HEAD generically\n\n refs.c                | 27 +++++++++++++++++++++++-\n refs/files-backend.c  | 49 ++++++++++++++++++++++---------------------\n refs/packed-backend.c |  1 +\n refs/refs-internal.h  | 11 +++++++++-\n 4 files changed, 62 insertions(+), 26 deletions(-)\n\n\nbase-commit: dc04167d378fb29d30e1647ff6ff51dd182bc9a3\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-705%2Fhanwen%2Ffetch-head-generically-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-705/hanwen/fetch-head-generically-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/705\n-- \ngitgitgadget\n"},{"id":"403826","messageId":"10b333695e913983de0885400833f406e8383de2.1597678796.git.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":"pull.705.git.1597678796.gitgitgadget@gmail.com","subject":"[PATCH 1/4] Split off reading loose ref data in separate function","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-17T15:39:53Z","receivedAt":"2020-08-17T15:40:23Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"From: Han-Wen Nienhuys <hanwen@google.com>\n\nThis prepares for handling FETCH_HEAD (which is not a regular ref)\nseparately from the ref backend.\n\nSigned-off-by: Han-Wen Nienhuys <hanwen@google.com>\n---\n refs/files-backend.c | 34 +++++++++++++++++++---------------\n refs/refs-internal.h |  6 ++++++\n 2 files changed, 25 insertions(+), 15 deletions(-)\n\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 985631f33e..3a3573986f 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -360,7 +360,6 @@ static int files_read_raw_ref(struct ref_store *ref_store,\n \tstruct strbuf sb_path = STRBUF_INIT;\n \tconst char *path;\n \tconst char *buf;\n-\tconst char *p;\n \tstruct stat st;\n \tint fd;\n \tint ret = -1;\n@@ -465,6 +464,21 @@ static int files_read_raw_ref(struct ref_store *ref_store,\n \tclose(fd);\n \tstrbuf_rtrim(&sb_contents);\n \tbuf = sb_contents.buf;\n+\n+\tret = parse_loose_ref_contents(buf, oid, referent, type);\n+\n+out:\n+\tsave_errno = errno;\n+\tstrbuf_release(&sb_path);\n+\tstrbuf_release(&sb_contents);\n+\terrno = save_errno;\n+\treturn ret;\n+}\n+\n+int parse_loose_ref_contents(const char *buf, struct object_id *oid,\n+\t\t\t     struct strbuf *referent, unsigned int *type)\n+{\n+\tconst char *p;\n \tif (skip_prefix(buf, \"ref:\", &buf)) {\n \t\twhile (isspace(*buf))\n \t\t\tbuf++;\n@@ -472,29 +486,19 @@ static int files_read_raw_ref(struct ref_store *ref_store,\n \t\tstrbuf_reset(referent);\n \t\tstrbuf_addstr(referent, buf);\n \t\t*type |= REF_ISSYMREF;\n-\t\tret = 0;\n-\t\tgoto out;\n+\t\treturn 0;\n \t}\n \n \t/*\n-\t * Please note that FETCH_HEAD has additional\n-\t * data after the sha.\n+\t * FETCH_HEAD has additional data after the sha.\n \t */\n \tif (parse_oid_hex(buf, oid, &p) ||\n \t    (*p != '\\0' && !isspace(*p))) {\n \t\t*type |= REF_ISBROKEN;\n \t\terrno = EINVAL;\n-\t\tgoto out;\n+\t\treturn -1;\n \t}\n-\n-\tret = 0;\n-\n-out:\n-\tsave_errno = errno;\n-\tstrbuf_release(&sb_path);\n-\tstrbuf_release(&sb_contents);\n-\terrno = save_errno;\n-\treturn ret;\n+\treturn 0;\n }\n \n static void unlock_ref(struct ref_lock *lock)\ndiff --git a/refs/refs-internal.h b/refs/refs-internal.h\nindex 357359a0be..24d79fb5c1 100644\n--- a/refs/refs-internal.h\n+++ b/refs/refs-internal.h\n@@ -674,6 +674,12 @@ struct ref_store {\n \tconst struct ref_storage_be *be;\n };\n \n+/*\n+ * Parse contents of a loose ref file.\n+ */\n+int parse_loose_ref_contents(const char *buf, struct object_id *oid,\n+\t\t\t     struct strbuf *referent, unsigned int *type);\n+\n /*\n  * Fill in the generic part of refs and add it to our collection of\n  * reference stores.\n-- \ngitgitgadget\n\n"},{"id":"403870","messageId":"52b397ec9efa68a6509f8750534489e62f7c2fb4.1597678796.git.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":"pull.705.git.1597678796.gitgitgadget@gmail.com","subject":"[PATCH 2/4] refs: fix comment about submodule ref_stores","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-17T15:39:54Z","receivedAt":"2020-08-17T19:15:26Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"From: Han-Wen Nienhuys <hanwen@google.com>\n\nSigned-off-by: Han-Wen Nienhuys <hanwen@google.com>\n---\n refs/refs-internal.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/refs/refs-internal.h b/refs/refs-internal.h\nindex 24d79fb5c1..9188ddbec2 100644\n--- a/refs/refs-internal.h\n+++ b/refs/refs-internal.h\n@@ -667,7 +667,7 @@ extern struct ref_storage_be refs_be_packed;\n /*\n  * A representation of the reference store for the main repository or\n  * a submodule. The ref_store instances for submodules are kept in a\n- * linked list.\n+ * hash map; see get_submodule_ref_store() for more info.\n  */\n struct ref_store {\n \t/* The backend describing this ref_store's storage scheme: */\n-- \ngitgitgadget\n\n"},{"id":"403871","messageId":"c624e17dc62dec2748e74d9c84dce56f959cc2d1.1597678796.git.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":"pull.705.git.1597678796.gitgitgadget@gmail.com","subject":"[PATCH 3/4] refs: move gitdir into base ref_store","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-17T15:39:55Z","receivedAt":"2020-08-17T19:15:44Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"From: Han-Wen Nienhuys <hanwen@google.com>\n\nSigned-off-by: Han-Wen Nienhuys <hanwen@google.com>\n---\n refs/files-backend.c  | 15 ++++++---------\n refs/packed-backend.c |  1 +\n refs/refs-internal.h  |  3 +++\n 3 files changed, 10 insertions(+), 9 deletions(-)\n\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 3a3573986f..dd712e47f4 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -67,7 +67,6 @@ struct files_ref_store {\n \tstruct ref_store base;\n \tunsigned int store_flags;\n \n-\tchar *gitdir;\n \tchar *gitcommondir;\n \n \tstruct ref_cache *loose;\n@@ -94,18 +93,17 @@ static struct ref_store *files_ref_store_create(const char *gitdir,\n \tstruct ref_store *ref_store = (struct ref_store *)refs;\n \tstruct strbuf sb = STRBUF_INIT;\n \n+\tref_store->gitdir = xstrdup(gitdir);\n \tbase_ref_store_init(ref_store, &refs_be_files);\n \trefs->store_flags = flags;\n \n-\trefs->gitdir = xstrdup(gitdir);\n \tget_common_dir_noenv(&sb, gitdir);\n \trefs->gitcommondir = strbuf_detach(&sb, NULL);\n \tstrbuf_addf(&sb, \"%s/packed-refs\", refs->gitcommondir);\n \trefs->packed_ref_store = packed_ref_store_create(sb.buf, flags);\n \tstrbuf_release(&sb);\n \n-\tchdir_notify_reparent(\"files-backend $GIT_DIR\",\n-\t\t\t      &refs->gitdir);\n+\tchdir_notify_reparent(\"files-backend $GIT_DIR\", &refs->base.gitdir);\n \tchdir_notify_reparent(\"files-backend $GIT_COMMONDIR\",\n \t\t\t      &refs->gitcommondir);\n \n@@ -176,7 +174,7 @@ static void files_reflog_path(struct files_ref_store *refs,\n \tswitch (ref_type(refname)) {\n \tcase REF_TYPE_PER_WORKTREE:\n \tcase REF_TYPE_PSEUDOREF:\n-\t\tstrbuf_addf(sb, \"%s/logs/%s\", refs->gitdir, refname);\n+\t\tstrbuf_addf(sb, \"%s/logs/%s\", refs->base.gitdir, refname);\n \t\tbreak;\n \tcase REF_TYPE_OTHER_PSEUDOREF:\n \tcase REF_TYPE_MAIN_PSEUDOREF:\n@@ -198,7 +196,7 @@ static void files_ref_path(struct files_ref_store *refs,\n \tswitch (ref_type(refname)) {\n \tcase REF_TYPE_PER_WORKTREE:\n \tcase REF_TYPE_PSEUDOREF:\n-\t\tstrbuf_addf(sb, \"%s/%s\", refs->gitdir, refname);\n+\t\tstrbuf_addf(sb, \"%s/%s\", refs->base.gitdir, refname);\n \t\tbreak;\n \tcase REF_TYPE_MAIN_PSEUDOREF:\n \t\tif (!skip_prefix(refname, \"main-worktree/\", &refname))\n@@ -2203,12 +2201,11 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st\n \t\tfiles_downcast(ref_store, REF_STORE_READ,\n \t\t\t       \"reflog_iterator_begin\");\n \n-\tif (!strcmp(refs->gitdir, refs->gitcommondir)) {\n+\tif (!strcmp(refs->base.gitdir, refs->gitcommondir)) {\n \t\treturn reflog_iterator_begin(ref_store, refs->gitcommondir);\n \t} else {\n \t\treturn merge_ref_iterator_begin(\n-\t\t\t0,\n-\t\t\treflog_iterator_begin(ref_store, refs->gitdir),\n+\t\t\t0, reflog_iterator_begin(ref_store, refs->base.gitdir),\n \t\t\treflog_iterator_begin(ref_store, refs->gitcommondir),\n \t\t\treflog_iterator_select, refs);\n \t}\ndiff --git a/refs/packed-backend.c b/refs/packed-backend.c\nindex 4458a0f69c..b912f2505f 100644\n--- a/refs/packed-backend.c\n+++ b/refs/packed-backend.c\n@@ -200,6 +200,7 @@ struct ref_store *packed_ref_store_create(const char *path,\n \tstruct ref_store *ref_store = (struct ref_store *)refs;\n \n \tbase_ref_store_init(ref_store, &refs_be_packed);\n+\tref_store->gitdir = xstrdup(path);\n \trefs->store_flags = store_flags;\n \n \trefs->path = xstrdup(path);\ndiff --git a/refs/refs-internal.h b/refs/refs-internal.h\nindex 9188ddbec2..527b0a6e2e 100644\n--- a/refs/refs-internal.h\n+++ b/refs/refs-internal.h\n@@ -672,6 +672,9 @@ extern struct ref_storage_be refs_be_packed;\n struct ref_store {\n \t/* The backend describing this ref_store's storage scheme: */\n \tconst struct ref_storage_be *be;\n+\n+\t/* The gitdir that this ref_store applies to: */\n+\tchar *gitdir;\n };\n \n /*\n-- \ngitgitgadget\n\n"},{"id":"403872","messageId":"d4e9c5f4996640e71ea47cb65867c4553bdf8f42.1597678796.git.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":"pull.705.git.1597678796.gitgitgadget@gmail.com","subject":"[PATCH 4/4] refs: read FETCH_HEAD generically","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-17T15:39:56Z","receivedAt":"2020-08-17T19:15:50Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"From: Han-Wen Nienhuys <hanwen@google.com>\n\nThe FETCH_HEAD ref must be stored in a file, regardless of the type of\nref backend. This is because it can hold more than just a single ref.\n\nTo accomodate FETCH_HEAD for alternate ref backends, read FETCH_HEAD\nfrom a file generically in refs_read_raw_ref()\n\nSigned-off-by: Han-Wen Nienhuys <hanwen@google.com>\n---\n refs.c | 27 ++++++++++++++++++++++++++-\n 1 file changed, 26 insertions(+), 1 deletion(-)\n\ndiff --git a/refs.c b/refs.c\nindex 2dd851fe81..ab7d62e237 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1634,11 +1634,36 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)\n \treturn refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);\n }\n \n+static int refs_read_fetch_head(struct ref_store *ref_store,\n+\t\t\t\tstruct object_id *oid, struct strbuf *referent,\n+\t\t\t\tunsigned int *type)\n+{\n+\tstruct strbuf full_path = STRBUF_INIT;\n+\tstruct strbuf content = STRBUF_INIT;\n+\tint result = -1;\n+\tstrbuf_addf(&full_path, \"%s/%s\", ref_store->gitdir, \"FETCH_HEAD\");\n+\n+\tif (strbuf_read_file(&content, full_path.buf, 0) < 0)\n+\t\tgoto done;\n+\n+\tresult = parse_loose_ref_contents(content.buf, oid, referent, type);\n+\n+done:\n+\tstrbuf_release(&full_path);\n+\tstrbuf_release(&content);\n+\treturn result;\n+}\n+\n int refs_read_raw_ref(struct ref_store *ref_store,\n \t\t      const char *refname, struct object_id *oid,\n \t\t      struct strbuf *referent, unsigned int *type)\n {\n-\treturn ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);\n+\tif (!strcmp(refname, \"FETCH_HEAD\")) {\n+\t\treturn refs_read_fetch_head(ref_store, oid, referent, type);\n+\t}\n+\n+\treturn ref_store->be->read_raw_ref(ref_store, refname, oid, referent,\n+\t\t\t\t\t   type);\n }\n \n /* This function needs to return a meaningful errno on failure */\n-- \ngitgitgadget\n"},{"id":"403876","messageId":"xmqqd03p12ol.fsf@gitster.c.googlers.com","threadId":"54058","inReplyTo":"pull.705.git.1597678796.gitgitgadget@gmail.com","subject":"Re: [PATCH 0/4] Handle FETCH_HEAD generically","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-08-17T19:40:26Z","receivedAt":"2020-08-17T19:40:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Han-Wen Nienhuys via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> This moves the FETCH_HEAD handling into refs.c as discussed in \n> https://public-inbox.org/git/xmqq5z9pav01.fsf@gitster.c.googlers.com/\n>\n> Han-Wen Nienhuys (4):\n>   Split off reading loose ref data in separate function\n>   refs: fix comment about submodule ref_stores\n>   refs: move gitdir into base ref_store\n>   refs: read FETCH_HEAD generically\n>\n>  refs.c                | 27 +++++++++++++++++++++++-\n>  refs/files-backend.c  | 49 ++++++++++++++++++++++---------------------\n>  refs/packed-backend.c |  1 +\n>  refs/refs-internal.h  | 11 +++++++++-\n>  4 files changed, 62 insertions(+), 26 deletions(-)\n\nNice.  Quite cleanly done.\n\nWill queue; thanks.\n\n"},{"id":"404010","messageId":"pull.705.v2.git.1597847278.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":"pull.705.git.1597678796.gitgitgadget@gmail.com","subject":"[PATCH v2 0/4] Handle FETCH_HEAD and MERGE_HEAD generically","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-19T14:27:54Z","receivedAt":"2020-08-19T14:28:08Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"This moves the FETCH_HEAD handling into refs.c as discussed in \nhttps://public-inbox.org/git/xmqq5z9pav01.fsf@gitster.c.googlers.com/\n\nHan-Wen Nienhuys (4):\n  refs: split off reading loose ref data in separate function\n  refs: fix comment about submodule ref_stores\n  refs: move gitdir into base ref_store\n  refs: read FETCH_HEAD and MERGE_HEAD generically\n\n refs.c                | 28 ++++++++++++++++++++++++-\n refs/files-backend.c  | 49 ++++++++++++++++++++++---------------------\n refs/packed-backend.c |  1 +\n refs/refs-internal.h  | 11 +++++++++-\n 4 files changed, 63 insertions(+), 26 deletions(-)\n\n\nbase-commit: 2befe97201e1f3175cce557866c5822793624b5a\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-705%2Fhanwen%2Ffetch-head-generically-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-705/hanwen/fetch-head-generically-v2\nPull-Request: https://github.com/gitgitgadget/git/pull/705\n\nRange-diff vs v1:\n\n 1:  10b333695e ! 1:  557727064d Split off reading loose ref data in separate function\n     @@ Metadata\n      Author: Han-Wen Nienhuys <hanwen@google.com>\n      \n       ## Commit message ##\n     -    Split off reading loose ref data in separate function\n     +    refs: split off reading loose ref data in separate function\n      \n          This prepares for handling FETCH_HEAD (which is not a regular ref)\n          separately from the ref backend.\n 2:  52b397ec9e = 2:  6da0e62e73 refs: fix comment about submodule ref_stores\n 3:  c624e17dc6 = 3:  6263b4b3f2 refs: move gitdir into base ref_store\n 4:  d4e9c5f499 ! 4:  a3e903e4c0 refs: read FETCH_HEAD generically\n     @@ Metadata\n      Author: Han-Wen Nienhuys <hanwen@google.com>\n      \n       ## Commit message ##\n     -    refs: read FETCH_HEAD generically\n     +    refs: read FETCH_HEAD and MERGE_HEAD generically\n      \n     -    The FETCH_HEAD ref must be stored in a file, regardless of the type of\n     -    ref backend. This is because it can hold more than just a single ref.\n     +    The FETCH_HEAD and MERGE_HEAD refs must be stored in a file, regardless of the\n     +    type of ref backend. This is because they can hold more than just a single ref.\n      \n     -    To accomodate FETCH_HEAD for alternate ref backends, read FETCH_HEAD\n     -    from a file generically in refs_read_raw_ref()\n     +    To accomodate them for alternate ref backends, read them from a file generically\n     +    in refs_read_raw_ref()\n      \n          Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>\n      \n     @@ refs.c: int for_each_rawref(each_ref_fn fn, void *cb_data)\n       \treturn refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);\n       }\n       \n     -+static int refs_read_fetch_head(struct ref_store *ref_store,\n     -+\t\t\t\tstruct object_id *oid, struct strbuf *referent,\n     -+\t\t\t\tunsigned int *type)\n     ++static int refs_read_special_head(struct ref_store *ref_store,\n     ++\t\t\t\t  const char *refname, struct object_id *oid,\n     ++\t\t\t\t  struct strbuf *referent, unsigned int *type)\n      +{\n      +\tstruct strbuf full_path = STRBUF_INIT;\n      +\tstruct strbuf content = STRBUF_INIT;\n      +\tint result = -1;\n     -+\tstrbuf_addf(&full_path, \"%s/%s\", ref_store->gitdir, \"FETCH_HEAD\");\n     ++\tstrbuf_addf(&full_path, \"%s/%s\", ref_store->gitdir, refname);\n      +\n      +\tif (strbuf_read_file(&content, full_path.buf, 0) < 0)\n      +\t\tgoto done;\n     @@ refs.c: int for_each_rawref(each_ref_fn fn, void *cb_data)\n       \t\t      struct strbuf *referent, unsigned int *type)\n       {\n      -\treturn ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);\n     -+\tif (!strcmp(refname, \"FETCH_HEAD\")) {\n     -+\t\treturn refs_read_fetch_head(ref_store, oid, referent, type);\n     ++\tif (!strcmp(refname, \"FETCH_HEAD\") || !strcmp(refname, \"MERGE_HEAD\")) {\n     ++\t\treturn refs_read_special_head(ref_store, refname, oid, referent,\n     ++\t\t\t\t\t      type);\n      +\t}\n      +\n      +\treturn ref_store->be->read_raw_ref(ref_store, refname, oid, referent,\n\n-- \ngitgitgadget\n"},{"id":"404011","messageId":"6da0e62e73a34e70535e3ef41b2259e18ff91c34.1597847278.git.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":"pull.705.v2.git.1597847278.gitgitgadget@gmail.com","subject":"[PATCH v2 2/4] refs: fix comment about submodule ref_stores","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-19T14:27:56Z","receivedAt":"2020-08-19T14:28:15Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"From: Han-Wen Nienhuys <hanwen@google.com>\n\nSigned-off-by: Han-Wen Nienhuys <hanwen@google.com>\n---\n refs/refs-internal.h | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/refs/refs-internal.h b/refs/refs-internal.h\nindex 24d79fb5c1..9188ddbec2 100644\n--- a/refs/refs-internal.h\n+++ b/refs/refs-internal.h\n@@ -667,7 +667,7 @@ extern struct ref_storage_be refs_be_packed;\n /*\n  * A representation of the reference store for the main repository or\n  * a submodule. The ref_store instances for submodules are kept in a\n- * linked list.\n+ * hash map; see get_submodule_ref_store() for more info.\n  */\n struct ref_store {\n \t/* The backend describing this ref_store's storage scheme: */\n-- \ngitgitgadget\n\n"},{"id":"404012","messageId":"6263b4b3f2dd2f0e77235f5f09daed7c0bd69099.1597847278.git.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":"pull.705.v2.git.1597847278.gitgitgadget@gmail.com","subject":"[PATCH v2 3/4] refs: move gitdir into base ref_store","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-19T14:27:57Z","receivedAt":"2020-08-19T14:28:18Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"From: Han-Wen Nienhuys <hanwen@google.com>\n\nSigned-off-by: Han-Wen Nienhuys <hanwen@google.com>\n---\n refs/files-backend.c  | 15 ++++++---------\n refs/packed-backend.c |  1 +\n refs/refs-internal.h  |  3 +++\n 3 files changed, 10 insertions(+), 9 deletions(-)\n\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 3a3573986f..dd712e47f4 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -67,7 +67,6 @@ struct files_ref_store {\n \tstruct ref_store base;\n \tunsigned int store_flags;\n \n-\tchar *gitdir;\n \tchar *gitcommondir;\n \n \tstruct ref_cache *loose;\n@@ -94,18 +93,17 @@ static struct ref_store *files_ref_store_create(const char *gitdir,\n \tstruct ref_store *ref_store = (struct ref_store *)refs;\n \tstruct strbuf sb = STRBUF_INIT;\n \n+\tref_store->gitdir = xstrdup(gitdir);\n \tbase_ref_store_init(ref_store, &refs_be_files);\n \trefs->store_flags = flags;\n \n-\trefs->gitdir = xstrdup(gitdir);\n \tget_common_dir_noenv(&sb, gitdir);\n \trefs->gitcommondir = strbuf_detach(&sb, NULL);\n \tstrbuf_addf(&sb, \"%s/packed-refs\", refs->gitcommondir);\n \trefs->packed_ref_store = packed_ref_store_create(sb.buf, flags);\n \tstrbuf_release(&sb);\n \n-\tchdir_notify_reparent(\"files-backend $GIT_DIR\",\n-\t\t\t      &refs->gitdir);\n+\tchdir_notify_reparent(\"files-backend $GIT_DIR\", &refs->base.gitdir);\n \tchdir_notify_reparent(\"files-backend $GIT_COMMONDIR\",\n \t\t\t      &refs->gitcommondir);\n \n@@ -176,7 +174,7 @@ static void files_reflog_path(struct files_ref_store *refs,\n \tswitch (ref_type(refname)) {\n \tcase REF_TYPE_PER_WORKTREE:\n \tcase REF_TYPE_PSEUDOREF:\n-\t\tstrbuf_addf(sb, \"%s/logs/%s\", refs->gitdir, refname);\n+\t\tstrbuf_addf(sb, \"%s/logs/%s\", refs->base.gitdir, refname);\n \t\tbreak;\n \tcase REF_TYPE_OTHER_PSEUDOREF:\n \tcase REF_TYPE_MAIN_PSEUDOREF:\n@@ -198,7 +196,7 @@ static void files_ref_path(struct files_ref_store *refs,\n \tswitch (ref_type(refname)) {\n \tcase REF_TYPE_PER_WORKTREE:\n \tcase REF_TYPE_PSEUDOREF:\n-\t\tstrbuf_addf(sb, \"%s/%s\", refs->gitdir, refname);\n+\t\tstrbuf_addf(sb, \"%s/%s\", refs->base.gitdir, refname);\n \t\tbreak;\n \tcase REF_TYPE_MAIN_PSEUDOREF:\n \t\tif (!skip_prefix(refname, \"main-worktree/\", &refname))\n@@ -2203,12 +2201,11 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st\n \t\tfiles_downcast(ref_store, REF_STORE_READ,\n \t\t\t       \"reflog_iterator_begin\");\n \n-\tif (!strcmp(refs->gitdir, refs->gitcommondir)) {\n+\tif (!strcmp(refs->base.gitdir, refs->gitcommondir)) {\n \t\treturn reflog_iterator_begin(ref_store, refs->gitcommondir);\n \t} else {\n \t\treturn merge_ref_iterator_begin(\n-\t\t\t0,\n-\t\t\treflog_iterator_begin(ref_store, refs->gitdir),\n+\t\t\t0, reflog_iterator_begin(ref_store, refs->base.gitdir),\n \t\t\treflog_iterator_begin(ref_store, refs->gitcommondir),\n \t\t\treflog_iterator_select, refs);\n \t}\ndiff --git a/refs/packed-backend.c b/refs/packed-backend.c\nindex 4458a0f69c..b912f2505f 100644\n--- a/refs/packed-backend.c\n+++ b/refs/packed-backend.c\n@@ -200,6 +200,7 @@ struct ref_store *packed_ref_store_create(const char *path,\n \tstruct ref_store *ref_store = (struct ref_store *)refs;\n \n \tbase_ref_store_init(ref_store, &refs_be_packed);\n+\tref_store->gitdir = xstrdup(path);\n \trefs->store_flags = store_flags;\n \n \trefs->path = xstrdup(path);\ndiff --git a/refs/refs-internal.h b/refs/refs-internal.h\nindex 9188ddbec2..527b0a6e2e 100644\n--- a/refs/refs-internal.h\n+++ b/refs/refs-internal.h\n@@ -672,6 +672,9 @@ extern struct ref_storage_be refs_be_packed;\n struct ref_store {\n \t/* The backend describing this ref_store's storage scheme: */\n \tconst struct ref_storage_be *be;\n+\n+\t/* The gitdir that this ref_store applies to: */\n+\tchar *gitdir;\n };\n \n /*\n-- \ngitgitgadget\n\n"},{"id":"404013","messageId":"a3e903e4c0b29a3c37a43b0e76060aa3bb250cfa.1597847278.git.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":"pull.705.v2.git.1597847278.gitgitgadget@gmail.com","subject":"[PATCH v2 4/4] refs: read FETCH_HEAD and MERGE_HEAD generically","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-19T14:27:58Z","receivedAt":"2020-08-19T14:28:19Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"From: Han-Wen Nienhuys <hanwen@google.com>\n\nThe FETCH_HEAD and MERGE_HEAD refs must be stored in a file, regardless of the\ntype of ref backend. This is because they can hold more than just a single ref.\n\nTo accomodate them for alternate ref backends, read them from a file generically\nin refs_read_raw_ref()\n\nSigned-off-by: Han-Wen Nienhuys <hanwen@google.com>\n---\n refs.c | 28 +++++++++++++++++++++++++++-\n 1 file changed, 27 insertions(+), 1 deletion(-)\n\ndiff --git a/refs.c b/refs.c\nindex cf91711968..3ee3afaf41 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1527,11 +1527,37 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)\n \treturn refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);\n }\n \n+static int refs_read_special_head(struct ref_store *ref_store,\n+\t\t\t\t  const char *refname, struct object_id *oid,\n+\t\t\t\t  struct strbuf *referent, unsigned int *type)\n+{\n+\tstruct strbuf full_path = STRBUF_INIT;\n+\tstruct strbuf content = STRBUF_INIT;\n+\tint result = -1;\n+\tstrbuf_addf(&full_path, \"%s/%s\", ref_store->gitdir, refname);\n+\n+\tif (strbuf_read_file(&content, full_path.buf, 0) < 0)\n+\t\tgoto done;\n+\n+\tresult = parse_loose_ref_contents(content.buf, oid, referent, type);\n+\n+done:\n+\tstrbuf_release(&full_path);\n+\tstrbuf_release(&content);\n+\treturn result;\n+}\n+\n int refs_read_raw_ref(struct ref_store *ref_store,\n \t\t      const char *refname, struct object_id *oid,\n \t\t      struct strbuf *referent, unsigned int *type)\n {\n-\treturn ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);\n+\tif (!strcmp(refname, \"FETCH_HEAD\") || !strcmp(refname, \"MERGE_HEAD\")) {\n+\t\treturn refs_read_special_head(ref_store, refname, oid, referent,\n+\t\t\t\t\t      type);\n+\t}\n+\n+\treturn ref_store->be->read_raw_ref(ref_store, refname, oid, referent,\n+\t\t\t\t\t   type);\n }\n \n /* This function needs to return a meaningful errno on failure */\n-- \ngitgitgadget\n"},{"id":"404014","messageId":"557727064d5e060e164984887652aa956b9d111c.1597847278.git.gitgitgadget@gmail.com","threadId":"54058","inReplyTo":"pull.705.v2.git.1597847278.gitgitgadget@gmail.com","subject":"[PATCH v2 1/4] refs: split off reading loose ref data in separate function","fromName":"Han-Wen Nienhuys via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-08-19T14:27:55Z","receivedAt":"2020-08-19T14:28:21Z","isPatch":true,"sender":{"key":"hanwen@google.com","avatar":"https://avatars.githubusercontent.com/u/31547?v=4"},"body":"From: Han-Wen Nienhuys <hanwen@google.com>\n\nThis prepares for handling FETCH_HEAD (which is not a regular ref)\nseparately from the ref backend.\n\nSigned-off-by: Han-Wen Nienhuys <hanwen@google.com>\n---\n refs/files-backend.c | 34 +++++++++++++++++++---------------\n refs/refs-internal.h |  6 ++++++\n 2 files changed, 25 insertions(+), 15 deletions(-)\n\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 985631f33e..3a3573986f 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -360,7 +360,6 @@ static int files_read_raw_ref(struct ref_store *ref_store,\n \tstruct strbuf sb_path = STRBUF_INIT;\n \tconst char *path;\n \tconst char *buf;\n-\tconst char *p;\n \tstruct stat st;\n \tint fd;\n \tint ret = -1;\n@@ -465,6 +464,21 @@ static int files_read_raw_ref(struct ref_store *ref_store,\n \tclose(fd);\n \tstrbuf_rtrim(&sb_contents);\n \tbuf = sb_contents.buf;\n+\n+\tret = parse_loose_ref_contents(buf, oid, referent, type);\n+\n+out:\n+\tsave_errno = errno;\n+\tstrbuf_release(&sb_path);\n+\tstrbuf_release(&sb_contents);\n+\terrno = save_errno;\n+\treturn ret;\n+}\n+\n+int parse_loose_ref_contents(const char *buf, struct object_id *oid,\n+\t\t\t     struct strbuf *referent, unsigned int *type)\n+{\n+\tconst char *p;\n \tif (skip_prefix(buf, \"ref:\", &buf)) {\n \t\twhile (isspace(*buf))\n \t\t\tbuf++;\n@@ -472,29 +486,19 @@ static int files_read_raw_ref(struct ref_store *ref_store,\n \t\tstrbuf_reset(referent);\n \t\tstrbuf_addstr(referent, buf);\n \t\t*type |= REF_ISSYMREF;\n-\t\tret = 0;\n-\t\tgoto out;\n+\t\treturn 0;\n \t}\n \n \t/*\n-\t * Please note that FETCH_HEAD has additional\n-\t * data after the sha.\n+\t * FETCH_HEAD has additional data after the sha.\n \t */\n \tif (parse_oid_hex(buf, oid, &p) ||\n \t    (*p != '\\0' && !isspace(*p))) {\n \t\t*type |= REF_ISBROKEN;\n \t\terrno = EINVAL;\n-\t\tgoto out;\n+\t\treturn -1;\n \t}\n-\n-\tret = 0;\n-\n-out:\n-\tsave_errno = errno;\n-\tstrbuf_release(&sb_path);\n-\tstrbuf_release(&sb_contents);\n-\terrno = save_errno;\n-\treturn ret;\n+\treturn 0;\n }\n \n static void unlock_ref(struct ref_lock *lock)\ndiff --git a/refs/refs-internal.h b/refs/refs-internal.h\nindex 357359a0be..24d79fb5c1 100644\n--- a/refs/refs-internal.h\n+++ b/refs/refs-internal.h\n@@ -674,6 +674,12 @@ struct ref_store {\n \tconst struct ref_storage_be *be;\n };\n \n+/*\n+ * Parse contents of a loose ref file.\n+ */\n+int parse_loose_ref_contents(const char *buf, struct object_id *oid,\n+\t\t\t     struct strbuf *referent, unsigned int *type);\n+\n /*\n  * Fill in the generic part of refs and add it to our collection of\n  * reference stores.\n-- \ngitgitgadget\n\n"},{"id":"404067","messageId":"xmqq1rk2tka1.fsf@gitster.c.googlers.com","threadId":"54058","inReplyTo":"pull.705.v2.git.1597847278.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 0/4] Handle FETCH_HEAD and MERGE_HEAD generically","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-08-19T21:09:42Z","receivedAt":"2020-08-19T21:09:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Han-Wen Nienhuys via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> This moves the FETCH_HEAD handling into refs.c as discussed in \n> https://public-inbox.org/git/xmqq5z9pav01.fsf@gitster.c.googlers.com/\n\nThanks.  The way the support for MERGE_HEAD is added to the series\nlooks very sensible, too.\n\nWill replace.\n\n>      -+static int refs_read_fetch_head(struct ref_store *ref_store,\n>      -+\t\t\t\tstruct object_id *oid, struct strbuf *referent,\n>      -+\t\t\t\tunsigned int *type)\n>      ++static int refs_read_special_head(struct ref_store *ref_store,\n>      ++\t\t\t\t  const char *refname, struct object_id *oid,\n>      ++\t\t\t\t  struct strbuf *referent, unsigned int *type)\n>       +{\n>       +\tstruct strbuf full_path = STRBUF_INIT;\n>       +\tstruct strbuf content = STRBUF_INIT;\n>       +\tint result = -1;\n>      -+\tstrbuf_addf(&full_path, \"%s/%s\", ref_store->gitdir, \"FETCH_HEAD\");\n>      ++\tstrbuf_addf(&full_path, \"%s/%s\", ref_store->gitdir, refname);\n>       +\n>       +\tif (strbuf_read_file(&content, full_path.buf, 0) < 0)\n>       +\t\tgoto done;\n>      @@ refs.c: int for_each_rawref(each_ref_fn fn, void *cb_data)\n>        \t\t      struct strbuf *referent, unsigned int *type)\n>        {\n>       -\treturn ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);\n>      -+\tif (!strcmp(refname, \"FETCH_HEAD\")) {\n>      -+\t\treturn refs_read_fetch_head(ref_store, oid, referent, type);\n>      ++\tif (!strcmp(refname, \"FETCH_HEAD\") || !strcmp(refname, \"MERGE_HEAD\")) {\n>      ++\t\treturn refs_read_special_head(ref_store, refname, oid, referent,\n>      ++\t\t\t\t\t      type);\n>       +\t}\n>       +\n>       +\treturn ref_store->be->read_raw_ref(ref_store, refname, oid, referent,\n"}]}