fetch: lift up parsing of "fetch.output" config variable

Parsing the display format happens inside of `display_state_init()`. As we only need to check for a simple config entry, this is a natural location to put this code as it means that display-state logic is neatly contained in a single location. We're about to introduce a new "porcelain" output format though that is intended to be parseable by machines, for example inside of a script. This format can be enabled by passing the `--porcelain` switch to git-fetch(1). As a consequence, we'll have to add a second callsite that influences the output format, which will become awkward to handle. Refactor the code such that callers are expected to pass the display format that is to be used into `display_state_init()`. This allows us to lift up the code into the main function, where we can then hook it into command line options parser in a follow-up commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed May 10, 2023 at 14:34 UTC 58afbe885c678c5cc6f6f83badca159871fc2cb3
1 file changed +32 -18
builtin/fetch.c
+32 -18
@@ -106,8 +106,14 @@ static int fetch_write_commit_graph = -1;
106 static int stdin_refspecs = 0;
107 static int negotiate_only;
108
109 +struct fetch_config {
110 + enum display_format display_format;
111 +};
112 +
113 static int git_fetch_config(const char *k, const char *v, void *cb)
114 {
115 + struct fetch_config *fetch_config = cb;
116 +
117 if (!strcmp(k, "fetch.prune")) {
118 fetch_prune_config = git_config_bool(k, v);
119 return 0;
@@ -146,6 +152,18 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
152 return 0;
153 }
154
155 + if (!strcmp(k, "fetch.output")) {
156 + if (!v)
157 + return config_error_nonbool(k);
158 + else if (!strcasecmp(v, "full"))
159 + fetch_config->display_format = DISPLAY_FORMAT_FULL;
160 + else if (!strcasecmp(v, "compact"))
161 + fetch_config->display_format = DISPLAY_FORMAT_COMPACT;
162 + else
163 + die(_("invalid value for '%s': '%s'"),
164 + "fetch.output", v);
165 + }
166 +
167 return git_default_config(k, v, cb);
168 }
169
@@ -802,14 +820,13 @@ static int refcol_width(const struct ref *ref_map, int compact_format)
820 }
821
822 static void display_state_init(struct display_state *display_state, struct ref *ref_map,
805 - const char *raw_url)
823 + const char *raw_url, enum display_format format)
824 {
807 - const char *format = "full";
825 int i;
826
827 memset(display_state, 0, sizeof(*display_state));
811 -
828 strbuf_init(&display_state->buf, 0);
829 + display_state->format = format;
830
831 if (raw_url)
832 display_state->url = transport_anonymize_url(raw_url);
@@ -826,15 +843,6 @@ static void display_state_init(struct display_state *display_state, struct ref *
843 if (verbosity < 0)
844 return;
845
829 - git_config_get_string_tmp("fetch.output", &format);
830 - if (!strcasecmp(format, "full"))
831 - display_state->format = DISPLAY_FORMAT_FULL;
832 - else if (!strcasecmp(format, "compact"))
833 - display_state->format = DISPLAY_FORMAT_COMPACT;
834 - else
835 - die(_("invalid value for '%s': '%s'"),
836 - "fetch.output", format);
837 -
846 switch (display_state->format) {
847 case DISPLAY_FORMAT_FULL:
848 case DISPLAY_FORMAT_COMPACT:
@@ -1608,7 +1616,8 @@ static int backfill_tags(struct display_state *display_state,
1616 }
1617
1618 static int do_fetch(struct transport *transport,
1611 - struct refspec *rs)
1619 + struct refspec *rs,
1620 + enum display_format display_format)
1621 {
1622 struct ref_transaction *transaction = NULL;
1623 struct ref *ref_map = NULL;
@@ -1694,7 +1703,7 @@ static int do_fetch(struct transport *transport,
1703 if (retcode)
1704 goto cleanup;
1705
1697 - display_state_init(&display_state, ref_map, transport->url);
1706 + display_state_init(&display_state, ref_map, transport->url, display_format);
1707
1708 if (atomic_fetch) {
1709 transaction = ref_transaction_begin(&err);
@@ -2077,7 +2086,8 @@ static inline void fetch_one_setup_partial(struct remote *remote)
2086 }
2087
2088 static int fetch_one(struct remote *remote, int argc, const char **argv,
2080 - int prune_tags_ok, int use_stdin_refspecs)
2089 + int prune_tags_ok, int use_stdin_refspecs,
2090 + enum display_format display_format)
2091 {
2092 struct refspec rs = REFSPEC_INIT_FETCH;
2093 int i;
@@ -2144,7 +2154,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv,
2154 sigchain_push_common(unlock_pack_on_signal);
2155 atexit(unlock_pack_atexit);
2156 sigchain_push(SIGPIPE, SIG_IGN);
2147 - exit_code = do_fetch(gtransport, &rs);
2157 + exit_code = do_fetch(gtransport, &rs, display_format);
2158 sigchain_pop(SIGPIPE);
2159 refspec_clear(&rs);
2160 transport_disconnect(gtransport);
@@ -2154,6 +2164,9 @@ static int fetch_one(struct remote *remote, int argc, const char **argv,
2164
2165 int cmd_fetch(int argc, const char **argv, const char *prefix)
2166 {
2167 + struct fetch_config config = {
2168 + .display_format = DISPLAY_FORMAT_FULL,
2169 + };
2170 int i;
2171 const char *bundle_uri;
2172 struct string_list list = STRING_LIST_INIT_DUP;
@@ -2173,7 +2186,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
2186 free(anon);
2187 }
2188
2176 - git_config(git_fetch_config, NULL);
2189 + git_config(git_fetch_config, &config);
2190 if (the_repository->gitdir) {
2191 prepare_repo_settings(the_repository);
2192 the_repository->settings.command_requires_full_index = 0;
@@ -2310,7 +2323,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
2323 } else if (remote) {
2324 if (filter_options.choice || repo_has_promisor_remote(the_repository))
2325 fetch_one_setup_partial(remote);
2313 - result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs);
2326 + result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs,
2327 + config.display_format);
2328 } else {
2329 int max_children = max_jobs;
2330