1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-05 07:06:34 +02:00

Merge branch 'rs/no-more-run-command-v'

Simplify the run-command API.

* rs/no-more-run-command-v:
  replace and remove run_command_v_opt()
  replace and remove run_command_v_opt_cd_env_tr2()
  replace and remove run_command_v_opt_tr2()
  replace and remove run_command_v_opt_cd_env()
  use child_process members "args" and "env" directly
  use child_process member "args" instead of string array variable
  sequencer: simplify building argument list in do_exec()
  bisect--helper: factor out do_bisect_run()
  bisect: simplify building "checkout" argument list
  am: simplify building "show" argument list
  run-command: fix return value comment
  merge: remove always-the-same "verbose" arguments
This commit is contained in:
Taylor Blau 2022-11-08 17:15:12 -05:00
commit be4ac3b197
27 changed files with 344 additions and 381 deletions

View File

@ -997,18 +997,17 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,
count = list_and_choose(s, files, opts); count = list_and_choose(s, files, opts);
opts->flags = 0; opts->flags = 0;
if (count > 0) { if (count > 0) {
struct strvec args = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
strvec_pushl(&args, "git", "diff", "-p", "--cached", strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached",
oid_to_hex(!is_initial ? &oid : oid_to_hex(!is_initial ? &oid :
s->r->hash_algo->empty_tree), s->r->hash_algo->empty_tree),
"--", NULL); "--", NULL);
for (i = 0; i < files->items.nr; i++) for (i = 0; i < files->items.nr; i++)
if (files->selected[i]) if (files->selected[i])
strvec_push(&args, strvec_push(&cmd.args,
files->items.items[i].string); files->items.items[i].string);
res = run_command_v_opt(args.v, 0); res = run_command(&cmd);
strvec_clear(&args);
} }
putchar('\n'); putchar('\n');

View File

@ -22,8 +22,6 @@ static struct oid_array skipped_revs;
static struct object_id *current_bad_oid; static struct object_id *current_bad_oid;
static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
static const char *term_bad; static const char *term_bad;
static const char *term_good; static const char *term_good;
@ -729,20 +727,22 @@ static int is_expected_rev(const struct object_id *oid)
enum bisect_error bisect_checkout(const struct object_id *bisect_rev, enum bisect_error bisect_checkout(const struct object_id *bisect_rev,
int no_checkout) int no_checkout)
{ {
char bisect_rev_hex[GIT_MAX_HEXSZ + 1];
struct commit *commit; struct commit *commit;
struct pretty_print_context pp = {0}; struct pretty_print_context pp = {0};
struct strbuf commit_msg = STRBUF_INIT; struct strbuf commit_msg = STRBUF_INIT;
oid_to_hex_r(bisect_rev_hex, bisect_rev);
update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR); update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
argv_checkout[2] = bisect_rev_hex;
if (no_checkout) { if (no_checkout) {
update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0, update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0,
UPDATE_REFS_DIE_ON_ERR); UPDATE_REFS_DIE_ON_ERR);
} else { } else {
if (run_command_v_opt(argv_checkout, RUN_GIT_CMD)) struct child_process cmd = CHILD_PROCESS_INIT;
cmd.git_cmd = 1;
strvec_pushl(&cmd.args, "checkout", "-q",
oid_to_hex(bisect_rev), "--", NULL);
if (run_command(&cmd))
/* /*
* Errors in `run_command()` itself, signaled by res < 0, * Errors in `run_command()` itself, signaled by res < 0,
* and errors in the child process, signaled by res > 0 * and errors in the child process, signaled by res > 0

View File

@ -240,8 +240,8 @@ static int refresh(int verbose, const struct pathspec *pathspec)
int run_add_interactive(const char *revision, const char *patch_mode, int run_add_interactive(const char *revision, const char *patch_mode,
const struct pathspec *pathspec) const struct pathspec *pathspec)
{ {
int status, i; int i;
struct strvec argv = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
int use_builtin_add_i = int use_builtin_add_i =
git_env_bool("GIT_TEST_ADD_I_USE_BUILTIN", -1); git_env_bool("GIT_TEST_ADD_I_USE_BUILTIN", -1);
@ -272,19 +272,18 @@ int run_add_interactive(const char *revision, const char *patch_mode,
return !!run_add_p(the_repository, mode, revision, pathspec); return !!run_add_p(the_repository, mode, revision, pathspec);
} }
strvec_push(&argv, "add--interactive"); strvec_push(&cmd.args, "add--interactive");
if (patch_mode) if (patch_mode)
strvec_push(&argv, patch_mode); strvec_push(&cmd.args, patch_mode);
if (revision) if (revision)
strvec_push(&argv, revision); strvec_push(&cmd.args, revision);
strvec_push(&argv, "--"); strvec_push(&cmd.args, "--");
for (i = 0; i < pathspec->nr; i++) for (i = 0; i < pathspec->nr; i++)
/* pass original pathspec, to be re-parsed */ /* pass original pathspec, to be re-parsed */
strvec_push(&argv, pathspec->items[i].original); strvec_push(&cmd.args, pathspec->items[i].original);
status = run_command_v_opt(argv.v, RUN_GIT_CMD); cmd.git_cmd = 1;
strvec_clear(&argv); return run_command(&cmd);
return status;
} }
int interactive_add(const char **argv, const char *prefix, int patch) int interactive_add(const char **argv, const char *prefix, int patch)

View File

