Skip to content

Commit 22bf580

Browse files
committed
Merge branch 'pw/stash-change-check-only-once' into jch
"git stash create/push" checked if there are checks that need to be saved twice, which has been reduced to just once. * pw/stash-change-check-only-once: stash: simplify reset_tree() function signature stash create: remove unnecessary index load and refresh stash create: rework temporary index creation stash push: avoid duplicate calls to preload_index() stash push: remove duplicate changes detection stash create: remove duplicate changes detection stash: use an enum for create status
2 parents 35266d0 + f3fd245 commit 22bf580

1 file changed

Lines changed: 62 additions & 75 deletions

File tree

‎builtin/stash.c‎

Lines changed: 62 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ static int clear_stash(int argc, const char **argv, const char *prefix,
331331
return do_clear_stash();
332332
}
333333

334-
static int reset_tree(struct object_id *i_tree, int update, int reset)
334+
static int reset_tree(struct object_id *i_tree)
335335
{
336336
int nr_trees = 1;
337337
struct unpack_trees_options opts;
@@ -357,10 +357,6 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
357357
opts.src_index = the_repository->index;
358358
opts.dst_index = the_repository->index;
359359
opts.merge = 1;
360-
opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0;
361-
opts.update = update;
362-
if (update)
363-
opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */
364360
opts.fn = oneway_merge;
365361

366362
if (unpack_trees(nr_trees, t, &opts))
@@ -373,7 +369,7 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
373369
}
374370

375371
static int create_index_from_tree(const struct object_id *tree_id,
376-
const char *index_path)
372+
const char *index_path, bool reset)
377373
{
378374
int nr_trees = 1;
379375
int ret = 0;
@@ -383,9 +379,6 @@ static int create_index_from_tree(const struct object_id *tree_id,
383379
struct index_state dst_istate = INDEX_STATE_INIT(the_repository);
384380
struct lock_file lock_file = LOCK_INIT;
385381

386-
repo_read_index_preload(the_repository, NULL, 0);
387-
refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL);
388-
389382
hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);
390383

391384
memset(&opts, 0, sizeof(opts));
@@ -402,7 +395,7 @@ static int create_index_from_tree(const struct object_id *tree_id,
402395
opts.src_index = the_repository->index;
403396
opts.dst_index = &dst_istate;
404397
opts.merge = 1;
405-
opts.reset = UNPACK_RESET_PROTECT_UNTRACKED;
398+
opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0;
406399
opts.fn = oneway_merge;
407400

408401
if (unpack_trees(nr_trees, t, &opts)) {
@@ -697,7 +690,7 @@ static enum stash_apply_result do_apply_stash(const char *prefix,
697690
}
698691

699692
if (has_index) {
700-
if (reset_tree(&index_tree, 0, 0))
693+
if (reset_tree(&index_tree))
701694
ret = -1;
702695
} else {
703696
unstage_changes_unless_new(&c_tree);
@@ -1204,9 +1197,6 @@ static int check_changes_tracked_files(const struct pathspec *ps)
12041197
if (repo_get_oid(the_repository, "HEAD", &dummy))
12051198
return -1;
12061199

1207-
if (repo_read_index(the_repository) < 0)
1208-
return -1;
1209-
12101200
repo_init_revisions(the_repository, &rev, NULL);
12111201
copy_pathspec(&rev.prune_data, ps);
12121202

@@ -1292,16 +1282,25 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
12921282
return ret;
12931283
}
12941284

1295-
static int stash_staged(struct stash_info *info, struct strbuf *out_patch,
1296-
int quiet)
1285+
enum create_result {
1286+
CREATE_ERROR = -1,
1287+
CREATE_SUCCESS,
1288+
/* No changes were stashed */
1289+
CREATE_EMPTY,
1290+
/* There were no changes to stash */
1291+
CREATE_NO_CHANGES,
1292+
};
1293+
1294+
static enum create_result stash_staged(struct stash_info *info,
1295+
struct strbuf *out_patch, int quiet)
12971296
{
1298-
int ret = 0;
1297+
enum create_result ret = 0;
12991298
struct child_process cp_diff_tree = CHILD_PROCESS_INIT;
13001299
struct index_state istate = INDEX_STATE_INIT(the_repository);
13011300

13021301
if (write_index_as_tree(&info->w_tree, &istate, the_repository->index_file,
13031302
0, NULL)) {
1304-
ret = -1;
1303+
ret = CREATE_ERROR;
13051304
goto done;
13061305
}
13071306

@@ -1310,26 +1309,26 @@ static int stash_staged(struct stash_info *info, struct strbuf *out_patch,
13101309
"--no-color",
13111310
"-U1", "HEAD", oid_to_hex(&info->w_tree), "--", NULL);
13121311
if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) {
1313-
ret = -1;
1312+
ret = CREATE_ERROR;
13141313
goto done;
13151314
}
13161315

13171316
if (!out_patch->len) {
13181317
if (!quiet)
13191318
fprintf_ln(stderr, _("No staged changes"));
1320-
ret = 1;
1319+
ret = CREATE_EMPTY;
13211320
}
13221321

13231322
done:
13241323
release_index(&istate);
13251324
return ret;
13261325
}
13271326

1328-
static int stash_patch(struct stash_info *info, const struct pathspec *ps,
1329-
struct strbuf *out_patch, int quiet,
1330-
struct interactive_options *interactive_opts)
1327+
static enum create_result stash_patch(struct stash_info *info,
1328+
const struct pathspec *ps, struct strbuf *out_patch, int quiet,
1329+
struct interactive_options *interactive_opts)
13311330
{
1332-
int ret = 0;
1331+
enum create_result ret = 0;
13331332
struct child_process cp_diff_tree = CHILD_PROCESS_INIT;
13341333
struct commit *head_commit;
13351334
const struct object_id *head_tree;
@@ -1340,17 +1339,17 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
13401339

13411340
head_commit = lookup_commit(the_repository, &info->b_commit);
13421341
if (!head_commit || repo_parse_commit(the_repository, head_commit)) {
1343-
ret = -1;
1342+
ret = CREATE_ERROR;
13441343
goto done;
13451344
}
13461345
head_tree = get_commit_tree_oid(head_commit);
13471346
if (!head_tree) {
1348-
ret = -1;
1347+
ret = CREATE_ERROR;
13491348
goto done;
13501349
}
13511350

1352-
if (create_index_from_tree(head_tree, stash_index_path.buf)) {
1353-
ret = -1;
1351+
if (create_index_from_tree(head_tree, stash_index_path.buf, true)) {
1352+
ret = CREATE_ERROR;
13541353
goto done;
13551354
}
13561355

@@ -1372,7 +1371,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
13721371
/* State of the working tree. */
13731372
if (write_index_as_tree(&info->w_tree, &istate, stash_index_path.buf, 0,
13741373
NULL)) {
1375-
ret = -1;
1374+
ret = CREATE_ERROR;
13761375
goto done;
13771376
}
13781377

@@ -1381,14 +1380,14 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
13811380
"--no-color",
13821381
oid_to_hex(&info->w_tree), "--", NULL);
13831382
if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) {
1384-
ret = -1;
1383+
ret = CREATE_ERROR;
13851384
goto done;
13861385
}
13871386

13881387
if (!out_patch->len) {
13891388
if (!quiet)
13901389
fprintf_ln(stderr, _("No changes selected"));
1391-
ret = 1;
1390+
ret = CREATE_EMPTY;
13921391
}
13931392

13941393
done:
@@ -1408,22 +1407,15 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
14081407
repo_init_revisions(the_repository, &rev, NULL);
14091408
copy_pathspec(&rev.prune_data, ps);
14101409

1411-
set_alternate_index_output(stash_index_path.buf);
1412-
if (reset_tree(&info->i_tree, 0, 0)) {
1410+
if (create_index_from_tree(&info->i_tree, stash_index_path.buf, false)) {
14131411
ret = -1;
14141412
goto done;
14151413
}
1416-
set_alternate_index_output(NULL);
14171414

14181415
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
14191416
rev.diffopt.format_callback = add_diff_to_buf;
14201417
rev.diffopt.format_callback_data = &diff_output;
14211418

1422-
if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) {
1423-
ret = -1;
1424-
goto done;
1425-
}
1426-
14271419
add_pending_object(&rev, parse_object(the_repository, &info->b_commit),
14281420
"");
14291421
run_diff_index(&rev, 0);
@@ -1455,13 +1447,13 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
14551447
return ret;
14561448
}
14571449

