Git fork

checkout-index: add parallel checkout support

Allow checkout-index to use the parallel checkout framework, honoring
the checkout.workers configuration.

There are two code paths in checkout-index which call
`checkout_entry()`, and thus, can make use of parallel checkout:
`checkout_file()`, which is used to write paths explicitly given at the
command line; and `checkout_all()`, which is used to write all paths in
the index, when the `--all` option is given.

In both operation modes, checkout-index doesn't abort immediately on a
`checkout_entry()` failure. Instead, it tries to check out all remaining
paths before exiting with a non-zero exit code. To keep this behavior
when parallel checkout is being used, we must allow
`run_parallel_checkout()` to try writing the queued entries before we
exit, even if we already got an error code from a previous
`checkout_entry()` call.

However, `checkout_all()` doesn't return on errors, it calls `exit()`
with code 128. We could make it call `run_parallel_checkout()` before
exiting, but it makes the code easier to follow if we unify the exit
path for both checkout-index modes at `cmd_checkout_index()`, and let
this function take care of the interactions with the parallel checkout
API. So let's do that.

With this change, we also have to consider whether we want to keep using
128 as the error code for `git checkout-index --all`, while we use 1 for
`git checkout-index <path>` (even when the actual error is the same).
Since there is not much value in having code 128 only for `--all`, and
there is no mention about it in the docs (so it's unlikely that changing
it will break any existing script), let's make both modes exit with code
1 on `checkout_entry()` errors.

Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Matheus Tavares and committed by
Junio C Hamano
70b052b2 60539506

+15 -9
+15 -9
builtin/checkout-index.c
··· 12 12 #include "cache-tree.h" 13 13 #include "parse-options.h" 14 14 #include "entry.h" 15 + #include "parallel-checkout.h" 15 16 16 17 #define CHECKOUT_ALL 4 17 18 static int nul_term_line; ··· 115 116 return -1; 116 117 } 117 118 118 - static void checkout_all(const char *prefix, int prefix_length) 119 + static int checkout_all(const char *prefix, int prefix_length) 119 120 { 120 121 int i, errs = 0; 121 122 struct cache_entry *last_ce = NULL; ··· 142 143 } 143 144 if (last_ce && to_tempfile) 144 145 write_tempfile_record(last_ce->name, prefix); 145 - if (errs) 146 - /* we have already done our error reporting. 147 - * exit with the same code as die(). 148 - */ 149 - exit(128); 146 + return !!errs; 150 147 } 151 148 152 149 static const char * const builtin_checkout_index_usage[] = { ··· 182 179 int force = 0, quiet = 0, not_new = 0; 183 180 int index_opt = 0; 184 181 int err = 0; 182 + int pc_workers, pc_threshold; 185 183 struct option builtin_checkout_index_options[] = { 186 184 OPT_BOOL('a', "all", &all, 187 185 N_("check out all files in the index")), ··· 236 234 hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); 237 235 } 238 236 237 + get_parallel_checkout_configs(&pc_workers, &pc_threshold); 238 + if (pc_workers > 1) 239 + init_parallel_checkout(); 240 + 239 241 /* Check out named files first */ 240 242 for (i = 0; i < argc; i++) { 241 243 const char *arg = argv[i]; ··· 275 277 strbuf_release(&buf); 276 278 } 277 279 280 + if (all) 281 + err |= checkout_all(prefix, prefix_length); 282 + 283 + if (pc_workers > 1) 284 + err |= run_parallel_checkout(&state, pc_workers, pc_threshold, 285 + NULL, NULL); 286 + 278 287 if (err) 279 288 return 1; 280 - 281 - if (all) 282 - checkout_all(prefix, prefix_length); 283 289 284 290 if (is_lock_file_locked(&lock_file) && 285 291 write_locked_index(&the_index, &lock_file, COMMIT_LOCK))