Skip to content

Commit 6100081

Browse files
Martin Ågrengitster
authored andcommitted
write_locked_index(): add flag to avoid writing unchanged index
We have several callers like if (active_cache_changed && write_locked_index(...)) handle_error(); rollback_lock_file(...); where the final rollback is needed because "!active_cache_changed" shortcuts the if-expression. There are also a few variants of this, including some if-else constructs that make it more clear when the explicit rollback is really needed. Teach `write_locked_index()` to take a new flag SKIP_IF_UNCHANGED and simplify the callers. Leave the most complicated of the callers (in builtin/update-index.c) unchanged. Rewriting it to use this new flag would end up duplicating logic. We could have made the new flag behave the other way round ("FORCE_WRITE"), but that could break existing users behind their backs. Let's take the more conservative approach. We can still migrate existing callers to use our new flag. Later we might even be able to flip the default, possibly without entirely ignoring the risk to in-flight or out-of-tree topics. Suggested-by: Jeff King <[email protected]> Signed-off-by: Martin Ågren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 350292a commit 6100081

File tree

10 files changed

+37
-40
lines changed

10 files changed

+37
-40
lines changed

builtin/add.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -534,10 +534,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
534534
unplug_bulk_checkin();
535535

536536
finish:
537-
if (active_cache_changed) {
538-
if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
539-
die(_("Unable to write new index file"));
540-
}
537+
if (write_locked_index(&the_index, &lock_file,
538+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
539+
die(_("Unable to write new index file"));
541540

542541
UNLEAK(pathspec);
543542
UNLEAK(dir);

builtin/commit.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -389,13 +389,9 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
389389
if (active_cache_changed
390390
|| !cache_tree_fully_valid(active_cache_tree))
391391
update_main_cache_tree(WRITE_TREE_SILENT);
392-
if (active_cache_changed) {
393-
if (write_locked_index(&the_index, &index_lock,
394-
COMMIT_LOCK))
395-
die(_("unable to write new_index file"));
396-
} else {
397-
rollback_lock_file(&index_lock);
398-
}
392+
if (write_locked_index(&the_index, &index_lock,
393+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
394+
die(_("unable to write new_index file"));
399395
commit_style = COMMIT_AS_IS;
400396
ret = get_index_file();
401397
goto out;

builtin/merge.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -651,10 +651,9 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
651651

652652
hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
653653
refresh_cache(REFRESH_QUIET);
654-
if (active_cache_changed &&
655-
write_locked_index(&the_index, &lock, COMMIT_LOCK))
654+
if (write_locked_index(&the_index, &lock,
655+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
656656
return error(_("Unable to write index."));
657-
rollback_lock_file(&lock);
658657

659658
if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) {
660659
int clean, x;
@@ -691,10 +690,9 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
691690
remoteheads->item, reversed, &result);
692691
if (clean < 0)
693692
exit(128);
694-
if (active_cache_changed &&
695-
write_locked_index(&the_index, &lock, COMMIT_LOCK))
693+
if (write_locked_index(&the_index, &lock,
694+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
696695
die (_("unable to write %s"), get_index_file());
697-
rollback_lock_file(&lock);
698696
return clean ? 0 : 1;
699697
} else {
700698
return try_merge_command(strategy, xopts_nr, xopts,
@@ -810,10 +808,9 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
810808

811809
hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
812810
refresh_cache(REFRESH_QUIET);
813-
if (active_cache_changed &&
814-
write_locked_index(&the_index, &lock, COMMIT_LOCK))
811+
if (write_locked_index(&the_index, &lock,
812+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
815813
return error(_("Unable to write index."));
816-
rollback_lock_file(&lock);
817814

818815
write_tree_trivial(&result_tree);
819816
printf(_("Wonderful.\n"));

builtin/mv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
293293
if (gitmodules_modified)
294294
stage_updated_gitmodules(&the_index);
295295

296-
if (active_cache_changed &&
297-
write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
296+
if (write_locked_index(&the_index, &lock_file,
297+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
298298
die(_("Unable to write new index file"));
299299

300300
return 0;

builtin/rm.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
385385
stage_updated_gitmodules(&the_index);
386386
}
387387

388-
if (active_cache_changed) {
389-
if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
390-
die(_("Unable to write new index file"));
391-
}
388+
if (write_locked_index(&the_index, &lock_file,
389+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
390+
die(_("Unable to write new index file"));
392391

393392
return 0;
394393
}

cache.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ extern int read_index_unmerged(struct index_state *);
599599

600600
/* For use with `write_locked_index()`. */
601601
#define COMMIT_LOCK (1 << 0)
602+
#define SKIP_IF_UNCHANGED (1 << 1)
602603

603604
/*
604605
* Write the index while holding an already-taken lock. Close the lock,
@@ -615,6 +616,9 @@ extern int read_index_unmerged(struct index_state *);
615616
* With `COMMIT_LOCK`, the lock is always committed or rolled back.
616617
* Without it, the lock is closed, but neither committed nor rolled
617618
* back.
619+
*
620+
* If `SKIP_IF_UNCHANGED` is given and the index is unchanged, nothing
621+
* is written (and the lock is rolled back if `COMMIT_LOCK` is given).
618622
*/
619623
extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
620624

merge-recursive.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,10 +2223,9 @@ int merge_recursive_generic(struct merge_options *o,
22232223
return clean;
22242224
}
22252225

2226-
if (active_cache_changed &&
2227-
write_locked_index(&the_index, &lock, COMMIT_LOCK))
2226+
if (write_locked_index(&the_index, &lock,
2227+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
22282228
return err(o, _("Unable to write index."));
2229-
rollback_lock_file(&lock);
22302229

22312230
return clean ? 0 : 1;
22322231
}

read-cache.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,6 +2538,12 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
25382538
int new_shared_index, ret;
25392539
struct split_index *si = istate->split_index;
25402540

2541+
if ((flags & SKIP_IF_UNCHANGED) && !istate->cache_changed) {
2542+
if (flags & COMMIT_LOCK)
2543+
rollback_lock_file(lock);
2544+
return 0;
2545+
}
2546+
25412547
if (istate->fsmonitor_last_update)
25422548
fill_fsmonitor_bitmap(istate);
25432549

rerere.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -719,11 +719,9 @@ static void update_paths(struct string_list *update)
719719
item->string);
720720
}
721721

722-
if (active_cache_changed) {
723-
if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
724-
die("Unable to write new index file");
725-
} else
726-
rollback_lock_file(&index_lock);
722+
if (write_locked_index(&the_index, &index_lock,
723+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
724+
die("Unable to write new index file");
727725
}
728726

729727
static void remove_variant(struct rerere_id *id)

sequencer.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -517,15 +517,14 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
517517
return clean;
518518
}
519519

520-
if (active_cache_changed &&
521-
write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
520+
if (write_locked_index(&the_index, &index_lock,
521+
COMMIT_LOCK | SKIP_IF_UNCHANGED))
522522
/*
523523
* TRANSLATORS: %s will be "revert", "cherry-pick" or
524524
* "rebase -i".
525525
*/
526526
return error(_("%s: Unable to write new index file"),
527527
_(action_name(opts)));
528-
rollback_lock_file(&index_lock);
529528

530529
if (!clean)
531530
append_conflicts_hint(msgbuf);
@@ -1713,13 +1712,13 @@ static int read_and_refresh_cache(struct replay_opts *opts)
17131712
_(action_name(opts)));
17141713
}
17151714
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
1716-
if (the_index.cache_changed && index_fd >= 0) {
1717-
if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK)) {
1715+
if (index_fd >= 0) {
1716+
if (write_locked_index(&the_index, &index_lock,
1717+
COMMIT_LOCK | SKIP_IF_UNCHANGED)) {
17181718
return error(_("git %s: failed to refresh the index"),
17191719
_(action_name(opts)));
17201720
}
17211721
}
1722-
rollback_lock_file(&index_lock);
17231722
return 0;
17241723
}
17251724

0 commit comments

Comments
 (0)