1458-
static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_buf,
1459-
int include_untracked, int patch_mode,
1460-
struct interactive_options *interactive_opts,
1461-
int only_staged, struct stash_info *info, struct strbuf *patch,
1462-
int quiet)
1450+
static enum create_result do_create_stash(const struct pathspec *ps,
1451+
struct strbuf *stash_msg_buf, int include_untracked,
1452+
int patch_mode, struct interactive_options *interactive_opts,
1453+
int only_staged, struct stash_info *info, struct strbuf *patch,
1454+
int quiet)
14631455
{
1464-
int ret = 0;
1456+
enum create_result ret = 0;
14651457
int flags = 0;
14661458
int untracked_commit_option = 0;
14671459
const char *head_short_sha1 = NULL;
@@ -1476,7 +1468,6 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
14761468

14771469
prepare_fallback_ident("git stash", "git@stash");
14781470

1479-
repo_read_index_preload(the_repository, NULL, 0);
14801471
if (repo_refresh_and_write_index(the_repository, REFRESH_QUIET, 0, 0,
14811472
NULL, NULL, NULL) < 0) {
14821473
ret = error(_("could not write index"));
@@ -1487,14 +1478,14 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
14871478
if (!quiet)
14881479
fprintf_ln(stderr, _("You do not have "
14891480
"the initial commit yet"));
1490-
ret = -1;
1481+
ret = CREATE_ERROR;
14911482
goto done;
14921483
} else {
14931484
head_commit = lookup_commit(the_repository, &info->b_commit);
14941485
}
14951486

14961487
if (!check_changes(ps, include_untracked, &untracked_files)) {
1497-
ret = 1;
1488+
ret = CREATE_NO_CHANGES;
14981489
goto done;
14991490
}
15001491

@@ -1521,7 +1512,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
15211512
if (!quiet)
15221513
fprintf_ln(stderr, _("Cannot save the current "
15231514
"index state"));
1524-
ret = -1;
1515+
ret = CREATE_ERROR;
15251516
goto done;
15261517
}
15271518

