stash: convert save to builtin
Add stash save to the helper and delete functions which are no longer needed (`show_help()`, `save_stash()`, `push_stash()`, `create_stash()`, `clear_stash()`, `untracked_files()` and `no_changes()`). Signed-off-by: Paul-Sebastian Ungureanu <ungureanupaulsebastian@gmail.com> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
1ac528c0b0
commit
64fe9c26a4
@ -26,6 +26,8 @@ static const char * const git_stash_helper_usage[] = {
|
|||||||
N_("git stash--helper [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
N_("git stash--helper [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>...]]"),
|
" [--] [<pathspec>...]]"),
|
||||||
|
N_("git stash--helper save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
||||||
|
" [-u|--include-untracked] [-a|--all] [<message>]"),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,6 +83,12 @@ static const char * const git_stash_helper_push_usage[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * const git_stash_helper_save_usage[] = {
|
||||||
|
N_("git stash--helper save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
||||||
|
" [-u|--include-untracked] [-a|--all] [<message>]"),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static const char *ref_stash = "refs/stash";
|
static const char *ref_stash = "refs/stash";
|
||||||
static struct strbuf stash_index_path = STRBUF_INIT;
|
static struct strbuf stash_index_path = STRBUF_INIT;
|
||||||
|
|
||||||
@ -1486,6 +1494,46 @@ static int push_stash(int argc, const char **argv, const char *prefix)
|
|||||||
include_untracked);
|
include_untracked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int save_stash(int argc, const char **argv, const char *prefix)
|
||||||
|
{
|
||||||
|
int keep_index = -1;
|
||||||
|
int patch_mode = 0;
|
||||||
|
int include_untracked = 0;
|
||||||
|
int quiet = 0;
|
||||||
|
int ret = 0;
|
||||||
|
const char *stash_msg = NULL;
|
||||||
|
struct pathspec ps;
|
||||||
|
struct strbuf stash_msg_buf = STRBUF_INIT;
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_BOOL('k', "keep-index", &keep_index,
|
||||||
|
N_("keep index")),
|
||||||
|
OPT_BOOL('p', "patch", &patch_mode,
|
||||||
|
N_("stash in patch mode")),
|
||||||
|
OPT__QUIET(&quiet, N_("quiet mode")),
|
||||||
|
OPT_BOOL('u', "include-untracked", &include_untracked,
|
||||||
|
N_("include untracked files in stash")),
|
||||||
|
OPT_SET_INT('a', "all", &include_untracked,
|
||||||
|
N_("include ignore files"), 2),
|
||||||
|
OPT_STRING('m', "message", &stash_msg, "message",
|
||||||
|
N_("stash message")),
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
argc = parse_options(argc, argv, prefix, options,
|
||||||
|
git_stash_helper_save_usage,
|
||||||
|
PARSE_OPT_KEEP_DASHDASH);
|
||||||
|
|
||||||
|
if (argc)
|
||||||
|
stash_msg = strbuf_join_argv(&stash_msg_buf, argc, argv, ' ');
|
||||||
|
|
||||||
|
memset(&ps, 0, sizeof(ps));
|
||||||
|
ret = do_push_stash(ps, stash_msg, quiet, keep_index,
|
||||||
|
patch_mode, include_untracked);
|
||||||
|
|
||||||
|
strbuf_release(&stash_msg_buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_stash__helper(int argc, const char **argv, const char *prefix)
|
int cmd_stash__helper(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
pid_t pid = getpid();
|
pid_t pid = getpid();
|
||||||
@ -1526,6 +1574,8 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix)
|
|||||||
return !!create_stash(argc, argv, prefix);
|
return !!create_stash(argc, argv, prefix);
|
||||||
else if (!strcmp(argv[0], "push"))
|
else if (!strcmp(argv[0], "push"))
|
||||||
return !!push_stash(argc, argv, prefix);
|
return !!push_stash(argc, argv, prefix);
|
||||||
|
else if (!strcmp(argv[0], "save"))
|
||||||
|
return !!save_stash(argc, argv, prefix);
|
||||||
|
|
||||||
usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
|
usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
|
||||||
git_stash_helper_usage, options);
|
git_stash_helper_usage, options);
|
||||||
|
328
git-stash.sh
328
git-stash.sh
@ -36,331 +36,6 @@ else
|
|||||||
reset_color=
|
reset_color=
|
||||||
fi
|
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 -- "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
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 () {
|
|
||||||
|
|
||||||
prepare_fallback_ident
|
|
||||||
|
|
||||||
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")"
|
|
||||||
}
|
|
||||||
|
|
||||||
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" -- "$@"
|
|
||||||
git stash--helper store -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
|
|
||||||
}
|
|
||||||
|
|
||||||
show_help () {
|
|
||||||
exec git help stash
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Parses the remaining options looking for flags and
|
# Parses the remaining options looking for flags and
|
||||||
# at most one revision defaulting to ${ref_stash}@{0}
|
# at most one revision defaulting to ${ref_stash}@{0}
|
||||||
@ -425,7 +100,8 @@ show)
|
|||||||
;;
|
;;
|
||||||
save)
|
save)
|
||||||
shift
|
shift
|
||||||
save_stash "$@"
|
cd "$START_DIR"
|
||||||
|
git stash--helper save "$@"
|
||||||
;;
|
;;
|
||||||
push)
|
push)
|
||||||
shift
|
shift
|
||||||
|
Loading…
Reference in New Issue
Block a user