#include "git-compat-util.h"
#include "add-patch.h"
#include "advice.h"
+#include "commit.h"
#include "config.h"
#include "diff.h"
#include "editor.h"
#include "environment.h"
#include "gettext.h"
+#include "hex.h"
#include "object-name.h"
#include "pager.h"
#include "read-cache-ll.h"
struct add_p_state {
struct repository *r;
+ struct index_state *index;
+ const char *index_file;
struct interactive_config cfg;
struct strbuf answer, buf;
cp->git_cmd = 1;
strvec_pushf(&cp->env,
- INDEX_ENVIRONMENT "=%s", s->r->index_file);
+ INDEX_ENVIRONMENT "=%s", s->index_file);
}
static int parse_range(const char **p,
strbuf_reset(&s->buf);
reassemble_patch(s, file_diff, 0, &s->buf);
- discard_index(s->r->index);
+ discard_index(s->index);
if (s->mode->apply_for_checkout)
apply_for_checkout(s, &s->buf,
s->mode->is_reverse);
NULL, 0, NULL, 0))
error(_("'git apply' failed"));
}
- if (repo_read_index(s->r) >= 0)
+ if (read_index_from(s->index, s->index_file, s->r->gitdir) >= 0 &&
+ s->index == s->r->index) {
repo_refresh_and_write_index(s->r, REFRESH_QUIET, 0,
1, NULL, NULL, NULL);
+ }
}
putchar('\n');
{
struct add_p_state s = {
.r = r,
+ .index = r->index,
+ .index_file = r->index_file,
.answer = STRBUF_INIT,
.buf = STRBUF_INIT,
.plain = STRBUF_INIT,
add_p_state_clear(&s);
return 0;
}
+
+int run_add_p_index(struct repository *r,
+ struct index_state *index,
+ const char *index_file,
+ struct interactive_options *opts,
+ const char *revision,
+ const struct pathspec *ps)
+{
+ struct patch_mode mode = {
+ .apply_args = { "--cached", NULL },
+ .apply_check_args = { "--cached", NULL },
+ .prompt_mode = {
+ N_("Stage mode change [y,n,q,a,d%s,?]? "),
+ N_("Stage deletion [y,n,q,a,d%s,?]? "),
+ N_("Stage addition [y,n,q,a,d%s,?]? "),
+ N_("Stage this hunk [y,n,q,a,d%s,?]? ")
+ },
+ .edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
+ "will immediately be marked for staging."),
+ .help_patch_text =
+ N_("y - stage this hunk\n"
+ "n - do not stage this hunk\n"
+ "q - quit; do not stage this hunk or any of the remaining "
+ "ones\n"
+ "a - stage this hunk and all later hunks in the file\n"
+ "d - do not stage this hunk or any of the later hunks in "
+ "the file\n"),
+ .index_only = 1,
+ };
+ struct add_p_state s = {
+ .r = r,
+ .index = index,
+ .index_file = index_file,
+ .answer = STRBUF_INIT,
+ .buf = STRBUF_INIT,
+ .plain = STRBUF_INIT,
+ .colored = STRBUF_INIT,
+ .mode = &mode,
+ .revision = revision,
+ };
+ struct strbuf parent_revision = STRBUF_INIT;
+ char parent_tree_oid[GIT_MAX_HEXSZ + 1];
+ size_t binary_count = 0;
+ struct commit *commit;
+ int ret;
+
+ commit = lookup_commit_reference_by_name(revision);
+ if (!commit) {
+ err(&s, _("Revision does not refer to a commit"));
+ ret = -1;
+ goto out;
+ }
+
+ if (commit->parents)
+ oid_to_hex_r(parent_tree_oid, get_commit_tree_oid(commit->parents->item));
+ else
+ oid_to_hex_r(parent_tree_oid, r->hash_algo->empty_tree);
+
+ strbuf_addf(&parent_revision, "%s~", revision);
+ mode.diff_cmd[0] = "diff-tree";
+ mode.diff_cmd[1] = "-r";
+ mode.diff_cmd[2] = parent_tree_oid;
+
+ interactive_config_init(&s.cfg, r, opts);
+
+ if (parse_diff(&s, ps) < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ for (size_t i = 0; i < s.file_diff_nr; i++) {
+ if (s.file_diff[i].binary && !s.file_diff[i].hunk_nr)
+ binary_count++;
+ else if (patch_update_file(&s, s.file_diff + i))
+ break;
+ }
+
+ if (s.file_diff_nr == 0) {
+ err(&s, _("No changes."));
+ ret = -1;
+ goto out;
+ }
+
+ if (binary_count == s.file_diff_nr) {
+ err(&s, _("Only binary files changed."));
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ strbuf_release(&parent_revision);
+ add_p_state_clear(&s);
+ return ret;
+}