Skip to content

Commit f980648

Browse files
pks-tgitster
authored andcommitted
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, working tree 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>
1 parent 7c77c7c commit f980648

File tree

2 files changed

+116
-4
lines changed

2 files changed

+116
-4
lines changed

add-patch.c

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
#include "git-compat-util.h"
55
#include "add-patch.h"
66
#include "advice.h"
7+
#include "commit.h"
78
#include "config.h"
89
#include "diff.h"
910
#include "editor.h"
1011
#include "environment.h"
1112
#include "gettext.h"
13+
#include "hex.h"
1214
#include "object-name.h"
1315
#include "pager.h"
1416
#include "read-cache-ll.h"
@@ -47,7 +49,7 @@ static struct patch_mode patch_mode_add = {
4749
N_("Stage mode change [y,n,q,a,d%s,?]? "),
4850
N_("Stage deletion [y,n,q,a,d%s,?]? "),
4951
N_("Stage addition [y,n,q,a,d%s,?]? "),
50-
N_("Stage this hunk [y,n,q,a,d%s,?]? ")
52+
N_("Stage this hunk [y,n,q,a,d%s,?]? "),
5153
},
5254
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
5355
"will immediately be marked for staging."),
@@ -263,6 +265,8 @@ struct hunk {
263265

264266
struct add_p_state {
265267
struct repository *r;
268+
struct index_state *index;
269+
const char *index_file;
266270
struct interactive_config cfg;
267271
struct strbuf answer, buf;
268272

@@ -437,7 +441,7 @@ static void setup_child_process(struct add_p_state *s,
437441

438442
cp->git_cmd = 1;
439443
strvec_pushf(&cp->env,
440-
INDEX_ENVIRONMENT "=%s", s->r->index_file);
444+
INDEX_ENVIRONMENT "=%s", s->index_file);
441445
}
442446

443447
static int parse_range(const char **p,
@@ -1903,7 +1907,7 @@ static int patch_update_file(struct add_p_state *s,
19031907
strbuf_reset(&s->buf);
19041908
reassemble_patch(s, file_diff, 0, &s->buf);
19051909

1906-
discard_index(s->r->index);
1910+
discard_index(s->index);
19071911
if (s->mode->apply_for_checkout)
19081912
apply_for_checkout(s, &s->buf,
19091913
s->mode->is_reverse);
@@ -1914,9 +1918,11 @@ static int patch_update_file(struct add_p_state *s,
19141918
NULL, 0, NULL, 0))
19151919
error(_("'git apply' failed"));
19161920
}
1917-
if (repo_read_index(s->r) >= 0)
1921+
if (read_index_from(s->index, s->index_file, s->r->gitdir) >= 0 &&
1922+
s->index == s->r->index) {
19181923
repo_refresh_and_write_index(s->r, REFRESH_QUIET, 0,
19191924
1, NULL, NULL, NULL);
1925+
}
19201926
}
19211927

19221928
putchar('\n');
@@ -1929,6 +1935,8 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
19291935
{
19301936
struct add_p_state s = {
19311937
.r = r,
1938+
.index = r->index,
1939+
.index_file = r->index_file,
19321940
.answer = STRBUF_INIT,
19331941
.buf = STRBUF_INIT,
19341942
.plain = STRBUF_INIT,
@@ -1987,3 +1995,99 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
19871995
add_p_state_clear(&s);
19881996
return 0;
19891997
}
1998+
1999+
int run_add_p_index(struct repository *r,
2000+
struct index_state *index,
2001+
const char *index_file,
2002+
struct interactive_options *opts,
2003+
const char *revision,
2004+
const struct pathspec *ps)
2005+
{
2006+
struct patch_mode mode = {
2007+
.apply_args = { "--cached", NULL },
2008+
.apply_check_args = { "--cached", NULL },
2009+
.prompt_mode = {
2010+
N_("Stage mode change [y,n,q,a,d%s,?]? "),
2011+
N_("Stage deletion [y,n,q,a,d%s,?]? "),
2012+
N_("Stage addition [y,n,q,a,d%s,?]? "),
2013+
N_("Stage this hunk [y,n,q,a,d%s,?]? ")
2014+
},
2015+
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
2016+
"will immediately be marked for staging."),
2017+
.help_patch_text =
2018+
N_("y - stage this hunk\n"
2019+
"n - do not stage this hunk\n"
2020+
"q - quit; do not stage this hunk or any of the remaining "
2021+
"ones\n"
2022+
"a - stage this hunk and all later hunks in the file\n"
2023+
"d - do not stage this hunk or any of the later hunks in "
2024+
"the file\n"),
2025+
.index_only = 1,
2026+
};
2027+
struct add_p_state s = {
2028+
.r = r,
2029+
.index = index,
2030+
.index_file = index_file,
2031+
.answer = STRBUF_INIT,
2032+
.buf = STRBUF_INIT,
2033+
.plain = STRBUF_INIT,
2034+
.colored = STRBUF_INIT,
2035+
.mode = &mode,
2036+
.revision = revision,
2037+
};
2038+
struct strbuf parent_revision = STRBUF_INIT;
2039+
char parent_tree_oid[GIT_MAX_HEXSZ + 1];
2040+
size_t binary_count = 0;
2041+
struct commit *commit;
2042+
int ret;
2043+
2044+
commit = lookup_commit_reference_by_name(revision);
2045+
if (!commit) {
2046+
err(&s, _("Revision does not refer to a commit"));
2047+
ret = -1;
2048+
goto out;
2049+
}
2050+
2051+
if (commit->parents)
2052+
oid_to_hex_r(parent_tree_oid, get_commit_tree_oid(commit->parents->item));
2053+
else
2054+
oid_to_hex_r(parent_tree_oid, r->hash_algo->empty_tree);
2055+
2056+
strbuf_addf(&parent_revision, "%s~", revision);
2057+
mode.diff_cmd[0] = "diff-tree";
2058+
mode.diff_cmd[1] = "-r";
2059+
mode.diff_cmd[2] = parent_tree_oid;
2060+
2061+
interactive_config_init(&s.cfg, r, opts);
2062+
2063+
if (parse_diff(&s, ps) < 0) {
2064+
ret = -1;
2065+
goto out;
2066+
}
2067+
2068+
for (size_t i = 0; i < s.file_diff_nr; i++) {
2069+
if (s.file_diff[i].binary && !s.file_diff[i].hunk_nr)
2070+
binary_count++;
2071+
else if (patch_update_file(&s, s.file_diff + i))
2072+
break;
2073+
}
2074+
2075+
if (s.file_diff_nr == 0) {
2076+
err(&s, _("No changes."));
2077+
ret = -1;
2078+
goto out;
2079+
}
2080+
2081+
if (binary_count == s.file_diff_nr) {
2082+
err(&s, _("Only binary files changed."));
2083+
ret = -1;
2084+
goto out;
2085+
}
2086+
2087+
ret = 0;
2088+
2089+
out:
2090+
strbuf_release(&parent_revision);
2091+
add_p_state_clear(&s);
2092+
return ret;
2093+
}

add-patch.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "color.h"
55

6+
struct index_state;
67
struct pathspec;
78
struct repository;
89

@@ -53,4 +54,11 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
5354
struct interactive_options *opts, const char *revision,
5455
const struct pathspec *ps);
5556

57+
int run_add_p_index(struct repository *r,
58+
struct index_state *index,
59+
const char *index_file,
60+
struct interactive_options *opts,
61+
const char *revision,
62+
const struct pathspec *ps);
63+
5664
#endif

0 commit comments

Comments
 (0)