add-patch: add support for in-memory index patching
With `run_add_p()` callers have the ability to apply changes from a specific revision to a repository's index. This infra supports several different modes, like for example applying changes to the index, worktree or both. One feature that is missing though is the ability to apply changes to an in-memory index different from the repository's index. Add a new function `run_add_p_index()` to plug this gap. This new function will be used in a subsequent commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>seen
parent
06abfd8ee7
commit
887b8ac77f
110
add-patch.c
110
add-patch.c
|
@ -4,11 +4,13 @@
|
||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
#include "add-patch.h"
|
#include "add-patch.h"
|
||||||
#include "advice.h"
|
#include "advice.h"
|
||||||
|
#include "commit.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "diff.h"
|
#include "diff.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
|
#include "hex.h"
|
||||||
#include "object-name.h"
|
#include "object-name.h"
|
||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
#include "read-cache-ll.h"
|
#include "read-cache-ll.h"
|
||||||
|
@ -263,6 +265,8 @@ struct hunk {
|
||||||
|
|
||||||
struct add_p_state {
|
struct add_p_state {
|
||||||
struct repository *r;
|
struct repository *r;
|
||||||
|
struct index_state *index;
|
||||||
|
const char *index_file;
|
||||||
struct interactive_config cfg;
|
struct interactive_config cfg;
|
||||||
struct strbuf answer, buf;
|
struct strbuf answer, buf;
|
||||||
|
|
||||||
|
@ -437,7 +441,7 @@ static void setup_child_process(struct add_p_state *s,
|
||||||
|
|
||||||
cp->git_cmd = 1;
|
cp->git_cmd = 1;
|
||||||
strvec_pushf(&cp->env,
|
strvec_pushf(&cp->env,
|
||||||
INDEX_ENVIRONMENT "=%s", s->r->index_file);
|
INDEX_ENVIRONMENT "=%s", s->index_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_range(const char **p,
|
static int parse_range(const char **p,
|
||||||
|
@ -1861,7 +1865,7 @@ soft_increment:
|
||||||
strbuf_reset(&s->buf);
|
strbuf_reset(&s->buf);
|
||||||
reassemble_patch(s, file_diff, 0, &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)
|
if (s->mode->apply_for_checkout)
|
||||||
apply_for_checkout(s, &s->buf,
|
apply_for_checkout(s, &s->buf,
|
||||||
s->mode->is_reverse);
|
s->mode->is_reverse);
|
||||||
|
@ -1872,10 +1876,12 @@ soft_increment:
|
||||||
NULL, 0, NULL, 0))
|
NULL, 0, NULL, 0))
|
||||||
error(_("'git apply' failed"));
|
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,
|
repo_refresh_and_write_index(s->r, REFRESH_QUIET, 0,
|
||||||
1, NULL, NULL, NULL);
|
1, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
return quit;
|
return quit;
|
||||||
|
@ -1887,6 +1893,8 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
|
||||||
{
|
{
|
||||||
struct add_p_state s = {
|
struct add_p_state s = {
|
||||||
.r = r,
|
.r = r,
|
||||||
|
.index = r->index,
|
||||||
|
.index_file = r->index_file,
|
||||||
.answer = STRBUF_INIT,
|
.answer = STRBUF_INIT,
|
||||||
.buf = STRBUF_INIT,
|
.buf = STRBUF_INIT,
|
||||||
.plain = STRBUF_INIT,
|
.plain = STRBUF_INIT,
|
||||||
|
@ -1945,3 +1953,99 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
|
||||||
add_p_state_clear(&s);
|
add_p_state_clear(&s);
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
|
||||||
|
struct index_state;
|
||||||
struct pathspec;
|
struct pathspec;
|
||||||
struct repository;
|
struct repository;
|
||||||
|
|
||||||
|
@ -53,4 +54,11 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
|
||||||
struct interactive_options *opts, const char *revision,
|
struct interactive_options *opts, const char *revision,
|
||||||
const struct pathspec *ps);
|
const struct pathspec *ps);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue