Thanks Junio for the review in the previous round.

Changes since v2:

- $IFS should now be supported by using "$@" everywhere instead of using
  a $files variable.
- Added a new patch showing the old behaviour of git stash create is
  preserved.
- Rephrased the documentation
- Simplified the option parsing in save_stash, by leaving the
  actual parsing to push_stash instead.

Interdiff below:

diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 8306bac397..be55e456fa 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -17,7 +17,7 @@ SYNOPSIS
             [-u|--include-untracked] [-a|--all] [<message>]]
 'git stash' push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
             [-u|--include-untracked] [-a|--all] [-m|--message <message>]]
-            [--] [<paths>...]
+            [--] [<pathspec>...]
 'git stash' clear
 'git stash' create [<message>]
 'git stash' create [-m <message>] [-u|--include-untracked <untracked|all>]
@@ -51,19 +51,21 @@ OPTIONS
 -------
 
 save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] 
[-q|--quiet] [<message>]::
-push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] 
[-q|--quiet] [-m|--message <message>] [--] [<paths>...]::
+push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] 
[-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]::
 
        Save your local modifications to a new 'stash' and roll them
-       back both in the working tree and in the index.
+       back to HEAD (in the working tree and in the index).
        The <message> part is optional and gives
        the description along with the stashed state.  For quickly making
        a snapshot, you can omit _both_ "save" and <message>, but giving
        only <message> does not trigger this action to prevent a misspelled
        subcommand from making an unwanted stash.
 +
-If the paths argument is given in 'git stash push', only these files
-are put in the new 'stash'.  In addition only the indicated files are
-changed in the working tree to match the index.
+When pathspec is given to 'git stash push', the new stash records the
+modified states only for the files that match the pathspec.  The index
+entries and working tree files are then rolled back to the state in
+HEAD only for these files, too, leaving files that do not match the
+pathspec intact.
 +
 If the `--keep-index` option is used, all changes already added to the
 index are left intact.
