static int clone_submodule(const char *path, const char *gitdir, const char *url, const char *depth, const char *reference, int quiet) { struct child_process cp; child_process_init(&cp); argv_array_push(&cp.args, "clone"); argv_array_push(&cp.args, "--no-checkout"); if (quiet) argv_array_push(&cp.args, "--quiet"); if (depth && *depth) argv_array_pushl(&cp.args, "--depth", depth, NULL); if (reference && *reference) argv_array_pushl(&cp.args, "--reference", reference, NULL); if (gitdir && *gitdir) argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL); argv_array_push(&cp.args, url); argv_array_push(&cp.args, path); cp.git_cmd = 1; cp.env = local_repo_env; cp.no_stdin = 1; return run_command(&cp); }
static int clone_submodule(const char *path, const char *gitdir, const char *url, const char *depth, struct string_list *reference, int quiet, int progress) { struct child_process cp = CHILD_PROCESS_INIT; argv_array_push(&cp.args, "clone"); argv_array_push(&cp.args, "--no-checkout"); if (quiet) argv_array_push(&cp.args, "--quiet"); if (progress) argv_array_push(&cp.args, "--progress"); if (depth && *depth) argv_array_pushl(&cp.args, "--depth", depth, NULL); if (reference->nr) { struct string_list_item *item; for_each_string_list_item(item, reference) argv_array_pushl(&cp.args, "--reference", item->string, NULL); } if (gitdir && *gitdir) argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL); argv_array_push(&cp.args, url); argv_array_push(&cp.args, path); cp.git_cmd = 1; prepare_submodule_repo_env(&cp.env_array); cp.no_stdin = 1; return run_command(&cp); }
static int stash_patch(struct stash_info *info, struct pathspec ps, struct strbuf *out_patch, int quiet) { int ret = 0; struct child_process cp_read_tree = CHILD_PROCESS_INIT; struct child_process cp_add_i = CHILD_PROCESS_INIT; struct child_process cp_diff_tree = CHILD_PROCESS_INIT; struct index_state istate = { NULL }; remove_path(stash_index_path.buf); cp_read_tree.git_cmd = 1; argv_array_pushl(&cp_read_tree.args, "read-tree", "HEAD", NULL); argv_array_pushf(&cp_read_tree.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); if (run_command(&cp_read_tree)) { ret = -1; goto done; } /* Find out what the user wants. */ cp_add_i.git_cmd = 1; argv_array_pushl(&cp_add_i.args, "add--interactive", "--patch=stash", "--", NULL); add_pathspecs(&cp_add_i.args, ps); argv_array_pushf(&cp_add_i.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); if (run_command(&cp_add_i)) { ret = -1; goto done; } /* State of the working tree. */ if (write_index_as_tree(&info->w_tree, &istate, stash_index_path.buf, 0, NULL)) { ret = -1; goto done; } cp_diff_tree.git_cmd = 1; argv_array_pushl(&cp_diff_tree.args, "diff-tree", "-p", "HEAD", oid_to_hex(&info->w_tree), "--", NULL); if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) { ret = -1; goto done; } if (!out_patch->len) { if (!quiet) fprintf_ln(stderr, _("No changes selected")); ret = 1; } done: discard_index(&istate); remove_path(stash_index_path.buf); return ret; }
static void changed_files(struct hashmap *result, const char *index_path, const char *workdir) { struct child_process update_index = CHILD_PROCESS_INIT; struct child_process diff_files = CHILD_PROCESS_INIT; struct strbuf index_env = STRBUF_INIT, buf = STRBUF_INIT; const char *git_dir = absolute_path(get_git_dir()), *env[] = { NULL, NULL }; FILE *fp; strbuf_addf(&index_env, "GIT_INDEX_FILE=%s", index_path); env[0] = index_env.buf; argv_array_pushl(&update_index.args, "--git-dir", git_dir, "--work-tree", workdir, "update-index", "--really-refresh", "-q", "--unmerged", NULL); update_index.no_stdin = 1; update_index.no_stdout = 1; update_index.no_stderr = 1; update_index.git_cmd = 1; update_index.use_shell = 0; update_index.clean_on_exit = 1; update_index.dir = workdir; update_index.env = env; /* Ignore any errors of update-index */ run_command(&update_index); argv_array_pushl(&diff_files.args, "--git-dir", git_dir, "--work-tree", workdir, "diff-files", "--name-only", "-z", NULL); diff_files.no_stdin = 1; diff_files.git_cmd = 1; diff_files.use_shell = 0; diff_files.clean_on_exit = 1; diff_files.out = -1; diff_files.dir = workdir; diff_files.env = env; if (start_command(&diff_files)) die("could not obtain raw diff"); fp = xfdopen(diff_files.out, "r"); while (!strbuf_getline_nul(&buf, fp)) { struct path_entry *entry; FLEX_ALLOC_STR(entry, path, buf.buf); hashmap_entry_init(entry, strhash(buf.buf)); hashmap_add(result, entry); } fclose(fp); if (finish_command(&diff_files)) die("diff-files did not exit properly"); strbuf_release(&index_env); strbuf_release(&buf); }
static int write_pack_data(int bundle_fd, struct lock_file *lock, struct rev_info *revs) { struct child_process pack_objects = CHILD_PROCESS_INIT; int i; argv_array_pushl(&pack_objects.args, "pack-objects", "--all-progress-implied", "--stdout", "--thin", "--delta-base-offset", NULL); pack_objects.in = -1; pack_objects.out = bundle_fd; pack_objects.git_cmd = 1; if (start_command(&pack_objects)) return error(_("Could not spawn pack-objects")); /* * start_command closed bundle_fd if it was > 1 * so set the lock fd to -1 so commit_lock_file() * won't fail trying to close it. */ lock->fd = -1; for (i = 0; i < revs->pending.nr; i++) { struct object *object = revs->pending.objects[i].item; if (object->flags & UNINTERESTING) write_or_die(pack_objects.in, "^", 1); write_or_die(pack_objects.in, sha1_to_hex(object->sha1), 40); write_or_die(pack_objects.in, "\n", 1); } close(pack_objects.in); if (finish_command(&pack_objects)) return error(_("pack-objects died")); return 0; }
static int upload_pack(void) { struct child_process cld = CHILD_PROCESS_INIT; argv_array_pushl(&cld.args, "upload-pack", "--strict", NULL); argv_array_pushf(&cld.args, "--timeout=%u", timeout); return run_service_command(&cld); }
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(); }
static int stash_working_tree(struct stash_info *info, struct pathspec ps) { int ret = 0; struct rev_info rev; struct child_process cp_upd_index = CHILD_PROCESS_INIT; struct strbuf diff_output = STRBUF_INIT; struct index_state istate = { NULL }; init_revisions(&rev, NULL); set_alternate_index_output(stash_index_path.buf); if (reset_tree(&info->i_tree, 0, 0)) { ret = -1; goto done; } set_alternate_index_output(NULL); rev.prune_data = ps; rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = add_diff_to_buf; rev.diffopt.format_callback_data = &diff_output; if (read_cache_preload(&rev.diffopt.pathspec) < 0) { ret = -1; goto done; } add_pending_object(&rev, parse_object(the_repository, &info->b_commit), ""); if (run_diff_index(&rev, 0)) { ret = -1; goto done; } cp_upd_index.git_cmd = 1; argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add", "--remove", "--stdin", NULL); argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); if (pipe_command(&cp_upd_index, diff_output.buf, diff_output.len, NULL, 0, NULL, 0)) { ret = -1; goto done; } if (write_index_as_tree(&info->w_tree, &istate, stash_index_path.buf, 0, NULL)) { ret = -1; goto done; } done: discard_index(&istate); UNLEAK(rev); object_array_clear(&rev.pending); strbuf_release(&diff_output); remove_path(stash_index_path.buf); return ret; }
/* Write the pack data to bundle_fd, then close it if it is > 1. */ static int write_pack_data(int bundle_fd, struct rev_info *revs) { struct child_process pack_objects = CHILD_PROCESS_INIT; int i; argv_array_pushl(&pack_objects.args, "pack-objects", "--all-progress-implied", "--stdout", "--thin", "--delta-base-offset", NULL); pack_objects.in = -1; pack_objects.out = bundle_fd; pack_objects.git_cmd = 1; if (start_command(&pack_objects)) return error(_("Could not spawn pack-objects")); for (i = 0; i < revs->pending.nr; i++) { struct object *object = revs->pending.objects[i].item; if (object->flags & UNINTERESTING) write_or_die(pack_objects.in, "^", 1); write_or_die(pack_objects.in, oid_to_hex(&object->oid), GIT_SHA1_HEXSZ); write_or_die(pack_objects.in, "\n", 1); } close(pack_objects.in); if (finish_command(&pack_objects)) return error(_("pack-objects died")); return 0; }
static int restore_untracked(struct object_id *u_tree) { int res; struct child_process cp = CHILD_PROCESS_INIT; /* * We need to run restore files from a given index, but without * affecting the current index, so we use GIT_INDEX_FILE with * run_command to fork processes that will not interfere. */ cp.git_cmd = 1; argv_array_push(&cp.args, "read-tree"); argv_array_push(&cp.args, oid_to_hex(u_tree)); argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); if (run_command(&cp)) { remove_path(stash_index_path.buf); return -1; } child_process_init(&cp); cp.git_cmd = 1; argv_array_pushl(&cp.args, "checkout-index", "--all", NULL); argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); res = run_command(&cp); remove_path(stash_index_path.buf); return res; }
static int do_drop_stash(const char *prefix, struct stash_info *info, int quiet) { int ret; struct child_process cp_reflog = CHILD_PROCESS_INIT; struct child_process cp = CHILD_PROCESS_INIT; /* * reflog does not provide a simple function for deleting refs. One will * need to be added to avoid implementing too much reflog code here */ cp_reflog.git_cmd = 1; argv_array_pushl(&cp_reflog.args, "reflog", "delete", "--updateref", "--rewrite", NULL); argv_array_push(&cp_reflog.args, info->revision.buf); ret = run_command(&cp_reflog); if (!ret) { if (!quiet) printf_ln(_("Dropped %s (%s)"), info->revision.buf, oid_to_hex(&info->w_commit)); } else { return error(_("%s: Could not drop stash entry"), info->revision.buf); } /* * This could easily be replaced by get_oid, but currently it will throw * a fatal error when a reflog is empty, which we can not recover from. */ cp.git_cmd = 1; /* Even though --quiet is specified, rev-parse still outputs the hash */ cp.no_stdout = 1; argv_array_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL); argv_array_pushf(&cp.args, "%s@{0}", ref_stash); ret = run_command(&cp); /* do_clear_stash if we just dropped the last stash entry */ if (ret) do_clear_stash(); return 0; }
static int update_submodules(void) { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; cp.no_stdin = 1; argv_array_pushl(&cp.args, "submodule", "update", "--recursive", "--checkout", NULL); return run_command(&cp); }
static int update_index(struct strbuf *out) { struct child_process cp = CHILD_PROCESS_INIT; /* * Update-index is very complicated and may need to have a public * function exposed in order to remove this forking. */ cp.git_cmd = 1; argv_array_pushl(&cp.args, "update-index", "--add", "--stdin", NULL); return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 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. * * 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; }
static int apply_cached(struct strbuf *out) { struct child_process cp = CHILD_PROCESS_INIT; /* * Apply currently only reads either from stdin or a file, thus * apply_all_patches would have to be updated to optionally take a * buffer. */ cp.git_cmd = 1; argv_array_pushl(&cp.args, "apply", "--cached", NULL); return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0); }
/** * 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; }
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; }
/* * NEEDSWORK: this function can go once the legacy-difftool Perl script is * retired. * * We intentionally avoid reading the config directly here, to avoid messing up * the GIT_* environment variables when we need to fall back to exec()ing the * Perl script. */ static int use_builtin_difftool(void) { struct child_process cp = CHILD_PROCESS_INIT; struct strbuf out = STRBUF_INIT; int ret; argv_array_pushl(&cp.args, "config", "--bool", "difftool.usebuiltin", NULL); cp.git_cmd = 1; if (capture_command(&cp, &out, 6)) return 0; strbuf_trim(&out); ret = !strcmp("true", out.buf); strbuf_release(&out); return ret; }
static int get_newly_staged(struct strbuf *out, struct object_id *c_tree) { struct child_process cp = CHILD_PROCESS_INIT; const char *c_tree_hex = oid_to_hex(c_tree); /* * diff-index is very similar to diff-tree above, and should be * converted together with update_index. */ cp.git_cmd = 1; argv_array_pushl(&cp.args, "diff-index", "--cached", "--name-only", "--diff-filter=A", NULL); argv_array_push(&cp.args, c_tree_hex); return pipe_command(&cp, NULL, 0, out, 0, NULL, 0); }
static int diff_tree_binary(struct strbuf *out, struct object_id *w_commit) { struct child_process cp = CHILD_PROCESS_INIT; const char *w_commit_hex = oid_to_hex(w_commit); /* * Diff-tree would not be very hard to replace with a native function, * however it should be done together with apply_cached. */ cp.git_cmd = 1; argv_array_pushl(&cp.args, "diff-tree", "--binary", NULL); argv_array_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex); return pipe_command(&cp, NULL, 0, out, 0, NULL, 0); }
int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output, struct strbuf *gpg_status) { struct child_process gpg = CHILD_PROCESS_INIT; struct tempfile *temp; int ret; struct strbuf buf = STRBUF_INIT; temp = mks_tempfile_t(".git_vtag_tmpXXXXXX"); if (!temp) return error_errno(_("could not create temporary file")); if (write_in_full(temp->fd, signature, signature_size) < 0 || close_tempfile_gently(temp) < 0) { error_errno(_("failed writing detached signature to '%s'"), temp->filename.buf); delete_tempfile(&temp); return -1; } argv_array_pushl(&gpg.args, gpg_program, "--status-fd=1", "--keyid-format=long", "--verify", temp->filename.buf, "-", NULL); if (!gpg_status) gpg_status = &buf; sigchain_push(SIGPIPE, SIG_IGN); ret = pipe_command(&gpg, payload, payload_size, gpg_status, 0, gpg_output, 0); sigchain_pop(SIGPIPE); delete_tempfile(&temp); ret |= !strstr(gpg_status->buf, "\n[GNUPG:] GOODSIG "); strbuf_release(&buf); /* no matter it was used or not */ return ret; }
/** * 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; }
/* * Note, "git status --porcelain" is used to determine if it's safe to * delete a whole worktree. "git status" does not ignore user * configuration, so if a normal "git status" shows "clean" for the * user, then it's ok to remove it. * * This assumption may be a bad one. We may want to ignore * (potentially bad) user settings and only delete a worktree when * it's absolutely safe to do so from _our_ point of view because we * know better. */ static void check_clean_worktree(struct worktree *wt, const char *original_path) { struct argv_array child_env = ARGV_ARRAY_INIT; struct child_process cp; char buf[1]; int ret; /* * Until we sort this out, all submodules are "dirty" and * will abort this function. */ validate_no_submodules(wt); argv_array_pushf(&child_env, "%s=%s/.git", GIT_DIR_ENVIRONMENT, wt->path); argv_array_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, wt->path); memset(&cp, 0, sizeof(cp)); argv_array_pushl(&cp.args, "status", "--porcelain", "--ignore-submodules=none", NULL); cp.env = child_env.argv; cp.git_cmd = 1; cp.dir = wt->path; cp.out = -1; ret = start_command(&cp); if (ret) die_errno(_("failed to run 'git status' on '%s'"), original_path); ret = xread(cp.out, buf, sizeof(buf)); if (ret) die(_("'%s' is dirty, use --force to delete it"), original_path); close(cp.out); ret = finish_command(&cp); if (ret) die_errno(_("failed to run 'git status' on '%s', code %d"), original_path, ret); }
int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key) { struct child_process gpg = CHILD_PROCESS_INIT; int ret; size_t i, j, bottom; struct strbuf gpg_status = STRBUF_INIT; argv_array_pushl(&gpg.args, gpg_program, "--status-fd=2", "-bsau", signing_key, NULL); bottom = signature->len; /* * When the username signingkey is bad, program could be terminated * because gpg exits without reading and then write gets SIGPIPE. */ sigchain_push(SIGPIPE, SIG_IGN); ret = pipe_command(&gpg, buffer->buf, buffer->len, signature, 1024, &gpg_status, 0); sigchain_pop(SIGPIPE); ret |= !strstr(gpg_status.buf, "\n[GNUPG:] SIG_CREATED "); strbuf_release(&gpg_status); if (ret) return error(_("gpg failed to sign the data")); /* Strip CR from the line endings, in case we are on Windows. */ for (i = j = bottom; i < signature->len; i++) if (signature->buf[i] != '\r') { if (i != j) signature->buf[j] = signature->buf[i]; j++; } strbuf_setlen(signature, j); return 0; }
/** * Given the repo and refspecs, sets fork_point to the point at which the * current branch forked from its remote-tracking branch. Returns 0 on success, * -1 on failure. */ static int get_rebase_fork_point(struct object_id *fork_point, const char *repo, const char *refspec) { int ret; struct branch *curr_branch; const char *remote_branch; struct child_process cp = CHILD_PROCESS_INIT; struct strbuf sb = STRBUF_INIT; curr_branch = branch_get("HEAD"); if (!curr_branch) return -1; if (refspec) remote_branch = get_tracking_branch(repo, refspec); else remote_branch = get_upstream_branch(repo); if (!remote_branch) return -1; argv_array_pushl(&cp.args, "merge-base", "--fork-point", remote_branch, curr_branch->name, NULL); cp.no_stdin = 1; cp.no_stderr = 1; cp.git_cmd = 1; ret = capture_command(&cp, &sb, GIT_SHA1_HEXSZ); if (ret) goto cleanup; ret = get_oid_hex(sb.buf, fork_point); if (ret) goto cleanup; cleanup: strbuf_release(&sb); return ret ? -1 : 0; }
static int save_untracked_files(struct stash_info *info, struct strbuf *msg, struct strbuf files) { int ret = 0; struct strbuf untracked_msg = STRBUF_INIT; struct child_process cp_upd_index = CHILD_PROCESS_INIT; struct index_state istate = { NULL }; cp_upd_index.git_cmd = 1; argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add", "--remove", "--stdin", NULL); argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); strbuf_addf(&untracked_msg, "untracked files on %s\n", msg->buf); if (pipe_command(&cp_upd_index, files.buf, files.len, NULL, 0, NULL, 0)) { ret = -1; goto done; } if (write_index_as_tree(&info->u_tree, &istate, stash_index_path.buf, 0, NULL)) { ret = -1; goto done; } if (commit_tree(untracked_msg.buf, untracked_msg.len, &info->u_tree, NULL, &info->u_commit, NULL, NULL)) { ret = -1; goto done; } done: discard_index(&istate); strbuf_release(&untracked_msg); remove_path(stash_index_path.buf); return ret; }
static int list_stash(int argc, const char **argv, const char *prefix) { struct child_process cp = CHILD_PROCESS_INIT; struct option options[] = { OPT_END() }; argc = parse_options(argc, argv, prefix, options, git_stash_list_usage, PARSE_OPT_KEEP_UNKNOWN); if (!ref_exists(ref_stash)) return 0; cp.git_cmd = 1; argv_array_pushl(&cp.args, "log", "--format=%gd: %gs", "-g", "--first-parent", "-m", NULL); argv_array_pushv(&cp.args, argv); argv_array_push(&cp.args, ref_stash); argv_array_push(&cp.args, "--"); return run_command(&cp); }
static int compute_and_write_prerequisites(int bundle_fd, struct rev_info *revs, int argc, const char **argv) { struct child_process rls = CHILD_PROCESS_INIT; struct strbuf buf = STRBUF_INIT; FILE *rls_fout; int i; argv_array_pushl(&rls.args, "rev-list", "--boundary", "--pretty=oneline", NULL); for (i = 1; i < argc; i++) argv_array_push(&rls.args, argv[i]); rls.out = -1; rls.git_cmd = 1; if (start_command(&rls)) return -1; rls_fout = xfdopen(rls.out, "r"); while (strbuf_getwholeline(&buf, rls_fout, '\n') != EOF) { unsigned char sha1[20]; if (buf.len > 0 && buf.buf[0] == '-') { write_or_die(bundle_fd, buf.buf, buf.len); if (!get_sha1_hex(buf.buf + 1, sha1)) { struct object *object = parse_object_or_die(sha1, buf.buf); object->flags |= UNINTERESTING; add_pending_object(revs, object, buf.buf); } } else if (!get_sha1_hex(buf.buf, sha1)) { struct object *object = parse_object_or_die(sha1, buf.buf); object->flags |= SHOWN; } } strbuf_release(&buf); fclose(rls_fout); if (finish_command(&rls)) return error(_("rev-list died")); return 0; }
static int use_builtin_stash(void) { struct child_process cp = CHILD_PROCESS_INIT; struct strbuf out = STRBUF_INIT; int ret, env = git_env_bool("GIT_TEST_STASH_USE_BUILTIN", -1); if (env != -1) return env; argv_array_pushl(&cp.args, "config", "--bool", "stash.usebuiltin", NULL); cp.git_cmd = 1; if (capture_command(&cp, &out, 6)) { strbuf_release(&out); return 1; } strbuf_trim(&out); ret = !strcmp("true", out.buf); strbuf_release(&out); return ret; }
static int branch_stash(int argc, const char **argv, const char *prefix) { int ret; const char *branch = NULL; struct stash_info info; struct child_process cp = CHILD_PROCESS_INIT; struct option options[] = { OPT_END() }; argc = parse_options(argc, argv, prefix, options, git_stash_branch_usage, 0); if (!argc) { fprintf_ln(stderr, _("No branch name specified")); return -1; } branch = argv[0]; if (get_stash_info(&info, argc - 1, argv + 1)) return -1; cp.git_cmd = 1; argv_array_pushl(&cp.args, "checkout", "-b", NULL); argv_array_push(&cp.args, branch); argv_array_push(&cp.args, oid_to_hex(&info.b_commit)); ret = run_command(&cp); if (!ret) ret = do_apply_stash(prefix, &info, 1, 0); if (!ret && info.is_stash_ref) ret = do_drop_stash(prefix, &info, 0); free_stash_info(&info); return ret; }