@@ -1533,37 +1524,37 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
15331524
if (!quiet)
15341525
fprintf_ln(stderr, _("Cannot save "
15351526
"the untracked files"));
1536-
ret = -1;
1527+
ret = CREATE_ERROR;
15371528
goto done;
15381529
}
15391530
untracked_commit_option = 1;
15401531
}
15411532
if (patch_mode) {
15421533
ret = stash_patch(info, ps, patch, quiet, interactive_opts);
1543-
if (ret < 0) {
1534+
if (ret == CREATE_ERROR) {
15441535
if (!quiet)
15451536
fprintf_ln(stderr, _("Cannot save the current "
15461537
"worktree state"));
15471538
goto done;
1548-
} else if (ret > 0) {
1539+
} else if (ret != CREATE_SUCCESS) {
15491540
goto done;
15501541
}
15511542
} else if (only_staged) {
15521543
ret = stash_staged(info, patch, quiet);
1553-
if (ret < 0) {
1544+
if (ret == CREATE_ERROR) {
15541545
if (!quiet)
15551546
fprintf_ln(stderr, _("Cannot save the current "
15561547
"staged state"));
15571548
goto done;
1558-
} else if (ret > 0) {
1549+
} else if (ret != CREATE_SUCCESS) {
15591550
goto done;
15601551
}
15611552
} else {
15621553
if (stash_working_tree(info, ps)) {
15631554
if (!quiet)
15641555
fprintf_ln(stderr, _("Cannot save the current "
15651556
"worktree state"));
1566-
ret = -1;
1557+
ret = CREATE_ERROR;
15671558
goto done;
15681559
}
15691560
}
@@ -1586,7 +1577,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
15861577
if (!quiet)
15871578
fprintf_ln(stderr, _("Cannot record "
15881579
"working tree state"));
1589-
ret = -1;
1580+
ret = CREATE_ERROR;
15901581
goto done;
15911582
}
15921583

@@ -1611,17 +1602,17 @@ static int create_stash(int argc, const char **argv, const char *prefix UNUSED,
16111602
strbuf_join_argv(&stash_msg_buf, argc - 1, ++argv, ' ');
16121603

16131604
memset(&ps, 0, sizeof(ps));
1614-
if (!check_changes_tracked_files(&ps))
1615-
return 0;
16161605

1606+
repo_read_index(the_repository);
16171607
ret = do_create_stash(&ps, &stash_msg_buf, 0, 0, NULL, 0, &info,
16181608
NULL, 0);
1619-
if (!ret)
1609+
if (ret == CREATE_SUCCESS)
16201610
printf_ln("%s", oid_to_hex(&info.w_commit));
16211611

16221612
free_stash_info(&info);
16231613
strbuf_release(&stash_msg_buf);
1624-
return ret;
1614+
/* Do not return an error if there are no changes */
1615+
return ret == CREATE_ERROR ? -1 : 0;
16251616
}
16261617

16271618
static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int quiet,
@@ -1630,6 +1621,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
16301621
int include_untracked, int only_staged)
16311622
{
16321623
int ret = 0;
1624+
enum create_result create_res;
16331625
struct stash_info info = STASH_INFO_INIT;
16341626
struct strbuf patch = STRBUF_INIT;
16351627
struct strbuf stash_msg_buf = STRBUF_INIT;
@@ -1657,7 +1649,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
16571649
goto done;
16581650
}
16591651

1660-
repo_read_index_preload(the_repository, NULL, 0);
1652+
repo_read_index(the_repository);
16611653
if (!include_untracked && ps->nr) {
16621654
char *ps_matched = xcalloc(ps->nr, 1);
16631655

@@ -1676,18 +1668,6 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
16761668
free(ps_matched);
16771669
}
16781670

1679-
if (repo_refresh_and_write_index(the_repository, REFRESH_QUIET, 0, 0,
1680-
NULL, NULL, NULL)) {
1681-
ret = error(_("could not write index"));
1682-
goto done;
1683-
}
1684-
1685-
if (!check_changes(ps, include_untracked, &untracked_files)) {
1686-
if (!quiet)
1687-
printf_ln(_("No local changes to save"));
1688-
goto done;
1689-
}
1690-
16911671
if (!refs_reflog_exists(get_main_ref_store(the_repository), ref_stash) && do_clear_stash()) {
16921672
ret = -1;
16931673
if (!quiet)
@@ -1697,8 +1677,15 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
16971677

16981678
if (stash_msg)
16991679
strbuf_addstr(&stash_msg_buf, stash_msg);
1700-
if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode,
1701-
interactive_opts, only_staged, &info, &patch, quiet)) {
1680+
create_res = do_create_stash(ps, &stash_msg_buf, include_untracked,
1681+
patch_mode, interactive_opts, only_staged,
1682+
&info, &patch, quiet);
1683+
if (create_res == CREATE_NO_CHANGES) {
1684+
if (!quiet)
1685+
printf_ln(_("No local changes to save"));
1686+
ret = 0;
1687+
goto done;
1688+
} else if (create_res != CREATE_SUCCESS) {
17021689
ret = -1;
17031690
goto done;
17041691
}

0 commit comments

Comments
 (0)