diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt index e31ea7d3037d55..7ef8c4791177b2 100644 --- a/Documentation/git-stash.txt +++ b/Documentation/git-stash.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'git stash' list [] -'git stash' show [] [] +'git stash' show [] 'git stash' drop [-q|--quiet] [] 'git stash' ( pop | apply ) [--index] [-q|--quiet] [] 'git stash' branch [] @@ -106,7 +106,7 @@ stash@{1}: On master: 9cc0589... Add git-stash The command takes options applicable to the 'git log' command to control what is shown and how. See linkgit:git-log[1]. -show [] []:: +show []:: Show the changes recorded in the stash entry as a diff between the stashed contents and the commit back when the stash entry was first diff --git a/Makefile b/Makefile index 8b3868ed8b4cf5..12421ad5f0138d 100644 --- a/Makefile +++ b/Makefile @@ -618,6 +618,7 @@ SCRIPT_SH += git-legacy-rebase.sh SCRIPT_SH += git-legacy-stash.sh SCRIPT_SH += git-remote-testgit.sh SCRIPT_SH += git-request-pull.sh +SCRIPT_SH += git-stash.sh SCRIPT_SH += git-submodule.sh SCRIPT_SH += git-web--browse.sh @@ -1098,7 +1099,6 @@ BUILTIN_OBJS += builtin/shortlog.o BUILTIN_OBJS += builtin/show-branch.o BUILTIN_OBJS += builtin/show-index.o BUILTIN_OBJS += builtin/show-ref.o -BUILTIN_OBJS += builtin/stash.o BUILTIN_OBJS += builtin/stripspace.o BUILTIN_OBJS += builtin/submodule--helper.o BUILTIN_OBJS += builtin/symbolic-ref.o diff --git a/builtin.h b/builtin.h index 97913ada19166f..bf226e9aaf3ab8 100644 --- a/builtin.h +++ b/builtin.h @@ -224,7 +224,6 @@ extern int cmd_show(int argc, const char **argv, const char *prefix); extern int cmd_show_branch(int argc, const char **argv, const char *prefix); extern int cmd_show_index(int argc, const char **argv, const char *prefix); extern int cmd_status(int argc, const char **argv, const char *prefix); -extern int cmd_stash(int argc, const char **argv, const char *prefix); extern int cmd_stripspace(int argc, const char **argv, const char *prefix); extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix); extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix); diff --git a/cache.h b/cache.h index 681307f716e689..3cf03cc3efda63 100644 --- a/cache.h +++ b/cache.h @@ -1312,7 +1312,6 @@ struct object_context { GET_OID_BLOB) extern int get_oid(const char *str, struct object_id *oid); -extern int get_oidf(struct object_id *oid, const char *fmt, ...); extern int get_oid_commit(const char *str, struct object_id *oid); extern int get_oid_committish(const char *str, struct object_id *oid); extern int get_oid_tree(const char *str, struct object_id *oid); diff --git a/git-stash.sh b/git-stash.sh new file mode 100755 index 00000000000000..94793c1a913abf --- /dev/null +++ b/git-stash.sh @@ -0,0 +1,752 @@ +#!/bin/sh +# Copyright (c) 2007, Nanako Shiraishi + +dashless=$(basename "$0" | sed -e 's/-/ /') +USAGE="list [] + or: $dashless show [] + or: $dashless drop [-q|--quiet] [] + or: $dashless ( pop | apply ) [--index] [-q|--quiet] [] + or: $dashless branch [] + or: $dashless save [--patch] [-k|--[no-]keep-index] [-q|--quiet] + [-u|--include-untracked] [-a|--all] [] + or: $dashless [push [--patch] [-k|--[no-]keep-index] [-q|--quiet] + [-u|--include-untracked] [-a|--all] [-m ] + [-- ...]] + or: $dashless clear" + +SUBDIRECTORY_OK=Yes +OPTIONS_SPEC= +START_DIR=$(pwd) +. git-sh-setup +require_work_tree +prefix=$(git rev-parse --show-prefix) || exit 1 +cd_to_toplevel + +TMP="$GIT_DIR/.git-stash.$$" +TMPindex=${GIT_INDEX_FILE-"$(git rev-parse --git-path index)"}.stash.$$ +trap 'rm -f "$TMP-"* "$TMPindex"' 0 + +ref_stash=refs/stash + +if git config --get-colorbool color.interactive; then + help_color="$(git config --get-color color.interactive.help 'red bold')" + reset_color="$(git config --get-color '' reset)" +else + help_color= + reset_color= +fi + +no_changes () { + git diff-index --quiet --cached HEAD --ignore-submodules -- "$@" && + git diff-files --quiet --ignore-submodules -- "$@" && + (test -z "$untracked" || test -z "$(untracked_files "$@")") +} + +untracked_files () { + if test "$1" = "-z" + then + shift + z=-z + else + z= + fi + excl_opt=--exclude-standard + test "$untracked" = "all" && excl_opt= + git ls-files -o $z $excl_opt -- "$@" +} + +clear_stash () { + if test $# != 0 + then + die "$(gettext "git stash clear with parameters is unimplemented")" + fi + if current=$(git rev-parse --verify --quiet $ref_stash) + then + git update-ref -d $ref_stash $current + fi +} + +create_stash () { + stash_msg= + untracked= + while test $# != 0 + do + case "$1" in + -m|--message) + shift + stash_msg=${1?"BUG: create_stash () -m requires an argument"} + ;; + -m*) + stash_msg=${1#-m} + ;; + --message=*) + stash_msg=${1#--message=} + ;; + -u|--include-untracked) + shift + untracked=${1?"BUG: create_stash () -u requires an argument"} + ;; + --) + shift + break + ;; + esac + shift + done + + git update-index -q --refresh + if no_changes "$@" + then + exit 0 + fi + + # state of the base commit + if b_commit=$(git rev-parse --verify HEAD) + then + head=$(git rev-list --oneline -n 1 HEAD --) + else + die "$(gettext "You do not have the initial commit yet")" + fi + + if branch=$(git symbolic-ref -q HEAD) + then + branch=${branch#refs/heads/} + else + branch='(no branch)' + fi + msg=$(printf '%s: %s' "$branch" "$head") + + # state of the index + i_tree=$(git write-tree) && + i_commit=$(printf 'index on %s\n' "$msg" | + git commit-tree $i_tree -p $b_commit) || + die "$(gettext "Cannot save the current index state")" + + if test -n "$untracked" + then + # Untracked files are stored by themselves in a parentless commit, for + # ease of unpacking later. + u_commit=$( + untracked_files -z "$@" | ( + GIT_INDEX_FILE="$TMPindex" && + export GIT_INDEX_FILE && + rm -f "$TMPindex" && + git update-index -z --add --remove --stdin && + u_tree=$(git write-tree) && + printf 'untracked files on %s\n' "$msg" | git commit-tree $u_tree && + rm -f "$TMPindex" + ) ) || die "$(gettext "Cannot save the untracked files")" + + untracked_commit_option="-p $u_commit"; + else + untracked_commit_option= + fi + + if test -z "$patch_mode" + then + + # state of the working tree + w_tree=$( ( + git read-tree --index-output="$TMPindex" -m $i_tree && + GIT_INDEX_FILE="$TMPindex" && + export GIT_INDEX_FILE && + git diff-index --name-only -z HEAD -- "$@" >"$TMP-stagenames" && + git update-index -z --add --remove --stdin <"$TMP-stagenames" && + git write-tree && + rm -f "$TMPindex" + ) ) || + die "$(gettext "Cannot save the current worktree state")" + + else + + rm -f "$TMP-index" && + GIT_INDEX_FILE="$TMP-index" git read-tree HEAD && + + # find out what the user wants + GIT_INDEX_FILE="$TMP-index" \ + git add--interactive --patch=stash -- "$@" && + + # state of the working tree + w_tree=$(GIT_INDEX_FILE="$TMP-index" git write-tree) || + die "$(gettext "Cannot save the current worktree state")" + + git diff-tree -p HEAD $w_tree -- >"$TMP-patch" && + test -s "$TMP-patch" || + die "$(gettext "No changes selected")" + + rm -f "$TMP-index" || + die "$(gettext "Cannot remove temporary index (can't happen)")" + + fi + + # create the stash + if test -z "$stash_msg" + then + stash_msg=$(printf 'WIP on %s' "$msg") + else + stash_msg=$(printf 'On %s: %s' "$branch" "$stash_msg") + fi + w_commit=$(printf '%s\n' "$stash_msg" | + git commit-tree $w_tree -p $b_commit -p $i_commit $untracked_commit_option) || + die "$(gettext "Cannot record working tree state")" +} + +store_stash () { + while test $# != 0 + do + case "$1" in + -m|--message) + shift + stash_msg="$1" + ;; + -m*) + stash_msg=${1#-m} + ;; + --message=*) + stash_msg=${1#--message=} + ;; + -q|--quiet) + quiet=t + ;; + *) + break + ;; + esac + shift + done + test $# = 1 || + die "$(eval_gettext "\"$dashless store\" requires one argument")" + + w_commit="$1" + if test -z "$stash_msg" + then + stash_msg="Created via \"git stash store\"." + fi + + git update-ref --create-reflog -m "$stash_msg" $ref_stash $w_commit + ret=$? + test $ret != 0 && test -z "$quiet" && + die "$(eval_gettext "Cannot update \$ref_stash with \$w_commit")" + return $ret +} + +push_stash () { + keep_index= + patch_mode= + untracked= + stash_msg= + while test $# != 0 + do + case "$1" in + -k|--keep-index) + keep_index=t + ;; + --no-keep-index) + keep_index=n + ;; + -p|--patch) + patch_mode=t + # only default to keep if we don't already have an override + test -z "$keep_index" && keep_index=t + ;; + -q|--quiet) + GIT_QUIET=t + ;; + -u|--include-untracked) + untracked=untracked + ;; + -a|--all) + untracked=all + ;; + -m|--message) + shift + test -z ${1+x} && usage + stash_msg=$1 + ;; + -m*) + stash_msg=${1#-m} + ;; + --message=*) + stash_msg=${1#--message=} + ;; + --help) + show_help + ;; + --) + shift + break + ;; + -*) + option="$1" + eval_gettextln "error: unknown option for 'stash push': \$option" + usage + ;; + *) + break + ;; + esac + shift + done + + eval "set $(git rev-parse --sq --prefix "$prefix" -- "$@")" + + if test -n "$patch_mode" && test -n "$untracked" + then + die "$(gettext "Can't use --patch and --include-untracked or --all at the same time")" + fi + + test -n "$untracked" || git ls-files --error-unmatch -- "$@" >/dev/null || exit 1 + + git update-index -q --refresh + if no_changes "$@" + then + say "$(gettext "No local changes to save")" + exit 0 + fi + + git reflog exists $ref_stash || + clear_stash || die "$(gettext "Cannot initialize stash")" + + 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 + test "$untracked" = "all" && CLEAN_X_OPTION=-x || CLEAN_X_OPTION= + if test -n "$untracked" && test $# = 0 + then + git clean --force --quiet -d $CLEAN_X_OPTION + fi + + if test $# != 0 + then + test -z "$untracked" && UPDATE_OPTION="-u" || UPDATE_OPTION= + test "$untracked" = "all" && FORCE_OPTION="--force" || FORCE_OPTION= + git add $UPDATE_OPTION $FORCE_OPTION -- "$@" + git diff-index -p --cached --binary HEAD -- "$@" | + git apply --index -R + else + git reset --hard -q + fi + + if test "$keep_index" = "t" && test -n "$i_tree" + then + git read-tree --reset $i_tree + git ls-files -z --modified -- "$@" | + git checkout-index -z --force --stdin + fi + else + git apply -R < "$TMP-patch" || + die "$(gettext "Cannot remove worktree changes")" + + if test "$keep_index" != "t" + then + git reset -q -- "$@" + fi + fi +} + +save_stash () { + push_options= + while test $# != 0 + do + case "$1" in + --) + shift + break + ;; + -*) + # pass all options through to push_stash + push_options="$push_options $1" + ;; + *) + break + ;; + esac + shift + done + + stash_msg="$*" + + if test -z "$stash_msg" + then + push_stash $push_options + else + push_stash $push_options -m "$stash_msg" + fi +} + +have_stash () { + git rev-parse --verify --quiet $ref_stash >/dev/null +} + +list_stash () { + have_stash || return 0 + git log --format="%gd: %gs" -g --first-parent -m "$@" $ref_stash -- +} + +show_stash () { + ALLOW_UNKNOWN_FLAGS=t + assert_stash_like "$@" + + if test -z "$FLAGS" + then + if test "$(git config --bool stash.showStat || echo true)" = "true" + then + FLAGS=--stat + fi + + if test "$(git config --bool stash.showPatch || echo false)" = "true" + then + FLAGS=${FLAGS}${FLAGS:+ }-p + fi + + if test -z "$FLAGS" + then + return 0 + fi + fi + + git diff ${FLAGS} $b_commit $w_commit +} + +show_help () { + exec git help stash + exit 1 +} + +# +# Parses the remaining options looking for flags and +# at most one revision defaulting to ${ref_stash}@{0} +# if none found. +# +# Derives related tree and commit objects from the +# revision, if one is found. +# +# stash records the work tree, and is a merge between the +# base commit (first parent) and the index tree (second parent). +# +# REV is set to the symbolic version of the specified stash-like commit +# IS_STASH_LIKE is non-blank if ${REV} looks like a stash +# IS_STASH_REF is non-blank if the ${REV} looks like a stash ref +# s is set to the SHA1 of the stash commit +# w_commit is set to the commit containing the working tree +# b_commit is set to the base commit +# i_commit is set to the commit containing the index tree +# u_commit is set to the commit containing the untracked files tree +# w_tree is set to the working tree +# b_tree is set to the base tree +# i_tree is set to the index tree +# u_tree is set to the untracked files tree +# +# GIT_QUIET is set to t if -q is specified +# INDEX_OPTION is set to --index if --index is specified. +# FLAGS is set to the remaining flags (if allowed) +# +# dies if: +# * too many revisions specified +# * no revision is specified and there is no stash stack +# * a revision is specified which cannot be resolve to a SHA1 +# * a non-existent stash reference is specified +# * unknown flags were set and ALLOW_UNKNOWN_FLAGS is not "t" +# + +parse_flags_and_rev() +{ + test "$PARSE_CACHE" = "$*" && return 0 # optimisation + PARSE_CACHE="$*" + + IS_STASH_LIKE= + IS_STASH_REF= + INDEX_OPTION= + s= + w_commit= + b_commit= + i_commit= + u_commit= + w_tree= + b_tree= + i_tree= + u_tree= + + FLAGS= + REV= + for opt + do + case "$opt" in + -q|--quiet) + GIT_QUIET=-t + ;; + --index) + INDEX_OPTION=--index + ;; + --help) + show_help + ;; + -*) + test "$ALLOW_UNKNOWN_FLAGS" = t || + die "$(eval_gettext "unknown option: \$opt")" + FLAGS="${FLAGS}${FLAGS:+ }$opt" + ;; + *) + REV="${REV}${REV:+ }'$opt'" + ;; + esac + done + + eval set -- $REV + + case $# in + 0) + have_stash || die "$(gettext "No stash entries found.")" + set -- ${ref_stash}@{0} + ;; + 1) + : + ;; + *) + die "$(eval_gettext "Too many revisions specified: \$REV")" + ;; + esac + + case "$1" in + *[!0-9]*) + : + ;; + *) + set -- "${ref_stash}@{$1}" + ;; + esac + + REV=$(git rev-parse --symbolic --verify --quiet "$1") || { + reference="$1" + die "$(eval_gettext "\$reference is not a valid reference")" + } + + i_commit=$(git rev-parse --verify --quiet "$REV^2") && + set -- $(git rev-parse "$REV" "$REV^1" "$REV:" "$REV^1:" "$REV^2:" 2>/dev/null) && + s=$1 && + w_commit=$1 && + b_commit=$2 && + w_tree=$3 && + b_tree=$4 && + i_tree=$5 && + IS_STASH_LIKE=t && + test "$ref_stash" = "$(git rev-parse --symbolic-full-name "${REV%@*}")" && + IS_STASH_REF=t + + u_commit=$(git rev-parse --verify --quiet "$REV^3") && + u_tree=$(git rev-parse "$REV^3:" 2>/dev/null) +} + +is_stash_like() +{ + parse_flags_and_rev "$@" + test -n "$IS_STASH_LIKE" +} + +assert_stash_like() { + is_stash_like "$@" || { + args="$*" + die "$(eval_gettext "'\$args' is not a stash-like commit")" + } +} + +is_stash_ref() { + is_stash_like "$@" && test -n "$IS_STASH_REF" +} + +assert_stash_ref() { + is_stash_ref "$@" || { + args="$*" + die "$(eval_gettext "'\$args' is not a stash reference")" + } +} + +apply_stash () { + + assert_stash_like "$@" + + git update-index -q --refresh || die "$(gettext "unable to refresh index")" + + # current index state + c_tree=$(git write-tree) || + die "$(gettext "Cannot apply a stash in the middle of a merge")" + + unstashed_index_tree= + if test -n "$INDEX_OPTION" && test "$b_tree" != "$i_tree" && + test "$c_tree" != "$i_tree" + then + git diff-tree --binary $s^2^..$s^2 | git apply --cached + test $? -ne 0 && + die "$(gettext "Conflicts in index. Try without --index.")" + unstashed_index_tree=$(git write-tree) || + die "$(gettext "Could not save index tree")" + git reset + fi + + if test -n "$u_tree" + then + GIT_INDEX_FILE="$TMPindex" git read-tree "$u_tree" && + GIT_INDEX_FILE="$TMPindex" git checkout-index --all && + rm -f "$TMPindex" || + die "$(gettext "Could not restore untracked files from stash entry")" + fi + + eval " + GITHEAD_$w_tree='Stashed changes' && + GITHEAD_$c_tree='Updated upstream' && + GITHEAD_$b_tree='Version stash was based on' && + export GITHEAD_$w_tree GITHEAD_$c_tree GITHEAD_$b_tree + " + + if test -n "$GIT_QUIET" + then + GIT_MERGE_VERBOSITY=0 && export GIT_MERGE_VERBOSITY + fi + if git merge-recursive $b_tree -- $c_tree $w_tree + then + # No conflict + if test -n "$unstashed_index_tree" + then + git read-tree "$unstashed_index_tree" + else + a="$TMP-added" && + git diff-index --cached --name-only --diff-filter=A $c_tree >"$a" && + git read-tree --reset $c_tree && + git update-index --add --stdin <"$a" || + die "$(gettext "Cannot unstage modified files")" + rm -f "$a" + fi + squelch= + if test -n "$GIT_QUIET" + then + squelch='>/dev/null 2>&1' + fi + (cd "$START_DIR" && eval "git status $squelch") || : + else + # Merge conflict; keep the exit status from merge-recursive + status=$? + git rerere + if test -n "$INDEX_OPTION" + then + gettextln "Index was not unstashed." >&2 + fi + exit $status + fi +} + +pop_stash() { + assert_stash_ref "$@" + + if apply_stash "$@" + then + drop_stash "$@" + else + status=$? + say "$(gettext "The stash entry is kept in case you need it again.")" + exit $status + fi +} + +drop_stash () { + assert_stash_ref "$@" + + git reflog delete --updateref --rewrite "${REV}" && + say "$(eval_gettext "Dropped \${REV} (\$s)")" || + die "$(eval_gettext "\${REV}: Could not drop stash entry")" + + # clear_stash if we just dropped the last stash entry + git rev-parse --verify --quiet "$ref_stash@{0}" >/dev/null || + clear_stash +} + +apply_to_branch () { + test -n "$1" || die "$(gettext "No branch name specified")" + branch=$1 + shift 1 + + set -- --index "$@" + assert_stash_like "$@" + + git checkout -b $branch $REV^ && + apply_stash "$@" && { + test -z "$IS_STASH_REF" || drop_stash "$@" + } +} + +test "$1" = "-p" && set "push" "$@" + +PARSE_CACHE='--not-parsed' +# The default command is "push" if nothing but options are given +seen_non_option= +for opt +do + case "$opt" in + --) break ;; + -*) ;; + *) seen_non_option=t; break ;; + esac +done + +test -n "$seen_non_option" || set "push" "$@" + +# Main command set +case "$1" in +list) + shift + list_stash "$@" + ;; +show) + shift + show_stash "$@" + ;; +save) + shift + save_stash "$@" + ;; +push) + shift + push_stash "$@" + ;; +apply) + shift + apply_stash "$@" + ;; +clear) + shift + clear_stash "$@" + ;; +create) + shift + create_stash -m "$*" && echo "$w_commit" + ;; +store) + shift + store_stash "$@" + ;; +drop) + shift + drop_stash "$@" + ;; +pop) + shift + pop_stash "$@" + ;; +branch) + shift + apply_to_branch "$@" + ;; +*) + case $# in + 0) + push_stash && + say "$(gettext "(To restore them type \"git stash apply\")")" + ;; + *) + usage + esac + ;; +esac diff --git a/git.c b/git.c index 24ade0123386d2..a18d517452bf96 100644 --- a/git.c +++ b/git.c @@ -550,12 +550,6 @@ static struct cmd_struct commands[] = { { "show-index", cmd_show_index }, { "show-ref", cmd_show_ref, RUN_SETUP }, { "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE }, - /* - * NEEDSWORK: Until the builtin stash is thoroughly robust and no - * longer needs redirection to the stash shell script this is kept as - * is, then should be changed to RUN_SETUP | NEED_WORK_TREE - */ - { "stash", cmd_stash }, { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE }, { "stripspace", cmd_stripspace }, { "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX | NO_PARSEOPT }, diff --git a/sha1-name.c b/sha1-name.c index 261b960bbd2b24..c9cc1318b7394e 100644 --- a/sha1-name.c +++ b/sha1-name.c @@ -1471,25 +1471,6 @@ int get_oid(const char *name, struct object_id *oid) return get_oid_with_context(name, 0, oid, &unused); } -/* - * This returns a non-zero value if the string (built using printf - * format and the given arguments) is not a valid object. - */ -int get_oidf(struct object_id *oid, const char *fmt, ...) -{ - va_list ap; - int ret; - struct strbuf sb = STRBUF_INIT; - - va_start(ap, fmt); - strbuf_vaddf(&sb, fmt, ap); - va_end(ap); - - ret = get_oid(sb.buf, oid); - strbuf_release(&sb); - - return ret; -} /* * Many callers know that the user meant to name a commit-ish by diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 9e06494ba0ef19..c934e507c0ae3f 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -8,22 +8,22 @@ test_description='Test git stash' . ./test-lib.sh test_expect_success 'stash some dirty working directory' ' - echo 1 >file && + echo 1 > file && git add file && echo unrelated >other-file && git add other-file && test_tick && git commit -m initial && - echo 2 >file && + echo 2 > file && git add file && - echo 3 >file && + echo 3 > file && test_tick && git stash && git diff-files --quiet && git diff-index --cached --quiet HEAD ' -cat >expect < expect << EOF diff --git a/file b/file index 0cfbf08..00750ed 100644 --- a/file @@ -35,7 +35,7 @@ EOF test_expect_success 'parents of stash' ' test $(git rev-parse stash^) = $(git rev-parse HEAD) && - git diff stash^2..stash >output && + git diff stash^2..stash > output && test_cmp output expect ' @@ -74,7 +74,7 @@ test_expect_success 'apply stashed changes' ' test_expect_success 'apply stashed changes (including index)' ' git reset --hard HEAD^ && - echo 6 >other-file && + echo 6 > other-file && git add other-file && test_tick && git commit -m other-file && @@ -99,12 +99,12 @@ test_expect_success 'stash drop complains of extra options' ' test_expect_success 'drop top stash' ' git reset --hard && - git stash list >expected && - echo 7 >file && + git stash list > stashlist1 && + echo 7 > file && git stash && git stash drop && - git stash list >actual && - test_cmp expected actual && + git stash list > stashlist2 && + test_cmp stashlist1 stashlist2 && git stash apply && test 3 = $(cat file) && test 1 = $(git show :file) && @@ -113,9 +113,9 @@ test_expect_success 'drop top stash' ' test_expect_success 'drop middle stash' ' git reset --hard && - echo 8 >file && + echo 8 > file && git stash && - echo 9 >file && + echo 9 > file && git stash && git stash drop stash@{1} && test 2 = $(git stash list | wc -l) && @@ -160,7 +160,7 @@ test_expect_success 'stash pop' ' test 0 = $(git stash list | wc -l) ' -cat >expect < expect << EOF diff --git a/file2 b/file2 new file mode 100644 index 0000000..1fe912c @@ -170,7 +170,7 @@ index 0000000..1fe912c +bar2 EOF -cat >expect1 < expect1 << EOF diff --git a/file b/file index 257cc56..5716ca5 100644 --- a/file @@ -180,7 +180,7 @@ index 257cc56..5716ca5 100644 +bar EOF -cat >expect2 < expect2 << EOF diff --git a/file b/file index 7601807..5716ca5 100644 --- a/file @@ -198,79 +198,79 @@ index 0000000..1fe912c EOF test_expect_success 'stash branch' ' - echo foo >file && + echo foo > file && git commit file -m first && - echo bar >file && - echo bar2 >file2 && + echo bar > file && + echo bar2 > file2 && git add file2 && git stash && - echo baz >file && + echo baz > file && git commit file -m second && git stash branch stashbranch && test refs/heads/stashbranch = $(git symbolic-ref HEAD) && test $(git rev-parse HEAD) = $(git rev-parse master^) && - git diff --cached >output && + git diff --cached > output && test_cmp output expect && - git diff >output && + git diff > output && test_cmp output expect1 && git add file && git commit -m alternate\ second && - git diff master..stashbranch >output && + git diff master..stashbranch > output && test_cmp output expect2 && test 0 = $(git stash list | wc -l) ' test_expect_success 'apply -q is quiet' ' - echo foo >file && + echo foo > file && git stash && - git stash apply -q >output.out 2>&1 && + git stash apply -q > output.out 2>&1 && test_must_be_empty output.out ' test_expect_success 'save -q is quiet' ' - git stash save --quiet >output.out 2>&1 && + git stash save --quiet > output.out 2>&1 && test_must_be_empty output.out ' test_expect_success 'pop -q is quiet' ' - git stash pop -q >output.out 2>&1 && + git stash pop -q > output.out 2>&1 && test_must_be_empty output.out ' test_expect_success 'pop -q --index works and is quiet' ' - echo foo >file && + echo foo > file && git add file && git stash save --quiet && - git stash pop -q --index >output.out 2>&1 && + git stash pop -q --index > output.out 2>&1 && test foo = "$(git show :file)" && test_must_be_empty output.out ' test_expect_success 'drop -q is quiet' ' git stash && - git stash drop -q >output.out 2>&1 && + git stash drop -q > output.out 2>&1 && test_must_be_empty output.out ' test_expect_success 'stash -k' ' - echo bar3 >file && - echo bar4 >file2 && + echo bar3 > file && + echo bar4 > file2 && git add file2 && git stash -k && test bar,bar4 = $(cat file),$(cat file2) ' test_expect_success 'stash --no-keep-index' ' - echo bar33 >file && - echo bar44 >file2 && + echo bar33 > file && + echo bar44 > file2 && git add file2 && git stash --no-keep-index && test bar,bar2 = $(cat file),$(cat file2) ' test_expect_success 'stash --invalid-option' ' - echo bar5 >file && - echo bar6 >file2 && + echo bar5 > file && + echo bar6 > file2 && git add file2 && test_must_fail git stash --invalid-option && test_must_fail git stash save --invalid-option && @@ -444,36 +444,6 @@ test_expect_failure 'stash file to directory' ' test foo = "$(cat file/file)" ' -test_expect_success 'giving too many ref arguments does not modify files' ' - git stash clear && - test_when_finished "git reset --hard HEAD" && - echo foo >file2 && - git stash && - echo bar >file2 && - git stash && - test-tool chmtime =123456789 file2 && - for type in apply pop "branch stash-branch" - do - test_must_fail git stash $type stash@{0} stash@{1} 2>err && - test_i18ngrep "Too many revisions" err && - test 123456789 = $(test-tool chmtime -g file2) || return 1 - done -' - -test_expect_success 'drop: too many arguments errors out (does nothing)' ' - git stash list >expect && - test_must_fail git stash drop stash@{0} stash@{1} 2>err && - test_i18ngrep "Too many revisions" err && - git stash list >actual && - test_cmp expect actual -' - -test_expect_success 'show: too many arguments errors out (does nothing)' ' - test_must_fail git stash show stash@{0} stash@{1} 2>err 1>out && - test_i18ngrep "Too many revisions" err && - test_must_be_empty out -' - test_expect_success 'stash create - no changes' ' git stash clear && test_when_finished "git reset --hard HEAD" && @@ -486,12 +456,11 @@ test_expect_success 'stash branch - no stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >>file && + echo foo >> file && STASH_ID=$(git stash create) && git reset --hard && git stash branch stash-branch ${STASH_ID} && - test_when_finished "git reset --hard HEAD && git checkout master && - git branch -D stash-branch" && + test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" && test $(git ls-files --modified | wc -l) -eq 1 ' @@ -499,31 +468,25 @@ test_expect_success 'stash branch - stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >>file && + echo foo >> file && git stash && test_when_finished "git stash drop" && - echo bar >>file && + echo bar >> file && STASH_ID=$(git stash create) && git reset --hard && git stash branch stash-branch ${STASH_ID} && - test_when_finished "git reset --hard HEAD && git checkout master && - git branch -D stash-branch" && + test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" && test $(git ls-files --modified | wc -l) -eq 1 ' -test_expect_success 'stash branch complains with no arguments' ' - test_must_fail git stash branch 2>err && - test_i18ngrep "No branch name specified" err -' - test_expect_success 'stash show format defaults to --stat' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >>file && + echo foo >> file && git stash && test_when_finished "git stash drop" && - echo bar >>file && + echo bar >> file && STASH_ID=$(git stash create) && git reset --hard && cat >expected <<-EOF && @@ -538,10 +501,10 @@ test_expect_success 'stash show - stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >>file && + echo foo >> file && git stash && test_when_finished "git stash drop" && - echo bar >>file && + echo bar >> file && STASH_ID=$(git stash create) && git reset --hard && echo "1 0 file" >expected && @@ -553,10 +516,10 @@ test_expect_success 'stash show -p - stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >>file && + echo foo >> file && git stash && test_when_finished "git stash drop" && - echo bar >>file && + echo bar >> file && STASH_ID=$(git stash create) && git reset --hard && cat >expected <<-EOF && @@ -576,7 +539,7 @@ test_expect_success 'stash show - no stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >>file && + echo foo >> file && STASH_ID=$(git stash create) && git reset --hard && echo "1 0 file" >expected && @@ -588,7 +551,7 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >>file && + echo foo >> file && STASH_ID=$(git stash create) && git reset --hard && cat >expected <<-EOF && @@ -604,13 +567,13 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' ' test_cmp expected actual ' -test_expect_success 'drop: fail early if specified stash is not a stash ref' ' +test_expect_success 'stash drop - fail early if specified stash is not a stash reference' ' git stash clear && test_when_finished "git reset --hard HEAD && git stash clear" && git reset --hard && - echo foo >file && + echo foo > file && git stash && - echo bar >file && + echo bar > file && git stash && test_must_fail git stash drop $(git rev-parse stash@{0}) && git stash pop && @@ -618,13 +581,13 @@ test_expect_success 'drop: fail early if specified stash is not a stash ref' ' git reset --hard HEAD ' -test_expect_success 'pop: fail early if specified stash is not a stash ref' ' +test_expect_success 'stash pop - fail early if specified stash is not a stash reference' ' git stash clear && test_when_finished "git reset --hard HEAD && git stash clear" && git reset --hard && - echo foo >file && + echo foo > file && git stash && - echo bar >file && + echo bar > file && git stash && test_must_fail git stash pop $(git rev-parse stash@{0}) && git stash pop && @@ -634,8 +597,8 @@ test_expect_success 'pop: fail early if specified stash is not a stash ref' ' test_expect_success 'ref with non-existent reflog' ' git stash clear && - echo bar5 >file && - echo bar6 >file2 && + echo bar5 > file && + echo bar6 > file2 && git add file2 && git stash && test_must_fail git rev-parse --quiet --verify does-not-exist && @@ -655,8 +618,8 @@ test_expect_success 'ref with non-existent reflog' ' test_expect_success 'invalid ref of the form stash@{n}, n >= N' ' git stash clear && test_must_fail git stash drop stash@{0} && - echo bar5 >file && - echo bar6 >file2 && + echo bar5 > file && + echo bar6 > file2 && git add file2 && git stash && test_must_fail git stash drop stash@{1} && @@ -682,7 +645,7 @@ test_expect_success 'invalid ref of the form "n", n >= N' ' git stash drop ' -test_expect_success 'branch: do not drop the stash if the branch exists' ' +test_expect_success 'stash branch should not drop the stash if the branch exists' ' git stash clear && echo foo >file && git add file && @@ -693,7 +656,7 @@ test_expect_success 'branch: do not drop the stash if the branch exists' ' git rev-parse stash@{0} -- ' -test_expect_success 'branch: should not drop the stash if the apply fails' ' +test_expect_success 'stash branch should not drop the stash if the apply fails' ' git stash clear && git reset HEAD~1 --hard && echo foo >file && @@ -707,7 +670,7 @@ test_expect_success 'branch: should not drop the stash if the apply fails' ' git rev-parse stash@{0} -- ' -test_expect_success 'apply: show same status as git status (relative to ./)' ' +test_expect_success 'stash apply shows status same as git status (relative to current directory)' ' git stash clear && echo 1 >subdir/subfile1 && echo 2 >subdir/subfile2 && @@ -726,7 +689,7 @@ test_expect_success 'apply: show same status as git status (relative to ./)' ' test_i18ncmp expect actual ' -cat >expect < expect << EOF diff --git a/HEAD b/HEAD new file mode 100644 index 0000000..fe0cbee @@ -739,14 +702,14 @@ EOF test_expect_success 'stash where working directory contains "HEAD" file' ' git stash clear && git reset --hard && - echo file-not-a-ref >HEAD && + echo file-not-a-ref > HEAD && git add HEAD && test_tick && git stash && git diff-files --quiet && git diff-index --cached --quiet HEAD && test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" && - git diff stash^..stash >output && + git diff stash^..stash > output && test_cmp output expect ' @@ -1048,7 +1011,7 @@ test_expect_success 'stash push -p with pathspec shows no changes only once' ' test_i18ncmp expect actual ' -test_expect_success 'push : show no changes when there are none' ' +test_expect_success 'stash push with pathspec shows no changes when there are none' ' >foo && git add foo && git commit -m "tmp" && @@ -1058,35 +1021,12 @@ test_expect_success 'push : show no changes when there are none' ' test_i18ncmp expect actual ' -test_expect_success 'push: not in the repository errors out' ' +test_expect_success 'stash push with pathspec not in the repository errors out' ' >untracked && test_must_fail git stash push untracked && test_path_is_file untracked ' -test_expect_success 'push: -q is quiet with changes' ' - >foo && - git add foo && - git stash push -q >output 2>&1 && - test_must_be_empty output -' - -test_expect_success 'push: -q is quiet with no changes' ' - git stash push -q >output 2>&1 && - test_must_be_empty output -' - -test_expect_success 'push: -q is quiet even if there is no initial commit' ' - git init foo_dir && - test_when_finished rm -rf foo_dir && - ( - cd foo_dir && - >bar && - test_must_fail git stash push -q >output 2>&1 && - test_must_be_empty output - ) -' - test_expect_success 'untracked files are left in place when -u is not given' ' >file && git add file && diff --git a/t/t3907-stash-show-config.sh b/t/t3907-stash-show-config.sh deleted file mode 100755 index 8fe369c1a11d44..00000000000000 --- a/t/t3907-stash-show-config.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh - -test_description='Test git stash show configuration.' - -. ./test-lib.sh - -test_expect_success 'setup' ' - test_commit file -' - -# takes three parameters: -# 1. the stash.showStat value (or "") -# 2. the stash.showPatch value (or "") -# 3. the diff options of the expected output (or nothing for no output) -test_stat_and_patch () { - if test "" = "$1" - then - test_might_fail git config --unset stash.showStat - else - test_config stash.showStat "$1" - fi && - - if test "" = "$2" - then - test_might_fail git config --unset stash.showPatch - else - test_config stash.showPatch "$2" - fi && - - shift && - shift && - echo 2 >file.t && - git diff "$@" >expect && - git stash && - git stash show >actual && - - if test -z "$1" - then - test_must_be_empty actual - else - test_cmp expect actual - fi -} - -test_expect_success 'showStat unset showPatch unset' ' - test_stat_and_patch "" "" --stat -' - -test_expect_success 'showStat unset showPatch false' ' - test_stat_and_patch "" false --stat -' - -test_expect_success 'showStat unset showPatch true' ' - test_stat_and_patch "" true --stat -p -' - -test_expect_success 'showStat false showPatch unset' ' - test_stat_and_patch false "" -' - -test_expect_success 'showStat false showPatch false' ' - test_stat_and_patch false false -' - -test_expect_success 'showStat false showPatch true' ' - test_stat_and_patch false true -p -' - -test_expect_success 'showStat true showPatch unset' ' - test_stat_and_patch true "" --stat -' - -test_expect_success 'showStat true showPatch false' ' - test_stat_and_patch true false --stat -' - -test_expect_success 'showStat true showPatch true' ' - test_stat_and_patch true true --stat -p -' - -test_done