@ -2187,14 +2187,12 @@ static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
int len; int len;
if (!is_null_oid(&state->orig_commit)) { if (!is_null_oid(&state->orig_commit)) {
const char *av[4] = { "show", NULL, "--", NULL }; struct child_process cmd = CHILD_PROCESS_INIT;
char *new_oid_str;
int ret;
av[1] = new_oid_str = xstrdup(oid_to_hex(&state->orig_commit)); strvec_pushl(&cmd.args, "show", oid_to_hex(&state->orig_commit),
ret = run_command_v_opt(av, RUN_GIT_CMD); "--", NULL);
free(new_oid_str); cmd.git_cmd = 1;
return ret; return run_command(&cmd);
} }
switch (sub_mode) { switch (sub_mode) {

View File

@ -220,18 +220,17 @@ static int bisect_reset(const char *commit)
} }
if (!ref_exists("BISECT_HEAD")) { if (!ref_exists("BISECT_HEAD")) {
struct strvec argv = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
strvec_pushl(&argv, "checkout", branch.buf, "--", NULL); cmd.git_cmd = 1;
if (run_command_v_opt(argv.v, RUN_GIT_CMD)) { strvec_pushl(&cmd.args, "checkout", branch.buf, "--", NULL);
if (run_command(&cmd)) {
error(_("could not check out original" error(_("could not check out original"
" HEAD '%s'. Try 'git bisect" " HEAD '%s'. Try 'git bisect"
" reset <commit>'."), branch.buf); " reset <commit>'."), branch.buf);
strbuf_release(&branch); strbuf_release(&branch);
strvec_clear(&argv);
return -1; return -1;
} }
strvec_clear(&argv);
} }
strbuf_release(&branch); strbuf_release(&branch);
@ -765,10 +764,12 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, const char **a
strbuf_read_file(&start_head, git_path_bisect_start(), 0); strbuf_read_file(&start_head, git_path_bisect_start(), 0);
strbuf_trim(&start_head); strbuf_trim(&start_head);
if (!no_checkout) { if (!no_checkout) {
const char *argv[] = { "checkout", start_head.buf, struct child_process cmd = CHILD_PROCESS_INIT;
"--", NULL };
if (run_command_v_opt(argv, RUN_GIT_CMD)) { cmd.git_cmd = 1;
strvec_pushl(&cmd.args, "checkout", start_head.buf,
"--", NULL);
if (run_command(&cmd)) {
res = error(_("checking out '%s' failed." res = error(_("checking out '%s' failed."
" Try 'git bisect start " " Try 'git bisect start "
"<valid-branch>'."), "<valid-branch>'."),
@ -1098,40 +1099,38 @@ static enum bisect_error bisect_skip(struct bisect_terms *terms, const char **ar
static int bisect_visualize(struct bisect_terms *terms, const char **argv, int argc) static int bisect_visualize(struct bisect_terms *terms, const char **argv, int argc)
{ {
struct strvec args = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
int flags = RUN_COMMAND_NO_STDIN, res = 0;
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
if (bisect_next_check(terms, NULL) != 0) if (bisect_next_check(terms, NULL) != 0)
return BISECT_FAILED; return BISECT_FAILED;
cmd.no_stdin = 1;
if (!argc) { if (!argc) {
if ((getenv("DISPLAY") || getenv("SESSIONNAME") || getenv("MSYSTEM") || if ((getenv("DISPLAY") || getenv("SESSIONNAME") || getenv("MSYSTEM") ||
getenv("SECURITYSESSIONID")) && exists_in_PATH("gitk")) { getenv("SECURITYSESSIONID")) && exists_in_PATH("gitk")) {
strvec_push(&args, "gitk"); strvec_push(&cmd.args, "gitk");
} else { } else {
strvec_push(&args, "log"); strvec_push(&cmd.args, "log");
flags |= RUN_GIT_CMD; cmd.git_cmd = 1;
} }
} else { } else {
if (argv[0][0] == '-') { if (argv[0][0] == '-') {
strvec_push(&args, "log"); strvec_push(&cmd.args, "log");
flags |= RUN_GIT_CMD; cmd.git_cmd = 1;
} else if (strcmp(argv[0], "tig") && !starts_with(argv[0], "git")) } else if (strcmp(argv[0], "tig") && !starts_with(argv[0], "git"))
flags |= RUN_GIT_CMD; cmd.git_cmd = 1;
strvec_pushv(&args, argv); strvec_pushv(&cmd.args, argv);
} }
strvec_pushl(&args, "--bisect", "--", NULL); strvec_pushl(&cmd.args, "--bisect", "--", NULL);
strbuf_read_file(&sb, git_path_bisect_names(), 0); strbuf_read_file(&sb, git_path_bisect_names(), 0);
sq_dequote_to_strvec(sb.buf, &args); sq_dequote_to_strvec(sb.buf, &cmd.args);
strbuf_release(&sb); strbuf_release(&sb);
res = run_command_v_opt(args.v, flags); return run_command(&cmd);
strvec_clear(&args);
return res;
} }
static int get_first_good(const char *refname UNUSED, static int get_first_good(const char *refname UNUSED,
@ -1142,8 +1141,17 @@ static int get_first_good(const char *refname UNUSED,
return 1; return 1;
} }
static int verify_good(const struct bisect_terms *terms, static int do_bisect_run(const char *command)
const char **quoted_argv) {
struct child_process cmd = CHILD_PROCESS_INIT;
printf(_("running %s\n"), command);
cmd.use_shell = 1;
strvec_push(&cmd.args, command);
return run_command(&cmd);
}
static int verify_good(const struct bisect_terms *terms, const char *command)
{ {
int rc; int rc;
enum bisect_error res; enum bisect_error res;
@ -1163,8 +1171,7 @@ static int verify_good(const struct bisect_terms *terms,
if (res != BISECT_OK) if (res != BISECT_OK)
return -1; return -1;
printf(_("running %s\n"), quoted_argv[0]); rc = do_bisect_run(command);
rc = run_command_v_opt(quoted_argv, RUN_USING_SHELL);
res = bisect_checkout(&current_rev, no_checkout); res = bisect_checkout(&current_rev, no_checkout);
if (res != BISECT_OK) if (res != BISECT_OK)
@ -1177,7 +1184,6 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
{ {
int res = BISECT_OK; int res = BISECT_OK;
struct strbuf command = STRBUF_INIT; struct strbuf command = STRBUF_INIT;
struct strvec run_args = STRVEC_INIT;
const char *new_state; const char *new_state;
int temporary_stdout_fd, saved_stdout; int temporary_stdout_fd, saved_stdout;
int is_first_run = 1; int is_first_run = 1;
@ -1192,11 +1198,8 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
return BISECT_FAILED; return BISECT_FAILED;
} }
strvec_push(&run_args, command.buf);
while (1) { while (1) {
printf(_("running %s\n"), command.buf); res = do_bisect_run(command.buf);
res = run_command_v_opt(run_args.v, RUN_USING_SHELL);
/* /*
* Exit code 126 and 127 can either come from the shell * Exit code 126 and 127 can either come from the shell
@ -1206,7 +1209,7 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
* missing or non-executable script. * missing or non-executable script.
*/ */
if (is_first_run && (res == 126 || res == 127)) { if (is_first_run && (res == 126 || res == 127)) {
int rc = verify_good(terms, run_args.v); int rc = verify_good(terms, command.buf);
is_first_run = 0; is_first_run = 0;
if (rc < 0) { if (rc < 0) {
error(_("unable to verify '%s' on good" error(_("unable to verify '%s' on good"
@ -1273,7 +1276,6 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
} }
strbuf_release(&command); strbuf_release(&command);
strvec_clear(&run_args);
return res; return res;
} }

View File

@ -653,9 +653,9 @@ static void update_head(const struct ref *our, const struct ref *remote,
static int git_sparse_checkout_init(const char *repo) static int git_sparse_checkout_init(const char *repo)
{ {
struct strvec argv = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
int result = 0; int result = 0;
strvec_pushl(&argv, "-C", repo, "sparse-checkout", "set", NULL); strvec_pushl(&cmd.args, "-C", repo, "sparse-checkout", "set", NULL);
/* /*
* We must apply the setting in the current process * We must apply the setting in the current process
@ -663,12 +663,12 @@ static int git_sparse_checkout_init(const char *repo)
*/ */
core_apply_sparse_checkout = 1; core_apply_sparse_checkout = 1;
if (run_command_v_opt(argv.v, RUN_GIT_CMD)) { cmd.git_cmd = 1;
if (run_command(&cmd)) {
error(_("failed to initialize sparse-checkout")); error(_("failed to initialize sparse-checkout"));
result = 1; result = 1;
} }
strvec_clear(&argv);
return result; return result;
} }
@ -733,37 +733,38 @@ static int checkout(int submodule_progress, int filter_submodules)
oid_to_hex(&oid), "1", NULL); oid_to_hex(&oid), "1", NULL);
if (!err && (option_recurse_submodules.nr > 0)) { if (!err && (option_recurse_submodules.nr > 0)) {
struct strvec args = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
strvec_pushl(&args, "submodule", "update", "--require-init", "--recursive", NULL); strvec_pushl(&cmd.args, "submodule", "update", "--require-init",
"--recursive", NULL);
if (option_shallow_submodules == 1) if (option_shallow_submodules == 1)
strvec_push(&args, "--depth=1"); strvec_push(&cmd.args, "--depth=1");
if (max_jobs != -1) if (max_jobs != -1)
strvec_pushf(&args, "--jobs=%d", max_jobs); strvec_pushf(&cmd.args, "--jobs=%d", max_jobs);
if (submodule_progress) if (submodule_progress)
strvec_push(&args, "--progress"); strvec_push(&cmd.args, "--progress");
if (option_verbosity < 0) if (option_verbosity < 0)
strvec_push(&args, "--quiet"); strvec_push(&cmd.args, "--quiet");
if (option_remote_submodules) { if (option_remote_submodules) {
strvec_push(&args, "--remote"); strvec_push(&cmd.args, "--remote");
strvec_push(&args, "--no-fetch"); strvec_push(&cmd.args, "--no-fetch");
} }
if (filter_submodules && filter_options.choice) if (filter_submodules && filter_options.choice)
strvec_pushf(&args, "--filter=%s", strvec_pushf(&cmd.args, "--filter=%s",
expand_list_objects_filter_spec(&filter_options)); expand_list_objects_filter_spec(&filter_options));
if (option_single_branch >= 0) if (option_single_branch >= 0)
strvec_push(&args, option_single_branch ? strvec_push(&cmd.args, option_single_branch ?
"--single-branch" : "--single-branch" :
"--no-single-branch"); "--no-single-branch");
err = run_command_v_opt(args.v, RUN_GIT_CMD); cmd.git_cmd = 1;
strvec_clear(&args); err = run_command(&cmd);
} }
return err; return err;
@ -864,11 +865,15 @@ static void write_refspec_config(const char *src_ref_prefix,
static void dissociate_from_references(void) static void dissociate_from_references(void)
{ {
static const char* argv[] = { "repack", "-a", "-d", NULL };
char *alternates = git_pathdup("objects/info/alternates"); char *alternates = git_pathdup("objects/info/alternates");
if (!access(alternates, F_OK)) { if (!access(alternates, F_OK)) {
if (run_command_v_opt(argv, RUN_GIT_CMD|RUN_COMMAND_NO_STDIN)) struct child_process cmd = CHILD_PROCESS_INIT;
cmd.git_cmd = 1;
cmd.no_stdin = 1;
strvec_pushl(&cmd.args, "repack", "-a", "-d", NULL);
if (run_command(&cmd))
die(_("cannot repack to clean up")); die(_("cannot repack to clean up"));
if (unlink(alternates) && errno != ENOENT) if (unlink(alternates) && errno != ENOENT)
die_errno(_("cannot unlink temporary alternates file")); die_errno(_("cannot unlink temporary alternates file"));

View File

@ -44,8 +44,11 @@ static int difftool_config(const char *var, const char *value, void *cb)
static int print_tool_help(void) static int print_tool_help(void)
{ {
const char *argv[] = { "mergetool", "--tool-help=diff", NULL }; struct child_process cmd = CHILD_PROCESS_INIT;
return run_command_v_opt(argv, RUN_GIT_CMD);
cmd.git_cmd = 1;
strvec_pushl(&cmd.args, "mergetool", "--tool-help=diff", NULL);
return run_command(&cmd);
} }
static int parse_index_info(char *p, int *mode1, int *mode2, static int parse_index_info(char *p, int *mode1, int *mode2,
@ -360,8 +363,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
struct pair_entry *entry; struct pair_entry *entry;
struct index_state wtindex; struct index_state wtindex;
struct checkout lstate, rstate; struct checkout lstate, rstate;
int flags = RUN_GIT_CMD, err = 0; int err = 0;
const char *helper_argv[] = { "difftool--helper", NULL, NULL, NULL }; struct child_process cmd = CHILD_PROCESS_INIT;
struct hashmap wt_modified, tmp_modified; struct hashmap wt_modified, tmp_modified;
int indices_loaded = 0; int indices_loaded = 0;
@ -563,16 +566,17 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
} }
strbuf_setlen(&ldir, ldir_len); strbuf_setlen(&ldir, ldir_len);
helper_argv[1] = ldir.buf;
strbuf_setlen(&rdir, rdir_len); strbuf_setlen(&rdir, rdir_len);
helper_argv[2] = rdir.buf;
if (extcmd) { if (extcmd) {
helper_argv[0] = extcmd; strvec_push(&cmd.args, extcmd);
flags = 0; } else {
} else strvec_push(&cmd.args, "difftool--helper");
cmd.git_cmd = 1;
setenv("GIT_DIFFTOOL_DIRDIFF", "true", 1); setenv("GIT_DIFFTOOL_DIRDIFF", "true", 1);
ret = run_command_v_opt(helper_argv, flags); }
strvec_pushl(&cmd.args, ldir.buf, rdir.buf, NULL);
ret = run_command(&cmd);
/* TODO: audit for interaction with sparse-index. */ /* TODO: audit for interaction with sparse-index. */
ensure_full_index(&wtindex); ensure_full_index(&wtindex);

View File

@ -1972,14 +1972,17 @@ static int fetch_multiple(struct string_list *list, int max_children)
} else } else
for (i = 0; i < list->nr; i++) { for (i = 0; i < list->nr; i++) {
const char *name = list->items[i].string; const char *name = list->items[i].string;
strvec_push(&argv, name); struct child_process cmd = CHILD_PROCESS_INIT;
strvec_pushv(&cmd.args, argv.v);
strvec_push(&cmd.args, name);
if (verbosity >= 0) if (verbosity >= 0)
printf(_("Fetching %s\n"), name); printf(_("Fetching %s\n"), name);
if (run_command_v_opt(argv.v, RUN_GIT_CMD)) { cmd.git_cmd = 1;
if (run_command(&cmd)) {
error(_("could not fetch %s"), name); error(_("could not fetch %s"), name);
result = 1; result = 1;
} }
strvec_pop(&argv);
} }
strvec_clear(&argv); strvec_clear(&argv);

View File

@ -167,9 +167,11 @@ static void gc_config(void)
struct maintenance_run_opts; struct maintenance_run_opts;
static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *opts) static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *opts)
{ {
const char *argv[] = { "pack-refs", "--all", "--prune", NULL }; struct child_process cmd = CHILD_PROCESS_INIT;
return run_command_v_opt(argv, RUN_GIT_CMD); cmd.git_cmd = 1;
strvec_pushl(&cmd.args, "pack-refs", "--all", "--prune", NULL);
return run_command(&cmd);
} }
static int too_many_loose_objects(void) static int too_many_loose_objects(void)
@ -535,8 +537,14 @@ static void gc_before_repack(void)
if (pack_refs && maintenance_task_pack_refs(NULL)) if (pack_refs && maintenance_task_pack_refs(NULL))
die(FAILED_RUN, "pack-refs"); die(FAILED_RUN, "pack-refs");
if (prune_reflogs && run_command_v_opt(reflog.v, RUN_GIT_CMD)) if (prune_reflogs) {
die(FAILED_RUN, reflog.v[0]); struct child_process cmd = CHILD_PROCESS_INIT;
cmd.git_cmd = 1;
strvec_pushv(&cmd.args, reflog.v);
if (run_command(&cmd))
die(FAILED_RUN, reflog.v[0]);
}
} }
int cmd_gc(int argc, const char **argv, const char *prefix) int cmd_gc(int argc, const char **argv, const char *prefix)
@ -550,6 +558,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
int daemonized = 0; int daemonized = 0;
int keep_largest_pack = -1; int keep_largest_pack = -1;
timestamp_t dummy; timestamp_t dummy;
struct child_process rerere_cmd = CHILD_PROCESS_INIT;
struct option builtin_gc_options[] = { struct option builtin_gc_options[] = {
OPT__QUIET(&quiet, N_("suppress progress reporting")), OPT__QUIET(&quiet, N_("suppress progress reporting")),
@ -675,11 +684,17 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
gc_before_repack(); gc_before_repack();
if (!repository_format_precious_objects) { if (!repository_format_precious_objects) {
if (run_command_v_opt(repack.v, struct child_process repack_cmd = CHILD_PROCESS_INIT;
RUN_GIT_CMD | RUN_CLOSE_OBJECT_STORE))
repack_cmd.git_cmd = 1;
repack_cmd.close_object_store = 1;
strvec_pushv(&repack_cmd.args, repack.v);
if (run_command(&repack_cmd))
die(FAILED_RUN, repack.v[0]); die(FAILED_RUN, repack.v[0]);
if (prune_expire) { if (prune_expire) {
struct child_process prune_cmd = CHILD_PROCESS_INIT;
/* run `git prune` even if using cruft packs */ /* run `git prune` even if using cruft packs */
strvec_push(&prune, prune_expire); strvec_push(&prune, prune_expire);
if (quiet) if (quiet)
@ -687,18 +702,26 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
if (has_promisor_remote()) if (has_promisor_remote())
strvec_push(&prune, strvec_push(&prune,
"--exclude-promisor-objects"); "--exclude-promisor-objects");
if (run_command_v_opt(prune.v, RUN_GIT_CMD)) prune_cmd.git_cmd = 1;
strvec_pushv(&prune_cmd.args, prune.v);
if (run_command(&prune_cmd))
die(FAILED_RUN, prune.v[0]); die(FAILED_RUN, prune.v[0]);
} }
} }
if (prune_worktrees_expire) { if (prune_worktrees_expire) {
struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT;
strvec_push(&prune_worktrees, prune_worktrees_expire); strvec_push(&prune_worktrees, prune_worktrees_expire);
if (run_command_v_opt(prune_worktrees.v, RUN_GIT_CMD)) prune_worktrees_cmd.git_cmd = 1;
strvec_pushv(&prune_worktrees_cmd.args, prune_worktrees.v);
if (run_command(&prune_worktrees_cmd))
die(FAILED_RUN, prune_worktrees.v[0]); die(FAILED_RUN, prune_worktrees.v[0]);
} }
if (run_command_v_opt(rerere.v, RUN_GIT_CMD)) rerere_cmd.git_cmd = 1;
strvec_pushv(&rerere_cmd.args, rerere.v);
if (run_command(&rerere_cmd))
die(FAILED_RUN, rerere.v[0]); die(FAILED_RUN, rerere.v[0]);
report_garbage = report_pack_garbage; report_garbage = report_pack_garbage;
@ -1913,20 +1936,16 @@ static char *schtasks_task_name(const char *frequency)
static int schtasks_remove_task(enum schedule_priority schedule) static int schtasks_remove_task(enum schedule_priority schedule)
{ {
const char *cmd = "schtasks"; const char *cmd = "schtasks";
int result; struct child_process child = CHILD_PROCESS_INIT;
struct strvec args = STRVEC_INIT;
const char *frequency = get_frequency(schedule); const char *frequency = get_frequency(schedule);
char *name = schtasks_task_name(frequency); char *name = schtasks_task_name(frequency);
get_schedule_cmd(&cmd, NULL); get_schedule_cmd(&cmd, NULL);
strvec_split(&args, cmd); strvec_split(&child.args, cmd);
strvec_pushl(&args, "/delete", "/tn", name, "/f", NULL); strvec_pushl(&child.args, "/delete", "/tn", name, "/f", NULL);
result = run_command_v_opt(args.v, 0);
strvec_clear(&args);
free(name); free(name);
return result;
return run_command(&child);
} }
static int schtasks_remove_tasks(void) static int schtasks_remove_tasks(void)

View File

@ -12,6 +12,7 @@ static int merge_entry(int pos, const char *path)
const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL }; const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
char hexbuf[4][GIT_MAX_HEXSZ + 1]; char hexbuf[4][GIT_MAX_HEXSZ + 1];
char ownbuf[4][60]; char ownbuf[4][60];
struct child_process cmd = CHILD_PROCESS_INIT;
if (pos >= active_nr) if (pos >= active_nr)
die("git merge-index: %s not in the cache", path); die("git merge-index: %s not in the cache", path);
@ -31,7 +32,8 @@ static int merge_entry(int pos, const char *path)
if (!found) if (!found)
die("git merge-index: %s not in the cache", path); die("git merge-index: %s not in the cache", path);
if (run_command_v_opt(arguments, 0)) { strvec_pushv(&cmd.args, arguments);
if (run_command(&cmd)) {
if (one_shot) if (one_shot)
err++; err++;
else { else {

View File

@ -345,60 +345,49 @@ static int save_state(struct object_id *stash)
return rc; return rc;
} }
static void read_empty(const struct object_id *oid, int verbose) static void read_empty(const struct object_id *oid)
{ {
int i = 0; struct child_process cmd = CHILD_PROCESS_INIT;
const char *args[7];
args[i++] = "read-tree"; strvec_pushl(&cmd.args, "read-tree", "-m", "-u", empty_tree_oid_hex(),
if (verbose) oid_to_hex(oid), NULL);
args[i++] = "-v"; cmd.git_cmd = 1;
args[i++] = "-m";
args[i++] = "-u";
args[i++] = empty_tree_oid_hex();
args[i++] = oid_to_hex(oid);
args[i] = NULL;
if (run_command_v_opt(args, RUN_GIT_CMD)) if (run_command(&cmd))
die(_("read-tree failed")); die(_("read-tree failed"));
} }
static void reset_hard(const struct object_id *oid, int verbose) static void reset_hard(const struct object_id *oid)
{ {
int i = 0; struct child_process cmd = CHILD_PROCESS_INIT;
const char *args[6];
args[i++] = "read-tree"; strvec_pushl(&cmd.args, "read-tree", "-v", "--reset", "-u",
if (verbose) oid_to_hex(oid), NULL);
args[i++] = "-v"; cmd.git_cmd = 1;
args[i++] = "--reset";
args[i++] = "-u";
args[i++] = oid_to_hex(oid);
args[i] = NULL;
if (run_command_v_opt(args, RUN_GIT_CMD)) if (run_command(&cmd))
die(_("read-tree failed")); die(_("read-tree failed"));
} }
static void restore_state(const struct object_id *head, static void restore_state(const struct object_id *head,
const struct object_id *stash) const struct object_id *stash)
{ {
struct strvec args = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
reset_hard(head, 1); reset_hard(head);
if (is_null_oid(stash)) if (is_null_oid(stash))
goto refresh_cache; goto refresh_cache;
strvec_pushl(&args, "stash", "apply", "--index", "--quiet", NULL); strvec_pushl(&cmd.args, "stash", "apply", "--index", "--quiet", NULL);
strvec_push(&args, oid_to_hex(stash)); strvec_push(&cmd.args, oid_to_hex(stash));
/* /*
* It is OK to ignore error here, for example when there was * It is OK to ignore error here, for example when there was
* nothing to restore. * nothing to restore.
*/ */
run_command_v_opt(args.v, RUN_GIT_CMD); cmd.git_cmd = 1;
strvec_clear(&args); run_command(&cmd);
refresh_cache: refresh_cache:
if (discard_cache() < 0 || read_cache() < 0) if (discard_cache() < 0 || read_cache() < 0)
@ -1470,7 +1459,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
check_trust_level); check_trust_level);
remote_head_oid = &remoteheads->item->object.oid; remote_head_oid = &remoteheads->item->object.oid;
read_empty(remote_head_oid, 0); read_empty(remote_head_oid);
update_ref("initial pull", "HEAD", remote_head_oid, NULL, 0, update_ref("initial pull", "HEAD", remote_head_oid, NULL, 0,
UPDATE_REFS_DIE_ON_ERR); UPDATE_REFS_DIE_ON_ERR);
goto done; goto done;

View File

@ -515,76 +515,75 @@ static void parse_repo_refspecs(int argc, const char **argv, const char **repo,
*/ */
static int run_fetch(const char *repo, const char **refspecs) static int run_fetch(const char *repo, const char **refspecs)
{ {
struct strvec args = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
int ret;
strvec_pushl(&args, "fetch", "--update-head-ok", NULL); strvec_pushl(&cmd.args, "fetch", "--update-head-ok", NULL);
/* Shared options */ /* Shared options */
argv_push_verbosity(&args); argv_push_verbosity(&cmd.args);
if (opt_progress) if (opt_progress)
strvec_push(&args, opt_progress); strvec_push(&cmd.args, opt_progress);
/* Options passed to git-fetch */ /* Options passed to git-fetch */
if (opt_all) if (opt_all)
strvec_push(&args, opt_all); strvec_push(&cmd.args, opt_all);
if (opt_append) if (opt_append)
strvec_push(&args, opt_append); strvec_push(&cmd.args, opt_append);
if (opt_upload_pack) if (opt_upload_pack)
strvec_push(&args, opt_upload_pack); strvec_push(&cmd.args, opt_upload_pack);
argv_push_force(&args); argv_push_force(&cmd.args);
if (opt_tags) if (opt_tags)
strvec_push(&args, opt_tags); strvec_push(&cmd.args, opt_tags);
if (opt_prune) if (opt_prune)
strvec_push(&args, opt_prune); strvec_push(&cmd.args, opt_prune);
if (recurse_submodules_cli != RECURSE_SUBMODULES_DEFAULT) if (recurse_submodules_cli != RECURSE_SUBMODULES_DEFAULT)
switch (recurse_submodules_cli) { switch (recurse_submodules_cli) {
case RECURSE_SUBMODULES_ON: case RECURSE_SUBMODULES_ON:
strvec_push(&args, "--recurse-submodules=on"); strvec_push(&cmd.args, "--recurse-submodules=on");
break; break;
case RECURSE_SUBMODULES_OFF: case RECURSE_SUBMODULES_OFF:
strvec_push(&args, "--recurse-submodules=no"); strvec_push(&cmd.args, "--recurse-submodules=no");
break; break;
case RECURSE_SUBMODULES_ON_DEMAND: case RECURSE_SUBMODULES_ON_DEMAND:
strvec_push(&args, "--recurse-submodules=on-demand"); strvec_push(&cmd.args, "--recurse-submodules=on-demand");
break; break;
default: default:
BUG("submodule recursion option not understood"); BUG("submodule recursion option not understood");
} }
if (max_children) if (max_children)
strvec_push(&args, max_children); strvec_push(&cmd.args, max_children);
if (opt_dry_run) if (opt_dry_run)
strvec_push(&args, "--dry-run"); strvec_push(&cmd.args, "--dry-run");
if (opt_keep) if (opt_keep)
strvec_push(&args, opt_keep); strvec_push(&cmd.args, opt_keep);
if (opt_depth) if (opt_depth)
strvec_push(&args, opt_depth); strvec_push(&cmd.args, opt_depth);
if (opt_unshallow) if (opt_unshallow)
strvec_push(&args, opt_unshallow); strvec_push(&cmd.args, opt_unshallow);
if (opt_update_shallow) if (opt_update_shallow)
strvec_push(&args, opt_update_shallow); strvec_push(&cmd.args, opt_update_shallow);
if (opt_refmap) if (opt_refmap)
strvec_push(&args, opt_refmap); strvec_push(&cmd.args, opt_refmap);
if (opt_ipv4) if (opt_ipv4)
strvec_push(&args, opt_ipv4); strvec_push(&cmd.args, opt_ipv4);
if (opt_ipv6) if (opt_ipv6)
strvec_push(&args, opt_ipv6); strvec_push(&cmd.args, opt_ipv6);
if (opt_show_forced_updates > 0) if (opt_show_forced_updates > 0)
strvec_push(&args, "--show-forced-updates"); strvec_push(&cmd.args, "--show-forced-updates");
else if (opt_show_forced_updates == 0) else if (opt_show_forced_updates == 0)
strvec_push(&args, "--no-show-forced-updates"); strvec_push(&cmd.args, "--no-show-forced-updates");
if (set_upstream) if (set_upstream)
strvec_push(&args, set_upstream); strvec_push(&cmd.args, set_upstream);
strvec_pushv(&args, opt_fetch.v); strvec_pushv(&cmd.args, opt_fetch.v);
if (repo) { if (repo) {
strvec_push(&args, repo); strvec_push(&cmd.args, repo);
strvec_pushv(&args, refspecs); strvec_pushv(&cmd.args, refspecs);
} else if (*refspecs) } else if (*refspecs)
BUG("refspecs without repo?"); BUG("refspecs without repo?");
ret = run_command_v_opt(args.v, RUN_GIT_CMD | RUN_CLOSE_OBJECT_STORE); cmd.git_cmd = 1;
strvec_clear(&args); cmd.close_object_store = 1;
return ret; return run_command(&cmd);
} }
/** /**
@ -653,52 +652,50 @@ static int update_submodules(void)
*/ */
static int run_merge(void) static int run_merge(void)
{ {
int ret; struct child_process cmd = CHILD_PROCESS_INIT;
struct strvec args = STRVEC_INIT;
strvec_pushl(&args, "merge", NULL); strvec_pushl(&cmd.args, "merge", NULL);
/* Shared options */ /* Shared options */
argv_push_verbosity(&args); argv_push_verbosity(&cmd.args);
if (opt_progress) if (opt_progress)
strvec_push(&args, opt_progress); strvec_push(&cmd.args, opt_progress);
/* Options passed to git-merge */ /* Options passed to git-merge */
if (opt_diffstat) if (opt_diffstat)
strvec_push(&args, opt_diffstat); strvec_push(&cmd.args, opt_diffstat);
if (opt_log) if (opt_log)
strvec_push(&args, opt_log); strvec_push(&cmd.args, opt_log);
if (opt_signoff) if (opt_signoff)
strvec_push(&args, opt_signoff); strvec_push(&cmd.args, opt_signoff);
if (opt_squash) if (opt_squash)
strvec_push(&args, opt_squash); strvec_push(&cmd.args, opt_squash);
if (opt_commit) if (opt_commit)
strvec_push(&args, opt_commit); strvec_push(&cmd.args, opt_commit);
if (opt_edit) if (opt_edit)
strvec_push(&args, opt_edit); strvec_push(&cmd.args, opt_edit);
if (cleanup_arg) if (cleanup_arg)
strvec_pushf(&args, "--cleanup=%s", cleanup_arg); strvec_pushf(&cmd.args, "--cleanup=%s", cleanup_arg);
if (opt_ff) if (opt_ff)
strvec_push(&args, opt_ff); strvec_push(&cmd.args, opt_ff);
if (opt_verify) if (opt_verify)
strvec_push(&args, opt_verify); strvec_push(&cmd.args, opt_verify);
if (opt_verify_signatures) if (opt_verify_signatures)
strvec_push(&args, opt_verify_signatures); strvec_push(&cmd.args, opt_verify_signatures);
strvec_pushv(&args, opt_strategies.v); strvec_pushv(&cmd.args, opt_strategies.v);
strvec_pushv(&args, opt_strategy_opts.v); strvec_pushv(&cmd.args, opt_strategy_opts.v);
if (opt_gpg_sign) if (opt_gpg_sign)
strvec_push(&args, opt_gpg_sign); strvec_push(&cmd.args, opt_gpg_sign);
if (opt_autostash == 0) if (opt_autostash == 0)
strvec_push(&args, "--no-autostash"); strvec_push(&cmd.args, "--no-autostash");
else if (opt_autostash == 1) else if (opt_autostash == 1)
strvec_push(&args, "--autostash"); strvec_push(&cmd.args, "--autostash");
if (opt_allow_unrelated_histories > 0) if (opt_allow_unrelated_histories > 0)
strvec_push(&args, "--allow-unrelated-histories"); strvec_push(&cmd.args, "--allow-unrelated-histories");
strvec_push(&args, "FETCH_HEAD"); strvec_push(&cmd.args, "FETCH_HEAD");
ret = run_command_v_opt(args.v, RUN_GIT_CMD); cmd.git_cmd = 1;
strvec_clear(&args); return run_command(&cmd);
return ret;
} }
/** /**
@ -879,43 +876,41 @@ static int get_rebase_newbase_and_upstream(struct object_id *newbase,
static int run_rebase(const struct object_id *newbase, static int run_rebase(const struct object_id *newbase,
const struct object_id *upstream) const struct object_id *upstream)
{ {
int ret; struct child_process cmd = CHILD_PROCESS_INIT;
struct strvec args = STRVEC_INIT;
strvec_push(&args, "rebase"); strvec_push(&cmd.args, "rebase");
/* Shared options */ /* Shared options */
argv_push_verbosity(&args); argv_push_verbosity(&cmd.args);
/* Options passed to git-rebase */ /* Options passed to git-rebase */
if (opt_rebase == REBASE_MERGES) if (opt_rebase == REBASE_MERGES)
strvec_push(&args, "--rebase-merges"); strvec_push(&cmd.args, "--rebase-merges");
else if (opt_rebase == REBASE_INTERACTIVE) else if (opt_rebase == REBASE_INTERACTIVE)
strvec_push(&args, "--interactive"); strvec_push(&cmd.args, "--interactive");
if (opt_diffstat) if (opt_diffstat)
strvec_push(&args, opt_diffstat); strvec_push(&cmd.args, opt_diffstat);
strvec_pushv(&args, opt_strategies.v); strvec_pushv(&cmd.args, opt_strategies.v);
strvec_pushv(&args, opt_strategy_opts.v); strvec_pushv(&cmd.args, opt_strategy_opts.v);
if (opt_gpg_sign) if (opt_gpg_sign)
strvec_push(&args, opt_gpg_sign); strvec_push(&cmd.args, opt_gpg_sign);
if (opt_signoff) if (opt_signoff)
strvec_push(&args, opt_signoff); strvec_push(&cmd.args, opt_signoff);
if (opt_autostash == 0) if (opt_autostash == 0)
strvec_push(&args, "--no-autostash"); strvec_push(&cmd.args, "--no-autostash");
else if (opt_autostash == 1) else if (opt_autostash == 1)
strvec_push(&args, "--autostash"); strvec_push(&cmd.args, "--autostash");
if (opt_verify_signatures && if (opt_verify_signatures &&
!strcmp(opt_verify_signatures, "--verify-signatures")) !strcmp(opt_verify_signatures, "--verify-signatures"))
warning(_("ignoring --verify-signatures for rebase")); warning(_("ignoring --verify-signatures for rebase"));
strvec_push(&args, "--onto"); strvec_push(&cmd.args, "--onto");
strvec_push(&args, oid_to_hex(newbase)); strvec_push(&cmd.args, oid_to_hex(newbase));
strvec_push(&args, oid_to_hex(upstream)); strvec_push(&cmd.args, oid_to_hex(upstream));
ret = run_command_v_opt(args.v, RUN_GIT_CMD); cmd.git_cmd = 1;
strvec_clear(&args); return run_command(&cmd);
return ret;
} }
static int get_can_ff(struct object_id *orig_head, static int get_can_ff(struct object_id *orig_head,

View File

@ -92,13 +92,15 @@ static int verbose;
static int fetch_remote(const char *name) static int fetch_remote(const char *name)
{ {
const char *argv[] = { "fetch", name, NULL, NULL }; struct child_process cmd = CHILD_PROCESS_INIT;
if (verbose) {
argv[1] = "-v"; strvec_push(&cmd.args, "fetch");
argv[2] = name; if (verbose)
} strvec_push(&cmd.args, "-v");
strvec_push(&cmd.args, name);
cmd.git_cmd = 1;
printf_ln(_("Updating %s"), name); printf_ln(_("Updating %s"), name);
if (run_command_v_opt(argv, RUN_GIT_CMD)) if (run_command(&cmd))
return error(_("Could not fetch %s"), name); return error(_("Could not fetch %s"), name);
return 0; return 0;
} }
@ -1508,37 +1510,35 @@ static int update(int argc, const char **argv, const char *prefix)
N_("prune remotes after fetching")), N_("prune remotes after fetching")),
OPT_END() OPT_END()
}; };
struct strvec fetch_argv = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
int default_defined = 0; int default_defined = 0;
int retval;
argc = parse_options(argc, argv, prefix, options, argc = parse_options(argc, argv, prefix, options,
builtin_remote_update_usage, builtin_remote_update_usage,
PARSE_OPT_KEEP_ARGV0); PARSE_OPT_KEEP_ARGV0);
strvec_push(&fetch_argv, "fetch"); strvec_push(&cmd.args, "fetch");
if (prune != -1) if (prune != -1)
strvec_push(&fetch_argv, prune ? "--prune" : "--no-prune"); strvec_push(&cmd.args, prune ? "--prune" : "--no-prune");
if (verbose) if (verbose)
strvec_push(&fetch_argv, "-v"); strvec_push(&cmd.args, "-v");
strvec_push(&fetch_argv, "--multiple"); strvec_push(&cmd.args, "--multiple");
if (argc < 2) if (argc < 2)
strvec_push(&fetch_argv, "default"); strvec_push(&cmd.args, "default");
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
strvec_push(&fetch_argv, argv[i]); strvec_push(&cmd.args, argv[i]);
if (strcmp(fetch_argv.v[fetch_argv.nr-1], "default") == 0) { if (strcmp(cmd.args.v[cmd.args.nr-1], "default") == 0) {
git_config(get_remote_default, &default_defined); git_config(get_remote_default, &default_defined);
if (!default_defined) { if (!default_defined) {
strvec_pop(&fetch_argv); strvec_pop(&cmd.args);
strvec_push(&fetch_argv, "--all"); strvec_push(&cmd.args, "--all");
} }
} }
retval = run_command_v_opt(fetch_argv.v, RUN_GIT_CMD); cmd.git_cmd = 1;
strvec_clear(&fetch_argv); return run_command(&cmd);
return retval;
} }
static int remove_all_fetch_refspecs(const char *key) static int remove_all_fetch_refspecs(const char *key)

View File

@ -196,16 +196,19 @@ static int read_yes_no_answer(void)
static int ask_yes_no_if_possible(const char *format, ...) static int ask_yes_no_if_possible(const char *format, ...)
{ {
char question[4096]; char question[4096];
const char *retry_hook[] = { NULL, NULL, NULL }; const char *retry_hook;
va_list args; va_list args;
va_start(args, format); va_start(args, format);
vsnprintf(question, sizeof(question), format, args); vsnprintf(question, sizeof(question), format, args);
va_end(args); va_end(args);
if ((retry_hook[0] = mingw_getenv("GIT_ASK_YESNO"))) { retry_hook = mingw_getenv("GIT_ASK_YESNO");
retry_hook[1] = question; if (retry_hook) {
return !run_command_v_opt(retry_hook, 0); struct child_process cmd = CHILD_PROCESS_INIT;
strvec_pushl(&cmd.args, retry_hook, question, NULL);
return !run_command(&cmd);
} }
if (!isatty(_fileno(stdin)) || !isatty(_fileno(stderr))) if (!isatty(_fileno(stdin)) || !isatty(_fileno(stderr)))

27
diff.c
View File

@ -4301,35 +4301,34 @@ static void run_external_diff(const char *pgm,
const char *xfrm_msg, const char *xfrm_msg,
struct diff_options *o) struct diff_options *o)
{ {
struct strvec argv = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
struct strvec env = STRVEC_INIT;
struct diff_queue_struct *q = &diff_queued_diff; struct diff_queue_struct *q = &diff_queued_diff;
strvec_push(&argv, pgm); strvec_push(&cmd.args, pgm);
strvec_push(&argv, name); strvec_push(&cmd.args, name);
if (one && two) { if (one && two) {
add_external_diff_name(o->repo, &argv, name, one); add_external_diff_name(o->repo, &cmd.args, name, one);
if (!other) if (!other)
add_external_diff_name(o->repo, &argv, name, two); add_external_diff_name(o->repo, &cmd.args, name, two);
else { else {
add_external_diff_name(o->repo, &argv, other, two); add_external_diff_name(o->repo, &cmd.args, other, two);
strvec_push(&argv, other); strvec_push(&cmd.args, other);
strvec_push(&argv, xfrm_msg); strvec_push(&cmd.args, xfrm_msg);
} }
} }
strvec_pushf(&env, "GIT_DIFF_PATH_COUNTER=%d", ++o->diff_path_counter); strvec_pushf(&cmd.env, "GIT_DIFF_PATH_COUNTER=%d",
strvec_pushf(&env, "GIT_DIFF_PATH_TOTAL=%d", q->nr); ++o->diff_path_counter);
strvec_pushf(&cmd.env, "GIT_DIFF_PATH_TOTAL=%d", q->nr);
diff_free_filespec_data(one); diff_free_filespec_data(one);
diff_free_filespec_data(two); diff_free_filespec_data(two);
if (run_command_v_opt_cd_env(argv.v, RUN_USING_SHELL, NULL, env.v)) cmd.use_shell = 1;
if (run_command(&cmd))
die(_("external diff died, stopping at %s"), name); die(_("external diff died, stopping at %s"), name);
remove_tempfile(); remove_tempfile();
strvec_clear(&argv);
strvec_clear(&env);
} }
static int similarity_index(struct diff_filepair *p) static int similarity_index(struct diff_filepair *p)

View File

@ -54,10 +54,14 @@ enum ipc_active_state fsmonitor_ipc__get_state(void)
static int spawn_daemon(void) static int spawn_daemon(void)
{ {
const char *args[] = { "fsmonitor--daemon", "start", NULL }; struct child_process cmd = CHILD_PROCESS_INIT;
return run_command_v_opt_tr2(args, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD, cmd.git_cmd = 1;
"fsmonitor"); cmd.no_stdin = 1;
cmd.trace2_child_class = "fsmonitor";
strvec_pushl(&cmd.args, "fsmonitor--daemon", "start", NULL);
return run_command(&cmd);
} }
int fsmonitor_ipc__send_query(const char *since_token, int fsmonitor_ipc__send_query(const char *since_token,

15
git.c
View File

@ -787,7 +787,7 @@ static int run_argv(int *argcp, const char ***argv)
if (!done_alias) if (!done_alias)
handle_builtin(*argcp, *argv); handle_builtin(*argcp, *argv);
else if (get_builtin(**argv)) { else if (get_builtin(**argv)) {
struct strvec args = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
int i; int i;
/* /*
@ -804,18 +804,21 @@ static int run_argv(int *argcp, const char ***argv)
commit_pager_choice(); commit_pager_choice();
strvec_push(&args, "git"); strvec_push(&cmd.args, "git");
for (i = 0; i < *argcp; i++) for (i = 0; i < *argcp; i++)
strvec_push(&args, (*argv)[i]); strvec_push(&cmd.args, (*argv)[i]);
trace_argv_printf(args.v, "trace: exec:"); trace_argv_printf(cmd.args.v, "trace: exec:");
/* /*
* if we fail because the command is not found, it is * if we fail because the command is not found, it is
* OK to return. Otherwise, we just pass along the status code. * OK to return. Otherwise, we just pass along the status code.
*/ */
i = run_command_v_opt_tr2(args.v, RUN_SILENT_EXEC_FAILURE | cmd.silent_exec_failure = 1;
RUN_CLEAN_ON_EXIT | RUN_WAIT_AFTER_CLEAN, "git_alias"); cmd.clean_on_exit = 1;
cmd.wait_after_clean = 1;
cmd.trace2_child_class = "git_alias";
i = run_command(&cmd);
if (i >= 0 || errno != ENOENT) if (i >= 0 || errno != ENOENT)
exit(i); exit(i);
die("could not execute builtin %s", **argv); die("could not execute builtin %s", **argv);

View File

@ -193,7 +193,7 @@ static enum ll_merge_result ll_ext_merge(const struct ll_merge_driver *fn,
struct strbuf cmd = STRBUF_INIT; struct strbuf cmd = STRBUF_INIT;
struct strbuf_expand_dict_entry dict[6]; struct strbuf_expand_dict_entry dict[6];
struct strbuf path_sq = STRBUF_INIT; struct strbuf path_sq = STRBUF_INIT;
const char *args[] = { NULL, NULL }; struct child_process child = CHILD_PROCESS_INIT;
int status, fd, i; int status, fd, i;
struct stat st; struct stat st;
enum ll_merge_result ret; enum ll_merge_result ret;
@ -219,8 +219,9 @@ static enum ll_merge_result ll_ext_merge(const struct ll_merge_driver *fn,
strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict); strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
args[0] = cmd.buf; child.use_shell = 1;
status = run_command_v_opt(args, RUN_USING_SHELL); strvec_push(&child.args, cmd.buf);
status = run_command(&child);
fd = open(temp[1], O_RDONLY); fd = open(temp[1], O_RDONLY);
if (fd < 0) if (fd < 0)
goto bad; goto bad;

18
merge.c
View File

@ -19,22 +19,22 @@ int try_merge_command(struct repository *r,
const char **xopts, struct commit_list *common, const char **xopts, struct commit_list *common,
const char *head_arg, struct commit_list *remotes) const char *head_arg, struct commit_list *remotes)
{ {
struct strvec args = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
int i, ret; int i, ret;
struct commit_list *j; struct commit_list *j;
strvec_pushf(&args, "merge-%s", strategy); strvec_pushf(&cmd.args, "merge-%s", strategy);
for (i = 0; i < xopts_nr; i++) for (i = 0; i < xopts_nr; i++)
strvec_pushf(&args, "--%s", xopts[i]); strvec_pushf(&cmd.args, "--%s", xopts[i]);
for (j = common; j; j = j->next) for (j = common; j; j = j->next)
strvec_push(&args, merge_argument(j->item)); strvec_push(&cmd.args, merge_argument(j->item));
strvec_push(&args, "--"); strvec_push(&cmd.args, "--");
strvec_push(&args, head_arg); strvec_push(&cmd.args, head_arg);
for (j = remotes; j; j = j->next) for (j = remotes; j; j = j->next)
strvec_push(&args, merge_argument(j->item)); strvec_push(&cmd.args, merge_argument(j->item));
ret = run_command_v_opt(args.v, RUN_GIT_CMD); cmd.git_cmd = 1;
strvec_clear(&args); ret = run_command(&cmd);
discard_index(r->index); discard_index(r->index);
if (repo_read_index(r) < 0) if (repo_read_index(r) < 0)

View File

@ -1004,41 +1004,6 @@ int run_command(struct child_process *cmd)
return finish_command(cmd); return finish_command(cmd);
} }
int run_command_v_opt(const char **argv, int opt)
{
return run_command_v_opt_cd_env(argv, opt, NULL, NULL);
}
int run_command_v_opt_tr2(const char **argv, int opt, const char *tr2_class)
{
return run_command_v_opt_cd_env_tr2(argv, opt, NULL, NULL, tr2_class);
}
int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env)
{
return run_command_v_opt_cd_env_tr2(argv, opt, dir, env, NULL);
}
int run_command_v_opt_cd_env_tr2(const char **argv, int opt, const char *dir,
const char *const *env, const char *tr2_class)
{
struct child_process cmd = CHILD_PROCESS_INIT;
strvec_pushv(&cmd.args, argv);
cmd.no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
cmd.git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
cmd.stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
cmd.silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
cmd.use_shell = opt & RUN_USING_SHELL ? 1 : 0;
cmd.clean_on_exit = opt & RUN_CLEAN_ON_EXIT ? 1 : 0;
cmd.wait_after_clean = opt & RUN_WAIT_AFTER_CLEAN ? 1 : 0;
cmd.close_object_store = opt & RUN_CLOSE_OBJECT_STORE ? 1 : 0;
cmd.dir = dir;
if (env)
strvec_pushv(&cmd.env, (const char **)env);
cmd.trace2_child_class = tr2_class;
return run_command(&cmd);
}
#ifndef NO_PTHREADS #ifndef NO_PTHREADS
static pthread_t main_thread; static pthread_t main_thread;
static int main_thread_set; static int main_thread_set;

View File

@ -150,9 +150,7 @@ struct child_process {
} }
/** /**
* The functions: child_process_init, start_command, finish_command, * The functions: start_command, finish_command, run_command do the following:
* run_command, run_command_v_opt, run_command_v_opt_cd_env, child_process_clear
* do the following:
* *
* - If a system call failed, errno is set and -1 is returned. A diagnostic * - If a system call failed, errno is set and -1 is returned. A diagnostic
* is printed. * is printed.
@ -224,36 +222,6 @@ int run_command(struct child_process *);
*/ */
int run_auto_maintenance(int quiet); int run_auto_maintenance(int quiet);
#define RUN_COMMAND_NO_STDIN (1<<0)
#define RUN_GIT_CMD (1<<1)
#define RUN_COMMAND_STDOUT_TO_STDERR (1<<2)
#define RUN_SILENT_EXEC_FAILURE (1<<3)
#define RUN_USING_SHELL (1<<4)
#define RUN_CLEAN_ON_EXIT (1<<5)
#define RUN_WAIT_AFTER_CLEAN (1<<6)
#define RUN_CLOSE_OBJECT_STORE (1<<7)
/**
* Convenience functions that encapsulate a sequence of
* start_command() followed by finish_command(). The argument argv
* specifies the program and its arguments. The argument opt is zero
* or more of the flags `RUN_COMMAND_NO_STDIN`, `RUN_GIT_CMD`,
* `RUN_COMMAND_STDOUT_TO_STDERR`, or `RUN_SILENT_EXEC_FAILURE`
* that correspond to the members .no_stdin, .git_cmd,
* .stdout_to_stderr, .silent_exec_failure of `struct child_process`.
* The argument dir corresponds the member .dir. The argument env
* corresponds to the member .env.
*/
int run_command_v_opt(const char **argv, int opt);
int run_command_v_opt_tr2(const char **argv, int opt, const char *tr2_class);
/*
* env (the environment) is to be formatted like environ: "VAR=VALUE".
* To unset an environment variable use just "VAR".
*/
int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env);
int run_command_v_opt_cd_env_tr2(const char **argv, int opt, const char *dir,
const char *const *env, const char *tr2_class);
/** /**
* Execute the given command, sending "in" to its stdin, and capturing its * Execute the given command, sending "in" to its stdin, and capturing its
* stdout and stderr in the "out" and "err" strbufs. Any of the three may * stdout and stderr in the "out" and "err" strbufs. Any of the three may

View File

@ -69,21 +69,18 @@ static void setup_enlistment_directory(int argc, const char **argv,
static int run_git(const char *arg, ...) static int run_git(const char *arg, ...)
{ {
struct strvec argv = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
va_list args; va_list args;
const char *p; const char *p;
int res;
va_start(args, arg); va_start(args, arg);
strvec_push(&argv, arg); strvec_push(&cmd.args, arg);
while ((p = va_arg(args, const char *))) while ((p = va_arg(args, const char *)))
strvec_push(&argv, p); strvec_push(&cmd.args, p);
va_end(args); va_end(args);
res = run_command_v_opt(argv.v, RUN_GIT_CMD); cmd.git_cmd = 1;
return run_command(&cmd);
strvec_clear(&argv);
return res;
} }
struct scalar_config { struct scalar_config {

View File

@ -3183,18 +3183,15 @@ static int rollback_is_safe(void)
static int reset_merge(const struct object_id *oid) static int reset_merge(const struct object_id *oid)
{ {
int ret; struct child_process cmd = CHILD_PROCESS_INIT;
struct strvec argv = STRVEC_INIT;
strvec_pushl(&argv, "reset", "--merge", NULL); cmd.git_cmd = 1;
strvec_pushl(&cmd.args, "reset", "--merge", NULL);
if (!is_null_oid(oid)) if (!is_null_oid(oid))
strvec_push(&argv, oid_to_hex(oid)); strvec_push(&cmd.args, oid_to_hex(oid));
ret = run_command_v_opt(argv.v, RUN_GIT_CMD); return run_command(&cmd);
strvec_clear(&argv);
return ret;
} }
static int rollback_single_pick(struct repository *r) static int rollback_single_pick(struct repository *r)
@ -3558,12 +3555,13 @@ static int error_failed_squash(struct repository *r,
static int do_exec(struct repository *r, const char *command_line) static int do_exec(struct repository *r, const char *command_line)
{ {
const char *child_argv[] = { NULL, NULL }; struct child_process cmd = CHILD_PROCESS_INIT;
int dirty, status; int dirty, status;
fprintf(stderr, _("Executing: %s\n"), command_line); fprintf(stderr, _("Executing: %s\n"), command_line);
child_argv[0] = command_line; cmd.use_shell = 1;
status = run_command_v_opt(child_argv, RUN_USING_SHELL); strvec_push(&cmd.args, command_line);
status = run_command(&cmd);
/* force re-reading of the cache */ /* force re-reading of the cache */
if (discard_index(r->index) < 0 || repo_read_index(r) < 0) if (discard_index(r->index) < 0 || repo_read_index(r) < 0)
@ -4867,14 +4865,14 @@ static int pick_commits(struct repository *r,
static int continue_single_pick(struct repository *r, struct replay_opts *opts) static int continue_single_pick(struct repository *r, struct replay_opts *opts)
{ {
struct strvec argv = STRVEC_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
int ret;
if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") && if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
!refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) !refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
return error(_("no cherry-pick or revert in progress")); return error(_("no cherry-pick or revert in progress"));
strvec_push(&argv, "commit"); cmd.git_cmd = 1;
strvec_push(&cmd.args, "commit");
/* /*
* continue_single_pick() handles the case of recovering from a * continue_single_pick() handles the case of recovering from a
@ -4887,11 +4885,9 @@ static int continue_single_pick(struct repository *r, struct replay_opts *opts)
* Include --cleanup=strip as well because we don't want the * Include --cleanup=strip as well because we don't want the
* "# Conflicts:" messages. * "# Conflicts:" messages.
*/ */
strvec_pushl(&argv, "--no-edit", "--cleanup=strip", NULL); strvec_pushl(&cmd.args, "--no-edit", "--cleanup=strip", NULL);
ret = run_command_v_opt(argv.v, RUN_GIT_CMD); return run_command(&cmd);
strvec_clear(&argv);
return ret;
} }
static int commit_staged_changes(struct repository *r, static int commit_staged_changes(struct repository *r,

17
shell.c
View File

@ -52,21 +52,24 @@ static void cd_to_homedir(void)
static void run_shell(void) static void run_shell(void)
{ {
int done = 0; int done = 0;
static const char *help_argv[] = { HELP_COMMAND, NULL }; struct child_process help_cmd = CHILD_PROCESS_INIT;
if (!access(NOLOGIN_COMMAND, F_OK)) { if (!access(NOLOGIN_COMMAND, F_OK)) {
/* Interactive login disabled. */ /* Interactive login disabled. */
const char *argv[] = { NOLOGIN_COMMAND, NULL }; struct child_process nologin_cmd = CHILD_PROCESS_INIT;
int status; int status;
status = run_command_v_opt(argv, 0); strvec_push(&nologin_cmd.args, NOLOGIN_COMMAND);
status = run_command(&nologin_cmd);
if (status < 0) if (status < 0)
exit(127); exit(127);
exit(status); exit(status);
} }
/* Print help if enabled */ /* Print help if enabled */
run_command_v_opt(help_argv, RUN_SILENT_EXEC_FAILURE); help_cmd.silent_exec_failure = 1;
strvec_push(&help_cmd.args, HELP_COMMAND);
run_command(&help_cmd);
do { do {
const char *prog; const char *prog;
@ -125,9 +128,13 @@ static void run_shell(void)
!strcmp(prog, "exit") || !strcmp(prog, "bye")) { !strcmp(prog, "exit") || !strcmp(prog, "bye")) {
done = 1; done = 1;
} else if (is_valid_cmd_name(prog)) { } else if (is_valid_cmd_name(prog)) {
struct child_process cmd = CHILD_PROCESS_INIT;
full_cmd = make_cmd(prog); full_cmd = make_cmd(prog);
argv[0] = full_cmd; argv[0] = full_cmd;
code = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE); cmd.silent_exec_failure = 1;
strvec_pushv(&cmd.args, argv);
code = run_command(&cmd);
if (code == -1 && errno == ENOENT) { if (code == -1 && errno == ENOENT) {
fprintf(stderr, "unrecognized command '%s'\n", prog); fprintf(stderr, "unrecognized command '%s'\n", prog);
} }

View File

@ -8,7 +8,7 @@ int cmd_main(int argc, const char **argv)
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
FILE *f; FILE *f;
int i; int i;
const char *child_argv[] = { NULL, NULL }; struct child_process cmd = CHILD_PROCESS_INIT;
/* First, print all parameters into $TRASH_DIRECTORY/ssh-output */ /* First, print all parameters into $TRASH_DIRECTORY/ssh-output */
if (!trash_directory) if (!trash_directory)
@ -25,6 +25,7 @@ int cmd_main(int argc, const char **argv)
/* Now, evaluate the *last* parameter */ /* Now, evaluate the *last* parameter */
if (argc < 2) if (argc < 2)
return 0; return 0;
child_argv[0] = argv[argc - 1]; cmd.use_shell = 1;
return run_command_v_opt(child_argv, RUN_USING_SHELL); strvec_push(&cmd.args, argv[argc - 1]);
return run_command(&cmd);
} }

View File

@ -132,6 +132,7 @@ static int ut_003error(int argc, const char **argv)
*/ */
static int ut_004child(int argc, const char **argv) static int ut_004child(int argc, const char **argv)
{ {
struct child_process cmd = CHILD_PROCESS_INIT;
int result; int result;
/* /*
@ -141,7 +142,8 @@ static int ut_004child(int argc, const char **argv)
if (!argc) if (!argc)
return 0; return 0;
result = run_command_v_opt(argv, 0); strvec_pushv(&cmd.args, argv);
result = run_command(&cmd);
exit(result); exit(result);
} }

View File

@ -10,9 +10,11 @@
* *
* Example: * Example:
* *
* struct child_process child = CHILD_PROCESS_INIT;
* struct tmp_objdir *t = tmp_objdir_create("incoming"); * struct tmp_objdir *t = tmp_objdir_create("incoming");
* if (!run_command_v_opt_cd_env(cmd, 0, NULL, tmp_objdir_env(t)) && * strvec_push(&child.args, cmd);
* !tmp_objdir_migrate(t)) * strvec_pushv(&child.env, tmp_objdir_env(t));
* if (!run_command(&child)) && !tmp_objdir_migrate(t))
* printf("success!\n"); * printf("success!\n");
* else * else
* die("failed...tmp_objdir will clean up for us"); * die("failed...tmp_objdir will clean up for us");