Merge branch 'ss/exc-flag-is-a-collection-of-bits'
[git/git.git] / dir.h
diff --git a/dir.h b/dir.h
index 124c073..301b737 100644 (file)
--- 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,13 @@ 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_cache(struct index_state *istate);
+void remove_untracked_cache(struct index_state *istate);
 #endif