Skip to content

Commit

Permalink
stash: optionally use the scripted version again
Browse files Browse the repository at this point in the history
We recently converted the `git stash` command from Unix shell scripts
to builtins.

Just like we have `rebase.useBuiltin` to fall back to the scripted
rebase, to give end users a way out when they discover a bug in the
builtin command, this commit adds support for `stash.useBuiltin`.

This is necessary because Git for Windows wants to ship the builtin
stash earlier than core Git: Git for Windows v2.19.0 will come with
the option of a drastically faster (if a lot less battle-tested)
`git stash`.

As the file name `git-stash` is already in use, let's rename the
scripted backend to `git-legacy-stash`.

To make the test suite pass with `stash.useBuiltin=false`, this commit
also backports rudimentary support for `-q` (but only *just* enough
to appease the test suite), and adds a super-ugly hack to force exit
code 129 for `git stash -h`.

Signed-off-by: Johannes Schindelin <[email protected]>
  • Loading branch information
dscho committed Nov 15, 2018
1 parent 94e9043 commit b1a3aaf
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
/git-init-db
/git-interpret-trailers
/git-instaweb
/git-legacy-stash
/git-log
/git-ls-files
/git-ls-remote
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ SCRIPT_SH += git-merge-resolve.sh
SCRIPT_SH += git-mergetool.sh
SCRIPT_SH += git-quiltimport.sh
SCRIPT_SH += git-rebase.sh
SCRIPT_SH += git-legacy-stash.sh
SCRIPT_SH += git-remote-testgit.sh
SCRIPT_SH += git-request-pull.sh
SCRIPT_SH += git-submodule.sh
Expand Down
35 changes: 35 additions & 0 deletions builtin/stash.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "revision.h"
#include "log-tree.h"
#include "diffcore.h"
#include "exec-cmd.h"

#define INCLUDE_ALL_FILES 2

Expand Down Expand Up @@ -1517,6 +1518,26 @@ static int save_stash(int argc, const char **argv, const char *prefix)
return ret;
}

static int use_builtin_stash(void)
{
struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf out = STRBUF_INIT;
int ret;

argv_array_pushl(&cp.args,
"config", "--bool", "stash.usebuiltin", NULL);
cp.git_cmd = 1;
if (capture_command(&cp, &out, 6)) {
strbuf_release(&out);
return 1;
}

strbuf_trim(&out);
ret = !strcmp("true", out.buf);
strbuf_release(&out);
return ret;
}

int cmd_stash(int argc, const char **argv, const char *prefix)
{
int i = -1;
Expand All @@ -1528,6 +1549,20 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
OPT_END()
};

if (!use_builtin_stash()) {
const char *path = mkpath("%s/git-legacy-stash",
git_exec_path());

if (sane_execvp(path, (char **)argv) < 0)
die_errno(_("could not exec %s"), path);
else
BUG("sane_execvp() returned???");
}

prefix = setup_git_directory();
trace_repo_setup(prefix);
setup_work_tree();

git_config(git_diff_basic_config, NULL);

argc = parse_options(argc, argv, prefix, options, git_stash_usage,
Expand Down
34 changes: 31 additions & 3 deletions git-stash.sh → git-legacy-stash.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,28 @@ 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 () {
stash_msg=
untracked=
Expand Down Expand Up @@ -95,15 +117,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
Expand Down Expand Up @@ -298,7 +323,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
Expand Down Expand Up @@ -353,6 +378,9 @@ save_stash () {
while test $# != 0
do
case "$1" in
-q|--quiet)
GIT_QUIET=t
;;
--)
shift
break
Expand Down
1 change: 1 addition & 0 deletions git-sh-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion git.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,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 },
{ "stash", cmd_stash, 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 },
Expand Down

0 comments on commit b1a3aaf

Please sign in to comment.