Skip to content

Commit fc87b2f

Browse files
rjustogitster
authored andcommitted
add-patch: render hunks through the pager
Make the print command trigger the pager when invoked using a capital 'P', to make it easier for the user to review long hunks. Note that if the PAGER ends unexpectedly before we've been able to send the payload, perhaps because the user is not interested in the whole thing, we might receive a SIGPIPE, which would abruptly and unexpectedly terminate the interactive session for the user. Therefore, we need to ignore a possible SIGPIPE signal. Add a test for this, in addition to the test for normal operation. For the SIGPIPE test, we need to make sure that we completely fill the operating system's buffer, otherwise we might not trigger the SIGPIPE signal. The normal size of this buffer in different OSs varies from a few KBs to 1MB. Use a payload large enough to guarantee that we exceed this limit. Signed-off-by: Rubén Justo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e8bd888 commit fc87b2f

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

add-patch.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
#include "environment.h"
88
#include "gettext.h"
99
#include "object-name.h"
10+
#include "pager.h"
1011
#include "read-cache-ll.h"
1112
#include "repository.h"
1213
#include "strbuf.h"
14+
#include "sigchain.h"
1315
#include "run-command.h"
1416
#include "strvec.h"
1517
#include "pathspec.h"
@@ -1391,7 +1393,7 @@ N_("j - leave this hunk undecided, see next undecided hunk\n"
13911393
"/ - search for a hunk matching the given regex\n"
13921394
"s - split the current hunk into smaller hunks\n"
13931395
"e - manually edit the current hunk\n"
1394-
"p - print the current hunk\n"
1396+
"p - print the current hunk, 'P' to use the pager\n"
13951397
"? - print help\n");
13961398

13971399
static int patch_update_file(struct add_p_state *s,
@@ -1402,7 +1404,7 @@ static int patch_update_file(struct add_p_state *s,
14021404
struct hunk *hunk;
14031405
char ch;
14041406
struct child_process cp = CHILD_PROCESS_INIT;
1405-
int colored = !!s->colored.len, quit = 0;
1407+
int colored = !!s->colored.len, quit = 0, use_pager = 0;
14061408
enum prompt_mode_type prompt_mode_type;
14071409
enum {
14081410
ALLOW_GOTO_PREVIOUS_HUNK = 1 << 0,
@@ -1452,9 +1454,18 @@ static int patch_update_file(struct add_p_state *s,
14521454
strbuf_reset(&s->buf);
14531455
if (file_diff->hunk_nr) {
14541456
if (rendered_hunk_index != hunk_index) {
1457+
if (use_pager) {
1458+
setup_pager();
1459+
sigchain_push(SIGPIPE, SIG_IGN);
1460+
}
14551461
render_hunk(s, hunk, 0, colored, &s->buf);
14561462
fputs(s->buf.buf, stdout);
14571463
rendered_hunk_index = hunk_index;
1464+
if (use_pager) {
1465+
sigchain_pop(SIGPIPE);
1466+
wait_for_pager();
1467+
use_pager = 0;
1468+
}
14581469
}
14591470

14601471
strbuf_reset(&s->buf);
@@ -1675,8 +1686,9 @@ static int patch_update_file(struct add_p_state *s,
16751686
hunk->use = USE_HUNK;
16761687
goto soft_increment;
16771688
}
1678-
} else if (s->answer.buf[0] == 'p') {
1689+
} else if (ch == 'p') {
16791690
rendered_hunk_index = -1;
1691+
use_pager = (s->answer.buf[0] == 'P') ? 1 : 0;
16801692
} else if (s->answer.buf[0] == '?') {
16811693
const char *p = _(help_patch_remainder), *eol = p;
16821694

t/t3701-add-interactive.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,38 @@ test_expect_success 'print again the hunk' '
591591
test_cmp expect actual.trimmed
592592
'
593593

594+
test_expect_success TTY 'print again the hunk (PAGER)' '
595+
test_when_finished "git reset" &&
596+
cat >expect <<-EOF &&
597+
<GREEN>+<RESET><GREEN>15<RESET>
598+
20<RESET>
599+
<BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>PAGER <CYAN>@@ -1,2 +1,3 @@<RESET>
600+
PAGER 10<RESET>
601+
PAGER <GREEN>+<RESET><GREEN>15<RESET>
602+
PAGER 20<RESET>
603+
<BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>
604+
EOF
605+
test_write_lines s y g 1 P |
606+
(
607+
GIT_PAGER="sed s/^/PAGER\ /" &&
608+
export GIT_PAGER &&
609+
test_terminal git add -p >actual
610+
) &&
611+
tail -n 7 <actual | test_decode_color >actual.trimmed &&
612+
test_cmp expect actual.trimmed
613+
'
614+
615+
test_expect_success TTY 'P handles SIGPIPE when writing to pager' '
616+
test_when_finished "rm -f huge_file; git reset" &&
617+
printf "\n%2500000s" Y >huge_file &&
618+
git add -N huge_file &&
619+
test_write_lines P q | (
620+
GIT_PAGER="head -n 1" &&
621+
export GIT_PAGER &&
622+
test_terminal git add -p
623+
)
624+
'
625+
594626
test_expect_success 'split hunk "add -p (edit)"' '
595627
# Split, say Edit and do nothing. Then:
596628
#

0 commit comments

Comments
 (0)