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>
Paul-Sebastian Ungureanu committed
Feb 25, 2019 at 23:16 UTC
64fe9c26a479082eb80a9d68e8b3b7686e8c2b26
2 files changed
+52
-326
builtin/stash--helper.c
+50
@@ -26,6 +26,8 @@ static const char * const git_stash_helper_usage[] = {
26
N_("git stash--helper [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
27
" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
28
" [--] [<pathspec>...]]"),
29
+ N_("git stash--helper save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
30
+ " [-u|--include-untracked] [-a|--all] [<message>]"),
31
NULL
32
};
33
@@ -81,6 +83,12 @@ static const char * const git_stash_helper_push_usage[] = {
83
NULL
84
};
85
86
+static const char * const git_stash_helper_save_usage[] = {
87
+ N_("git stash--helper save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
88
+ " [-u|--include-untracked] [-a|--all] [<message>]"),
89
+ NULL
90
+};
91
+
92
static const char *ref_stash = "refs/stash";
93
static struct strbuf stash_index_path = STRBUF_INIT;
94
@@ -1486,6 +1494,46 @@ static int push_stash(int argc, const char **argv, const char *prefix)
1494
include_untracked);
1495
}
1496
1497
+static int save_stash(int argc, const char **argv, const char *prefix)
1498
+{
1499
+ int keep_index = -1;
1500
+ int patch_mode = 0;
1501
+ int include_untracked = 0;
1502
+ int quiet = 0;
1503
+ int ret = 0;
1504
+ const char *stash_msg = NULL;
1505
+ struct pathspec ps;
1506
+ struct strbuf stash_msg_buf = STRBUF_INIT;
1507
+ struct option options[] = {
1508
+ OPT_BOOL('k', "keep-index", &keep_index,
1509
+ N_("keep index")),
1510
+ OPT_BOOL('p', "patch", &patch_mode,
1511
+ N_("stash in patch mode")),
1512
+ OPT__QUIET(&quiet, N_("quiet mode")),
1513
+ OPT_BOOL('u', "include-untracked", &include_untracked,
1514
+ N_("include untracked files in stash")),
1515
+ OPT_SET_INT('a', "all", &include_untracked,
1516
+ N_("include ignore files"), 2),
1517
+ OPT_STRING('m', "message", &stash_msg, "message",
1518
+ N_("stash message")),
1519
+ OPT_END()
1520
+ };
1521
+
1522
+ argc = parse_options(argc, argv, prefix, options,
1523
+ git_stash_helper_save_usage,
1524
+ PARSE_OPT_KEEP_DASHDASH);
1525
+
1526
+ if (argc)
1527
+ stash_msg = strbuf_join_argv(&stash_msg_buf, argc, argv, ' ');
1528
+
1529
+ memset(&ps, 0, sizeof(ps));
1530
+ ret = do_push_stash(ps, stash_msg, quiet, keep_index,
1531
+ patch_mode, include_untracked);
1532
+
1533
+ strbuf_release(&stash_msg_buf);
1534
+ return ret;
1535
+}
1536
+
1537
int cmd_stash__helper(int argc, const char **argv, const char *prefix)
1538
{
1539
pid_t pid = getpid();
@@ -1526,6 +1574,8 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix)
1574
return !!create_stash(argc, argv, prefix);
1575
else if (!strcmp(argv[0], "push"))
1576
return !!push_stash(argc, argv, prefix);
1577
+ else if (!strcmp(argv[0], "save"))
1578
+ return !!save_stash(argc, argv, prefix);
1579
1580
usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
1581
git_stash_helper_usage, options);
git-stash.sh
+2
-326
@@ -36,331 +36,6 @@ else
36
reset_color=
37
fi
38
39
-no_changes () {
40
- git diff-index --quiet --cached HEAD --ignore-submodules -- "$@" &&
41
- git diff-files --quiet --ignore-submodules -- "$@" &&
42
- (test -z "$untracked" || test -z "$(untracked_files "$@")")
43
-}
44
-
45
-untracked_files () {
46
- if test "$1" = "-z"
47
- then
48
- shift
49
- z=-z
50
- else
51
- z=
52
- fi
53
- excl_opt=--exclude-standard
54
- test "$untracked" = "all" && excl_opt=
55
- git ls-files -o $z $excl_opt -- "$@"
56
-}
57
-
58
-prepare_fallback_ident () {
59
- if ! git -c user.useconfigonly=yes var GIT_COMMITTER_IDENT >/dev/null 2>&1
60
- then
61
- GIT_AUTHOR_NAME="git stash"
62
- GIT_AUTHOR_EMAIL=git@stash
63
- GIT_COMMITTER_NAME="git stash"
64
- GIT_COMMITTER_EMAIL=git@stash
65
- export GIT_AUTHOR_NAME
66
- export GIT_AUTHOR_EMAIL
67
- export GIT_COMMITTER_NAME
68
- export GIT_COMMITTER_EMAIL
69
- fi
70
-}
71
-
72
-clear_stash () {
73
- if test $# != 0
74
- then
75
- die "$(gettext "git stash clear with parameters is unimplemented")"
76
- fi
77
- if current=$(git rev-parse --verify --quiet $ref_stash)
78
- then
79
- git update-ref -d $ref_stash $current
80
- fi
81
-}
82
-
83
-create_stash () {
84
-
85
- prepare_fallback_ident
86
-
87
- stash_msg=
88
- untracked=
89
- while test $# != 0
90
- do
91
- case "$1" in
92
- -m|--message)
93
- shift
94
- stash_msg=${1?"BUG: create_stash () -m requires an argument"}
95
- ;;
96
- -m*)
97
- stash_msg=${1#-m}
98
- ;;
99
- --message=*)
100
- stash_msg=${1#--message=}
101
- ;;
102
- -u|--include-untracked)
103
- shift
104
- untracked=${1?"BUG: create_stash () -u requires an argument"}
105
- ;;
106
- --)
107
- shift
108
- break
109
- ;;
110
- esac
111
- shift
112
- done
113
-
114
- git update-index -q --refresh
115
- if no_changes "$@"
116
- then
117
- exit 0
118
- fi
119
-
120
- # state of the base commit
121
- if b_commit=$(git rev-parse --verify HEAD)
122
- then
123
- head=$(git rev-list --oneline -n 1 HEAD --)
124
- else
125
- die "$(gettext "You do not have the initial commit yet")"
126
- fi
127
-
128
- if branch=$(git symbolic-ref -q HEAD)
129
- then
130
- branch=${branch#refs/heads/}
131
- else
132
- branch='(no branch)'
133
- fi
134
- msg=$(printf '%s: %s' "$branch" "$head")
135
-
136
- # state of the index
137
- i_tree=$(git write-tree) &&
138
- i_commit=$(printf 'index on %s\n' "$msg" |
139
- git commit-tree $i_tree -p $b_commit) ||
140
- die "$(gettext "Cannot save the current index state")"
141
-
142
- if test -n "$untracked"
143
- then
144
- # Untracked files are stored by themselves in a parentless commit, for
145
- # ease of unpacking later.
146
- u_commit=$(
147
- untracked_files -z "$@" | (
148
- GIT_INDEX_FILE="$TMPindex" &&
149
- export GIT_INDEX_FILE &&
150
- rm -f "$TMPindex" &&
151
- git update-index -z --add --remove --stdin &&
152
- u_tree=$(git write-tree) &&
153
- printf 'untracked files on %s\n' "$msg" | git commit-tree $u_tree &&
154
- rm -f "$TMPindex"
155
- ) ) || die "$(gettext "Cannot save the untracked files")"
156
-
157
- untracked_commit_option="-p $u_commit";
158
- else
159
- untracked_commit_option=
160
- fi
161
-
162
- if test -z "$patch_mode"
163
- then
164
-
165
- # state of the working tree
166
- w_tree=$( (
167
- git read-tree --index-output="$TMPindex" -m $i_tree &&
168
- GIT_INDEX_FILE="$TMPindex" &&
169
- export GIT_INDEX_FILE &&
170
- git diff-index --name-only -z HEAD -- "$@" >"$TMP-stagenames" &&
171
- git update-index -z --add --remove --stdin <"$TMP-stagenames" &&
172
- git write-tree &&
173
- rm -f "$TMPindex"
174
- ) ) ||
175
- die "$(gettext "Cannot save the current worktree state")"
176
-
177
- else
178
-
179
- rm -f "$TMP-index" &&
180
- GIT_INDEX_FILE="$TMP-index" git read-tree HEAD &&
181
-
182
- # find out what the user wants
183
- GIT_INDEX_FILE="$TMP-index" \
184
- git add--interactive --patch=stash -- "$@" &&
185
-
186
- # state of the working tree
187
- w_tree=$(GIT_INDEX_FILE="$TMP-index" git write-tree) ||
188
- die "$(gettext "Cannot save the current worktree state")"
189
-
190
- git diff-tree -p HEAD $w_tree -- >"$TMP-patch" &&
191
- test -s "$TMP-patch" ||
192
- die "$(gettext "No changes selected")"
193
-
194
- rm -f "$TMP-index" ||
195
- die "$(gettext "Cannot remove temporary index (can't happen)")"
196
-
197
- fi
198
-
199
- # create the stash
200
- if test -z "$stash_msg"
201
- then
202
- stash_msg=$(printf 'WIP on %s' "$msg")
203
- else
204
- stash_msg=$(printf 'On %s: %s' "$branch" "$stash_msg")
205
- fi
206
- w_commit=$(printf '%s\n' "$stash_msg" |
207
- git commit-tree $w_tree -p $b_commit -p $i_commit $untracked_commit_option) ||
208
- die "$(gettext "Cannot record working tree state")"
209
-}
210
-
211
-push_stash () {
212
- keep_index=
213
- patch_mode=
214
- untracked=
215
- stash_msg=
216
- while test $# != 0
217
- do
218
- case "$1" in
219
- -k|--keep-index)
220
- keep_index=t
221
- ;;
222
- --no-keep-index)
223
- keep_index=n
224
- ;;
225
- -p|--patch)
226
- patch_mode=t
227
- # only default to keep if we don't already have an override
228
- test -z "$keep_index" && keep_index=t
229
- ;;
230
- -q|--quiet)
231
- GIT_QUIET=t
232
- ;;
233
- -u|--include-untracked)
234
- untracked=untracked
235
- ;;
236
- -a|--all)
237
- untracked=all
238
- ;;
239
- -m|--message)
240
- shift
241
- test -z ${1+x} && usage
242
- stash_msg=$1
243
- ;;
244
- -m*)
245
- stash_msg=${1#-m}
246
- ;;
247
- --message=*)
248
- stash_msg=${1#--message=}
249
- ;;
250
- --help)
251
- show_help
252
- ;;
253
- --)
254
- shift
255
- break
256
- ;;
257
- -*)
258
- option="$1"
259
- eval_gettextln "error: unknown option for 'stash push': \$option"
260
- usage
261
- ;;
262
- *)
263
- break
264
- ;;
265
- esac
266
- shift
267
- done
268
-
269
- eval "set $(git rev-parse --sq --prefix "$prefix" -- "$@")"
270
-
271
- if test -n "$patch_mode" && test -n "$untracked"
272
- then
273
- die "$(gettext "Can't use --patch and --include-untracked or --all at the same time")"
274
- fi
275
-
276
- test -n "$untracked" || git ls-files --error-unmatch -- "$@" >/dev/null || exit 1
277
-
278
- git update-index -q --refresh
279
- if no_changes "$@"
280
- then
281
- say "$(gettext "No local changes to save")"
282
- exit 0
283
- fi
284
-
285
- git reflog exists $ref_stash ||
286
- clear_stash || die "$(gettext "Cannot initialize stash")"
287
-
288
- create_stash -m "$stash_msg" -u "$untracked" -- "$@"
289
- git stash--helper store -m "$stash_msg" -q $w_commit ||
290
- die "$(gettext "Cannot save the current status")"
291
- say "$(eval_gettext "Saved working directory and index state \$stash_msg")"
292
-
293
- if test -z "$patch_mode"
294
- then
295
- test "$untracked" = "all" && CLEAN_X_OPTION=-x || CLEAN_X_OPTION=
296
- if test -n "$untracked" && test $# = 0
297
- then
298
- git clean --force --quiet -d $CLEAN_X_OPTION
299
- fi
300
-
301
- if test $# != 0
302
- then
303
- test -z "$untracked" && UPDATE_OPTION="-u" || UPDATE_OPTION=
304
- test "$untracked" = "all" && FORCE_OPTION="--force" || FORCE_OPTION=
305
- git add $UPDATE_OPTION $FORCE_OPTION -- "$@"
306
- git diff-index -p --cached --binary HEAD -- "$@" |
307
- git apply --index -R
308
- else
309
- git reset --hard -q
310
- fi
311
-
312
- if test "$keep_index" = "t" && test -n "$i_tree"
313
- then
314
- git read-tree --reset $i_tree
315
- git ls-files -z --modified -- "$@" |
316
- git checkout-index -z --force --stdin
317
- fi
318
- else
319
- git apply -R < "$TMP-patch" ||
320
- die "$(gettext "Cannot remove worktree changes")"
321
-
322
- if test "$keep_index" != "t"
323
- then
324
- git reset -q -- "$@"
325
- fi
326
- fi
327
-}
328
-
329
-save_stash () {
330
- push_options=
331
- while test $# != 0
332
- do
333
- case "$1" in
334
- --)
335
- shift
336
- break
337
- ;;
338
- -*)
339
- # pass all options through to push_stash
340
- push_options="$push_options $1"
341
- ;;
342
- *)
343
- break
344
- ;;
345
- esac
346
- shift
347
- done
348
-
349
- stash_msg="$*"
350
-
351
- if test -z "$stash_msg"
352
- then
353
- push_stash $push_options
354
- else
355
- push_stash $push_options -m "$stash_msg"
356
- fi
357
-}
358
-
359
-show_help () {
360
- exec git help stash
361
- exit 1
362
-}
363
-
39
#
40
# Parses the remaining options looking for flags and
41
# at most one revision defaulting to ${ref_stash}@{0}
@@ -425,7 +100,8 @@ show)
100
;;
101
save)
102
shift
428
- save_stash "$@"
103
+ cd "$START_DIR"
104
+ git stash--helper save "$@"
105
;;
106
push)
107
shift