refactor "ref->merge" flag

Each "struct ref" has a boolean flag that is set by the fetch code to determine whether the ref should be marked as "not-for-merge" or not when we write it out to FETCH_HEAD. It would be useful to turn this boolean into a tri-state, with the third state meaning "do not bother writing it out to FETCH_HEAD at all". That would let us add extra refs to the set of refs to be stored (e.g., to store copies of things we fetched) without impacting FETCH_HEAD. This patch turns it into an enum that covers the tri-state case, and hopefully makes the code more explicit and easier to read. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed May 11, 2013 at 18:15 UTC 900f2814b8da951a450f5762dabb1b248dd77abc
2 files changed +48 -23
builtin/fetch.c
+35 -22
@@ -119,7 +119,7 @@ static void add_merge_config(struct ref **head,
119
120 for (rm = *head; rm; rm = rm->next) {
121 if (branch_merge_matches(branch, i, rm->name)) {
122 - rm->merge = 1;
122 + rm->fetch_head_status = FETCH_HEAD_MERGE;
123 break;
124 }
125 }
@@ -140,7 +140,7 @@ static void add_merge_config(struct ref **head,
140 refspec.src = branch->merge[i]->src;
141 get_fetch_map(remote_refs, &refspec, tail, 1);
142 for (rm = *old_tail; rm; rm = rm->next)
143 - rm->merge = 1;
143 + rm->fetch_head_status = FETCH_HEAD_MERGE;
144 }
145 }
146
@@ -167,7 +167,7 @@ static struct ref *get_ref_map(struct transport *transport,
167 }
168 /* Merge everything on the command line, but not --tags */
169 for (rm = ref_map; rm; rm = rm->next)
170 - rm->merge = 1;
170 + rm->fetch_head_status = FETCH_HEAD_MERGE;
171 if (tags == TAGS_SET)
172 get_fetch_map(remote_refs, tag_refspec, &tail, 0);
173 } else {
@@ -186,7 +186,7 @@ static struct ref *get_ref_map(struct transport *transport,
186 *autotags = 1;
187 if (!i && !has_merge && ref_map &&
188 !remote->fetch[0].pattern)
189 - ref_map->merge = 1;
189 + ref_map->fetch_head_status = FETCH_HEAD_MERGE;
190 }
191 /*
192 * if the remote we're fetching from is the same
@@ -202,7 +202,7 @@ static struct ref *get_ref_map(struct transport *transport,
202 ref_map = get_remote_ref(remote_refs, "HEAD");
203 if (!ref_map)
204 die(_("Couldn't find remote ref HEAD"));
205 - ref_map->merge = 1;
205 + ref_map->fetch_head_status = FETCH_HEAD_MERGE;
206 tail = &ref_map->next;
207 }
208 }
@@ -389,7 +389,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
389 const char *what, *kind;
390 struct ref *rm;
391 char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD");
392 - int want_merge;
392 + int want_status;
393
394 fp = fopen(filename, "a");
395 if (!fp)
@@ -407,19 +407,22 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
407 }
408
409 /*
410 - * The first pass writes objects to be merged and then the
411 - * second pass writes the rest, in order to allow using
412 - * FETCH_HEAD as a refname to refer to the ref to be merged.
410 + * We do a pass for each fetch_head_status type in their enum order, so
411 + * merged entries are written before not-for-merge. That lets readers
412 + * use FETCH_HEAD as a refname to refer to the ref to be merged.
413 */
414 - for (want_merge = 1; 0 <= want_merge; want_merge--) {
414 + for (want_status = FETCH_HEAD_MERGE;
415 + want_status <= FETCH_HEAD_IGNORE;
416 + want_status++) {
417 for (rm = ref_map; rm; rm = rm->next) {
418 struct ref *ref = NULL;
419 + const char *merge_status_marker = "";
420
421 commit = lookup_commit_reference_gently(rm->old_sha1, 1);
422 if (!commit)
420 - rm->merge = 0;
423 + rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
424
422 - if (rm->merge != want_merge)
425 + if (rm->fetch_head_status != want_status)
426 continue;
427
428 if (rm->peer_ref) {
@@ -465,16 +468,26 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
468 strbuf_addf(&note, "%s ", kind);
469 strbuf_addf(&note, "'%s' of ", what);
470 }
468 - fprintf(fp, "%s\t%s\t%s",
469 - sha1_to_hex(rm->old_sha1),
470 - rm->merge ? "" : "not-for-merge",
471 - note.buf);
472 - for (i = 0; i < url_len; ++i)
473 - if ('\n' == url[i])
474 - fputs("\\n", fp);
475 - else
476 - fputc(url[i], fp);
477 - fputc('\n', fp);
471 + switch (rm->fetch_head_status) {
472 + case FETCH_HEAD_NOT_FOR_MERGE:
473 + merge_status_marker = "not-for-merge";
474 + /* fall-through */
475 + case FETCH_HEAD_MERGE:
476 + fprintf(fp, "%s\t%s\t%s",
477 + sha1_to_hex(rm->old_sha1),
478 + merge_status_marker,
479 + note.buf);
480 + for (i = 0; i < url_len; ++i)
481 + if ('\n' == url[i])
482 + fputs("\\n", fp);
483 + else
484 + fputc(url[i], fp);
485 + fputc('\n', fp);
486 + break;
487 + default:
488 + /* do not write anything to FETCH_HEAD */
489 + break;
490 + }
491
492 strbuf_reset(&note);
493 if (ref) {
cache.h
+13 -1
@@ -1024,9 +1024,21 @@ struct ref {
1024 unsigned int
1025 force:1,
1026 forced_update:1,
1027 - merge:1,
1027 deletion:1,
1028 matched:1;
1029 +
1030 + /*
1031 + * Order is important here, as we write to FETCH_HEAD
1032 + * in numeric order. And the default NOT_FOR_MERGE
1033 + * should be 0, so that xcalloc'd structures get it
1034 + * by default.
1035 + */
1036 + enum {
1037 + FETCH_HEAD_MERGE = -1,
1038 + FETCH_HEAD_NOT_FOR_MERGE = 0,
1039 + FETCH_HEAD_IGNORE = 1
1040 + } fetch_head_status;
1041 +
1042 enum {
1043 REF_STATUS_NONE = 0,
1044 REF_STATUS_OK,