int finish_command(struct child_process *cmd) { int ret = wait_or_whine(cmd->pid, cmd->argv[0]); argv_array_clear(&cmd->args); argv_array_clear(&cmd->env_array); return ret; }
static int bisect_reset(const char *commit) { struct strbuf branch = STRBUF_INIT; if (!commit) { if (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) { printf(_("We are not bisecting.\n")); return 0; } strbuf_rtrim(&branch); } else { struct object_id oid; if (get_oid_commit(commit, &oid)) return error(_("'%s' is not a valid commit"), commit); strbuf_addstr(&branch, commit); } if (!file_exists(git_path_bisect_head())) { struct argv_array argv = ARGV_ARRAY_INIT; argv_array_pushl(&argv, "checkout", branch.buf, "--", NULL); if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { strbuf_release(&branch); argv_array_clear(&argv); return error(_("could not check out original" " HEAD '%s'. Try 'git bisect" "reset <commit>'."), branch.buf); } argv_array_clear(&argv); } strbuf_release(&branch); return bisect_clean_state(); }
int run_hook(const char *index_file, const char *name, ...) { struct child_process hook; struct argv_array argv = ARGV_ARRAY_INIT; const char *p, *env[2]; char index[PATH_MAX]; va_list args; int ret; if (access(git_path("hooks/%s", name), X_OK) < 0) return 0; va_start(args, name); argv_array_push(&argv, git_path("hooks/%s", name)); while ((p = va_arg(args, const char *))) argv_array_push(&argv, p); va_end(args); memset(&hook, 0, sizeof(hook)); hook.argv = argv.argv; hook.no_stdin = 1; hook.stdout_to_stderr = 1; if (index_file) { snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file); env[0] = index; env[1] = NULL; hook.env = env; } ret = run_command(&hook); argv_array_clear(&argv); return ret; }
static int show_stash(int argc, const char **argv, const char *prefix) { int i; int opts = 0; int ret = 0; struct stash_info info; struct rev_info rev; struct argv_array stash_args = ARGV_ARRAY_INIT; struct option options[] = { OPT_END() }; init_diff_ui_defaults(); git_config(git_diff_ui_config, NULL); init_revisions(&rev, prefix); for (i = 1; i < argc; i++) { if (argv[i][0] != '-') argv_array_push(&stash_args, argv[i]); else opts++; } ret = get_stash_info(&info, stash_args.argc, stash_args.argv); argv_array_clear(&stash_args); if (ret) return -1; /* * The config settings are applied only if there are not passed * any options. */ if (!opts) { git_config(git_stash_config, NULL); if (show_stat) rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT; if (show_patch) rev.diffopt.output_format |= DIFF_FORMAT_PATCH; if (!show_stat && !show_patch) { free_stash_info(&info); return 0; } } argc = setup_revisions(argc, argv, &rev, NULL); if (argc > 1) { free_stash_info(&info); usage_with_options(git_stash_show_usage, options); } rev.diffopt.flags.recursive = 1; setup_diff_pager(&rev.diffopt); diff_tree_oid(&info.b_commit, &info.w_commit, "", &rev.diffopt); log_tree_diff_flush(&rev); free_stash_info(&info); return diff_result_code(&rev.diffopt, 0); }
/* * If we are cherry-pick, and if the merge did not result in * hand-editing, we will hit this commit and inherit the original * author date and name. * If we are revert, or if our cherry-pick results in a hand merge, * we had better say that the current user is responsible for that. */ static int run_git_commit(const char *defmsg, struct replay_opts *opts, int allow_empty) { struct argv_array array; int rc; char *gpg_sign; argv_array_init(&array); argv_array_push(&array, "commit"); argv_array_push(&array, "-n"); if (opts->gpg_sign) { gpg_sign = xmalloc(3 + strlen(opts->gpg_sign)); sprintf(gpg_sign, "-S%s", opts->gpg_sign); argv_array_push(&array, gpg_sign); free(gpg_sign); } if (opts->signoff) argv_array_push(&array, "-s"); if (!opts->edit) { argv_array_push(&array, "-F"); argv_array_push(&array, defmsg); } if (allow_empty) argv_array_push(&array, "--allow-empty"); if (opts->allow_empty_message) argv_array_push(&array, "--allow-empty-message"); rc = run_command_v_opt(array.argv, RUN_GIT_CMD); argv_array_clear(&array); return rc; }
static int convert_graft_file(int force) { const char *graft_file = get_graft_file(); FILE *fp = fopen_or_warn(graft_file, "r"); struct strbuf buf = STRBUF_INIT, err = STRBUF_INIT; struct argv_array args = ARGV_ARRAY_INIT; if (!fp) return -1; while (strbuf_getline(&buf, fp) != EOF) { if (*buf.buf == '#') continue; argv_array_split(&args, buf.buf); if (args.argc && create_graft(args.argc, args.argv, force, 1)) strbuf_addf(&err, "\n\t%s", buf.buf); argv_array_clear(&args); } fclose(fp); strbuf_release(&buf); if (!err.len) return unlink_or_warn(graft_file); warning(_("could not convert the following graft(s):\n%s"), err.buf); strbuf_release(&err); return -1; }
/* * If we are cherry-pick, and if the merge did not result in * hand-editing, we will hit this commit and inherit the original * author date and name. * If we are revert, or if our cherry-pick results in a hand merge, * we had better say that the current user is responsible for that. */ static int run_git_commit(const char *defmsg, struct replay_opts *opts, int allow_empty) { struct argv_array array; int rc; argv_array_init(&array); argv_array_push(&array, "commit"); argv_array_push(&array, "-n"); if (opts->signoff) argv_array_push(&array, "-s"); if (!opts->edit) { argv_array_push(&array, "-F"); argv_array_push(&array, defmsg); } if (allow_empty) argv_array_push(&array, "--allow-empty"); if (opts->allow_empty_message) argv_array_push(&array, "--allow-empty-message"); rc = run_command_v_opt(array.argv, RUN_GIT_CMD); argv_array_clear(&array); return rc; }
int try_merge_command(const char *strategy, size_t xopts_nr, const char **xopts, struct commit_list *common, const char *head_arg, struct commit_list *remotes) { struct argv_array args = ARGV_ARRAY_INIT; int i, ret; struct commit_list *j; argv_array_pushf(&args, "merge-%s", strategy); for (i = 0; i < xopts_nr; i++) argv_array_pushf(&args, "--%s", xopts[i]); for (j = common; j; j = j->next) argv_array_push(&args, merge_argument(j->item)); argv_array_push(&args, "--"); argv_array_push(&args, head_arg); for (j = remotes; j; j = j->next) argv_array_push(&args, merge_argument(j->item)); ret = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); discard_cache(); if (read_cache() < 0) die(_("failed to read the cache")); resolve_undo_clear(); return ret; }
/* * If we are cherry-pick, and if the merge did not result in * hand-editing, we will hit this commit and inherit the original * author date and name. * If we are revert, or if our cherry-pick results in a hand merge, * we had better say that the current user is responsible for that. */ static int run_git_commit(const char *defmsg, struct replay_opts *opts, int allow_empty) { struct argv_array array; int rc; const char *value; argv_array_init(&array); argv_array_push(&array, "commit"); argv_array_push(&array, "-n"); if (opts->gpg_sign) argv_array_pushf(&array, "-S%s", opts->gpg_sign); if (opts->signoff) argv_array_push(&array, "-s"); if (!opts->edit) { argv_array_push(&array, "-F"); argv_array_push(&array, defmsg); if (!opts->signoff && !opts->record_origin && git_config_get_value("commit.cleanup", &value)) argv_array_push(&array, "--cleanup=verbatim"); } if (allow_empty) argv_array_push(&array, "--allow-empty"); if (opts->allow_empty_message) argv_array_push(&array, "--allow-empty-message"); rc = run_command_v_opt(array.argv, RUN_GIT_CMD); argv_array_clear(&array); return rc; }
int run_hook_ve(const char *const *env, const char *name, va_list args) { struct child_process hook; struct argv_array argv = ARGV_ARRAY_INIT; const char *p; int ret; p = find_hook(name); if (!p) return 0; argv_array_push(&argv, p); while ((p = va_arg(args, const char *))) argv_array_push(&argv, p); memset(&hook, 0, sizeof(hook)); hook.argv = argv.argv; hook.env = env; hook.no_stdin = 1; hook.stdout_to_stderr = 1; ret = run_command(&hook); argv_array_clear(&argv); return ret; }
static void handle_builtin(int argc, const char **argv) { struct argv_array args = ARGV_ARRAY_INIT; const char *cmd; struct cmd_struct *builtin; strip_extension(argv); cmd = argv[0]; /* Turn "git cmd --help" into "git help --exclude-guides cmd" */ if (argc > 1 && !strcmp(argv[1], "--help")) { int i; argv[1] = argv[0]; argv[0] = cmd = "help"; for (i = 0; i < argc; i++) { argv_array_push(&args, argv[i]); if (!i) argv_array_push(&args, "--exclude-guides"); } argc++; argv = args.argv; } builtin = get_builtin(cmd); if (builtin) exit(run_builtin(builtin, argc, argv)); argv_array_clear(&args); }
struct git_graph *graph_init(struct rev_info *opt) { struct git_graph *graph = xmalloc(sizeof(struct git_graph)); if (!column_colors) { char *string; if (git_config_get_string("log.graphcolors", &string)) { /* not configured -- use default */ graph_set_column_colors(column_colors_ansi, column_colors_ansi_max); } else { static struct argv_array custom_colors = ARGV_ARRAY_INIT; argv_array_clear(&custom_colors); parse_graph_colors_config(&custom_colors, string); free(string); /* graph_set_column_colors takes a max-index, not a count */ graph_set_column_colors(custom_colors.argv, custom_colors.argc - 1); } } graph->commit = NULL; graph->revs = opt; graph->num_parents = 0; graph->expansion_row = 0; graph->state = GRAPH_PADDING; graph->prev_state = GRAPH_PADDING; graph->commit_index = 0; graph->prev_commit_index = 0; graph->num_columns = 0; graph->num_new_columns = 0; graph->mapping_size = 0; /* * Start the column color at the maximum value, since we'll * always increment it for the first commit we output. * This way we start at 0 for the first commit. */ graph->default_column_color = column_colors_max - 1; /* * Allocate a reasonably large default number of columns * We'll automatically grow columns later if we need more room. */ graph->column_capacity = 30; ALLOC_ARRAY(graph->columns, graph->column_capacity); ALLOC_ARRAY(graph->new_columns, graph->column_capacity); ALLOC_ARRAY(graph->mapping, 2 * graph->column_capacity); ALLOC_ARRAY(graph->new_mapping, 2 * graph->column_capacity); /* * The diff output prefix callback, with this we can make * all the diff output to align with the graph lines. */ opt->diffopt.output_prefix = diff_output_prefix_callback; opt->diffopt.output_prefix_data = graph; return graph; }
static int execv_shell_cmd(const char **argv) { struct argv_array nargv = ARGV_ARRAY_INIT; prepare_shell_cmd(&nargv, argv); trace_argv_printf(nargv.argv, "trace: exec:"); sane_execvp(nargv.argv[0], (char **)nargv.argv); argv_array_clear(&nargv); return -1; }
/* * If we are cherry-pick, and if the merge did not result in * hand-editing, we will hit this commit and inherit the original * author date and name. * * If we are revert, or if our cherry-pick results in a hand merge, * we had better say that the current user is responsible for that. * * An exception is when run_git_commit() is called during an * interactive rebase: in that case, we will want to retain the * author metadata. */ static int run_git_commit(const char *defmsg, struct replay_opts *opts, int allow_empty, int edit, int amend, int cleanup_commit_message) { char **env = NULL; struct argv_array array; int rc; const char *value; if (is_rebase_i(opts)) { env = read_author_script(); if (!env) { const char *gpg_opt = gpg_sign_opt_quoted(opts); return error(_(staged_changes_advice), gpg_opt, gpg_opt); } } argv_array_init(&array); argv_array_push(&array, "commit"); argv_array_push(&array, "-n"); if (amend) argv_array_push(&array, "--amend"); if (opts->gpg_sign) argv_array_pushf(&array, "-S%s", opts->gpg_sign); if (opts->signoff) argv_array_push(&array, "-s"); if (defmsg) argv_array_pushl(&array, "-F", defmsg, NULL); if (cleanup_commit_message) argv_array_push(&array, "--cleanup=strip"); if (edit) argv_array_push(&array, "-e"); else if (!cleanup_commit_message && !opts->signoff && !opts->record_origin && git_config_get_value("commit.cleanup", &value)) argv_array_push(&array, "--cleanup=verbatim"); if (allow_empty) argv_array_push(&array, "--allow-empty"); if (opts->allow_empty_message) argv_array_push(&array, "--allow-empty-message"); rc = run_command_v_opt_cd_env(array.argv, RUN_GIT_CMD, NULL, (const char *const *)env); argv_array_clear(&array); free(env); return rc; }
/** * Runs git-fetch, returning its exit status. `repo` and `refspecs` are the * repository and refspecs to fetch, or NULL if they are not provided. */ static int run_fetch(const char *repo, const char **refspecs) { struct argv_array args = ARGV_ARRAY_INIT; int ret; argv_array_pushl(&args, "fetch", "--update-head-ok", NULL); /* Shared options */ argv_push_verbosity(&args); if (opt_progress) argv_array_push(&args, opt_progress); /* Options passed to git-fetch */ if (opt_all) argv_array_push(&args, opt_all); if (opt_append) argv_array_push(&args, opt_append); if (opt_upload_pack) argv_array_push(&args, opt_upload_pack); argv_push_force(&args); if (opt_tags) argv_array_push(&args, opt_tags); if (opt_prune) argv_array_push(&args, opt_prune); if (opt_recurse_submodules) argv_array_push(&args, opt_recurse_submodules); if (max_children) argv_array_push(&args, max_children); if (opt_dry_run) argv_array_push(&args, "--dry-run"); if (opt_keep) argv_array_push(&args, opt_keep); if (opt_depth) argv_array_push(&args, opt_depth); if (opt_unshallow) argv_array_push(&args, opt_unshallow); if (opt_update_shallow) argv_array_push(&args, opt_update_shallow); if (opt_refmap) argv_array_push(&args, opt_refmap); if (repo) { argv_array_push(&args, repo); argv_array_pushv(&args, refspecs); } else if (*refspecs) die("BUG: refspecs without repo?"); ret = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); return ret; }
int execv_git_cmd(const char **argv) { struct argv_array nargv = ARGV_ARRAY_INIT; prepare_git_cmd(&nargv, argv); trace_argv_printf(nargv.argv, "trace: exec:"); /* execvp() can only ever return if it fails */ sane_execvp("git", (char **)nargv.argv); trace_printf("trace: exec failed: %s\n", strerror(errno)); argv_array_clear(&nargv); return -1; }
static int push_git(struct discovery *heads, int nr_spec, char **specs) { struct rpc_state rpc; int i, err; struct argv_array args; struct string_list_item *cas_option; struct strbuf preamble = STRBUF_INIT; argv_array_init(&args); argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status", NULL); if (options.thin) argv_array_push(&args, "--thin"); if (options.dry_run) argv_array_push(&args, "--dry-run"); if (options.push_cert == SEND_PACK_PUSH_CERT_ALWAYS) argv_array_push(&args, "--signed=yes"); else if (options.push_cert == SEND_PACK_PUSH_CERT_IF_ASKED) argv_array_push(&args, "--signed=if-asked"); if (options.verbosity == 0) argv_array_push(&args, "--quiet"); else if (options.verbosity > 1) argv_array_push(&args, "--verbose"); for (i = 0; i < options.push_options.nr; i++) argv_array_pushf(&args, "--push-option=%s", options.push_options.items[i].string); argv_array_push(&args, options.progress ? "--progress" : "--no-progress"); for_each_string_list_item(cas_option, &cas_options) argv_array_push(&args, cas_option->string); argv_array_push(&args, url.buf); argv_array_push(&args, "--stdin"); for (i = 0; i < nr_spec; i++) packet_buf_write(&preamble, "%s\n", specs[i]); packet_buf_flush(&preamble); memset(&rpc, 0, sizeof(rpc)); rpc.service_name = "git-receive-pack", rpc.argv = args.argv; rpc.stdin_preamble = &preamble; err = rpc_service(&rpc, heads); if (rpc.result.len) write_or_die(1, rpc.result.buf, rpc.result.len); strbuf_release(&rpc.result); strbuf_release(&preamble); argv_array_clear(&args); return err; }
/** * Given the current HEAD SHA1, the merge head returned from git-fetch and the * fork point calculated by get_rebase_fork_point(), runs git-rebase with the * appropriate arguments and returns its exit status. */ static int run_rebase(const struct object_id *curr_head, const struct object_id *merge_head, const struct object_id *fork_point) { int ret; struct object_id oct_merge_base; struct argv_array args = ARGV_ARRAY_INIT; if (!get_octopus_merge_base(&oct_merge_base, curr_head, merge_head, fork_point)) if (!is_null_oid(fork_point) && oideq(&oct_merge_base, fork_point)) fork_point = NULL; argv_array_push(&args, "rebase"); /* Shared options */ argv_push_verbosity(&args); /* Options passed to git-rebase */ if (opt_rebase == REBASE_MERGES) argv_array_push(&args, "--rebase-merges"); else if (opt_rebase == REBASE_PRESERVE) argv_array_push(&args, "--preserve-merges"); else if (opt_rebase == REBASE_INTERACTIVE) argv_array_push(&args, "--interactive"); if (opt_diffstat) argv_array_push(&args, opt_diffstat); argv_array_pushv(&args, opt_strategies.argv); argv_array_pushv(&args, opt_strategy_opts.argv); if (opt_gpg_sign) argv_array_push(&args, opt_gpg_sign); if (opt_autostash == 0) argv_array_push(&args, "--no-autostash"); else if (opt_autostash == 1) argv_array_push(&args, "--autostash"); if (opt_verify_signatures && !strcmp(opt_verify_signatures, "--verify-signatures")) warning(_("ignoring --verify-signatures for rebase")); argv_array_push(&args, "--onto"); argv_array_push(&args, oid_to_hex(merge_head)); if (fork_point && !is_null_oid(fork_point)) argv_array_push(&args, oid_to_hex(fork_point)); else argv_array_push(&args, oid_to_hex(merge_head)); ret = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); return ret; }
static void calculate_changed_submodule_paths(void) { struct rev_info rev; struct commit *commit; struct argv_array argv = ARGV_ARRAY_INIT; /* No need to check if there are no submodules configured */ if (!config_name_for_path.nr) return; init_revisions(&rev, NULL); argv_array_push(&argv, "--"); /* argv[0] program name */ sha1_array_for_each_unique(&ref_tips_after_fetch, add_sha1_to_argv, &argv); argv_array_push(&argv, "--not"); sha1_array_for_each_unique(&ref_tips_before_fetch, add_sha1_to_argv, &argv); setup_revisions(argv.argc, argv.argv, &rev, NULL); if (prepare_revision_walk(&rev)) die("revision walk setup failed"); /* * Collect all submodules (whether checked out or not) for which new * commits have been recorded upstream in "changed_submodule_paths". */ while ((commit = get_revision(&rev))) { struct commit_list *parent = commit->parents; while (parent) { struct diff_options diff_opts; diff_setup(&diff_opts); DIFF_OPT_SET(&diff_opts, RECURSIVE); diff_opts.output_format |= DIFF_FORMAT_CALLBACK; diff_opts.format_callback = submodule_collect_changed_cb; if (diff_setup_done(&diff_opts) < 0) die("diff_setup_done failed"); diff_tree_sha1(parent->item->object.sha1, commit->object.sha1, "", &diff_opts); diffcore_std(&diff_opts); diff_flush(&diff_opts); parent = parent->next; } } argv_array_clear(&argv); sha1_array_clear(&ref_tips_before_fetch); sha1_array_clear(&ref_tips_after_fetch); initialized_fetch_ref_tips = 0; }
/* Returns 1 if a shallow list is sent or 0 otherwise */ static int send_shallow_list(int depth, int deepen_rev_list, timestamp_t deepen_since, struct string_list *deepen_not, struct object_array *shallows) { int ret = 0; if (depth > 0 && deepen_rev_list) die("git upload-pack: deepen and deepen-since (or deepen-not) cannot be used together"); if (depth > 0) { deepen(depth, deepen_relative, shallows); ret = 1; } else if (deepen_rev_list) { struct argv_array av = ARGV_ARRAY_INIT; int i; argv_array_push(&av, "rev-list"); if (deepen_since) argv_array_pushf(&av, "--max-age=%"PRItime, deepen_since); if (deepen_not->nr) { argv_array_push(&av, "--not"); for (i = 0; i < deepen_not->nr; i++) { struct string_list_item *s = deepen_not->items + i; argv_array_push(&av, s->string); } argv_array_push(&av, "--not"); } for (i = 0; i < want_obj.nr; i++) { struct object *o = want_obj.objects[i].item; argv_array_push(&av, oid_to_hex(&o->oid)); } deepen_by_rev_list(av.argc, av.argv, shallows); argv_array_clear(&av); ret = 1; } else { if (shallows->nr > 0) { int i; for (i = 0; i < shallows->nr; i++) register_shallow(the_repository, &shallows->objects[i].item->oid); } } shallow_nr += shallows->nr; return ret; }
/** * Given the current HEAD SHA1, the merge head returned from git-fetch and the * fork point calculated by get_rebase_fork_point(), runs git-rebase with the * appropriate arguments and returns its exit status. */ static int run_rebase(const unsigned char *curr_head, const unsigned char *merge_head, const unsigned char *fork_point) { int ret; unsigned char oct_merge_base[GIT_SHA1_RAWSZ]; struct argv_array args = ARGV_ARRAY_INIT; if (!get_octopus_merge_base(oct_merge_base, curr_head, merge_head, fork_point)) if (!is_null_sha1(fork_point) && !hashcmp(oct_merge_base, fork_point)) fork_point = NULL; argv_array_push(&args, "rebase"); /* Shared options */ argv_push_verbosity(&args); /* Options passed to git-rebase */ if (opt_rebase == REBASE_PRESERVE) argv_array_push(&args, "--preserve-merges"); else if (opt_rebase == REBASE_INTERACTIVE) argv_array_push(&args, "--interactive"); if (opt_diffstat) argv_array_push(&args, opt_diffstat); argv_array_pushv(&args, opt_strategies.argv); argv_array_pushv(&args, opt_strategy_opts.argv); if (opt_gpg_sign) argv_array_push(&args, opt_gpg_sign); if (opt_autostash == 0) argv_array_push(&args, "--no-autostash"); else if (opt_autostash == 1) argv_array_push(&args, "--autostash"); argv_array_push(&args, "--onto"); argv_array_push(&args, sha1_to_hex(merge_head)); if (fork_point && !is_null_sha1(fork_point)) argv_array_push(&args, sha1_to_hex(fork_point)); else argv_array_push(&args, sha1_to_hex(merge_head)); ret = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); return ret; }
int run_hook(const char *index_file, const char *name, ...) { struct child_process hook; struct argv_array argv = ARGV_ARRAY_INIT; const char *p, *env[2]; char index[PATH_MAX]; va_list args; int ret; // If this is not reset to NULL, then strange stuff happens hook_directory = NULL; // Load the configuration for hooks.directory git_config(git_hook_config, NULL); // If the configuration is not set for hooks directory, set it to the // default GIT_PATH/hooks directory that we all know and love. if(hook_directory == NULL) hook_directory = git_path("hooks"); if (access(mkpath("%s/%s", hook_directory, name), X_OK) < 0) return 0; va_start(args, name); argv_array_push(&argv, mkpath("%s/%s", hook_directory, name)); while ((p = va_arg(args, const char *))) argv_array_push(&argv, p); va_end(args); memset(&hook, 0, sizeof(hook)); hook.argv = argv.argv; hook.no_stdin = 1; hook.stdout_to_stderr = 1; if (index_file) { snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file); env[0] = index; env[1] = NULL; hook.env = env; } ret = run_command(&hook); argv_array_clear(&argv); return ret; }
static void run_service(const char **argv) { const char *encoding = getenv("HTTP_CONTENT_ENCODING"); const char *user = getenv("REMOTE_USER"); const char *host = getenv("REMOTE_ADDR"); struct argv_array env = ARGV_ARRAY_INIT; int gzipped_request = 0; struct child_process cld; if (encoding && !strcmp(encoding, "gzip")) gzipped_request = 1; else if (encoding && !strcmp(encoding, "x-gzip")) gzipped_request = 1; if (!user || !*user) user = "******"; if (!host || !*host) host = "(none)"; if (!getenv("GIT_COMMITTER_NAME")) argv_array_pushf(&env, "GIT_COMMITTER_NAME=%s", user); if (!getenv("GIT_COMMITTER_EMAIL")) argv_array_pushf(&env, "GIT_COMMITTER_EMAIL=%s@http.%s", user, host); memset(&cld, 0, sizeof(cld)); cld.argv = argv; cld.env = env.argv; if (gzipped_request) cld.in = -1; cld.git_cmd = 1; if (start_command(&cld)) exit(1); close(1); if (gzipped_request) inflate_request(argv[0], cld.in); else close(0); if (finish_command(&cld)) exit(1); argv_array_clear(&env); }
static const char *update_worktree(unsigned char *sha1) { const char *retval; const char *work_tree = git_work_tree_cfg ? git_work_tree_cfg : ".."; struct argv_array env = ARGV_ARRAY_INIT; if (is_bare_repository()) return "denyCurrentBranch = updateInstead needs a worktree"; argv_array_pushf(&env, "GIT_DIR=%s", absolute_path(get_git_dir())); if (!find_hook(push_to_checkout_hook)) retval = push_to_deploy(sha1, &env, work_tree); else retval = push_to_checkout(sha1, &env, work_tree); argv_array_clear(&env); return retval; }
int run_add_interactive(const char *revision, const char *patch_mode, const struct pathspec *pathspec) { int status, i; struct argv_array argv = ARGV_ARRAY_INIT; argv_array_push(&argv, "add--interactive"); if (patch_mode) argv_array_push(&argv, patch_mode); if (revision) argv_array_push(&argv, revision); argv_array_push(&argv, "--"); for (i = 0; i < pathspec->nr; i++) /* pass original pathspec, to be re-parsed */ argv_array_push(&argv, pathspec->items[i].original); status = run_command_v_opt(argv.argv, RUN_GIT_CMD); argv_array_clear(&argv); return status; }
/** * Runs git-merge, returning its exit status. */ static int run_merge(void) { int ret; struct argv_array args = ARGV_ARRAY_INIT; argv_array_pushl(&args, "merge", NULL); /* Shared options */ argv_push_verbosity(&args); if (opt_progress) argv_array_push(&args, opt_progress); /* Options passed to git-merge */ if (opt_diffstat) argv_array_push(&args, opt_diffstat); if (opt_log) argv_array_push(&args, opt_log); if (opt_signoff) argv_array_push(&args, opt_signoff); if (opt_squash) argv_array_push(&args, opt_squash); if (opt_commit) argv_array_push(&args, opt_commit); if (opt_edit) argv_array_push(&args, opt_edit); if (opt_ff) argv_array_push(&args, opt_ff); if (opt_verify_signatures) argv_array_push(&args, opt_verify_signatures); argv_array_pushv(&args, opt_strategies.argv); argv_array_pushv(&args, opt_strategy_opts.argv); if (opt_gpg_sign) argv_array_push(&args, opt_gpg_sign); if (opt_allow_unrelated_histories > 0) argv_array_push(&args, "--allow-unrelated-histories"); argv_array_push(&args, "FETCH_HEAD"); ret = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); return ret; }
static int run_post_command_hook(void) { char *lock; int ret = 0; /* * Only run post_command if pre_command succeeded in this process */ if (!run_post_hook) return 0; lock = getenv("COMMAND_HOOK_LOCK"); if (!lock || strcmp(lock, "true")) return 0; argv_array_pushf(&sargv, "--exit_code=%u", exit_code); ret = run_hook_argv(NULL, "post-command", sargv.argv); run_post_hook = 0; argv_array_clear(&sargv); setenv("COMMAND_HOOK_LOCK", "false", 1); return ret; }
int fetch_populated_submodules(const struct argv_array *options, const char *prefix, int command_line_option, int quiet, int max_parallel_jobs) { int i; struct submodule_parallel_fetch spf = SPF_INIT; spf.work_tree = get_git_work_tree(); spf.command_line_option = command_line_option; spf.quiet = quiet; spf.prefix = prefix; if (!spf.work_tree) goto out; if (read_cache() < 0) die("index file corrupt"); argv_array_push(&spf.args, "fetch"); for (i = 0; i < options->argc; i++) argv_array_push(&spf.args, options->argv[i]); argv_array_push(&spf.args, "--recurse-submodules-default"); /* default value, "--submodule-prefix" and its value are added later */ if (max_parallel_jobs < 0) max_parallel_jobs = parallel_jobs; calculate_changed_submodule_paths(); run_processes_parallel(max_parallel_jobs, get_next_submodule, fetch_start_failure, fetch_finish, &spf); argv_array_clear(&spf.args); out: string_list_clear(&changed_submodule_paths, 1); return spf.result; }
static int push_git(struct discovery *heads, int nr_spec, char **specs) { struct rpc_state rpc; int i, err; struct argv_array args; struct string_list_item *cas_option; argv_array_init(&args); argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status", NULL); if (options.thin) argv_array_push(&args, "--thin"); if (options.dry_run) argv_array_push(&args, "--dry-run"); if (options.verbosity == 0) argv_array_push(&args, "--quiet"); else if (options.verbosity > 1) argv_array_push(&args, "--verbose"); argv_array_push(&args, options.progress ? "--progress" : "--no-progress"); for_each_string_list_item(cas_option, &cas_options) argv_array_push(&args, cas_option->string); argv_array_push(&args, url.buf); for (i = 0; i < nr_spec; i++) argv_array_push(&args, specs[i]); memset(&rpc, 0, sizeof(rpc)); rpc.service_name = "git-receive-pack", rpc.argv = args.argv; err = rpc_service(&rpc, heads); if (rpc.result.len) write_or_die(1, rpc.result.buf, rpc.result.len); strbuf_release(&rpc.result); argv_array_clear(&args); return err; }
int start_command(struct child_process *cmd) { int need_in, need_out, need_err; int fdin[2], fdout[2], fderr[2]; int failed_errno; char *str; if (!cmd->argv) cmd->argv = cmd->args.argv; if (!cmd->env) cmd->env = cmd->env_array.argv; /* * In case of errors we must keep the promise to close FDs * that have been passed in via ->in and ->out. */ need_in = !cmd->no_stdin && cmd->in < 0; if (need_in) { if (pipe(fdin) < 0) { failed_errno = errno; if (cmd->out > 0) close(cmd->out); str = "standard input"; goto fail_pipe; } cmd->in = fdin[1]; } need_out = !cmd->no_stdout && !cmd->stdout_to_stderr && cmd->out < 0; if (need_out) { if (pipe(fdout) < 0) { failed_errno = errno; if (need_in) close_pair(fdin); else if (cmd->in) close(cmd->in); str = "standard output"; goto fail_pipe; } cmd->out = fdout[0]; } need_err = !cmd->no_stderr && cmd->err < 0; if (need_err) { if (pipe(fderr) < 0) { failed_errno = errno; if (need_in) close_pair(fdin); else if (cmd->in) close(cmd->in); if (need_out) close_pair(fdout); else if (cmd->out) close(cmd->out); str = "standard error"; fail_pipe: error("cannot create %s pipe for %s: %s", str, cmd->argv[0], strerror(failed_errno)); child_process_clear(cmd); errno = failed_errno; return -1; } cmd->err = fderr[0]; } trace_argv_printf(cmd->argv, "trace: run_command:"); fflush(NULL); #ifndef GIT_WINDOWS_NATIVE { int notify_pipe[2]; if (pipe(notify_pipe)) notify_pipe[0] = notify_pipe[1] = -1; cmd->pid = fork(); failed_errno = errno; if (!cmd->pid) { /* * Redirect the channel to write syscall error messages to * before redirecting the process's stderr so that all die() * in subsequent call paths use the parent's stderr. */ if (cmd->no_stderr || need_err) { int child_err = dup(2); set_cloexec(child_err); set_error_handle(fdopen(child_err, "w")); } close(notify_pipe[0]); set_cloexec(notify_pipe[1]); child_notifier = notify_pipe[1]; atexit(notify_parent); if (cmd->no_stdin) dup_devnull(0); else if (need_in) { dup2(fdin[0], 0); close_pair(fdin); } else if (cmd->in) { dup2(cmd->in, 0); close(cmd->in); } if (cmd->no_stderr) dup_devnull(2); else if (need_err) { dup2(fderr[1], 2); close_pair(fderr); } else if (cmd->err > 1) { dup2(cmd->err, 2); close(cmd->err); } if (cmd->no_stdout) dup_devnull(1); else if (cmd->stdout_to_stderr) dup2(2, 1); else if (need_out) { dup2(fdout[1], 1); close_pair(fdout); } else if (cmd->out > 1) { dup2(cmd->out, 1); close(cmd->out); } if (cmd->dir && chdir(cmd->dir)) die_errno("exec '%s': cd to '%s' failed", cmd->argv[0], cmd->dir); if (cmd->env) { for (; *cmd->env; cmd->env++) { if (strchr(*cmd->env, '=')) putenv((char *)*cmd->env); else unsetenv(*cmd->env); } } if (cmd->git_cmd) execv_git_cmd(cmd->argv); else if (cmd->use_shell) execv_shell_cmd(cmd->argv); else sane_execvp(cmd->argv[0], (char *const*) cmd->argv); if (errno == ENOENT) { if (!cmd->silent_exec_failure) error("cannot run %s: %s", cmd->argv[0], strerror(ENOENT)); exit(127); } else { die_errno("cannot exec '%s'", cmd->argv[0]); } } if (cmd->pid < 0) error("cannot fork() for %s: %s", cmd->argv[0], strerror(errno)); else if (cmd->clean_on_exit) mark_child_for_cleanup(cmd->pid); /* * Wait for child's execvp. If the execvp succeeds (or if fork() * failed), EOF is seen immediately by the parent. Otherwise, the * child process sends a single byte. * Note that use of this infrastructure is completely advisory, * therefore, we keep error checks minimal. */ close(notify_pipe[1]); if (read(notify_pipe[0], ¬ify_pipe[1], 1) == 1) { /* * At this point we know that fork() succeeded, but execvp() * failed. Errors have been reported to our stderr. */ wait_or_whine(cmd->pid, cmd->argv[0], 0); failed_errno = errno; cmd->pid = -1; } close(notify_pipe[0]); } #else { int fhin = 0, fhout = 1, fherr = 2; const char **sargv = cmd->argv; struct argv_array nargv = ARGV_ARRAY_INIT; if (cmd->no_stdin) fhin = open("/dev/null", O_RDWR); else if (need_in) fhin = dup(fdin[0]); else if (cmd->in) fhin = dup(cmd->in); if (cmd->no_stderr) fherr = open("/dev/null", O_RDWR); else if (need_err) fherr = dup(fderr[1]); else if (cmd->err > 2) fherr = dup(cmd->err); if (cmd->no_stdout) fhout = open("/dev/null", O_RDWR); else if (cmd->stdout_to_stderr) fhout = dup(fherr); else if (need_out) fhout = dup(fdout[1]); else if (cmd->out > 1) fhout = dup(cmd->out); if (cmd->git_cmd) cmd->argv = prepare_git_cmd(&nargv, cmd->argv); else if (cmd->use_shell) cmd->argv = prepare_shell_cmd(&nargv, cmd->argv); cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, (char**) cmd->env, cmd->dir, fhin, fhout, fherr); failed_errno = errno; if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT)) error("cannot spawn %s: %s", cmd->argv[0], strerror(errno)); if (cmd->clean_on_exit && cmd->pid >= 0) mark_child_for_cleanup(cmd->pid); argv_array_clear(&nargv); cmd->argv = sargv; if (fhin != 0) close(fhin); if (fhout != 1) close(fhout); if (fherr != 2) close(fherr); } #endif if (cmd->pid < 0) { if (need_in) close_pair(fdin); else if (cmd->in) close(cmd->in); if (need_out) close_pair(fdout); else if (cmd->out) close(cmd->out); if (need_err) close_pair(fderr); else if (cmd->err) close(cmd->err); child_process_clear(cmd); errno = failed_errno; return -1; } if (need_in) close(fdin[0]); else if (cmd->in) close(cmd->in); if (need_out) close(fdout[1]); else if (cmd->out) close(cmd->out); if (need_err) close(fderr[1]); else if (cmd->err) close(cmd->err); return 0; }