mirror of
https://github.com/git-for-windows/git.git
synced 2026-03-17 22:19:19 -05:00
Merge 'ps/stash-in-c'
This merges the builtin stash. Upstream Git did not integrate it into any stable integration branch yet, but the performance improvements are substantial enough, especially on Windows, that we really, really, really want to have it early. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -82,6 +82,7 @@
|
||||
/git-interpret-trailers
|
||||
/git-instaweb
|
||||
/git-legacy-rebase
|
||||
/git-legacy-stash
|
||||
/git-log
|
||||
/git-ls-files
|
||||
/git-ls-remote
|
||||
|
||||
@@ -9,7 +9,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git stash' list [<options>]
|
||||
'git stash' show [<stash>]
|
||||
'git stash' show [<options>] [<stash>]
|
||||
'git stash' drop [-q|--quiet] [<stash>]
|
||||
'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
|
||||
'git stash' branch <branchname> [<stash>]
|
||||
@@ -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 [<stash>]::
|
||||
show [<options>] [<stash>]::
|
||||
|
||||
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
|
||||
|
||||
3
Makefile
3
Makefile
@@ -617,9 +617,9 @@ SCRIPT_SH += git-merge-resolve.sh
|
||||
SCRIPT_SH += git-mergetool.sh
|
||||
SCRIPT_SH += git-quiltimport.sh
|
||||
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
|
||||
|
||||
@@ -1117,6 +1117,7 @@ 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
|
||||
|
||||
@@ -225,6 +225,7 @@ 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);
|
||||
|
||||
1637
builtin/stash.c
Normal file
1637
builtin/stash.c
Normal file
File diff suppressed because it is too large
Load Diff
2
cache.h
2
cache.h
@@ -1333,6 +1333,7 @@ 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);
|
||||
@@ -1490,6 +1491,7 @@ extern const char *git_sequence_editor(void);
|
||||
extern const char *git_pager(int stdout_is_tty);
|
||||
extern int is_terminal_dumb(void);
|
||||
extern int git_ident_config(const char *, const char *, void *);
|
||||
void prepare_fallback_ident(const char *name, const char *email);
|
||||
extern void reset_ident_date(void);
|
||||
|
||||
struct ident_split {
|
||||
|
||||
@@ -55,6 +55,20 @@ untracked_files () {
|
||||
git ls-files -o $z $excl_opt -- "$@"
|
||||
}
|
||||
|
||||
prepare_fallback_ident () {
|
||||
if ! git -c user.useconfigonly=yes var GIT_COMMITTER_IDENT >/dev/null 2>&1
|
||||
then
|
||||
GIT_AUTHOR_NAME="git stash"
|
||||
GIT_AUTHOR_EMAIL=git@stash
|
||||
GIT_COMMITTER_NAME="git stash"
|
||||
GIT_COMMITTER_EMAIL=git@stash
|
||||
export GIT_AUTHOR_NAME
|
||||
export GIT_AUTHOR_EMAIL
|
||||
export GIT_COMMITTER_NAME
|
||||
export GIT_COMMITTER_EMAIL
|
||||
fi
|
||||
}
|
||||
|
||||
clear_stash () {
|
||||
if test $# != 0
|
||||
then
|
||||
@@ -66,7 +80,32 @@ clear_stash () {
|
||||
fi
|
||||
}
|
||||
|
||||
maybe_quiet () {
|
||||
case "$1" in
|
||||
--keep-stdout)
|
||||
shift
|
||||
if test -n "$GIT_QUIET"
|
||||
then
|
||||
eval "$@" 2>/dev/null
|
||||
else
|
||||
eval "$@"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if test -n "$GIT_QUIET"
|
||||
then
|
||||
eval "$@" >/dev/null 2>&1
|
||||
else
|
||||
eval "$@"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
create_stash () {
|
||||
|
||||
prepare_fallback_ident
|
||||
|
||||
stash_msg=
|
||||
untracked=
|
||||
while test $# != 0
|
||||
@@ -95,15 +134,18 @@ create_stash () {
|
||||
done
|
||||
|
||||
git update-index -q --refresh
|
||||
if no_changes "$@"
|
||||
if maybe_quiet no_changes "$@"
|
||||
then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# state of the base commit
|
||||
if b_commit=$(git rev-parse --verify HEAD)
|
||||
if b_commit=$(maybe_quiet --keep-stdout git rev-parse --verify HEAD)
|
||||
then
|
||||
head=$(git rev-list --oneline -n 1 HEAD --)
|
||||
elif test -n "$GIT_QUIET"
|
||||
then
|
||||
exit 1
|
||||
else
|
||||
die "$(gettext "You do not have the initial commit yet")"
|
||||
fi
|
||||
@@ -298,7 +340,7 @@ push_stash () {
|
||||
test -n "$untracked" || git ls-files --error-unmatch -- "$@" >/dev/null || exit 1
|
||||
|
||||
git update-index -q --refresh
|
||||
if no_changes "$@"
|
||||
if maybe_quiet no_changes "$@"
|
||||
then
|
||||
say "$(gettext "No local changes to save")"
|
||||
exit 0
|
||||
@@ -353,6 +395,9 @@ save_stash () {
|
||||
while test $# != 0
|
||||
do
|
||||
case "$1" in
|
||||
-q|--quiet)
|
||||
GIT_QUIET=t
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
@@ -101,6 +101,7 @@ $LONG_USAGE")"
|
||||
case "$1" in
|
||||
-h)
|
||||
echo "$LONG_USAGE"
|
||||
case "$0" in *git-legacy-stash) exit 129;; esac
|
||||
exit
|
||||
esac
|
||||
fi
|
||||
|
||||
6
git.c
6
git.c
@@ -554,6 +554,12 @@ 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 },
|
||||
|
||||
20
ident.c
20
ident.c
@@ -505,6 +505,26 @@ int git_ident_config(const char *var, const char *value, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_env_if(const char *key, const char *value, int *given, int bit)
|
||||
{
|
||||
if ((*given & bit) || getenv(key))
|
||||
return; /* nothing to do */
|
||||
setenv(key, value, 0);
|
||||
*given |= bit;
|
||||
}
|
||||
|
||||
void prepare_fallback_ident(const char *name, const char *email)
|
||||
{
|
||||
set_env_if("GIT_AUTHOR_NAME", name,
|
||||
&author_ident_explicitly_given, IDENT_NAME_GIVEN);
|
||||
set_env_if("GIT_AUTHOR_EMAIL", email,
|
||||
&author_ident_explicitly_given, IDENT_MAIL_GIVEN);
|
||||
set_env_if("GIT_COMMITTER_NAME", name,
|
||||
&committer_ident_explicitly_given, IDENT_NAME_GIVEN);
|
||||
set_env_if("GIT_COMMITTER_EMAIL", email,
|
||||
&committer_ident_explicitly_given, IDENT_MAIL_GIVEN);
|
||||
}
|
||||
|
||||
static int buf_cmp(const char *a_begin, const char *a_end,
|
||||
const char *b_begin, const char *b_end)
|
||||
{
|
||||
|
||||
19
sha1-name.c
19
sha1-name.c
@@ -1542,6 +1542,25 @@ 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
|
||||
|
||||
51
strbuf.c
51
strbuf.c
@@ -249,6 +249,42 @@ void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
|
||||
strbuf_splice(sb, pos, 0, data, len);
|
||||
}
|
||||
|
||||
void strbuf_vinsertf(struct strbuf *sb, size_t pos, const char *fmt, va_list ap)
|
||||
{
|
||||
int len, len2;
|
||||
char save;
|
||||
va_list cp;
|
||||
|
||||
if (pos > sb->len)
|
||||
die("`pos' is too far after the end of the buffer");
|
||||
va_copy(cp, ap);
|
||||
len = vsnprintf(sb->buf + sb->len, 0, fmt, cp);
|
||||
va_end(cp);
|
||||
if (len < 0)
|
||||
BUG("your vsnprintf is broken (returned %d)", len);
|
||||
if (!len)
|
||||
return; /* nothing to do */
|
||||
if (unsigned_add_overflows(sb->len, len))
|
||||
die("you want to use way too much memory");
|
||||
strbuf_grow(sb, len);
|
||||
memmove(sb->buf + pos + len, sb->buf + pos, sb->len - pos);
|
||||
/* vsnprintf() will append a NUL, overwriting one of our characters */
|
||||
save = sb->buf[pos + len];
|
||||
len2 = vsnprintf(sb->buf + pos, len + 1, fmt, ap);
|
||||
sb->buf[pos + len] = save;
|
||||
if (len2 != len)
|
||||
BUG("your vsnprintf is broken (returns inconsistent lengths)");
|
||||
strbuf_setlen(sb, sb->len + len);
|
||||
}
|
||||
|
||||
void strbuf_insertf(struct strbuf *sb, size_t pos, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
strbuf_vinsertf(sb, pos, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
|
||||
{
|
||||
strbuf_splice(sb, pos, len, "", 0);
|
||||
@@ -268,6 +304,21 @@ void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2)
|
||||
strbuf_setlen(sb, sb->len + sb2->len);
|
||||
}
|
||||
|
||||
const char *strbuf_join_argv(struct strbuf *buf,
|
||||
int argc, const char **argv, char delim)
|
||||
{
|
||||
if (!argc)
|
||||
return buf->buf;
|
||||
|
||||
strbuf_addstr(buf, *argv);
|
||||
while (--argc) {
|
||||
strbuf_addch(buf, delim);
|
||||
strbuf_addstr(buf, *(++argv));
|
||||
}
|
||||
|
||||
return buf->buf;
|
||||
}
|
||||
|
||||
void strbuf_addchars(struct strbuf *sb, int c, size_t n)
|
||||
{
|
||||
strbuf_grow(sb, n);
|
||||
|
||||
16
strbuf.h
16
strbuf.h
@@ -244,6 +244,15 @@ void strbuf_addchars(struct strbuf *sb, int c, size_t n);
|
||||
*/
|
||||
void strbuf_insert(struct strbuf *sb, size_t pos, const void *, size_t);
|
||||
|
||||
/**
|
||||
* Insert data to the given position of the buffer giving a printf format
|
||||
* string. The contents will be shifted, not overwritten.
|
||||
*/
|
||||
void strbuf_vinsertf(struct strbuf *sb, size_t pos, const char *fmt,
|
||||
va_list ap);
|
||||
|
||||
void strbuf_insertf(struct strbuf *sb, size_t pos, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Remove given amount of data from a given position of the buffer.
|
||||
*/
|
||||
@@ -288,6 +297,13 @@ static inline void strbuf_addstr(struct strbuf *sb, const char *s)
|
||||
*/
|
||||
void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2);
|
||||
|
||||
/**
|
||||
* Join the arguments into a buffer. `delim` is put between every
|
||||
* two arguments.
|
||||
*/
|
||||
const char *strbuf_join_argv(struct strbuf *buf, int argc,
|
||||
const char **argv, char delim);
|
||||
|
||||
/**
|
||||
* This function can be used to expand a format string containing
|
||||
* placeholders. To that end, it parses the string and calls the specified
|
||||
|
||||
4
t/README
4
t/README
@@ -349,6 +349,10 @@ GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the
|
||||
builtin version of git-rebase. See 'rebase.useBuiltin' in
|
||||
git-config(1).
|
||||
|
||||
GIT_TEST_STASH_USE_BUILTIN=<boolean>, when false, disables the
|
||||
built-in version of git-stash. See 'stash.useBuiltin' in
|
||||
git-config(1).
|
||||
|
||||
GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading
|
||||
of the index for the whole test suite by bypassing the default number of
|
||||
cache entries and thread minimums. Setting this to 1 will make the
|
||||
|
||||
200
t/t3903-stash.sh
200
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 << EOF
|
||||
cat >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 expect output
|
||||
'
|
||||
|
||||
@@ -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 > stashlist1 &&
|
||||
echo 7 > file &&
|
||||
git stash list >expected &&
|
||||
echo 7 >file &&
|
||||
git stash &&
|
||||
git stash drop &&
|
||||
git stash list > stashlist2 &&
|
||||
test_cmp stashlist1 stashlist2 &&
|
||||
git stash list >actual &&
|
||||
test_cmp expected actual &&
|
||||
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 << EOF
|
||||
cat >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 << EOF
|
||||
cat >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 << EOF
|
||||
cat >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 expect output &&
|
||||
git diff > output &&
|
||||
git diff >output &&
|
||||
test_cmp expect1 output &&
|
||||
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 &&
|
||||
@@ -287,6 +287,14 @@ test_expect_success 'stash an added file' '
|
||||
test new = "$(cat file3)"
|
||||
'
|
||||
|
||||
test_expect_success 'stash --intent-to-add file' '
|
||||
git reset --hard &&
|
||||
echo new >file4 &&
|
||||
git add --intent-to-add file4 &&
|
||||
test_when_finished "git rm -f file4" &&
|
||||
test_must_fail git stash
|
||||
'
|
||||
|
||||
test_expect_success 'stash rm then recreate' '
|
||||
git reset --hard &&
|
||||
git rm file &&
|
||||
@@ -444,6 +452,36 @@ 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" &&
|
||||
@@ -456,11 +494,12 @@ 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
|
||||
'
|
||||
|
||||
@@ -468,25 +507,31 @@ 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 &&
|
||||
@@ -501,10 +546,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 &&
|
||||
@@ -516,10 +561,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 &&
|
||||
@@ -539,7 +584,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 &&
|
||||
@@ -551,7 +596,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 &&
|
||||
@@ -567,13 +612,13 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' '
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'stash drop - fail early if specified stash is not a stash reference' '
|
||||
test_expect_success 'drop: fail early if specified stash is not a stash ref' '
|
||||
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 &&
|
||||
@@ -581,13 +626,13 @@ test_expect_success 'stash drop - fail early if specified stash is not a stash r
|
||||
git reset --hard HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'stash pop - fail early if specified stash is not a stash reference' '
|
||||
test_expect_success 'pop: fail early if specified stash is not a stash ref' '
|
||||
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 &&
|
||||
@@ -597,8 +642,8 @@ test_expect_success 'stash pop - fail early if specified stash is not a stash re
|
||||
|
||||
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 &&
|
||||
@@ -618,8 +663,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} &&
|
||||
@@ -645,7 +690,7 @@ test_expect_success 'invalid ref of the form "n", n >= N' '
|
||||
git stash drop
|
||||
'
|
||||
|
||||
test_expect_success 'stash branch should not drop the stash if the branch exists' '
|
||||
test_expect_success 'branch: do not drop the stash if the branch exists' '
|
||||
git stash clear &&
|
||||
echo foo >file &&
|
||||
git add file &&
|
||||
@@ -656,7 +701,7 @@ test_expect_success 'stash branch should not drop the stash if the branch exists
|
||||
git rev-parse stash@{0} --
|
||||
'
|
||||
|
||||
test_expect_success 'stash branch should not drop the stash if the apply fails' '
|
||||
test_expect_success 'branch: should not drop the stash if the apply fails' '
|
||||
git stash clear &&
|
||||
git reset HEAD~1 --hard &&
|
||||
echo foo >file &&
|
||||
@@ -670,7 +715,7 @@ test_expect_success 'stash branch should not drop the stash if the apply fails'
|
||||
git rev-parse stash@{0} --
|
||||
'
|
||||
|
||||
test_expect_success 'stash apply shows status same as git status (relative to current directory)' '
|
||||
test_expect_success 'apply: show same status as git status (relative to ./)' '
|
||||
git stash clear &&
|
||||
echo 1 >subdir/subfile1 &&
|
||||
echo 2 >subdir/subfile2 &&
|
||||
@@ -689,7 +734,7 @@ test_expect_success 'stash apply shows status same as git status (relative to cu
|
||||
test_i18ncmp expect actual
|
||||
'
|
||||
|
||||
cat > expect << EOF
|
||||
cat >expect <<EOF
|
||||
diff --git a/HEAD b/HEAD
|
||||
new file mode 100644
|
||||
index 0000000..fe0cbee
|
||||
@@ -702,14 +747,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 expect output
|
||||
'
|
||||
|
||||
@@ -1011,7 +1056,7 @@ test_expect_success 'stash push -p with pathspec shows no changes only once' '
|
||||
test_i18ncmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'stash push with pathspec shows no changes when there are none' '
|
||||
test_expect_success 'push <pathspec>: show no changes when there are none' '
|
||||
>foo &&
|
||||
git add foo &&
|
||||
git commit -m "tmp" &&
|
||||
@@ -1021,12 +1066,35 @@ test_expect_success 'stash push with pathspec shows no changes when there are no
|
||||
test_i18ncmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'stash push with pathspec not in the repository errors out' '
|
||||
test_expect_success 'push: <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 &&
|
||||
|
||||
83
t/t3907-stash-show-config.sh
Executable file
83
t/t3907-stash-show-config.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/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 "<unset>")
|
||||
# 2. the stash.showPatch value (or "<unset>")
|
||||
# 3. the diff options of the expected output (or nothing for no output)
|
||||
test_stat_and_patch () {
|
||||
if test "<unset>" = "$1"
|
||||
then
|
||||
test_unconfig stash.showStat
|
||||
else
|
||||
test_config stash.showStat "$1"
|
||||
fi &&
|
||||
|
||||
if test "<unset>" = "$2"
|
||||
then
|
||||
test_unconfig stash.showPatch
|
||||
else
|
||||
test_config stash.showPatch "$2"
|
||||
fi &&
|
||||
|
||||
shift 2 &&
|
||||
echo 2 >file.t &&
|
||||
if test $# != 0
|
||||
then
|
||||
git diff "$@" >expect
|
||||
fi &&
|
||||
git stash &&
|
||||
git stash show >actual &&
|
||||
|
||||
if test $# = 0
|
||||
then
|
||||
test_must_be_empty actual
|
||||
else
|
||||
test_cmp expect actual
|
||||
fi
|
||||
}
|
||||
|
||||
test_expect_success 'showStat unset showPatch unset' '
|
||||
test_stat_and_patch "<unset>" "<unset>" --stat
|
||||
'
|
||||
|
||||
test_expect_success 'showStat unset showPatch false' '
|
||||
test_stat_and_patch "<unset>" false --stat
|
||||
'
|
||||
|
||||
test_expect_success 'showStat unset showPatch true' '
|
||||
test_stat_and_patch "<unset>" true --stat -p
|
||||
'
|
||||
|
||||
test_expect_success 'showStat false showPatch unset' '
|
||||
test_stat_and_patch false "<unset>"
|
||||
'
|
||||
|
||||
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 "<unset>" --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
|
||||
Reference in New Issue
Block a user