stash push: support the --pathspec-from-file option
Decisions taken for simplicity: 1) For now, `--pathspec-from-file` is declared incompatible with `--patch`, even when <file> is not `-`. Such use case is not really expected. 2) It is not allowed to pass pathspec in both args and file. Signed-off-by: Alexandr Miloslavskiy <alexandr.miloslavskiy@syntevo.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
8c3713cede
commit
8a98758a8d
@ -15,6 +15,7 @@ SYNOPSIS
|
|||||||
'git stash' branch <branchname> [<stash>]
|
'git stash' branch <branchname> [<stash>]
|
||||||
'git stash' [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
|
'git stash' [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
|
||||||
[-u|--include-untracked] [-a|--all] [-m|--message <message>]
|
[-u|--include-untracked] [-a|--all] [-m|--message <message>]
|
||||||
|
[--pathspec-from-file=<file> [--pathspec-file-nul]]
|
||||||
[--] [<pathspec>...]]
|
[--] [<pathspec>...]]
|
||||||
'git stash' clear
|
'git stash' clear
|
||||||
'git stash' create [<message>]
|
'git stash' create [<message>]
|
||||||
@ -46,7 +47,7 @@ stash index (e.g. the integer `n` is equivalent to `stash@{n}`).
|
|||||||
COMMANDS
|
COMMANDS
|
||||||
--------
|
--------
|
||||||
|
|
||||||
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]::
|
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--pathspec-from-file=<file> [--pathspec-file-nul]] [--] [<pathspec>...]::
|
||||||
|
|
||||||
Save your local modifications to a new 'stash entry' and roll them
|
Save your local modifications to a new 'stash entry' and roll them
|
||||||
back to HEAD (in the working tree and in the index).
|
back to HEAD (in the working tree and in the index).
|
||||||
@ -194,6 +195,23 @@ to learn how to operate the `--patch` mode.
|
|||||||
The `--patch` option implies `--keep-index`. You can use
|
The `--patch` option implies `--keep-index`. You can use
|
||||||
`--no-keep-index` to override this.
|
`--no-keep-index` to override this.
|
||||||
|
|
||||||
|
--pathspec-from-file=<file>::
|
||||||
|
This option is only valid for `push` command.
|
||||||
|
+
|
||||||
|
Pathspec is passed in `<file>` instead of commandline args. If
|
||||||
|
`<file>` is exactly `-` then standard input is used. Pathspec
|
||||||
|
elements are separated by LF or CR/LF. Pathspec elements can be
|
||||||
|
quoted as explained for the configuration variable `core.quotePath`
|
||||||
|
(see linkgit:git-config[1]). See also `--pathspec-file-nul` and
|
||||||
|
global `--literal-pathspecs`.
|
||||||
|
|
||||||
|
--pathspec-file-nul::
|
||||||
|
This option is only valid for `push` command.
|
||||||
|
+
|
||||||
|
Only meaningful with `--pathspec-from-file`. Pathspec elements are
|
||||||
|
separated with NUL character and all other characters are taken
|
||||||
|
literally (including newlines and quotes).
|
||||||
|
|
||||||
-q::
|
-q::
|
||||||
--quiet::
|
--quiet::
|
||||||
This option is only valid for `apply`, `drop`, `pop`, `push`,
|
This option is only valid for `apply`, `drop`, `pop`, `push`,
|
||||||
|
@ -27,6 +27,7 @@ static const char * const git_stash_usage[] = {
|
|||||||
N_("git stash clear"),
|
N_("git stash clear"),
|
||||||
N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
||||||
" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
|
" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
|
||||||
|
" [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
|
||||||
" [--] [<pathspec>...]]"),
|
" [--] [<pathspec>...]]"),
|
||||||
N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
||||||
" [-u|--include-untracked] [-a|--all] [<message>]"),
|
" [-u|--include-untracked] [-a|--all] [<message>]"),
|
||||||
@ -1456,7 +1457,9 @@ static int push_stash(int argc, const char **argv, const char *prefix,
|
|||||||
int patch_mode = 0;
|
int patch_mode = 0;
|
||||||
int include_untracked = 0;
|
int include_untracked = 0;
|
||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
|
int pathspec_file_nul = 0;
|
||||||
const char *stash_msg = NULL;
|
const char *stash_msg = NULL;
|
||||||
|
const char *pathspec_from_file = NULL;
|
||||||
struct pathspec ps;
|
struct pathspec ps;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOL('k', "keep-index", &keep_index,
|
OPT_BOOL('k', "keep-index", &keep_index,
|
||||||
@ -1470,6 +1473,8 @@ static int push_stash(int argc, const char **argv, const char *prefix,
|
|||||||
N_("include ignore files"), 2),
|
N_("include ignore files"), 2),
|
||||||
OPT_STRING('m', "message", &stash_msg, N_("message"),
|
OPT_STRING('m', "message", &stash_msg, N_("message"),
|
||||||
N_("stash message")),
|
N_("stash message")),
|
||||||
|
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
|
||||||
|
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1492,6 +1497,21 @@ static int push_stash(int argc, const char **argv, const char *prefix,
|
|||||||
|
|
||||||
parse_pathspec(&ps, 0, PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
|
parse_pathspec(&ps, 0, PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
|
||||||
prefix, argv);
|
prefix, argv);
|
||||||
|
|
||||||
|
if (pathspec_from_file) {
|
||||||
|
if (patch_mode)
|
||||||
|
die(_("--pathspec-from-file is incompatible with --patch"));
|
||||||
|
|
||||||
|
if (ps.nr)
|
||||||
|
die(_("--pathspec-from-file is incompatible with pathspec arguments"));
|
||||||
|
|
||||||
|
parse_pathspec_file(&ps, 0,
|
||||||
|
PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
|
||||||
|
prefix, pathspec_from_file, pathspec_file_nul);
|
||||||
|
} else if (pathspec_file_nul) {
|
||||||
|
die(_("--pathspec-file-nul requires --pathspec-from-file"));
|
||||||
|
}
|
||||||
|
|
||||||
return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
|
return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
|
||||||
include_untracked);
|
include_untracked);
|
||||||
}
|
}
|
||||||
|
100
t/t3909-stash-pathspec-file.sh
Executable file
100
t/t3909-stash-pathspec-file.sh
Executable file
@ -0,0 +1,100 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='stash --pathspec-from-file'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_tick
|
||||||
|
|
||||||
|
test_expect_success setup '
|
||||||
|
>fileA.t &&
|
||||||
|
>fileB.t &&
|
||||||
|
>fileC.t &&
|
||||||
|
>fileD.t &&
|
||||||
|
git add fileA.t fileB.t fileC.t fileD.t &&
|
||||||
|
git commit -m "Files" &&
|
||||||
|
|
||||||
|
git tag checkpoint
|
||||||
|
'
|
||||||
|
|
||||||
|
restore_checkpoint () {
|
||||||
|
git reset --hard checkpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_expect () {
|
||||||
|
git stash show --name-status >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success 'simplest' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
# More files are written to make sure that git didnt ignore
|
||||||
|
# --pathspec-from-file, stashing everything
|
||||||
|
echo A >fileA.t &&
|
||||||
|
echo B >fileB.t &&
|
||||||
|
echo C >fileC.t &&
|
||||||
|
echo D >fileD.t &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
M fileA.t
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo fileA.t | git stash push --pathspec-from-file=- &&
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--pathspec-file-nul' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
# More files are written to make sure that git didnt ignore
|
||||||
|
# --pathspec-from-file, stashing everything
|
||||||
|
echo A >fileA.t &&
|
||||||
|
echo B >fileB.t &&
|
||||||
|
echo C >fileC.t &&
|
||||||
|
echo D >fileD.t &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
M fileA.t
|
||||||
|
M fileB.t
|
||||||
|
EOF
|
||||||
|
|
||||||
|
printf "fileA.t\0fileB.t\0" | git stash push --pathspec-from-file=- --pathspec-file-nul &&
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'only touches what was listed' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
# More files are written to make sure that git didnt ignore
|
||||||
|
# --pathspec-from-file, stashing everything
|
||||||
|
echo A >fileA.t &&
|
||||||
|
echo B >fileB.t &&
|
||||||
|
echo C >fileC.t &&
|
||||||
|
echo D >fileD.t &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
M fileB.t
|
||||||
|
M fileC.t
|
||||||
|
EOF
|
||||||
|
|
||||||
|
printf "fileB.t\nfileC.t\n" | git stash push --pathspec-from-file=- &&
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'error conditions' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
echo A >fileA.t &&
|
||||||
|
echo fileA.t >list &&
|
||||||
|
|
||||||
|
test_must_fail git stash push --pathspec-from-file=list --patch 2>err &&
|
||||||
|
test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
|
||||||
|
|
||||||
|
test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
|
||||||
|
test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
|
||||||
|
|
||||||
|
test_must_fail git stash push --pathspec-file-nul 2>err &&
|
||||||
|
test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue
Block a user