@@ -1418,7 +1418,44 @@ N_("j - go to the next undecided hunk, roll over at the bottom\n"
14181418 "e - manually edit the current hunk\n"
14191419 "p - print the current hunk\n"
14201420 "P - print the current hunk using the pager\n"
1421- "? - print help\n" );
1421+ "> - go to the next file, roll over at the bottom\n"
1422+ "< - go to the previous file, roll over at the top\n"
1423+ "? - print help\n"
1424+ "HUNKS SUMMARY - Hunks: %d, USE: %d, SKIP: %d\n" );
1425+
1426+ static void apply_patch (struct add_p_state * s , struct file_diff * file_diff )
1427+ {
1428+ struct child_process cp = CHILD_PROCESS_INIT ;
1429+ size_t j ;
1430+
1431+ /* Any hunk to be used? */
1432+ for (j = 0 ; j < file_diff -> hunk_nr ; j ++ )
1433+ if (file_diff -> hunk [j ].use == USE_HUNK )
1434+ break ;
1435+
1436+ if (j < file_diff -> hunk_nr ||
1437+ (!file_diff -> hunk_nr && file_diff -> head .use == USE_HUNK )) {
1438+ /* At least one hunk selected: apply */
1439+ strbuf_reset (& s -> buf );
1440+ reassemble_patch (s , file_diff , 0 , & s -> buf );
1441+
1442+ discard_index (s -> s .r -> index );
1443+ if (s -> mode -> apply_for_checkout )
1444+ apply_for_checkout (s , & s -> buf ,
1445+ s -> mode -> is_reverse );
1446+ else {
1447+ setup_child_process (s , & cp , "apply" , NULL );
1448+ strvec_pushv (& cp .args , s -> mode -> apply_args );
1449+ if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
1450+ NULL , 0 , NULL , 0 ))
1451+ error (_ ("'git apply' failed" ));
1452+ }
1453+ if (repo_read_index (s -> s .r ) >= 0 )
1454+ repo_refresh_and_write_index (s -> s .r , REFRESH_QUIET , 0 ,
1455+ 1 , NULL , NULL , NULL );
1456+ }
1457+
1458+ }
14221459
14231460static size_t dec_mod (size_t a , size_t m )
14241461{
@@ -1441,20 +1478,21 @@ static bool get_first_undecided(const struct file_diff *file_diff, size_t *idx)
14411478 return false;
14421479}
14431480
1444- static int patch_update_file (struct add_p_state * s ,
1445- struct file_diff * file_diff )
1481+ static ssize_t patch_update_file (struct add_p_state * s , size_t idx )
14461482{
14471483 size_t hunk_index = 0 ;
14481484 ssize_t i , undecided_previous , undecided_next , rendered_hunk_index = -1 ;
14491485 struct hunk * hunk ;
14501486 char ch ;
1451- struct child_process cp = CHILD_PROCESS_INIT ;
1452- int colored = !!s -> colored .len , quit = 0 , use_pager = 0 ;
1487+ int colored = !!s -> colored .len , use_pager = 0 ;
14531488 enum prompt_mode_type prompt_mode_type ;
1489+ int all_decided = 0 ;
1490+ struct file_diff * file_diff = s -> file_diff + idx ;
1491+ ssize_t patch_update_resp = (ssize_t )idx ;
14541492
14551493 /* Empty added files have no hunks */
14561494 if (!file_diff -> hunk_nr && !file_diff -> added )
1457- return 0 ;
1495+ return patch_update_resp + 1 ;
14581496
14591497 strbuf_reset (& s -> buf );
14601498 render_diff_header (s , file_diff , colored , & s -> buf );
@@ -1468,7 +1506,9 @@ static int patch_update_file(struct add_p_state *s,
14681506 ALLOW_GOTO_NEXT_UNDECIDED_HUNK = 1 << 3 ,
14691507 ALLOW_SEARCH_AND_GOTO = 1 << 4 ,
14701508 ALLOW_SPLIT = 1 << 5 ,
1471- ALLOW_EDIT = 1 << 6
1509+ ALLOW_EDIT = 1 << 6 ,
1510+ ALLOW_GOTO_PREVIOUS_FILE = 1 << 7 ,
1511+ ALLOW_GOTO_NEXT_FILE = 1 << 8
14721512 } permitted = 0 ;
14731513
14741514 if (hunk_index >= file_diff -> hunk_nr )
@@ -1499,9 +1539,14 @@ static int patch_update_file(struct add_p_state *s,
14991539
15001540 /* Everything decided? */
15011541 if (undecided_previous < 0 && undecided_next < 0 &&
1502- hunk -> use != UNDECIDED_HUNK )
1503- break ;
1504-
1542+ hunk -> use != UNDECIDED_HUNK ) {
1543+ if (!s -> s .auto_advance )
1544+ all_decided = 1 ;
1545+ else {
1546+ patch_update_resp ++ ;
1547+ break ;
1548+ }
1549+ }
15051550 strbuf_reset (& s -> buf );
15061551 if (file_diff -> hunk_nr ) {
15071552 if (rendered_hunk_index != hunk_index ) {
@@ -1549,6 +1594,14 @@ static int patch_update_file(struct add_p_state *s,
15491594 permitted |= ALLOW_EDIT ;
15501595 strbuf_addstr (& s -> buf , ",e" );
15511596 }
1597+ if (!s -> s .auto_advance && s -> file_diff_nr > 1 ) {
1598+ permitted |= ALLOW_GOTO_NEXT_FILE ;
1599+ strbuf_addstr (& s -> buf , ",>" );
1600+ }
1601+ if (!s -> s .auto_advance && s -> file_diff_nr > 1 ) {
1602+ permitted |= ALLOW_GOTO_PREVIOUS_FILE ;
1603+ strbuf_addstr (& s -> buf , ",<" );
1604+ }
15521605 strbuf_addstr (& s -> buf , ",p,P" );
15531606 }
15541607 if (file_diff -> deleted )
@@ -1577,7 +1630,7 @@ static int patch_update_file(struct add_p_state *s,
15771630 fputs (s -> s .reset_color_interactive , stdout );
15781631 fflush (stdout );
15791632 if (read_single_character (s ) == EOF ) {
1580- quit = 1 ;
1633+ patch_update_resp = - 1 ;
15811634 break ;
15821635 }
15831636
@@ -1623,8 +1676,30 @@ static int patch_update_file(struct add_p_state *s,
16231676 hunk -> use = SKIP_HUNK ;
16241677 }
16251678 } else if (ch == 'q' ) {
1626- quit = 1 ;
1679+ patch_update_resp = - 1 ;
16271680 break ;
1681+ } else if (!s -> s .auto_advance && s -> answer .buf [0 ] == '>' ) {
1682+ if (permitted & ALLOW_GOTO_NEXT_FILE ) {
1683+ if (patch_update_resp == s -> file_diff_nr - 1 )
1684+ patch_update_resp = 0 ;
1685+ else
1686+ patch_update_resp ++ ;
1687+ break ;
1688+ } else {
1689+ err (s , _ ("No next file" ));
1690+ continue ;
1691+ }
1692+ } else if (!s -> s .auto_advance && s -> answer .buf [0 ] == '<' ) {
1693+ if (permitted & ALLOW_GOTO_PREVIOUS_FILE ) {
1694+ if (patch_update_resp == 0 )
1695+ patch_update_resp = s -> file_diff_nr - 1 ;
1696+ else
1697+ patch_update_resp -- ;
1698+ break ;
1699+ } else {
1700+ err (s , _ ("No previous file" ));
1701+ continue ;
1702+ }
16281703 } else if (s -> answer .buf [0 ] == 'K' ) {
16291704 if (permitted & ALLOW_GOTO_PREVIOUS_HUNK )
16301705 hunk_index = dec_mod (hunk_index ,
@@ -1770,6 +1845,18 @@ static int patch_update_file(struct add_p_state *s,
17701845 * commands shown in the prompt that are not
17711846 * always available.
17721847 */
1848+ if (all_decided && !strncmp (p , "HUNKS SUMMARY" , 13 )) {
1849+ int total = file_diff -> hunk_nr , used = 0 , skipped = 0 ;
1850+
1851+ for (i = 0 ; i < file_diff -> hunk_nr ; i ++ ) {
1852+ if (file_diff -> hunk [i ].use == USE_HUNK )
1853+ used += 1 ;
1854+ if (file_diff -> hunk [i ].use == SKIP_HUNK )
1855+ skipped += 1 ;
1856+ }
1857+ color_fprintf_ln (stdout , s -> s .help_color , _ (p ),
1858+ total , used , skipped );
1859+ }
17731860 if (* p != '?' && !strchr (s -> buf .buf , * p ))
17741861 continue ;
17751862
@@ -1782,35 +1869,11 @@ static int patch_update_file(struct add_p_state *s,
17821869 }
17831870 }
17841871
1785- /* Any hunk to be used? */
1786- for (i = 0 ; i < file_diff -> hunk_nr ; i ++ )
1787- if (file_diff -> hunk [i ].use == USE_HUNK )
1788- break ;
1789-
1790- if (i < file_diff -> hunk_nr ||
1791- (!file_diff -> hunk_nr && file_diff -> head .use == USE_HUNK )) {
1792- /* At least one hunk selected: apply */
1793- strbuf_reset (& s -> buf );
1794- reassemble_patch (s , file_diff , 0 , & s -> buf );
1795-
1796- discard_index (s -> s .r -> index );
1797- if (s -> mode -> apply_for_checkout )
1798- apply_for_checkout (s , & s -> buf ,
1799- s -> mode -> is_reverse );
1800- else {
1801- setup_child_process (s , & cp , "apply" , NULL );
1802- strvec_pushv (& cp .args , s -> mode -> apply_args );
1803- if (pipe_command (& cp , s -> buf .buf , s -> buf .len ,
1804- NULL , 0 , NULL , 0 ))
1805- error (_ ("'git apply' failed" ));
1806- }
1807- if (repo_read_index (s -> s .r ) >= 0 )
1808- repo_refresh_and_write_index (s -> s .r , REFRESH_QUIET , 0 ,
1809- 1 , NULL , NULL , NULL );
1810- }
1872+ if (s -> s .auto_advance )
1873+ apply_patch (s , file_diff );
18111874
18121875 putchar ('\n' );
1813- return quit ;
1876+ return patch_update_resp ;
18141877}
18151878
18161879int run_add_p (struct repository * r , enum add_p_mode mode ,
@@ -1821,6 +1884,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
18211884 { r }, STRBUF_INIT , STRBUF_INIT , STRBUF_INIT , STRBUF_INIT
18221885 };
18231886 size_t i , binary_count = 0 ;
1887+ ssize_t patch_update_resp ;
18241888
18251889 init_add_i_state (& s .s , r , o );
18261890
@@ -1859,11 +1923,20 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
18591923 return -1 ;
18601924 }
18611925
1862- for (i = 0 ; i < s .file_diff_nr ; i ++ )
1863- if (s .file_diff [i ].binary && !s .file_diff [i ].hunk_nr )
1926+ for (i = 0 ; i < s .file_diff_nr ;) {
1927+ if (s .file_diff [i ].binary && !s .file_diff [i ].hunk_nr ) {
18641928 binary_count ++ ;
1865- else if (patch_update_file (& s , s .file_diff + i ))
1929+ i ++ ;
1930+ continue ;
1931+ }
1932+ patch_update_resp = patch_update_file (& s , i );
1933+ if (patch_update_resp < 0 )
18661934 break ;
1935+ i = (size_t )patch_update_resp ;
1936+ }
1937+ if (!s .s .auto_advance )
1938+ for (i = 0 ; i < s .file_diff_nr ; i ++ )
1939+ apply_patch (& s , s .file_diff + i );
18671940
18681941 if (s .file_diff_nr == 0 )
18691942 err (& s , _ ("No changes." ));
0 commit comments