summaryrefslogtreecommitdiff
path: root/add-patch.c
diff options
context:
space:
mode:
authorJohannes Schindelin <johannes.schindelin@gmx.de>2019-12-13 08:08:03 (GMT)
committerJunio C Hamano <gitster@pobox.com>2019-12-13 20:37:14 (GMT)
commitd6cf873340703098f2d7f54be457e4db1b32cf7b (patch)
tree98b9b8e925113bd30fd7074b0833a91a8f5edb0d /add-patch.c
parent9254bdfb4f971be4be5364341a0387e8a1f3734a (diff)
downloadgit-d6cf873340703098f2d7f54be457e4db1b32cf7b.zip
git-d6cf873340703098f2d7f54be457e4db1b32cf7b.tar.gz
git-d6cf873340703098f2d7f54be457e4db1b32cf7b.tar.bz2
built-in add -p: implement the '/' ("search regex") command
This patch implements the hunk searching feature in the C version of `git add -p`. A test is added to verify that this behavior matches the one of the Perl version of `git add -p`. Note that this involves a change of behavior: the Perl version uses (of course) the Perl flavor of regular expressions, while this patch uses the regcomp()/regexec(), i.e. POSIX extended regular expressions. In practice, this behavior change is unlikely to matter. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'add-patch.c')
-rw-r--r--add-patch.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/add-patch.c b/add-patch.c
index fdbb1e3..fd72850 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -1013,6 +1013,7 @@ N_("y - stage this hunk\n"
"k - leave this hunk undecided, see previous undecided hunk\n"
"K - leave this hunk undecided, see previous hunk\n"
"g - select a hunk to go to\n"
+ "/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
"? - print help\n");
@@ -1072,7 +1073,7 @@ static int patch_update_file(struct add_p_state *s,
if (hunk_index + 1 < file_diff->hunk_nr)
strbuf_addstr(&s->buf, ",J");
if (file_diff->hunk_nr > 1)
- strbuf_addstr(&s->buf, ",g");
+ strbuf_addstr(&s->buf, ",g,/");
if (hunk->splittable_into > 1)
strbuf_addstr(&s->buf, ",s");
if (hunk_index + 1 > file_diff->mode_change &&
@@ -1177,6 +1178,53 @@ soft_increment:
"Sorry, only %d hunks available.",
file_diff->hunk_nr),
(int)file_diff->hunk_nr);
+ } else if (s->answer.buf[0] == '/') {
+ regex_t regex;
+ int ret;
+
+ if (file_diff->hunk_nr < 2) {
+ err(s, _("No other hunks to search"));
+ continue;
+ }
+ strbuf_remove(&s->answer, 0, 1);
+ strbuf_trim_trailing_newline(&s->answer);
+ if (s->answer.len == 0) {
+ printf("%s", _("search for regex? "));
+ fflush(stdout);
+ if (strbuf_getline(&s->answer,
+ stdin) == EOF)
+ break;
+ strbuf_trim_trailing_newline(&s->answer);
+ if (s->answer.len == 0)
+ continue;
+ }
+ ret = regcomp(&regex, s->answer.buf,
+ REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
+ if (ret) {
+ char errbuf[1024];
+
+ regerror(ret, &regex, errbuf, sizeof(errbuf));
+ err(s, _("Malformed search regexp %s: %s"),
+ s->answer.buf, errbuf);
+ continue;
+ }
+ i = hunk_index;
+ for (;;) {
+ /* render the hunk into a scratch buffer */
+ render_hunk(s, file_diff->hunk + i, 0, 0,
+ &s->buf);
+ if (regexec(&regex, s->buf.buf, 0, NULL, 0)
+ != REG_NOMATCH)
+ break;
+ i++;
+ if (i == file_diff->hunk_nr)
+ i = 0;
+ if (i != hunk_index)
+ continue;
+ err(s, _("No hunk matches the given pattern"));
+ break;
+ }
+ hunk_index = i;
} else if (s->answer.buf[0] == 's') {
size_t splittable_into = hunk->splittable_into;
if (splittable_into < 2)