{"thread":{"id":"31352","subject":"[PATCH v2 01/17] t5500: add tests of error output for missing refs","startedAt":"2012-08-25T06:44:10Z","lastAt":"2012-08-26T17:20:21Z","messageCount":19,"participants":["mhagger@alum.mit.edu","Junio C Hamano"],"isPatch":true,"patchVersion":2,"patchTotal":17},"messages":[{"id":"197823","messageId":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":null,"subject":"[PATCH v2 00/17] Clean up how fetch_pack() handles the heads list","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:10Z","receivedAt":"2012-08-25T06:44:10Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nRe-roll, incorporating Jeff's suggestions.  Some commit messages have\nalso been improved, but the only interdiff is that match_pos is\nrenamed to head_pos in filter_refs().\n\nThis patch series applies to the merge between master and\njc/maint-push-refs-all, though the dependency on the latter is only\ntextual.\n\nMichael Haggerty (17):\n  t5500: add tests of error output for missing refs\n  Rename static function fetch_pack() to http_fetch_pack()\n  Fix formatting.\n  Name local variables more consistently\n  Do not check the same head_pos twice\n  Let fetch_pack() inform caller about number of unique heads\n  Pass nr_heads to do_pack_ref() by reference\n  Pass nr_heads to everything_local() by reference\n  Pass nr_heads to filter_refs() by reference\n  Remove ineffective optimization\n  filter_refs(): do not leave gaps in return_refs\n  filter_refs(): compress unmatched refs in heads array\n  cmd_fetch_pack: return early if finish_connect() returns an error\n  Report missing refs even if no existing refs were received\n  cmd_fetch_pack(): simplify computation of return value\n  fetch_pack(): free matching heads\n  filter_refs(): simplify logic\n\n builtin/fetch-pack.c  | 128 ++++++++++++++++++++------------------------------\n fetch-pack.h          |  19 +++++---\n http-walker.c         |   4 +-\n t/t5500-fetch-pack.sh |  32 ++++++++++++-\n transport.c           |   8 ++--\n 5 files changed, 101 insertions(+), 90 deletions(-)\n\n-- \n1.7.11.3\n"},{"id":"197811","messageId":"1345877067-11841-2-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 01/17] t5500: add tests of error output for missing refs","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:11Z","receivedAt":"2012-08-25T06:44:11Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nIf \"git fetch-pack\" is called with reference names that do not exist\non the remote, then it should emit an error message\n\n    error: no such remote ref refs/heads/xyzzy\n\nThis is currently broken if *only* missing references are passed to\n\"git fetch-pack\".\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n t/t5500-fetch-pack.sh | 30 ++++++++++++++++++++++++++++++\n 1 file changed, 30 insertions(+)\n\ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex e80a2af..3cc3346 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -397,4 +397,34 @@ test_expect_success 'test duplicate refs from stdin' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'set up tests of missing reference' '\n+\tcat >expect-error <<-\\EOF\n+\terror: no such remote ref refs/heads/xyzzy\n+\tEOF\n+'\n+\n+test_expect_failure 'test lonely missing ref' '\n+\t(\n+\tcd client &&\n+\ttest_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy\n+\t) >/dev/null 2>error-m &&\n+\ttest_cmp expect-error error-m\n+'\n+\n+test_expect_success 'test missing ref after existing' '\n+\t(\n+\tcd client &&\n+\ttest_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy\n+\t) >/dev/null 2>error-em &&\n+\ttest_cmp expect-error error-em\n+'\n+\n+test_expect_success 'test missing ref before existing' '\n+\t(\n+\tcd client &&\n+\ttest_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A\n+\t) >/dev/null 2>error-me &&\n+\ttest_cmp expect-error error-me\n+'\n+\n test_done\n-- \n1.7.11.3\n"},{"id":"197812","messageId":"1345877067-11841-3-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 02/17] Rename static function fetch_pack() to http_fetch_pack()","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:12Z","receivedAt":"2012-08-25T06:44:12Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nAvoid confusion with the non-static function of the same name from\nfetch-pack.h.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n http-walker.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/http-walker.c b/http-walker.c\nindex 51a906e..1516c5e 100644\n--- a/http-walker.c\n+++ b/http-walker.c\n@@ -396,7 +396,7 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo)\n \treturn ret;\n }\n \n-static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned char *sha1)\n+static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigned char *sha1)\n {\n \tstruct packed_git *target;\n \tint ret;\n@@ -524,7 +524,7 @@ static int fetch(struct walker *walker, unsigned char *sha1)\n \tif (!fetch_object(walker, altbase, sha1))\n \t\treturn 0;\n \twhile (altbase) {\n-\t\tif (!fetch_pack(walker, altbase, sha1))\n+\t\tif (!http_fetch_pack(walker, altbase, sha1))\n \t\t\treturn 0;\n \t\tfetch_alternates(walker, data->alt->base);\n \t\taltbase = altbase->next;\n-- \n1.7.11.3\n"},{"id":"197824","messageId":"1345877067-11841-4-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 03/17] Fix formatting.","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:13Z","receivedAt":"2012-08-25T06:44:13Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c |  8 ++++----\n fetch-pack.h         | 12 ++++++------\n 2 files changed, 10 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex 7912d2b..cc21047 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -1062,10 +1062,10 @@ static int compare_heads(const void *a, const void *b)\n struct ref *fetch_pack(struct fetch_pack_args *my_args,\n \t\t       int fd[], struct child_process *conn,\n \t\t       const struct ref *ref,\n-\t\tconst char *dest,\n-\t\tint nr_heads,\n-\t\tchar **heads,\n-\t\tchar **pack_lockfile)\n+\t\t       const char *dest,\n+\t\t       int nr_heads,\n+\t\t       char **heads,\n+\t\t       char **pack_lockfile)\n {\n \tstruct stat st;\n \tstruct ref *ref_cpy;\ndiff --git a/fetch-pack.h b/fetch-pack.h\nindex 7c2069c..1dbe90f 100644\n--- a/fetch-pack.h\n+++ b/fetch-pack.h\n@@ -18,11 +18,11 @@ struct fetch_pack_args {\n };\n \n struct ref *fetch_pack(struct fetch_pack_args *args,\n-\t\tint fd[], struct child_process *conn,\n-\t\tconst struct ref *ref,\n-\t\tconst char *dest,\n-\t\tint nr_heads,\n-\t\tchar **heads,\n-\t\tchar **pack_lockfile);\n+\t\t       int fd[], struct child_process *conn,\n+\t\t       const struct ref *ref,\n+\t\t       const char *dest,\n+\t\t       int nr_heads,\n+\t\t       char **heads,\n+\t\t       char **pack_lockfile);\n \n #endif\n-- \n1.7.11.3\n"},{"id":"197813","messageId":"1345877067-11841-5-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 04/17] Name local variables more consistently","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:14Z","receivedAt":"2012-08-25T06:44:14Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nUse the names (nr_heads, heads) consistently across functions, instead\nof sometimes naming the same values (nr_match, match).\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 35 +++++++++++++++++------------------\n 1 file changed, 17 insertions(+), 18 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex cc21047..76288a2 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -521,27 +521,27 @@ static void mark_recent_complete_commits(unsigned long cutoff)\n \t}\n }\n \n-static void filter_refs(struct ref **refs, int nr_match, char **match)\n+static void filter_refs(struct ref **refs, int nr_heads, char **heads)\n {\n \tstruct ref **return_refs;\n \tstruct ref *newlist = NULL;\n \tstruct ref **newtail = &newlist;\n \tstruct ref *ref, *next;\n \tstruct ref *fastarray[32];\n-\tint match_pos;\n+\tint head_pos;\n \n-\tif (nr_match && !args.fetch_all) {\n-\t\tif (ARRAY_SIZE(fastarray) < nr_match)\n-\t\t\treturn_refs = xcalloc(nr_match, sizeof(struct ref *));\n+\tif (nr_heads && !args.fetch_all) {\n+\t\tif (ARRAY_SIZE(fastarray) < nr_heads)\n+\t\t\treturn_refs = xcalloc(nr_heads, sizeof(struct ref *));\n \t\telse {\n \t\t\treturn_refs = fastarray;\n-\t\t\tmemset(return_refs, 0, sizeof(struct ref *) * nr_match);\n+\t\t\tmemset(return_refs, 0, sizeof(struct ref *) * nr_heads);\n \t\t}\n \t}\n \telse\n \t\treturn_refs = NULL;\n \n-\tmatch_pos = 0;\n+\thead_pos = 0;\n \tfor (ref = *refs; ref; ref = next) {\n \t\tnext = ref->next;\n \t\tif (!memcmp(ref->name, \"refs/\", 5) &&\n@@ -556,17 +556,17 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)\n \t\t}\n \t\telse {\n \t\t\tint cmp = -1;\n-\t\t\twhile (match_pos < nr_match) {\n-\t\t\t\tcmp = strcmp(ref->name, match[match_pos]);\n+\t\t\twhile (head_pos < nr_heads) {\n+\t\t\t\tcmp = strcmp(ref->name, heads[head_pos]);\n \t\t\t\tif (cmp < 0) /* definitely do not have it */\n \t\t\t\t\tbreak;\n \t\t\t\telse if (cmp == 0) { /* definitely have it */\n-\t\t\t\t\tmatch[match_pos][0] = '\\0';\n-\t\t\t\t\treturn_refs[match_pos] = ref;\n+\t\t\t\t\theads[head_pos][0] = '\\0';\n+\t\t\t\t\treturn_refs[head_pos] = ref;\n \t\t\t\t\tbreak;\n \t\t\t\t}\n \t\t\t\telse /* might have it; keep looking */\n-\t\t\t\t\tmatch_pos++;\n+\t\t\t\t\thead_pos++;\n \t\t\t}\n \t\t\tif (!cmp)\n \t\t\t\tcontinue; /* we will link it later */\n@@ -576,7 +576,7 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)\n \n \tif (!args.fetch_all) {\n \t\tint i;\n-\t\tfor (i = 0; i < nr_match; i++) {\n+\t\tfor (i = 0; i < nr_heads; i++) {\n \t\t\tref = return_refs[i];\n \t\t\tif (ref) {\n \t\t\t\t*newtail = ref;\n@@ -595,7 +595,7 @@ static void mark_alternate_complete(const struct ref *ref, void *unused)\n \tmark_complete(NULL, ref->old_sha1, 0, NULL);\n }\n \n-static int everything_local(struct ref **refs, int nr_match, char **match)\n+static int everything_local(struct ref **refs, int nr_heads, char **heads)\n {\n \tstruct ref *ref;\n \tint retval;\n@@ -646,7 +646,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match)\n \t\t}\n \t}\n \n-\tfilter_refs(refs, nr_match, match);\n+\tfilter_refs(refs, nr_heads, heads);\n \n \tfor (retval = 1, ref = *refs; ref ; ref = ref->next) {\n \t\tconst unsigned char *remote = ref->old_sha1;\n@@ -777,8 +777,7 @@ static int get_pack(int xd[2], char **pack_lockfile)\n \n static struct ref *do_fetch_pack(int fd[2],\n \t\tconst struct ref *orig_ref,\n-\t\tint nr_match,\n-\t\tchar **match,\n+\t\tint nr_heads, char **heads,\n \t\tchar **pack_lockfile)\n {\n \tstruct ref *ref = copy_ref_list(orig_ref);\n@@ -819,7 +818,7 @@ static struct ref *do_fetch_pack(int fd[2],\n \t\t\tfprintf(stderr, \"Server supports ofs-delta\\n\");\n \t} else\n \t\tprefer_ofs_delta = 0;\n-\tif (everything_local(&ref, nr_match, match)) {\n+\tif (everything_local(&ref, nr_heads, heads)) {\n \t\tpacket_flush(fd[1]);\n \t\tgoto all_done;\n \t}\n-- \n1.7.11.3\n"},{"id":"197825","messageId":"1345877067-11841-6-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 05/17] Do not check the same head_pos twice","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:15Z","receivedAt":"2012-08-25T06:44:15Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nOnce a match has been found at head_pos, the entry is zeroed and no\nfuture attempts will match that entry.  So increment head_pos to avoid\nchecking against the zeroed-out entry during the next iteration.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex 76288a2..bda3c0c 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -561,8 +561,8 @@ static void filter_refs(struct ref **refs, int nr_heads, char **heads)\n \t\t\t\tif (cmp < 0) /* definitely do not have it */\n \t\t\t\t\tbreak;\n \t\t\t\telse if (cmp == 0) { /* definitely have it */\n-\t\t\t\t\theads[head_pos][0] = '\\0';\n \t\t\t\t\treturn_refs[head_pos] = ref;\n+\t\t\t\t\theads[head_pos++][0] = '\\0';\n \t\t\t\t\tbreak;\n \t\t\t\t}\n \t\t\t\telse /* might have it; keep looking */\n-- \n1.7.11.3\n"},{"id":"197827","messageId":"1345877067-11841-7-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 06/17] Let fetch_pack() inform caller about number of unique heads","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:16Z","receivedAt":"2012-08-25T06:44:16Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nfetch_pack() removes duplicates from the list (nr_heads, heads),\nthereby shrinking the list.  But previously, the caller was not\ninformed about the shrinkage.  This would cause a spurious error\nmessage to be emitted by cmd_fetch_pack() if \"git fetch-pack\" is\ncalled with duplicate refnames.\n\nSo change the signature of fetch_pack() to accept nr_heads by\nreference, and if any duplicates were removed then modify it to\nreflect the number of remaining references.\n\nThe last test of t5500 inexplicably *required* \"git fetch-pack\" to\nfail when fetching a list of references that contains duplicates;\ni.e., it insisted on the buggy behavior.  So change the test to expect\nthe correct behavior.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c  | 12 ++++++------\n fetch-pack.h          |  2 +-\n t/t5500-fetch-pack.sh |  2 +-\n transport.c           |  2 +-\n 4 files changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex bda3c0c..cf65998 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -1021,7 +1021,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)\n \tget_remote_heads(fd[0], &ref, 0, NULL);\n \n \tref = fetch_pack(&args, fd, conn, ref, dest,\n-\t\tnr_heads, heads, pack_lockfile_ptr);\n+\t\t&nr_heads, heads, pack_lockfile_ptr);\n \tif (pack_lockfile) {\n \t\tprintf(\"lock %s\\n\", pack_lockfile);\n \t\tfflush(stdout);\n@@ -1062,7 +1062,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,\n \t\t       int fd[], struct child_process *conn,\n \t\t       const struct ref *ref,\n \t\t       const char *dest,\n-\t\t       int nr_heads,\n+\t\t       int *nr_heads,\n \t\t       char **heads,\n \t\t       char **pack_lockfile)\n {\n@@ -1077,16 +1077,16 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,\n \t\t\tst.st_mtime = 0;\n \t}\n \n-\tif (heads && nr_heads) {\n-\t\tqsort(heads, nr_heads, sizeof(*heads), compare_heads);\n-\t\tnr_heads = remove_duplicates(nr_heads, heads);\n+\tif (heads && *nr_heads) {\n+\t\tqsort(heads, *nr_heads, sizeof(*heads), compare_heads);\n+\t\t*nr_heads = remove_duplicates(*nr_heads, heads);\n \t}\n \n \tif (!ref) {\n \t\tpacket_flush(fd[1]);\n \t\tdie(\"no matching remote head\");\n \t}\n-\tref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);\n+\tref_cpy = do_fetch_pack(fd, ref, *nr_heads, heads, pack_lockfile);\n \n \tif (args.depth > 0) {\n \t\tstruct cache_time mtime;\ndiff --git a/fetch-pack.h b/fetch-pack.h\nindex 1dbe90f..a9d505b 100644\n--- a/fetch-pack.h\n+++ b/fetch-pack.h\n@@ -21,7 +21,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,\n \t\t       int fd[], struct child_process *conn,\n \t\t       const struct ref *ref,\n \t\t       const char *dest,\n-\t\t       int nr_heads,\n+\t\t       int *nr_heads,\n \t\t       char **heads,\n \t\t       char **pack_lockfile);\n \ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex 3cc3346..0d4edcb 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -391,7 +391,7 @@ test_expect_success 'fetch mixed refs from cmdline and stdin' '\n test_expect_success 'test duplicate refs from stdin' '\n \t(\n \tcd client &&\n-\ttest_must_fail git fetch-pack --stdin --no-progress .. <../input.dup\n+\tgit fetch-pack --stdin --no-progress .. <../input.dup\n \t) >output &&\n \tcut -d \" \" -f 2 <output | sort >actual &&\n \ttest_cmp expect actual\ndiff --git a/transport.c b/transport.c\nindex 1811b50..f7bbf58 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -548,7 +548,7 @@ static int fetch_refs_via_pack(struct transport *transport,\n \n \trefs = fetch_pack(&args, data->fd, data->conn,\n \t\t\t  refs_tmp ? refs_tmp : transport->remote_refs,\n-\t\t\t  dest, nr_heads, heads, &transport->pack_lockfile);\n+\t\t\t  dest, &nr_heads, heads, &transport->pack_lockfile);\n \tclose(data->fd[0]);\n \tclose(data->fd[1]);\n \tif (finish_connect(data->conn))\n-- \n1.7.11.3\n"},{"id":"197815","messageId":"1345877067-11841-8-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 07/17] Pass nr_heads to do_pack_ref() by reference","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:17Z","receivedAt":"2012-08-25T06:44:17Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nThis is the first of a few baby steps towards changing filter_refs()\nto compress matched refs out of the list rather than overwriting the\nfirst character of such references with '\\0'.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex cf65998..fae4f7c 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -777,7 +777,7 @@ static int get_pack(int xd[2], char **pack_lockfile)\n \n static struct ref *do_fetch_pack(int fd[2],\n \t\tconst struct ref *orig_ref,\n-\t\tint nr_heads, char **heads,\n+\t\tint *nr_heads, char **heads,\n \t\tchar **pack_lockfile)\n {\n \tstruct ref *ref = copy_ref_list(orig_ref);\n@@ -818,7 +818,7 @@ static struct ref *do_fetch_pack(int fd[2],\n \t\t\tfprintf(stderr, \"Server supports ofs-delta\\n\");\n \t} else\n \t\tprefer_ofs_delta = 0;\n-\tif (everything_local(&ref, nr_heads, heads)) {\n+\tif (everything_local(&ref, *nr_heads, heads)) {\n \t\tpacket_flush(fd[1]);\n \t\tgoto all_done;\n \t}\n@@ -1086,7 +1086,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,\n \t\tpacket_flush(fd[1]);\n \t\tdie(\"no matching remote head\");\n \t}\n-\tref_cpy = do_fetch_pack(fd, ref, *nr_heads, heads, pack_lockfile);\n+\tref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);\n \n \tif (args.depth > 0) {\n \t\tstruct cache_time mtime;\n-- \n1.7.11.3\n"},{"id":"197814","messageId":"1345877067-11841-9-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 08/17] Pass nr_heads to everything_local() by reference","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:18Z","receivedAt":"2012-08-25T06:44:18Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex fae4f7c..a4bb0ff 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -595,7 +595,7 @@ static void mark_alternate_complete(const struct ref *ref, void *unused)\n \tmark_complete(NULL, ref->old_sha1, 0, NULL);\n }\n \n-static int everything_local(struct ref **refs, int nr_heads, char **heads)\n+static int everything_local(struct ref **refs, int *nr_heads, char **heads)\n {\n \tstruct ref *ref;\n \tint retval;\n@@ -646,7 +646,7 @@ static int everything_local(struct ref **refs, int nr_heads, char **heads)\n \t\t}\n \t}\n \n-\tfilter_refs(refs, nr_heads, heads);\n+\tfilter_refs(refs, *nr_heads, heads);\n \n \tfor (retval = 1, ref = *refs; ref ; ref = ref->next) {\n \t\tconst unsigned char *remote = ref->old_sha1;\n@@ -818,7 +818,7 @@ static struct ref *do_fetch_pack(int fd[2],\n \t\t\tfprintf(stderr, \"Server supports ofs-delta\\n\");\n \t} else\n \t\tprefer_ofs_delta = 0;\n-\tif (everything_local(&ref, *nr_heads, heads)) {\n+\tif (everything_local(&ref, nr_heads, heads)) {\n \t\tpacket_flush(fd[1]);\n \t\tgoto all_done;\n \t}\n-- \n1.7.11.3\n"},{"id":"197826","messageId":"1345877067-11841-10-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 09/17] Pass nr_heads to filter_refs() by reference","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:19Z","receivedAt":"2012-08-25T06:44:19Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex a4bb0ff..c47090d 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -521,7 +521,7 @@ static void mark_recent_complete_commits(unsigned long cutoff)\n \t}\n }\n \n-static void filter_refs(struct ref **refs, int nr_heads, char **heads)\n+static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n {\n \tstruct ref **return_refs;\n \tstruct ref *newlist = NULL;\n@@ -530,12 +530,12 @@ static void filter_refs(struct ref **refs, int nr_heads, char **heads)\n \tstruct ref *fastarray[32];\n \tint head_pos;\n \n-\tif (nr_heads && !args.fetch_all) {\n-\t\tif (ARRAY_SIZE(fastarray) < nr_heads)\n-\t\t\treturn_refs = xcalloc(nr_heads, sizeof(struct ref *));\n+\tif (*nr_heads && !args.fetch_all) {\n+\t\tif (ARRAY_SIZE(fastarray) < *nr_heads)\n+\t\t\treturn_refs = xcalloc(*nr_heads, sizeof(struct ref *));\n \t\telse {\n \t\t\treturn_refs = fastarray;\n-\t\t\tmemset(return_refs, 0, sizeof(struct ref *) * nr_heads);\n+\t\t\tmemset(return_refs, 0, sizeof(struct ref *) * *nr_heads);\n \t\t}\n \t}\n \telse\n@@ -556,7 +556,7 @@ static void filter_refs(struct ref **refs, int nr_heads, char **heads)\n \t\t}\n \t\telse {\n \t\t\tint cmp = -1;\n-\t\t\twhile (head_pos < nr_heads) {\n+\t\t\twhile (head_pos < *nr_heads) {\n \t\t\t\tcmp = strcmp(ref->name, heads[head_pos]);\n \t\t\t\tif (cmp < 0) /* definitely do not have it */\n \t\t\t\t\tbreak;\n@@ -576,7 +576,7 @@ static void filter_refs(struct ref **refs, int nr_heads, char **heads)\n \n \tif (!args.fetch_all) {\n \t\tint i;\n-\t\tfor (i = 0; i < nr_heads; i++) {\n+\t\tfor (i = 0; i < *nr_heads; i++) {\n \t\t\tref = return_refs[i];\n \t\t\tif (ref) {\n \t\t\t\t*newtail = ref;\n@@ -646,7 +646,7 @@ static int everything_local(struct ref **refs, int *nr_heads, char **heads)\n \t\t}\n \t}\n \n-\tfilter_refs(refs, *nr_heads, heads);\n+\tfilter_refs(refs, nr_heads, heads);\n \n \tfor (retval = 1, ref = *refs; ref ; ref = ref->next) {\n \t\tconst unsigned char *remote = ref->old_sha1;\n-- \n1.7.11.3\n"},{"id":"197816","messageId":"1345877067-11841-11-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 10/17] Remove ineffective optimization","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:20Z","receivedAt":"2012-08-25T06:44:20Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nI cannot find a scenario in which this function is called any\nsignificant number of times, so simplify the code by always allocating\nan array for return_refs rather than trying to use a stack-allocated\narray for small lists.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 14 +++-----------\n 1 file changed, 3 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex c47090d..ca1ddd9 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -527,17 +527,10 @@ static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n \tstruct ref *newlist = NULL;\n \tstruct ref **newtail = &newlist;\n \tstruct ref *ref, *next;\n-\tstruct ref *fastarray[32];\n \tint head_pos;\n \n-\tif (*nr_heads && !args.fetch_all) {\n-\t\tif (ARRAY_SIZE(fastarray) < *nr_heads)\n-\t\t\treturn_refs = xcalloc(*nr_heads, sizeof(struct ref *));\n-\t\telse {\n-\t\t\treturn_refs = fastarray;\n-\t\t\tmemset(return_refs, 0, sizeof(struct ref *) * *nr_heads);\n-\t\t}\n-\t}\n+\tif (*nr_heads && !args.fetch_all)\n+\t\treturn_refs = xcalloc(*nr_heads, sizeof(struct ref *));\n \telse\n \t\treturn_refs = NULL;\n \n@@ -584,8 +577,7 @@ static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n \t\t\t\tnewtail = &ref->next;\n \t\t\t}\n \t\t}\n-\t\tif (return_refs != fastarray)\n-\t\t\tfree(return_refs);\n+\t\tfree(return_refs);\n \t}\n \t*refs = newlist;\n }\n-- \n1.7.11.3\n"},{"id":"197828","messageId":"1345877067-11841-12-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 11/17] filter_refs(): do not leave gaps in return_refs","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:21Z","receivedAt":"2012-08-25T06:44:21Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nIt used to be that this function processed refnames in some arbitrary\norder but wanted to return them in the order that they were requested,\nnot the order that they were processed.  Now, the refnames are\nprocessed in sorted order, so there is no reason to go to the extra\neffort.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 15 ++++++---------\n 1 file changed, 6 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex ca1ddd9..a995357 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -527,14 +527,13 @@ static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n \tstruct ref *newlist = NULL;\n \tstruct ref **newtail = &newlist;\n \tstruct ref *ref, *next;\n-\tint head_pos;\n+\tint head_pos = 0, matched = 0;\n \n \tif (*nr_heads && !args.fetch_all)\n \t\treturn_refs = xcalloc(*nr_heads, sizeof(struct ref *));\n \telse\n \t\treturn_refs = NULL;\n \n-\thead_pos = 0;\n \tfor (ref = *refs; ref; ref = next) {\n \t\tnext = ref->next;\n \t\tif (!memcmp(ref->name, \"refs/\", 5) &&\n@@ -554,7 +553,7 @@ static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n \t\t\t\tif (cmp < 0) /* definitely do not have it */\n \t\t\t\t\tbreak;\n \t\t\t\telse if (cmp == 0) { /* definitely have it */\n-\t\t\t\t\treturn_refs[head_pos] = ref;\n+\t\t\t\t\treturn_refs[matched++] = ref;\n \t\t\t\t\theads[head_pos++][0] = '\\0';\n \t\t\t\t\tbreak;\n \t\t\t\t}\n@@ -569,13 +568,11 @@ static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n \n \tif (!args.fetch_all) {\n \t\tint i;\n-\t\tfor (i = 0; i < *nr_heads; i++) {\n+\t\tfor (i = 0; i < matched; i++) {\n \t\t\tref = return_refs[i];\n-\t\t\tif (ref) {\n-\t\t\t\t*newtail = ref;\n-\t\t\t\tref->next = NULL;\n-\t\t\t\tnewtail = &ref->next;\n-\t\t\t}\n+\t\t\t*newtail = ref;\n+\t\t\tref->next = NULL;\n+\t\t\tnewtail = &ref->next;\n \t\t}\n \t\tfree(return_refs);\n \t}\n-- \n1.7.11.3\n"},{"id":"197818","messageId":"1345877067-11841-13-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 12/17] filter_refs(): compress unmatched refs in heads array","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:22Z","receivedAt":"2012-08-25T06:44:22Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nRemove any references that were received from the remote from the list\n(*nr_heads, heads) of requested references by squeezing them out of\nthe list (rather than overwriting their names with NUL characters, as\nbefore).  On exit, *nr_heads is the number of requested references\nthat were not received.\n\nDocument this aspect of fetch_pack() in a comment in the header file.\n(More documentation is obviously still needed.)\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 21 +++++++++++++--------\n fetch-pack.h         |  6 ++++++\n transport.c          |  3 ++-\n 3 files changed, 21 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex a995357..5ba1cef 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -527,7 +527,7 @@ static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n \tstruct ref *newlist = NULL;\n \tstruct ref **newtail = &newlist;\n \tstruct ref *ref, *next;\n-\tint head_pos = 0, matched = 0;\n+\tint head_pos = 0, matched = 0, unmatched = 0;\n \n \tif (*nr_heads && !args.fetch_all)\n \t\treturn_refs = xcalloc(*nr_heads, sizeof(struct ref *));\n@@ -554,11 +554,12 @@ static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n \t\t\t\t\tbreak;\n \t\t\t\telse if (cmp == 0) { /* definitely have it */\n \t\t\t\t\treturn_refs[matched++] = ref;\n-\t\t\t\t\theads[head_pos++][0] = '\\0';\n+\t\t\t\t\thead_pos++;\n \t\t\t\t\tbreak;\n \t\t\t\t}\n-\t\t\t\telse /* might have it; keep looking */\n-\t\t\t\t\thead_pos++;\n+\t\t\t\telse { /* might have it; keep looking */\n+\t\t\t\t\theads[unmatched++] = heads[head_pos++];\n+\t\t\t\t}\n \t\t\t}\n \t\t\tif (!cmp)\n \t\t\t\tcontinue; /* we will link it later */\n@@ -568,6 +569,12 @@ static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n \n \tif (!args.fetch_all) {\n \t\tint i;\n+\n+\t\t/* copy remaining unmatched heads: */\n+\t\twhile (head_pos < *nr_heads)\n+\t\t\theads[unmatched++] = heads[head_pos++];\n+\t\t*nr_heads = unmatched;\n+\n \t\tfor (i = 0; i < matched; i++) {\n \t\t\tref = return_refs[i];\n \t\t\t*newtail = ref;\n@@ -1028,10 +1035,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)\n \t\t * silently succeed without issuing an error.\n \t\t */\n \t\tfor (i = 0; i < nr_heads; i++)\n-\t\t\tif (heads[i] && heads[i][0]) {\n-\t\t\t\terror(\"no such remote ref %s\", heads[i]);\n-\t\t\t\tret = 1;\n-\t\t\t}\n+\t\t\terror(\"no such remote ref %s\", heads[i]);\n+\t\tret = 1;\n \t}\n \twhile (ref) {\n \t\tprintf(\"%s %s\\n\",\ndiff --git a/fetch-pack.h b/fetch-pack.h\nindex a9d505b..915858e 100644\n--- a/fetch-pack.h\n+++ b/fetch-pack.h\n@@ -17,6 +17,12 @@ struct fetch_pack_args {\n \t\tstateless_rpc:1;\n };\n \n+/*\n+ * (*nr_heads, heads) is an array of pointers to the full names of\n+ * remote references that should be updated from.  On return, both\n+ * will have been changed to list only the names that were not found\n+ * on the remote.\n+ */\n struct ref *fetch_pack(struct fetch_pack_args *args,\n \t\t       int fd[], struct child_process *conn,\n \t\t       const struct ref *ref,\ndiff --git a/transport.c b/transport.c\nindex f7bbf58..3c38d44 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -520,6 +520,7 @@ static int fetch_refs_via_pack(struct transport *transport,\n \tstruct git_transport_data *data = transport->data;\n \tchar **heads = xmalloc(nr_heads * sizeof(*heads));\n \tchar **origh = xmalloc(nr_heads * sizeof(*origh));\n+\tint orig_nr_heads = nr_heads;\n \tconst struct ref *refs;\n \tchar *dest = xstrdup(transport->url);\n \tstruct fetch_pack_args args;\n@@ -558,7 +559,7 @@ static int fetch_refs_via_pack(struct transport *transport,\n \n \tfree_refs(refs_tmp);\n \n-\tfor (i = 0; i < nr_heads; i++)\n+\tfor (i = 0; i < orig_nr_heads; i++)\n \t\tfree(origh[i]);\n \tfree(origh);\n \tfree(heads);\n-- \n1.7.11.3\n"},{"id":"197817","messageId":"1345877067-11841-14-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 13/17] cmd_fetch_pack: return early if finish_connect() returns an error","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:23Z","receivedAt":"2012-08-25T06:44:23Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nThis simplifies the logic without changing the behavior.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex 5ba1cef..f04fd59 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -1025,10 +1025,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)\n \tclose(fd[0]);\n \tclose(fd[1]);\n \tif (finish_connect(conn))\n-\t\tref = NULL;\n-\tret = !ref;\n+\t\treturn 1;\n \n-\tif (!ret && nr_heads) {\n+\tret = !ref;\n+\tif (ref && nr_heads) {\n \t\t/* If the heads to pull were given, we should have\n \t\t * consumed all of them by matching the remote.\n \t\t * Otherwise, 'git fetch remote no-such-ref' would\n-- \n1.7.11.3\n"},{"id":"197819","messageId":"1345877067-11841-15-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 14/17] Report missing refs even if no existing refs were received","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:24Z","receivedAt":"2012-08-25T06:44:24Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nThis fixes a test in t5500.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c  | 2 +-\n t/t5500-fetch-pack.sh | 2 +-\n 2 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex f04fd59..00ac3b1 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -1028,7 +1028,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)\n \t\treturn 1;\n \n \tret = !ref;\n-\tif (ref && nr_heads) {\n+\tif (nr_heads) {\n \t\t/* If the heads to pull were given, we should have\n \t\t * consumed all of them by matching the remote.\n \t\t * Otherwise, 'git fetch remote no-such-ref' would\ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex 0d4edcb..f78a118 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -403,7 +403,7 @@ test_expect_success 'set up tests of missing reference' '\n \tEOF\n '\n \n-test_expect_failure 'test lonely missing ref' '\n+test_expect_success 'test lonely missing ref' '\n \t(\n \tcd client &&\n \ttest_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy\n-- \n1.7.11.3\n"},{"id":"197820","messageId":"1345877067-11841-16-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 15/17] cmd_fetch_pack(): simplify computation of return value","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:25Z","receivedAt":"2012-08-25T06:44:25Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nSet the final value at initialization rather than initializing it then\nsometimes changing it.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 21 ++++++++++-----------\n 1 file changed, 10 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex 00ac3b1..c49dadf 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -1027,17 +1027,16 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)\n \tif (finish_connect(conn))\n \t\treturn 1;\n \n-\tret = !ref;\n-\tif (nr_heads) {\n-\t\t/* If the heads to pull were given, we should have\n-\t\t * consumed all of them by matching the remote.\n-\t\t * Otherwise, 'git fetch remote no-such-ref' would\n-\t\t * silently succeed without issuing an error.\n-\t\t */\n-\t\tfor (i = 0; i < nr_heads; i++)\n-\t\t\terror(\"no such remote ref %s\", heads[i]);\n-\t\tret = 1;\n-\t}\n+\tret = !ref || nr_heads;\n+\n+\t/*\n+\t * If the heads to pull were given, we should have consumed\n+\t * all of them by matching the remote.  Otherwise, 'git fetch\n+\t * remote no-such-ref' would silently succeed without issuing\n+\t * an error.\n+\t */\n+\tfor (i = 0; i < nr_heads; i++)\n+\t\terror(\"no such remote ref %s\", heads[i]);\n \twhile (ref) {\n \t\tprintf(\"%s %s\\n\",\n \t\t       sha1_to_hex(ref->old_sha1), ref->name);\n-- \n1.7.11.3\n"},{"id":"197821","messageId":"1345877067-11841-17-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 16/17] fetch_pack(): free matching heads","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:26Z","receivedAt":"2012-08-25T06:44:26Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nfetch_pack() used to delete entries from the input list (*nr_heads,\nheads) and drop them on the floor.  (Even earlier versions dropped\nsome names on the floor and modified others.)  This forced\nfetch_refs_via_pack() to create a separate copy of the original list\nso that it could free all of the names.\n\nInstead, teach fetch_pack() to free any names that it discards from\nthe list, and change fetch_refs_via_pack() to free only the remaining\n(unmatched) names.\n\nDocument the change in the function comment in the header file.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 4 +++-\n fetch-pack.h         | 7 ++++---\n transport.c          | 9 +++------\n 3 files changed, 10 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex c49dadf..1bc4599 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -554,7 +554,7 @@ static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n \t\t\t\t\tbreak;\n \t\t\t\telse if (cmp == 0) { /* definitely have it */\n \t\t\t\t\treturn_refs[matched++] = ref;\n-\t\t\t\t\thead_pos++;\n+\t\t\t\t\tfree(heads[head_pos++]);\n \t\t\t\t\tbreak;\n \t\t\t\t}\n \t\t\t\telse { /* might have it; keep looking */\n@@ -844,6 +844,8 @@ static int remove_duplicates(int nr_heads, char **heads)\n \tfor (src = dst = 1; src < nr_heads; src++)\n \t\tif (strcmp(heads[src], heads[dst-1]))\n \t\t\theads[dst++] = heads[src];\n+\t\telse\n+\t\t\tfree(heads[src]);\n \treturn dst;\n }\n \ndiff --git a/fetch-pack.h b/fetch-pack.h\nindex 915858e..d1860eb 100644\n--- a/fetch-pack.h\n+++ b/fetch-pack.h\n@@ -19,9 +19,10 @@ struct fetch_pack_args {\n \n /*\n  * (*nr_heads, heads) is an array of pointers to the full names of\n- * remote references that should be updated from.  On return, both\n- * will have been changed to list only the names that were not found\n- * on the remote.\n+ * remote references that should be updated from.  The names must have\n+ * been allocated from the heap.  The names that are found in the\n+ * remote will be removed from the list and freed; the others will be\n+ * left in the front of the array with *nr_heads adjusted accordingly.\n  */\n struct ref *fetch_pack(struct fetch_pack_args *args,\n \t\t       int fd[], struct child_process *conn,\ndiff --git a/transport.c b/transport.c\nindex 3c38d44..f94b753 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -519,8 +519,6 @@ static int fetch_refs_via_pack(struct transport *transport,\n {\n \tstruct git_transport_data *data = transport->data;\n \tchar **heads = xmalloc(nr_heads * sizeof(*heads));\n-\tchar **origh = xmalloc(nr_heads * sizeof(*origh));\n-\tint orig_nr_heads = nr_heads;\n \tconst struct ref *refs;\n \tchar *dest = xstrdup(transport->url);\n \tstruct fetch_pack_args args;\n@@ -539,7 +537,7 @@ static int fetch_refs_via_pack(struct transport *transport,\n \targs.depth = data->options.depth;\n \n \tfor (i = 0; i < nr_heads; i++)\n-\t\torigh[i] = heads[i] = xstrdup(to_fetch[i]->name);\n+\t\theads[i] = xstrdup(to_fetch[i]->name);\n \n \tif (!data->got_remote_heads) {\n \t\tconnect_setup(transport, 0, 0);\n@@ -559,9 +557,8 @@ static int fetch_refs_via_pack(struct transport *transport,\n \n \tfree_refs(refs_tmp);\n \n-\tfor (i = 0; i < orig_nr_heads; i++)\n-\t\tfree(origh[i]);\n-\tfree(origh);\n+\tfor (i = 0; i < nr_heads; i++)\n+\t\tfree(heads[i]);\n \tfree(heads);\n \tfree(dest);\n \treturn (refs ? 0 : -1);\n-- \n1.7.11.3\n"},{"id":"197822","messageId":"1345877067-11841-18-git-send-email-mhagger@alum.mit.edu","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 17/17] filter_refs(): simplify logic","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2012-08-25T06:44:27Z","receivedAt":"2012-08-25T06:44:27Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n* Build linked list of return values as we go rather than recording\n  them in a temporary array and linking them up later.\n\n* Handle ref in a single if...else statement in the main loop, to make\n  it clear that each ref has exactly two possible destinies.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n builtin/fetch-pack.c | 56 ++++++++++++++++++----------------------------------\n 1 file changed, 19 insertions(+), 37 deletions(-)\n\ndiff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c\nindex 1bc4599..db77ee6 100644\n--- a/builtin/fetch-pack.c\n+++ b/builtin/fetch-pack.c\n@@ -523,66 +523,48 @@ static void mark_recent_complete_commits(unsigned long cutoff)\n \n static void filter_refs(struct ref **refs, int *nr_heads, char **heads)\n {\n-\tstruct ref **return_refs;\n \tstruct ref *newlist = NULL;\n \tstruct ref **newtail = &newlist;\n \tstruct ref *ref, *next;\n-\tint head_pos = 0, matched = 0, unmatched = 0;\n-\n-\tif (*nr_heads && !args.fetch_all)\n-\t\treturn_refs = xcalloc(*nr_heads, sizeof(struct ref *));\n-\telse\n-\t\treturn_refs = NULL;\n+\tint head_pos = 0, unmatched = 0;\n \n \tfor (ref = *refs; ref; ref = next) {\n+\t\tint keep_ref = 0;\n \t\tnext = ref->next;\n \t\tif (!memcmp(ref->name, \"refs/\", 5) &&\n \t\t    check_refname_format(ref->name, 0))\n \t\t\t; /* trash */\n \t\telse if (args.fetch_all &&\n-\t\t\t (!args.depth || prefixcmp(ref->name, \"refs/tags/\") )) {\n-\t\t\t*newtail = ref;\n-\t\t\tref->next = NULL;\n-\t\t\tnewtail = &ref->next;\n-\t\t\tcontinue;\n-\t\t}\n-\t\telse {\n-\t\t\tint cmp = -1;\n+\t\t\t   (!args.depth || prefixcmp(ref->name, \"refs/tags/\")))\n+\t\t\tkeep_ref = 1;\n+\t\telse\n \t\t\twhile (head_pos < *nr_heads) {\n-\t\t\t\tcmp = strcmp(ref->name, heads[head_pos]);\n-\t\t\t\tif (cmp < 0) /* definitely do not have it */\n+\t\t\t\tint cmp = strcmp(ref->name, heads[head_pos]);\n+\t\t\t\tif (cmp < 0) { /* definitely do not have it */\n \t\t\t\t\tbreak;\n-\t\t\t\telse if (cmp == 0) { /* definitely have it */\n-\t\t\t\t\treturn_refs[matched++] = ref;\n+\t\t\t\t} else if (cmp == 0) { /* definitely have it */\n \t\t\t\t\tfree(heads[head_pos++]);\n+\t\t\t\t\tkeep_ref = 1;\n \t\t\t\t\tbreak;\n-\t\t\t\t}\n-\t\t\t\telse { /* might have it; keep looking */\n+\t\t\t\t} else { /* might have it; keep looking */\n \t\t\t\t\theads[unmatched++] = heads[head_pos++];\n \t\t\t\t}\n \t\t\t}\n-\t\t\tif (!cmp)\n-\t\t\t\tcontinue; /* we will link it later */\n-\t\t}\n-\t\tfree(ref);\n-\t}\n-\n-\tif (!args.fetch_all) {\n-\t\tint i;\n \n-\t\t/* copy remaining unmatched heads: */\n-\t\twhile (head_pos < *nr_heads)\n-\t\t\theads[unmatched++] = heads[head_pos++];\n-\t\t*nr_heads = unmatched;\n-\n-\t\tfor (i = 0; i < matched; i++) {\n-\t\t\tref = return_refs[i];\n+\t\tif (keep_ref) {\n \t\t\t*newtail = ref;\n \t\t\tref->next = NULL;\n \t\t\tnewtail = &ref->next;\n+\t\t} else {\n+\t\t\tfree(ref);\n \t\t}\n-\t\tfree(return_refs);\n \t}\n+\n+\t/* copy any remaining unmatched heads: */\n+\twhile (head_pos < *nr_heads)\n+\t\theads[unmatched++] = heads[head_pos++];\n+\t*nr_heads = unmatched;\n+\n \t*refs = newlist;\n }\n \n-- \n1.7.11.3\n"},{"id":"197861","messageId":"7v7gslwox6.fsf@alter.siamese.dyndns.org","threadId":"31352","inReplyTo":"1345877067-11841-1-git-send-email-mhagger@alum.mit.edu","subject":"Re: [PATCH v2 00/17] Clean up how fetch_pack() handles the heads list","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-08-26T17:20:21Z","receivedAt":"2012-08-26T17:20:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"mhagger@alum.mit.edu writes:\n\n> Re-roll, incorporating Jeff's suggestions.  Some commit messages have\n> also been improved, but the only interdiff is that match_pos is\n> renamed to head_pos in filter_refs().\n>\n> This patch series applies to the merge between master and\n> jc/maint-push-refs-all, though the dependency on the latter is only\n> textual.\n\nI've read this twice and saw nothing questionable in the series\n(other than that the titles of a few weren't clear enough when\nplaced in a short-log like below).  Very nicely done.\n\nThanks.  Will queue.\n\n> Michael Haggerty (17):\n>   t5500: add tests of error output for missing refs\n>   Rename static function fetch_pack() to http_fetch_pack()\n>   Fix formatting.\n>   Name local variables more consistently\n>   Do not check the same head_pos twice\n>   Let fetch_pack() inform caller about number of unique heads\n>   Pass nr_heads to do_pack_ref() by reference\n>   Pass nr_heads to everything_local() by reference\n>   Pass nr_heads to filter_refs() by reference\n>   Remove ineffective optimization\n>   filter_refs(): do not leave gaps in return_refs\n>   filter_refs(): compress unmatched refs in heads array\n>   cmd_fetch_pack: return early if finish_connect() returns an error\n>   Report missing refs even if no existing refs were received\n>   cmd_fetch_pack(): simplify computation of return value\n>   fetch_pack(): free matching heads\n>   filter_refs(): simplify logic\n>\n>  builtin/fetch-pack.c  | 128 ++++++++++++++++++++------------------------------\n>  fetch-pack.h          |  19 +++++---\n>  http-walker.c         |   4 +-\n>  t/t5500-fetch-pack.sh |  32 ++++++++++++-\n>  transport.c           |   8 ++--\n>  5 files changed, 101 insertions(+), 90 deletions(-)\n"}]}