On Fri, Jan 08, 2021 at 03:40:17PM -0800, Junio C Hamano wrote: > Patrick Steinhardt writes: > > +static void append_fetch_head(struct fetch_head *fetch_head, const char *old_oid, > > It is clear from the type these days but variable names like > "old_oid" hint the readers that they are not a hexadecimal object > name string but either an array of uchar[40] or a struct object_id; > perhaps "old_oid_hex" would be less misleading. > > If the caller does have struct object_id, then it would be even > better to take it as-is as a parameter and use oid_to_hex_r() on it in > this function when it is given to fprintf(). [Nit #1] Agreed. [snip] > > + fprintf(fetch_head->fp, "%s\t%s\t%s", > > + old_oid, merge_status_marker, note); > > + for (i = 0; i < url_len; ++i) > > + if ('\n' == url[i]) > > + fputs("\\n", fetch_head->fp); > > + else > > + fputc(url[i], fetch_head->fp); > > + fputc('\n', fetch_head->fp); > > +} > > OK. This is the "case FETCH_HEAD_NOT_FOR_MERGE" and "case > FETCH_HEAD_MERGE" parts in the original. > > As an abstraction, it may be better to make the caller pass a > boolean "is this for merge?" and keep the knowledge of what exact > string is used for merge_status_marker to this function, instead of > letting the caller passing it as a parameter in the string form. > After all, we never allow anything other than an empty string or a > fixed "not-for-merge" string in that place in the file format. > [Nit #2] I think it's even nicer to just pass in `rm->fetch_head_status` directly, which allows us to move below switch into `append_fetch_head`. [snip] > > + fclose(fetch_head->fp); > > +} > > > @@ -909,22 +959,19 @@ N_("It took %.2f seconds to check forced updates. You can use\n" > > static int store_updated_refs(const char *raw_url, const char *remote_name, > > int connectivity_checked, struct ref *ref_map) > > { > > - FILE *fp; > > + struct fetch_head fetch_head; > > And that is why this variable is left uninitialised on stack and it > is OK. An alternative design would be to initialize fetch_head.fp > to NULL, and return early with "if (!fetch_head->fp)" in the two > functions that take fetch_head struct. That way, we have less > reliance on the global variable write_fetch_head. I like your proposal more. I wasn't quite happy with leaving `fp` uninitialized, and using it as a sentinel for whether to write something or not feels natural to me. [snip] > > @@ -1016,16 +1063,10 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, > > merge_status_marker = "not-for-merge"; > > /* fall-through */ > > case FETCH_HEAD_MERGE: > > - fprintf(fp, "%s\t%s\t%s", > > - oid_to_hex(&rm->old_oid), > > - merge_status_marker, > > - note.buf); > > - for (i = 0; i < url_len; ++i) > > - if ('\n' == url[i]) > > - fputs("\\n", fp); > > - else > > - fputc(url[i], fp); > > - fputc('\n', fp); > > + append_fetch_head(&fetch_head, > > + oid_to_hex(&rm->old_oid), > > + merge_status_marker, > > + note.buf, url, url_len); > > Here, we can lose merge_status_marker variable from this caller, and > then this caller becomes: > > switch (rm->fetch_head_status) { > case FETCH_HEAD_NOT_FOR_MERGE: > case FETCH_HEAD_MERGE: > append_fetch_head(&fetch_head, &rm->old_oid, > rm->fetch_head_status == FETCH_HEAD_MERGE, > note.buf, url, url_len); > > Note that I am passing "is this a ref to be merged?" boolean to keep > the exact string of "not-for-merge" in the callee. As said above, I'm just moving this complete switch into `append_fetch_head` and pass `rm->fetch_head_status`. Patrick