stash: allow "git stash [<options>] --patch <pathspec>" to assume push

The support for assuming "push" when "-p" is given introduced in 9e140909f61 (stash: allow pathspecs in the no verb form, 2017-02-28) is very narrow, neither "git stash -m <message> -p <pathspec>" nor "git stash --patch <pathspec>" imply "push" and die instead. Relax this by passing PARSE_OPT_STOP_AT_NON_OPTION when push is being assumed and then setting "force_assume" if "--patch" was present. This means "git stash <pathspec> -p" still dies so that it does not assume the user meant "push" if they mistype a subcommand name but "git stash -m <message> -p <pathspec>" will now succeed. The test added in the last commit is adjusted to check that push is still assumed when "--patch" comes after other options on the command-line. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Phillip Wood committed Jun 7, 2025 at 10:45 UTC 468817bab2ab5fd9b71a8df49e02b8d5521b1631
2 files changed +9 -5
builtin/stash.c
+7 -3
@@ -1789,11 +1789,15 @@ static int push_stash(int argc, const char **argv, const char *prefix,
1789 int ret;
1790
1791 if (argc) {
1792 - force_assume = argc > 1 && !strcmp(argv[1], "-p");
1792 + int flags = PARSE_OPT_KEEP_DASHDASH;
1793 +
1794 + if (push_assumed)
1795 + flags |= PARSE_OPT_STOP_AT_NON_OPTION;
1796 +
1797 argc = parse_options(argc, argv, prefix, options,
1798 push_assumed ? git_stash_usage :
1795 - git_stash_push_usage,
1796 - PARSE_OPT_KEEP_DASHDASH);
1799 + git_stash_push_usage, flags);
1800 + force_assume |= patch_mode;
1801 }
1802
1803 if (argc) {
t/t3903-stash.sh
+2 -2
@@ -1177,13 +1177,13 @@ test_expect_success 'stash -- <pathspec> stashes and restores the file' '
1177 test_path_is_file bar
1178 '
1179
1180 -test_expect_success 'stash -p <pathspec> stash and restores the file' '
1180 +test_expect_success 'stash --patch <pathspec> stash and restores the file' '
1181 test_write_lines b c >file &&
1182 git commit -m "add a few lines" file &&
1183 test_write_lines a b c d >file &&
1184 test_write_lines b c d >expect-file &&
1185 echo changed-other-file >other-file &&
1186 - test_write_lines s y n | git stash -p file &&
1186 + test_write_lines s y n | git stash -m "stash bar" --patch file &&
1187 test_cmp expect-file file &&
1188 echo changed-other-file >expect &&
1189 test_cmp expect other-file &&