On Mon, May 08, 2023 at 04:42:46PM -0700, Glen Choo wrote: > This version looks great! I only have minor comments. > > Patrick Steinhardt writes: > > > A notable ommission here is that the output format does not include the > > remote from which a reference was fetched, which might be important > > information especially in the context of multi-remote fetches. But as > > such a format would require us to print the remote for every single > > reference update due to parallelizable fetches it feels wasteful for the > > most likely usecase, which is when fetching from a single remote. > > > > In a similar spirit, a second restriction is that this cannot be used > > with `--recurse-submodules`. This is because any reference updates would > > be ambiguous without also printing the repository in which the update > > happens. > > > > Considering that both multi-remote and submodule fetches are rather > > niche and likely not going to be useful for the majority of usecases > > these omissions feel acceptable. If usecases for either of these come up > > in the future though it is easy enough to add a new "porcelain-v2" > > format that adds this information. > > As a point of clarification, I think these options aren't niche in > themselves, but they are more user-facing, so using them _in conjunction > with_ --porcelain is probably pretty niche, so I think this is okay for > now. Yeah, that's what I indeed intended to say. Will clarify. [snip] > > @@ -1830,6 +1857,7 @@ struct parallel_fetch_state { > > const char **argv; > > struct string_list *remotes; > > int next, result; > > + enum display_format format; > > }; > > > > static int fetch_next_remote(struct child_process *cp, > > @@ -1849,7 +1877,7 @@ static int fetch_next_remote(struct child_process *cp, > > strvec_push(&cp->args, remote); > > cp->git_cmd = 1; > > > > - if (verbosity >= 0) > > + if (verbosity >= 0 && state->format != DISPLAY_FORMAT_PORCELAIN) > > printf(_("Fetching %s\n"), remote); > > > > return 1; > > Here and elsewhere, I wonder if it's clearer to name the variable > "porcelain" and separate it from "enum display_format". Then we can > check "porcelain" directly instead of using "format == > DISPLAY_FORMAT_PORCELAIN" as a proxy... For now I'd like to keep this as-is: it's easier to keep track of this when there is only a single variable that keeps track of the output format. But if we were to add additional porcelain formats in the future I agree that it would be nice to refactor the code as you propose. I'd rather keep the simpler version for now though where we only have a single state to worry about. > > +static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset) > > +{ > > + enum display_format *format = opt->value; > > + *format = DISPLAY_FORMAT_PORCELAIN; > > + return 0; > > +} > > + > > int cmd_fetch(int argc, const char **argv, const char *prefix) > > { > > const char *bundle_uri; > > @@ -2104,6 +2140,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) > > PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules), > > OPT_BOOL(0, "dry-run", &dry_run, > > N_("dry run")), > > + OPT_CALLBACK_F(0, "porcelain", &display_format, NULL, N_("machine-readable output"), > > + PARSE_OPT_NOARG|PARSE_OPT_NONEG, opt_parse_porcelain), > > OPT_BOOL(0, "write-fetch-head", &write_fetch_head, > > N_("write fetched references to the FETCH_HEAD file")), > > OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")), > > e.g. since we are reusing the "display_format" variable, we need to make > sure we parse "--porcelain" after we read "fetch.output". I > double-checked to make sure we were doing the right thing, though it > would be nice to not have to worry about those sorts of things. This > shouldn't hold up the series though. In fact it is the other way round: we parse `--porcelain` first and then only read "fetch.output" in the case where the `display_format` variable is still set to `DISPLAY_FORMAT_UNKNOWN`. So in the end there is no fragile order dependence here -- it would work just the same regardless of whether we first parse command line options or the configuration. > > +test_expect_success 'fetch porcelain with multiple remotes' ' > > + test_when_finished "rm -rf porcelain" && > > + > > + git clone . porcelain && > > + git -C porcelain remote add second-remote "$PWD" && > > + git -C porcelain fetch second-remote && > > + > > + test_commit --no-tag multi-commit && > > + old_commit=$(git rev-parse HEAD~) && > > + new_commit=$(git rev-parse HEAD) && > > + > > + cat >expect <<-EOF && > > + $old_commit $new_commit refs/remotes/origin/force-updated > > + $old_commit $new_commit refs/remotes/second-remote/force-updated > > + EOF > > The only thing in this test that relies on the previous test is that > HEAD is pointing to "force-updated", and it's hard to tell where HEAD is > since the previous test is so long. Could we create a new branch > instead? Makes sense, done. Patrick