summaryrefslogtreecommitdiff
path: root/dir.h
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2015-05-26 13:24:45 -0700
committerJunio C Hamano <gitster@pobox.com>2015-05-26 13:24:46 -0700
commit38ccaf93bbf5a99dbff908068292ffaa5bafe25e (patch)
treecd1b379e0ebd26c6b5576e023c67338c41462d4e /dir.h
parenta26d48a46e8d7df58e7a91e7aac6795e29ddbd6d (diff)
parentaeb6f8b3a2bbfd8b48a967139fbf4581e5345182 (diff)
downloadgit-38ccaf93bbf5a99dbff908068292ffaa5bafe25e.tar.gz
Merge branch 'nd/untracked-cache'
Teach the index to optionally remember already seen untracked files to speed up "git status" in a working tree with tons of cruft. * nd/untracked-cache: (24 commits) git-status.txt: advertisement for untracked cache untracked cache: guard and disable on system changes mingw32: add uname() t7063: tests for untracked cache update-index: test the system before enabling untracked cache update-index: manually enable or disable untracked cache status: enable untracked cache untracked-cache: temporarily disable with $GIT_DISABLE_UNTRACKED_CACHE untracked cache: mark index dirty if untracked cache is updated untracked cache: print stats with $GIT_TRACE_UNTRACKED_STATS untracked cache: avoid racy timestamps read-cache.c: split racy stat test to a separate function untracked cache: invalidate at index addition or removal untracked cache: load from UNTR index extension untracked cache: save to an index extension ewah: add convenient wrapper ewah_serialize_strbuf() untracked cache: don't open non-existent .gitignore untracked cache: mark what dirs should be recursed/saved untracked cache: record/validate dir mtime and reuse cached output untracked cache: make a wrapper around {open,read,close}dir() ...
Diffstat (limited to 'dir.h')
-rw-r--r--dir.h82
1 files changed, 82 insertions, 0 deletions
diff --git a/dir.h b/dir.h
index 72b73c65dc..7b5855dd80 100644
--- a/dir.h
+++ b/dir.h
@@ -66,6 +66,7 @@ struct exclude_stack {
struct exclude_stack *prev; /* the struct exclude_stack for the parent directory */
int baselen;
int exclude_ix; /* index of exclude_list within EXC_DIRS exclude_list_group */
+ struct untracked_cache_dir *ucd;
};
struct exclude_list_group {
@@ -73,6 +74,73 @@ struct exclude_list_group {
struct exclude_list *el;
};
+struct sha1_stat {
+ struct stat_data stat;
+ unsigned char sha1[20];
+ int valid;
+};
+
+/*
+ * Untracked cache
+ *
+ * The following inputs are sufficient to determine what files in a
+ * directory are excluded:
+ *
+ * - The list of files and directories of the directory in question
+ * - The $GIT_DIR/index
+ * - dir_struct flags
+ * - The content of $GIT_DIR/info/exclude
+ * - The content of core.excludesfile
+ * - The content (or the lack) of .gitignore of all parent directories
+ * from $GIT_WORK_TREE
+ * - The check_only flag in read_directory_recursive (for
+ * DIR_HIDE_EMPTY_DIRECTORIES)
+ *
+ * The first input can be checked using directory mtime. In many
+ * filesystems, directory mtime (stat_data field) is updated when its
+ * files or direct subdirs are added or removed.
+ *
+ * The second one can be hooked from cache_tree_invalidate_path().
+ * Whenever a file (or a submodule) is added or removed from a
+ * directory, we invalidate that directory.
+ *
+ * The remaining inputs are easy, their SHA-1 could be used to verify
+ * their contents (exclude_sha1[], info_exclude_sha1[] and
+ * excludes_file_sha1[])
+ */
+struct untracked_cache_dir {
+ struct untracked_cache_dir **dirs;
+ char **untracked;
+ struct stat_data stat_data;
+ unsigned int untracked_alloc, dirs_nr, dirs_alloc;
+ unsigned int untracked_nr;
+ unsigned int check_only : 1;
+ /* all data except 'dirs' in this struct are good */
+ unsigned int valid : 1;
+ unsigned int recurse : 1;
+ /* null SHA-1 means this directory does not have .gitignore */
+ unsigned char exclude_sha1[20];
+ char name[FLEX_ARRAY];
+};
+
+struct untracked_cache {
+ struct sha1_stat ss_info_exclude;
+ struct sha1_stat ss_excludes_file;
+ const char *exclude_per_dir;
+ struct strbuf ident;
+ /*
+ * dir_struct#flags must match dir_flags or the untracked
+ * cache is ignored.
+ */
+ unsigned dir_flags;
+ struct untracked_cache_dir *root;
+ /* Statistics */
+ int dir_created;
+ int gitignore_invalidated;
+ int dir_invalidated;
+ int dir_opened;
+};
+
struct dir_struct {
int nr, alloc;
int ignored_nr, ignored_alloc;
@@ -120,6 +188,12 @@ struct dir_struct {
struct exclude_stack *exclude_stack;
struct exclude *exclude;
struct strbuf basebuf;
+
+ /* Enable untracked file cache if set */
+ struct untracked_cache *untracked;
+ struct sha1_stat ss_info_exclude;
+ struct sha1_stat ss_excludes_file;
+ unsigned unmanaged_exclude_files;
};
/*
@@ -226,4 +300,12 @@ static inline int dir_path_match(const struct dir_entry *ent,
has_trailing_dir);
}
+void untracked_cache_invalidate_path(struct index_state *, const char *);
+void untracked_cache_remove_from_index(struct index_state *, const char *);
+void untracked_cache_add_to_index(struct index_state *, const char *);
+
+void free_untracked_cache(struct untracked_cache *);
+struct untracked_cache *read_untracked_extension(const void *data, unsigned long sz);
+void write_untracked_extension(struct strbuf *out, struct untracked_cache *untracked);
+void add_untracked_ident(struct untracked_cache *);
#endif