summaryrefslogtreecommitdiff
path: root/read-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'read-cache.c')
-rw-r--r--read-cache.c74
1 files changed, 59 insertions, 15 deletions
diff --git a/read-cache.c b/read-cache.c
index cbe73f1..60355f5 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -28,6 +28,7 @@
#include "sparse-index.h"
#include "csum-file.h"
#include "promisor-remote.h"
+#include "hook.h"
/* Mask for the name length in ce_flags in the on-disk index */
@@ -133,7 +134,7 @@ static void replace_index_entry(struct index_state *istate, int nr, struct cache
void rename_index_entry_at(struct index_state *istate, int nr, const char *new_name)
{
- struct cache_entry *old_entry = istate->cache[nr], *new_entry;
+ struct cache_entry *old_entry = istate->cache[nr], *new_entry, *refreshed;
int namelen = strlen(new_name);
new_entry = make_empty_cache_entry(istate, namelen);
@@ -146,7 +147,20 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
cache_tree_invalidate_path(istate, old_entry->name);
untracked_cache_remove_from_index(istate, old_entry->name);
remove_index_entry_at(istate, nr);
- add_index_entry(istate, new_entry, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
+
+ /*
+ * Refresh the new index entry. Using 'refresh_cache_entry' ensures
+ * we only update stat info if the entry is otherwise up-to-date (i.e.,
+ * the contents/mode haven't changed). This ensures that we reflect the
+ * 'ctime' of the rename in the index without (incorrectly) updating
+ * the cached stat info to reflect unstaged changes on disk.
+ */
+ refreshed = refresh_cache_entry(istate, new_entry, CE_MATCH_REFRESH);
+ if (refreshed && refreshed != new_entry) {
+ add_index_entry(istate, refreshed, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
+ discard_cache_entry(new_entry);
+ } else
+ add_index_entry(istate, new_entry, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
}
void fill_stat_data(struct stat_data *sd, struct stat *st)
@@ -735,7 +749,7 @@ static struct cache_entry *create_alias_ce(struct index_state *istate,
void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
{
struct object_id oid;
- if (write_object_file("", 0, blob_type, &oid))
+ if (write_object_file("", 0, OBJ_BLOB, &oid))
die(_("cannot create an empty blob in the object database"));
oidcpy(&ce->oid, &oid);
}
@@ -1339,9 +1353,6 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
int new_only = option & ADD_CACHE_NEW_ONLY;
- if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
- cache_tree_invalidate_path(istate, ce->name);
-
/*
* If this entry's path sorts after the last entry in the index,
* we can avoid searching for it.
@@ -1352,6 +1363,13 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
else
pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce), EXPAND_SPARSE);
+ /*
+ * Cache tree path should be invalidated only after index_name_stage_pos,
+ * in case it expands a sparse index.
+ */
+ if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
+ cache_tree_invalidate_path(istate, ce->name);
+
/* existing match? Just replace it. */
if (pos >= 0) {
if (!new_only)
@@ -2242,6 +2260,20 @@ static unsigned long load_cache_entries_threaded(struct index_state *istate, con
return consumed;
}
+static void set_new_index_sparsity(struct index_state *istate)
+{
+ /*
+ * If the index's repo exists, mark it sparse according to
+ * repo settings.
+ */
+ if (istate->repo) {
+ prepare_repo_settings(istate->repo);
+ if (!istate->repo->settings.command_requires_full_index &&
+ is_sparse_index_allowed(istate, 0))
+ istate->sparse_index = 1;
+ }
+}
+
/* remember to discard_cache() before reading a different cache! */
int do_read_index(struct index_state *istate, const char *path, int must_exist)
{
@@ -2263,8 +2295,10 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
istate->timestamp.nsec = 0;
fd = open(path, O_RDONLY);
if (fd < 0) {
- if (!must_exist && errno == ENOENT)
+ if (!must_exist && errno == ENOENT) {
+ set_new_index_sparsity(istate);
return 0;
+ }
die_errno(_("%s: index file open failed"), path);
}
@@ -2775,7 +2809,7 @@ static int repo_verify_index(struct repository *repo)
return verify_index_from(repo->index, repo->index_file);
}
-static int has_racy_timestamp(struct index_state *istate)
+int has_racy_timestamp(struct index_state *istate)
{
int entries = istate->cache_nr;
int i;
@@ -2837,7 +2871,7 @@ static int record_ieot(void)
* rely on it.
*/
static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
- int strip_extensions)
+ int strip_extensions, unsigned flags)
{
uint64_t start = getnanotime();
struct hashfile *f;
@@ -2851,6 +2885,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
int drop_cache_tree = istate->drop_cache_tree;
off_t offset;
+ int csum_fsync_flag;
int ieot_entries = 1;
struct index_entry_offset_table *ieot = NULL;
int nr, nr_threads;
@@ -3009,6 +3044,9 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
!is_null_oid(&istate->split_index->base_oid)) {
struct strbuf sb = STRBUF_INIT;
+ if (istate->sparse_index)
+ die(_("cannot write split index for a sparse index"));
+
err = write_link_extension(&sb, istate) < 0 ||
write_index_ext_header(f, eoie_c, CACHE_EXT_LINK,
sb.len) < 0;
@@ -3081,7 +3119,13 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
return -1;
}
- finalize_hashfile(f, istate->oid.hash, CSUM_HASH_IN_STREAM);
+ csum_fsync_flag = 0;
+ if (!alternate_index_output && (flags & COMMIT_LOCK))
+ csum_fsync_flag = CSUM_FSYNC;
+
+ finalize_hashfile(f, istate->oid.hash, FSYNC_COMPONENT_INDEX,
+ CSUM_HASH_IN_STREAM | csum_fsync_flag);
+
if (close_tempfile_gently(tempfile)) {
error(_("could not close '%s'"), get_tempfile_path(tempfile));
return -1;
@@ -3136,7 +3180,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
*/
trace2_region_enter_printf("index", "do_write_index", the_repository,
"%s", get_lock_file_path(lock));
- ret = do_write_index(istate, lock->tempfile, 0);
+ ret = do_write_index(istate, lock->tempfile, 0, flags);
trace2_region_leave_printf("index", "do_write_index", the_repository,
"%s", get_lock_file_path(lock));
@@ -3150,7 +3194,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
else
ret = close_lock_file_gently(lock);
- run_hook_le(NULL, "post-index-change",
+ run_hooks_l("post-index-change",
istate->updated_workdir ? "1" : "0",
istate->updated_skipworktree ? "1" : "0", NULL);
istate->updated_workdir = 0;
@@ -3230,7 +3274,7 @@ static int clean_shared_index_files(const char *current_hex)
}
static int write_shared_index(struct index_state *istate,
- struct tempfile **temp)
+ struct tempfile **temp, unsigned flags)
{
struct split_index *si = istate->split_index;
int ret, was_full = !istate->sparse_index;
@@ -3240,7 +3284,7 @@ static int write_shared_index(struct index_state *istate,
trace2_region_enter_printf("index", "shared/do_write_index",
the_repository, "%s", get_tempfile_path(*temp));
- ret = do_write_index(si->base, *temp, 1);
+ ret = do_write_index(si->base, *temp, 1, flags);
trace2_region_leave_printf("index", "shared/do_write_index",
the_repository, "%s", get_tempfile_path(*temp));
@@ -3349,7 +3393,7 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
ret = do_write_locked_index(istate, lock, flags);
goto out;
}
- ret = write_shared_index(istate, &temp);
+ ret = write_shared_index(istate, &temp, flags);
saved_errno = errno;
if (is_tempfile_active(temp))