convert: display progress for filtered objects that have been delayed

In 2841e8f ("convert: add "status=delayed" to filter process protocol", 2017-06-30) we taught the filter process protocol to delayed responses. These responses are processed after the "Checking out files" phase. If the processing takes noticeable time, then the user might think Git is stuck. Display the progress of the delayed responses to let the user know that Git is still processing objects. This works very well for objects that can be filtered quickly. If filtering of an individual object takes noticeable time, then the user might still think that Git is stuck. However, in that case the user would at least know what Git is doing. It would be technical more correct to display "Checking out files whose content filtering has been delayed". For brevity we only print "Filtering content". The finish_delayed_checkout() call was moved below the stop_progress() call in unpack-trees.c to ensure that the "Checking out files" progress is properly stopped before the "Filtering content" progress starts in finish_delayed_checkout(). Signed-off-by: Lars Schneider <larsxschneider@gmail.com> Suggested-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Lars Schneider committed Aug 20, 2017 at 17:47 UTC 52f1d62eb44faf569edca360ec9af9ddd4045fe0
2 files changed +16 -2
entry.c
+15 -1
@@ -3,6 +3,7 @@
3 #include "dir.h"
4 #include "streaming.h"
5 #include "submodule.h"
6 +#include "progress.h"
7
8 static void create_directories(const char *path, int path_len,
9 const struct checkout *state)
@@ -161,16 +162,23 @@ static int remove_available_paths(struct string_list_item *item, void *cb_data)
162 int finish_delayed_checkout(struct checkout *state)
163 {
164 int errs = 0;
165 + unsigned delayed_object_count;
166 + off_t filtered_bytes = 0;
167 struct string_list_item *filter, *path;
168 + struct progress *progress;
169 struct delayed_checkout *dco = state->delayed_checkout;
170
171 if (!state->delayed_checkout)
172 return errs;
173
174 dco->state = CE_RETRY;
175 + delayed_object_count = dco->paths.nr;
176 + progress = start_progress_delay(
177 + _("Filtering content"), delayed_object_count, 50, 1);
178 while (dco->filters.nr > 0) {
179 for_each_string_list_item(filter, &dco->filters) {
180 struct string_list available_paths = STRING_LIST_INIT_NODUP;
181 + display_progress(progress, delayed_object_count - dco->paths.nr);
182
183 if (!async_query_available_blobs(filter->string, &available_paths)) {
184 /* Filter reported an error */
@@ -216,11 +224,17 @@ int finish_delayed_checkout(struct checkout *state)
224 }
225 ce = index_file_exists(state->istate, path->string,
226 strlen(path->string), 0);
219 - errs |= (ce ? checkout_entry(ce, state, NULL) : 1);
227 + if (ce) {
228 + errs |= checkout_entry(ce, state, NULL);
229 + filtered_bytes += ce->ce_stat_data.sd_size;
230 + display_throughput(progress, filtered_bytes);
231 + } else
232 + errs = 1;
233 }
234 }
235 string_list_remove_empty_items(&dco->filters, 0);
236 }
237 + stop_progress(&progress);
238 string_list_clear(&dco->filters, 0);
239
240 /* At this point we should not have any delayed paths anymore. */
unpack-trees.c
+1 -1
@@ -394,8 +394,8 @@ static int check_updates(struct unpack_trees_options *o)
394 }
395 }
396 }
397 - errs |= finish_delayed_checkout(&state);
397 stop_progress(&progress);
398 + errs |= finish_delayed_checkout(&state);
399 if (o->update)
400 git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
401 return errs != 0;