aboutsummaryrefslogtreecommitdiff
path: root/add-patch.c
diff options
context:
space:
mode:
authorAbraham Samuel Adekunle <abrahamadekunle50@gmail.com>2026-02-14 12:06:55 +0100
committerJunio C Hamano <gitster@pobox.com>2026-02-17 10:48:37 -0800
commit417b181f99ce53f50dea6541430cfe1f1f359a6a (patch)
treebd03be33de615da9b805861191aa59440d232b16 /add-patch.c
parentd3cce5e76fcbce00d33013424bece954f11fa2f3 (diff)
downloadgit-417b181f99ce53f50dea6541430cfe1f1f359a6a.tar.xz
add-patch: allow interfile navigation when selecting hunks
After deciding on all hunks in a file, the interactive session advances automatically to the next file if there is another, or the process ends. Now using the `--no-auto-advance` flag with `--patch`, the process does not advance automatically. A user can choose to go to the next file by pressing '>' or the previous file by pressing '<', before or after deciding on all hunks in the current file. After all hunks have been decided in a file, the user can still rework with the file by applying the options available in the permit set for that hunk, and after all the decisions, the user presses 'q' to submit. After all hunks have been decided, the user can press '?' which will show the hunk selection summary in the help patch remainder text including the total hunks, number of hunks marked for use and number of hunks marked for skip. This feature is enabled by passing the `--no-auto-advance` flag to `--patch` option of the subcommands add, stash, reset, and checkout. Signed-off-by: Abraham Samuel Adekunle <abrahamadekunle50@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'add-patch.c')
-rw-r--r--add-patch.c66
1 files changed, 61 insertions, 5 deletions
diff --git a/add-patch.c b/add-patch.c
index d6528d4818..d9900d58d5 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -1418,7 +1418,10 @@ N_("j - go to the next undecided hunk, roll over at the bottom\n"
"e - manually edit the current hunk\n"
"p - print the current hunk\n"
"P - print the current hunk using the pager\n"
- "? - print help\n");
+ "> - go to the next file, roll over at the bottom\n"
+ "< - go to the previous file, roll over at the top\n"
+ "? - print help\n"
+ "HUNKS SUMMARY - Hunks: %d, USE: %d, SKIP: %d\n");
static void apply_patch(struct add_p_state *s, struct file_diff *file_diff)
{
@@ -1483,6 +1486,7 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
char ch;
int colored = !!s->colored.len, use_pager = 0;
enum prompt_mode_type prompt_mode_type;
+ int all_decided = 0;
struct file_diff *file_diff = s->file_diff + idx;
size_t patch_update_resp = idx;
@@ -1501,7 +1505,9 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
ALLOW_GOTO_NEXT_UNDECIDED_HUNK = 1 << 3,
ALLOW_SEARCH_AND_GOTO = 1 << 4,
ALLOW_SPLIT = 1 << 5,
- ALLOW_EDIT = 1 << 6
+ ALLOW_EDIT = 1 << 6,
+ ALLOW_GOTO_PREVIOUS_FILE = 1 << 7,
+ ALLOW_GOTO_NEXT_FILE = 1 << 8
} permitted = 0;
if (hunk_index >= file_diff->hunk_nr)
@@ -1533,8 +1539,12 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
/* Everything decided? */
if (undecided_previous < 0 && undecided_next < 0 &&
hunk->use != UNDECIDED_HUNK) {
- patch_update_resp++;
- break;
+ if (!s->s.auto_advance)
+ all_decided = 1;
+ else {
+ patch_update_resp++;
+ break;
+ }
}
strbuf_reset(&s->buf);
if (file_diff->hunk_nr) {
@@ -1583,6 +1593,14 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
permitted |= ALLOW_EDIT;
strbuf_addstr(&s->buf, ",e");
}
+ if (!s->s.auto_advance && s->file_diff_nr > 1) {
+ permitted |= ALLOW_GOTO_NEXT_FILE;
+ strbuf_addstr(&s->buf, ",>");
+ }
+ if (!s->s.auto_advance && s->file_diff_nr > 1) {
+ permitted |= ALLOW_GOTO_PREVIOUS_FILE;
+ strbuf_addstr(&s->buf, ",<");
+ }
strbuf_addstr(&s->buf, ",p,P");
}
if (file_diff->deleted)
@@ -1653,6 +1671,28 @@ soft_increment:
} else if (ch == 'q') {
patch_update_resp = s->file_diff_nr;
break;
+ } else if (!s->s.auto_advance && s->answer.buf[0] == '>') {
+ if (permitted & ALLOW_GOTO_NEXT_FILE) {
+ if (patch_update_resp == s->file_diff_nr - 1)
+ patch_update_resp = 0;
+ else
+ patch_update_resp++;
+ break;
+ } else {
+ err(s, _("No next file"));
+ continue;
+ }
+ } else if (!s->s.auto_advance && s->answer.buf[0] == '<') {
+ if (permitted & ALLOW_GOTO_PREVIOUS_FILE) {
+ if (patch_update_resp == 0)
+ patch_update_resp = s->file_diff_nr - 1;
+ else
+ patch_update_resp--;
+ break;
+ } else {
+ err(s, _("No previous file"));
+ continue;
+ }
} else if (s->answer.buf[0] == 'K') {
if (permitted & ALLOW_GOTO_PREVIOUS_HUNK)
hunk_index = dec_mod(hunk_index,
@@ -1798,6 +1838,18 @@ soft_increment:
* commands shown in the prompt that are not
* always available.
*/
+ if (all_decided && !strncmp(p, "HUNKS SUMMARY", 13)) {
+ int total = file_diff->hunk_nr, used = 0, skipped = 0;
+
+ for (i = 0; i < file_diff->hunk_nr; i++) {
+ if (file_diff->hunk[i].use == USE_HUNK)
+ used += 1;
+ if (file_diff->hunk[i].use == SKIP_HUNK)
+ skipped += 1;
+ }
+ color_fprintf_ln(stdout, s->s.help_color, _(p),
+ total, used, skipped);
+ }
if (*p != '?' && !strchr(s->buf.buf, *p))
continue;
@@ -1810,7 +1862,8 @@ soft_increment:
}
}
- apply_patch(s, file_diff);
+ if (s->s.auto_advance)
+ apply_patch(s, file_diff);
putchar('\n');
return patch_update_resp;
@@ -1871,6 +1924,9 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
if ((i = patch_update_file(&s, i)) == s.file_diff_nr)
break;
}
+ if (!s.s.auto_advance)
+ for (i = 0; i < s.file_diff_nr; i++)
+ apply_patch(&s, s.file_diff + i);
if (s.file_diff_nr == 0)
err(&s, _("No changes."));