diff --git a/git-stash.sh b/git-stash.sh
index 0072a38b4c..46367d40aa 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -41,7 +41,7 @@ no_changes () {
 untracked_files () {
        excl_opt=--exclude-standard
        test "$untracked" = "all" && excl_opt=
-       git ls-files -o -z $excl_opt -- $1
+       git ls-files -o -z $excl_opt -- "$@"
 }
 
 clear_stash () {
@@ -59,13 +59,12 @@ create_stash () {
        stash_msg=
        untracked=
        new_style=
-       files=
        while test $# != 0
        do
                case "$1" in
                -m|--message)
                        shift
-                       stash_msg="$1"
+                       stash_msg=${1?"-m needs an argument"}
                        new_style=t
                        ;;
                -u|--include-untracked)
@@ -75,7 +74,6 @@ create_stash () {
                        ;;
                --)
                        shift
-                       files="$@"
                        new_style=t
                        break
                        ;;
@@ -106,6 +104,10 @@ create_stash () {
        if test -z "$new_style"
        then
                stash_msg="$*"
+               while test $# != 0
+               do
+                       shift
+               done
        fi
 
        git update-index -q --refresh
@@ -141,7 +143,7 @@ create_stash () {
                # Untracked files are stored by themselves in a parentless 
commit, for
                # ease of unpacking later.
                u_commit=$(
-                       untracked_files $files | (
+                       untracked_files "$@" | (
                                GIT_INDEX_FILE="$TMPindex" &&
                                export GIT_INDEX_FILE &&
                                rm -f "$TMPindex" &&
@@ -164,7 +166,7 @@ create_stash () {
                        git read-tree --index-output="$TMPindex" -m $i_tree &&
                        GIT_INDEX_FILE="$TMPindex" &&
                        export GIT_INDEX_FILE &&
-                       git diff-index --name-only -z HEAD -- $files 
>"$TMP-stagenames" &&
+                       git diff-index --name-only -z HEAD -- "$@" 
>"$TMP-stagenames" &&
                        git update-index -z --add --remove --stdin 
<"$TMP-stagenames" &&
                        git write-tree &&
                        rm -f "$TMPindex"
@@ -178,7 +180,7 @@ create_stash () {
 
                # find out what the user wants
                GIT_INDEX_FILE="$TMP-index" \
-                       git add--interactive --patch=stash -- $files &&
+                       git add--interactive --patch=stash -- "$@" &&
 
                # state of the working tree
                w_tree=$(GIT_INDEX_FILE="$TMP-index" git write-tree) ||
@@ -268,7 +270,7 @@ push_stash () {
                        ;;
                -m|--message)
                        shift
-                       stash_msg=$1
+                       stash_msg=${1?"-m needs an argument"}
                        ;;
                --help)
                        show_help
@@ -300,8 +302,6 @@ push_stash () {
                shift
        done
 
-       files="$*"
-
        if test -n "$patch_mode" && test -n "$untracked"
        then
                die "$(gettext "Can't use --patch and --include-untracked or 
--all at the same time")"
@@ -316,14 +316,14 @@ push_stash () {
        git reflog exists $ref_stash ||
                clear_stash || die "$(gettext "Cannot initialize stash")"
 
-       create_stash -m "$stash_msg" -u "$untracked" -- $files
+       create_stash -m "$stash_msg" -u "$untracked" -- "$@"
        store_stash -m "$stash_msg" -q $w_commit ||
        die "$(gettext "Cannot save the current status")"
        say "$(eval_gettext "Saved working directory and index state 
\$stash_msg")"
 
        if test -z "$patch_mode"
        then
-               if test -n "$files"
+               if test $# != 0
                then
                        git ls-files -z -- "$@" | xargs -0 git reset --
                        git ls-files -z --modified -- "$@" | xargs -0 git 
checkout HEAD --
@@ -334,7 +334,7 @@ push_stash () {
                test "$untracked" = "all" && CLEAN_X_OPTION=-x || 
CLEAN_X_OPTION=
                if test -n "$untracked"
                then
-                       git clean --force --quiet -d $CLEAN_X_OPTION -- $files
+                       git clean --force --quiet -d $CLEAN_X_OPTION -- "$@"
                fi
 
                if test "$keep_index" = "t" && test -n "$i_tree"
@@ -357,24 +357,6 @@ save_stash () {
        while test $# != 0
        do
                case "$1" in
-               -k|--keep-index)
-                       push_options="-k $push_options"
-                       ;;
-               --no-keep-index)
-                       push_options="--no-keep-index $push_options"
-                       ;;
-               -p|--patch)
-                       push_options="-p $push_options"
-                       ;;
-               -q|--quiet)
-                       push_options="-q $push_options"
-                       ;;
-               -u|--include-untracked)
-                       push_options="-u $push_options"
-                       ;;
-               -a|--all)
-                       push_options="-a $push_options"
-                       ;;
                --help)
                        show_help
                        ;;
@@ -383,20 +365,8 @@ save_stash () {
                        break
                        ;;
                -*)
-                       option="$1"
-                       # TRANSLATORS: $option is an invalid option, like
-                       # `--blah-blah'. The 7 spaces at the beginning of the
-                       # second line correspond to "error: ". So you should 
line
-                       # up the second line with however many characters the
-                       # translation of "error: " takes in your language. E.g. 
in
-                       # English this is:
-                       #
-                       #    $ git stash save --blah-blah 2>&1 | head -n 2
-                       #    error: unknown option for 'stash save': --blah-blah
-                       #           To provide a message, use git stash save -- 
'--blah-blah'
-                       eval_gettextln "error: unknown option for 'stash save': 
\$option
-       To provide a message, use git stash save -- '\$option'"
-                       usage
+                       # pass all options through to push_stash
+                       push_options="$push_options $1"
                        ;;
                *)
                        break
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index ca4c44aa9c..461fe46045 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -784,7 +784,7 @@ test_expect_success 'push -m shows right message' '
        test_cmp expect actual
 '
 
-test_expect_success 'deprecated version of stash create stores correct 
message' '
+test_expect_success 'create stores correct message' '
        >foo &&
        git add foo &&
        STASH_ID=$(git stash create "create test message") &&
@@ -793,6 +793,15 @@ test_expect_success 'deprecated version of stash create 
stores correct message'
        test_cmp expect actual
 '
 
+test_expect_success 'create with multiple arguments for the message' '
+       >foo &&
+       git add foo &&
+       STASH_ID=$(git stash create test untracked) &&
+       echo "On master: test untracked" >expect &&
+       git show --pretty=%s ${STASH_ID} | head -n1 >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'new style stash create stores correct message' '
        >foo &&
        git add foo &&
diff --git a/t/t3905-stash-include-untracked.sh 
b/t/t3905-stash-include-untracked.sh
index f372fc8ca8..9a98e31a3e 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -185,4 +185,30 @@ test_expect_success 'stash save --all is stash poppable' '
        test -s .gitignore
 '
 
+test_expect_success 'stash push --include-untracked with pathspec' '
+       >foo &&
+       >bar &&
+       git stash push --include-untracked -- foo &&
+       test_path_is_file bar &&
+       test_path_is_missing foo &&
+       git stash pop &&
+       test_path_is_file bar &&
+       test_path_is_file foo
+'
+
+test_expect_success 'stash push with $IFS character' '
+       >"foo   bar" &&
+       >foo &&
+       >bar &&
+       git add foo* &&
+       git stash push --include-untracked -- foo* &&
+       test_path_is_missing "foo       bar" &&
+       test_path_is_missing foo &&
+       test_path_is_file bar &&
+       git stash pop &&
+       test_path_is_file "foo  bar" &&
+       test_path_is_file foo &&
+       test_path_is_file bar
+'
+
 test_done

Thomas Gummerer (5):
  Documentation/stash: remove mention of git reset --hard
  stash: introduce push verb
  stash: add test for the create command line arguments
  stash: introduce new format create
  stash: teach 'push' (and 'create') to honor pathspec

 Documentation/git-stash.txt        |  17 ++++-
 git-stash.sh                       | 124 +++++++++++++++++++++++++++++++++----
 t/t3903-stash.sh                   |  78 +++++++++++++++++++++++
 t/t3905-stash-include-untracked.sh |  26 ++++++++
 4 files changed, 230 insertions(+), 15 deletions(-)

-- 
2.12.0.rc0.208.g81c5d00b20.dirty

Reply via email to