Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'read-cache.c')
-rw-r--r--read-cache.c90
1 files changed, 78 insertions, 12 deletions
diff --git a/read-cache.c b/read-cache.c
index 62594a8f51..aa0c6fe490 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -25,6 +25,7 @@
#include "fsmonitor.h"
#include "thread-utils.h"
#include "progress.h"
+#include "sparse-index.h"
/* Mask for the name length in ce_flags in the on-disk index */
@@ -47,6 +48,7 @@
#define CACHE_EXT_FSMONITOR 0x46534D4E /* "FSMN" */
#define CACHE_EXT_ENDOFINDEXENTRIES 0x454F4945 /* "EOIE" */
#define CACHE_EXT_INDEXENTRYOFFSETTABLE 0x49454F54 /* "IEOT" */
+#define CACHE_EXT_SPARSE_DIRECTORIES 0x73646972 /* "sdir" */
/* changes that can be kept in $GIT_DIR/index (basically all extensions) */
#define EXTMASK (RESOLVE_UNDO_CHANGED | CACHE_TREE_CHANGED | \
@@ -101,6 +103,9 @@ static const char *alternate_index_output;
static void set_index_entry(struct index_state *istate, int nr, struct cache_entry *ce)
{
+ if (S_ISSPARSEDIR(ce->ce_mode))
+ istate->sparse_index = 1;
+
istate->cache[nr] = ce;
add_name_hash(istate, ce);
}
@@ -544,7 +549,7 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char
return 0;
}
-static int index_name_stage_pos(const struct index_state *istate, const char *name, int namelen, int stage)
+static int index_name_stage_pos(struct index_state *istate, const char *name, int namelen, int stage)
{
int first, last;
@@ -562,10 +567,31 @@ static int index_name_stage_pos(const struct index_state *istate, const char *na
}
first = next+1;
}
+
+ if (istate->sparse_index &&
+ first > 0) {
+ /* Note: first <= istate->cache_nr */
+ struct cache_entry *ce = istate->cache[first - 1];
+
+ /*
+ * If we are in a sparse-index _and_ the entry before the
+ * insertion position is a sparse-directory entry that is
+ * an ancestor of 'name', then we need to expand the index
+ * and search again. This will only trigger once, because
+ * thereafter the index is fully expanded.
+ */
+ if (S_ISSPARSEDIR(ce->ce_mode) &&
+ ce_namelen(ce) < namelen &&
+ !strncmp(name, ce->name, ce_namelen(ce))) {
+ ensure_full_index(istate);
+ return index_name_stage_pos(istate, name, namelen, stage);
+ }
+ }
+
return -first-1;
}
-int index_name_pos(const struct index_state *istate, const char *name, int namelen)
+int index_name_pos(struct index_state *istate, const char *name, int namelen)
{
return index_name_stage_pos(istate, name, namelen, 0);
}
@@ -985,7 +1011,7 @@ inside:
}
}
if (protect_ntfs) {
-#ifdef GIT_WINDOWS_NATIVE
+#if defined GIT_WINDOWS_NATIVE || defined __CYGWIN__
if (c == '\\')
return 0;
#endif
@@ -999,8 +1025,14 @@ inside:
c = *path++;
if ((c == '.' && !verify_dotfile(path, mode)) ||
- is_dir_sep(c) || c == '\0')
+ is_dir_sep(c))
return 0;
+ /*
+ * allow terminating directory separators for
+ * sparse directory entries.
+ */
+ if (c == '\0')
+ return S_ISDIR(mode);
} else if (c == '\\' && protect_ntfs) {
if (is_ntfs_dotgit(path))
return 0;
@@ -1546,6 +1578,8 @@ int refresh_index(struct index_state *istate, unsigned int flags,
*/
preload_index(istate, pathspec, 0);
trace2_region_enter("index", "refresh", NULL);
+ /* TODO: audit for interaction with sparse-index. */
+ ensure_full_index(istate);
for (i = 0; i < istate->cache_nr; i++) {
struct cache_entry *ce, *new_entry;
int cache_errno = 0;
@@ -1763,6 +1797,10 @@ static int read_index_extension(struct index_state *istate,
case CACHE_EXT_INDEXENTRYOFFSETTABLE:
/* already handled in do_read_index() */
break;
+ case CACHE_EXT_SPARSE_DIRECTORIES:
+ /* no content, only an indicator */
+ istate->sparse_index = 1;
+ break;
default:
if (*ext < 'A' || 'Z' < *ext)
return error(_("index uses %.4s extension, which we do not understand"),
@@ -2100,7 +2138,7 @@ static unsigned long load_cache_entries_threaded(struct index_state *istate, con
/* ensure we have no more threads than we have blocks to process */
if (nr_threads > ieot->nr)
nr_threads = ieot->nr;
- data = xcalloc(nr_threads, sizeof(*data));
+ CALLOC_ARRAY(data, nr_threads);
offset = ieot_start = 0;
ieot_blocks = DIV_ROUND_UP(ieot->nr, nr_threads);
@@ -2202,7 +2240,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
istate->version = ntohl(hdr->hdr_version);
istate->cache_nr = ntohl(hdr->hdr_entries);
istate->cache_alloc = alloc_nr(istate->cache_nr);
- istate->cache = xcalloc(istate->cache_alloc, sizeof(*istate->cache));
+ CALLOC_ARRAY(istate->cache, istate->cache_alloc);
istate->initialized = 1;
p.istate = istate;
@@ -2276,6 +2314,12 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
trace2_data_intmax("index", the_repository, "read/cache_nr",
istate->cache_nr);
+ if (!istate->repo)
+ istate->repo = the_repository;
+ prepare_repo_settings(istate->repo);
+ if (istate->repo->settings.command_requires_full_index)
+ ensure_full_index(istate);
+
return istate->cache_nr;
unmap:
@@ -2329,7 +2373,7 @@ int read_index_from(struct index_state *istate, const char *path,
if (split_index->base)
discard_index(split_index->base);
else
- split_index->base = xcalloc(1, sizeof(*split_index->base));
+ CALLOC_ARRAY(split_index->base, 1);
base_oid_hex = oid_to_hex(&split_index->base_oid);
base_path = xstrfmt("%s/sharedindex.%s", gitdir, base_oid_hex);
@@ -2376,6 +2420,7 @@ int discard_index(struct index_state *istate)
cache_tree_free(&(istate->cache_tree));
istate->initialized = 0;
istate->fsmonitor_has_run_once = 0;
+ FREE_AND_NULL(istate->fsmonitor_last_update);
FREE_AND_NULL(istate->cache);
istate->cache_alloc = 0;
discard_split_index(istate);
@@ -2459,6 +2504,8 @@ int repo_index_has_changes(struct repository *repo,
diff_flush(&opt);
return opt.flags.has_changes != 0;
} else {
+ /* TODO: audit for interaction with sparse-index. */
+ ensure_full_index(istate);
for (i = 0; sb && i < istate->cache_nr; i++) {
if (i)
strbuf_addch(sb, ' ');
@@ -3014,6 +3061,10 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
if (err)
return -1;
}
+ if (istate->sparse_index) {
+ if (write_index_ext_header(&c, &eoie_c, newfd, CACHE_EXT_SPARSE_DIRECTORIES, 0) < 0)
+ return -1;
+ }
/*
* CACHE_EXT_ENDOFINDEXENTRIES must be written as the last entry before the SHA1
@@ -3073,6 +3124,14 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
unsigned flags)
{
int ret;
+ int was_full = !istate->sparse_index;
+
+ ret = convert_to_sparse(istate);
+
+ if (ret) {
+ warning(_("failed to convert to a sparse-index"));
+ return ret;
+ }
/*
* TODO trace2: replace "the_repository" with the actual repo instance
@@ -3084,6 +3143,9 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
trace2_region_leave_printf("index", "do_write_index", the_repository,
"%s", get_lock_file_path(lock));
+ if (was_full)
+ ensure_full_index(istate);
+
if (ret)
return ret;
if (flags & COMMIT_LOCK)
@@ -3174,9 +3236,10 @@ static int write_shared_index(struct index_state *istate,
struct tempfile **temp)
{
struct split_index *si = istate->split_index;
- int ret;
+ int ret, was_full = !istate->sparse_index;
move_cache_to_base_index(istate);
+ convert_to_sparse(istate);
trace2_region_enter_printf("index", "shared/do_write_index",
the_repository, "%s", get_tempfile_path(*temp));
@@ -3184,6 +3247,9 @@ static int write_shared_index(struct index_state *istate,
trace2_region_leave_printf("index", "shared/do_write_index",
the_repository, "%s", get_tempfile_path(*temp));
+ if (was_full)
+ ensure_full_index(istate);
+
if (ret)
return ret;
ret = adjust_shared_perm(get_tempfile_path(*temp));
@@ -3352,8 +3418,8 @@ int repo_read_index_unmerged(struct repository *repo)
* We helpfully remove a trailing "/" from directories so that
* the output of read_directory can be used as-is.
*/
-int index_name_is_other(const struct index_state *istate, const char *name,
- int namelen)
+int index_name_is_other(struct index_state *istate, const char *name,
+ int namelen)
{
int pos;
if (namelen && name[namelen - 1] == '/')
@@ -3371,7 +3437,7 @@ int index_name_is_other(const struct index_state *istate, const char *name,
return 1;
}
-void *read_blob_data_from_index(const struct index_state *istate,
+void *read_blob_data_from_index(struct index_state *istate,
const char *path, unsigned long *size)
{
int pos, len;
@@ -3430,7 +3496,7 @@ void stat_validity_update(struct stat_validity *sv, int fd)
stat_validity_clear(sv);
else {
if (!sv->sd)
- sv->sd = xcalloc(1, sizeof(struct stat_data));
+ CALLOC_ARRAY(sv->sd, 1);
fill_stat_data(sv->sd, &st);
}
}