{"thread":{"id":"61793","subject":"[PATCH] add-patch: end \"add -p\" gracefully on EOF","startedAt":"2024-07-17T16:22:20Z","lastAt":"2024-07-17T16:22:20Z","messageCount":1,"participants":["Rubén Justo"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"498839","messageId":"42a04aac-3f60-4259-9c9e-f46e9b6e33b3@gmail.com","threadId":"61793","inReplyTo":null,"subject":"[PATCH] add-patch: end \"add -p\" gracefully on EOF","fromName":"Rubén Justo","fromEmail":"rjusto@gmail.com","sentAt":"2024-07-17T16:22:16Z","receivedAt":"2024-07-17T16:22:20Z","isPatch":true,"sender":{"key":"rjusto@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5685487?v=4"},"body":"If we receive an EOF during the loop in `patch_update_file()`, we break\nthe loop.  However, the loop in `run_add_p()` could brings us back to\n`patch_update_file()`, to only receive EOF again.\n\nThis is a sample output:\n\n   $ touch a b c\n   $ git add -N a b c\n   $ printf \"%s\\n\" Z | git add -p\n   diff --git a/a b/a\n   new file mode 100644\n   index 0000000..e69de29\n   (1/1) Stage addition [y,n,q,a,d,?]? Unknown command 'Z' (use '?' for help)\n   (1/1) Stage addition [y,n,q,a,d,?]?\n   diff --git a/b b/b\n   new file mode 100644\n   index 0000000..e69de29\n   (1/1) Stage addition [y,n,q,a,d,?]?\n   diff --git a/c b/c\n   new file mode 100644\n   index 0000000..e69de29\n   (1/1) Stage addition [y,n,q,a,d,?]?\n\nWhen we see a \"quit\", this is the, much more expected, result:\n\n   $ printf \"%s\\n\" Z q | git add -p\n   diff --git a/a b/a\n   new file mode 100644\n   index 0000000..e69de29\n   (1/1) Stage addition [y,n,q,a,d,?]? Unknown command 'Z' (use '?' for help)\n   (1/1) Stage addition [y,n,q,a,d,?]?\n\nWe can assume that EOF is a synonym for 'q'.  Let's do that.\n\nWe've had this behavior since before the port to C of \"add -p\", which\nwas ported faithfully.  Let's fix it today and live happily ever after.\n\nSigned-off-by: Rubén Justo <rjusto@gmail.com>\n---\n add-patch.c                |  4 +++-\n t/t3701-add-interactive.sh | 13 +++++++++++++\n 2 files changed, 16 insertions(+), 1 deletion(-)\n\ndiff --git a/add-patch.c b/add-patch.c\nindex 6e176cd21a..d8c5496a9b 100644\n--- a/add-patch.c\n+++ b/add-patch.c\n@@ -1508,8 +1508,10 @@ static int patch_update_file(struct add_p_state *s,\n \t\tif (*s->s.reset_color)\n \t\t\tfputs(s->s.reset_color, stdout);\n \t\tfflush(stdout);\n-\t\tif (read_single_character(s) == EOF)\n+\t\tif (read_single_character(s) == EOF) {\n+\t\t\tquit = 1;\n \t\t\tbreak;\n+\t\t}\n \n \t\tif (!s->answer.len)\n \t\t\tcontinue;\ndiff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh\nindex 5d78868ac1..6bf0c0b6ca 100755\n--- a/t/t3701-add-interactive.sh\n+++ b/t/t3701-add-interactive.sh\n@@ -56,6 +56,19 @@ test_expect_success 'unknown command' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'end gracefully on EOF' '\n+\ttest_when_finished \"git reset --hard; rm -f a b\" &&\n+\ttouch a b &&\n+\tgit add -N a b &&\n+\tgit diff a >expect &&\n+\tcat >>expect <<-EOF &&\n+\t(1/1) Stage addition [y,n,q,a,d,?]? Unknown command ${SQ}R${SQ} (use ${SQ}?${SQ} for help)\n+\t(1/1) Stage addition [y,n,q,a,d,?]?$SP\n+\tEOF\n+\ttest_write_lines R | git add -p >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'setup (initial)' '\n \techo content >file &&\n \tgit add file &&\n-- \n2.45.1\n"}]}