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>maint
parent
9254bdfb4f
commit
d6cf873340
50
add-patch.c
50
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 undecided hunk\n"
|
||||||
"K - leave this hunk undecided, see previous hunk\n"
|
"K - leave this hunk undecided, see previous hunk\n"
|
||||||
"g - select a hunk to go to\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"
|
"s - split the current hunk into smaller hunks\n"
|
||||||
"e - manually edit the current hunk\n"
|
"e - manually edit the current hunk\n"
|
||||||
"? - print help\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)
|
if (hunk_index + 1 < file_diff->hunk_nr)
|
||||||
strbuf_addstr(&s->buf, ",J");
|
strbuf_addstr(&s->buf, ",J");
|
||||||
if (file_diff->hunk_nr > 1)
|
if (file_diff->hunk_nr > 1)
|
||||||
strbuf_addstr(&s->buf, ",g");
|
strbuf_addstr(&s->buf, ",g,/");
|
||||||
if (hunk->splittable_into > 1)
|
if (hunk->splittable_into > 1)
|
||||||
strbuf_addstr(&s->buf, ",s");
|
strbuf_addstr(&s->buf, ",s");
|
||||||
if (hunk_index + 1 > file_diff->mode_change &&
|
if (hunk_index + 1 > file_diff->mode_change &&
|
||||||
|
@ -1177,6 +1178,53 @@ soft_increment:
|
||||||
"Sorry, only %d hunks available.",
|
"Sorry, only %d hunks available.",
|
||||||
file_diff->hunk_nr),
|
file_diff->hunk_nr),
|
||||||
(int)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(®ex, s->answer.buf,
|
||||||
|
REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
|
||||||
|
if (ret) {
|
||||||
|
char errbuf[1024];
|
||||||
|
|
||||||
|
regerror(ret, ®ex, 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(®ex, 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') {
|
} else if (s->answer.buf[0] == 's') {
|
||||||
size_t splittable_into = hunk->splittable_into;
|
size_t splittable_into = hunk->splittable_into;
|
||||||
if (splittable_into < 2)
|
if (splittable_into < 2)
|
||||||
|
|
|
@ -429,6 +429,20 @@ test_expect_success 'goto hunk' '
|
||||||
test_cmp expect actual.trimmed
|
test_cmp expect actual.trimmed
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'navigate to hunk via regex' '
|
||||||
|
test_when_finished "git reset" &&
|
||||||
|
tr _ " " >expect <<-EOF &&
|
||||||
|
(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,?]? @@ -1,2 +1,3 @@
|
||||||
|
_10
|
||||||
|
+15
|
||||||
|
_20
|
||||||
|
(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?_
|
||||||
|
EOF
|
||||||
|
test_write_lines s y /1,2 | git add -p >actual &&
|
||||||
|
tail -n 5 <actual >actual.trimmed &&
|
||||||
|
test_cmp expect actual.trimmed
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'split hunk "add -p (edit)"' '
|
test_expect_success 'split hunk "add -p (edit)"' '
|
||||||
# Split, say Edit and do nothing. Then:
|
# Split, say Edit and do nothing. Then:
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in New Issue