apply.c: remove implicit dependency on the_index
[gitweb.git] / read-cache.c
index b07369660baa64961c08ab7bac41e7d3f75c3710..3a930bbcc1af792840e0af9dfe65b94b19faa00c 100644 (file)
@@ -6,11 +6,14 @@
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
 #include "config.h"
+#include "diff.h"
+#include "diffcore.h"
 #include "tempfile.h"
 #include "lockfile.h"
 #include "cache-tree.h"
 #include "refs.h"
 #include "dir.h"
+#include "object-store.h"
 #include "tree.h"
 #include "commit.h"
 #include "blob.h"
@@ -1490,7 +1493,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
                if (ignore_submodules && S_ISGITLINK(ce->ce_mode))
                        continue;
 
-               if (pathspec && !ce_path_match(ce, pathspec, seen))
+               if (pathspec && !ce_path_match(&the_index, ce, pathspec, seen))
                        filtered = 1;
 
                if (ce_stage(ce)) {
@@ -2050,8 +2053,10 @@ int discard_index(struct index_state *istate)
         * Cache entries in istate->cache[] should have been allocated
         * from the memory pool associated with this index, or from an
         * associated split_index. There is no need to free individual
-        * cache entries.
+        * cache entries. validate_cache_entries can detect when this
+        * assertion does not hold.
         */
+       validate_cache_entries(istate);
 
        resolve_undo_clear_index(istate);
        istate->cache_nr = 0;
@@ -2068,13 +2073,45 @@ int discard_index(struct index_state *istate)
        istate->untracked = NULL;
 
        if (istate->ce_mem_pool) {
-               mem_pool_discard(istate->ce_mem_pool);
+               mem_pool_discard(istate->ce_mem_pool, should_validate_cache_entries());
                istate->ce_mem_pool = NULL;
        }
 
        return 0;
 }
 
+/*
+ * Validate the cache entries of this index.
+ * All cache entries associated with this index
+ * should have been allocated by the memory pool
+ * associated with this index, or by a referenced
+ * split index.
+ */
+void validate_cache_entries(const struct index_state *istate)
+{
+       int i;
+
+       if (!should_validate_cache_entries() ||!istate || !istate->initialized)
+               return;
+
+       for (i = 0; i < istate->cache_nr; i++) {
+               if (!istate) {
+                       die("internal error: cache entry is not allocated from expected memory pool");
+               } else if (!istate->ce_mem_pool ||
+                       !mem_pool_contains(istate->ce_mem_pool, istate->cache[i])) {
+                       if (!istate->split_index ||
+                               !istate->split_index->base ||
+                               !istate->split_index->base->ce_mem_pool ||
+                               !mem_pool_contains(istate->split_index->base->ce_mem_pool, istate->cache[i])) {
+                               die("internal error: cache entry is not allocated from expected memory pool");
+                       }
+               }
+       }
+
+       if (istate->split_index)
+               validate_cache_entries(istate->split_index->base);
+}
+
 int unmerged_index(const struct index_state *istate)
 {
        int i;
@@ -2085,6 +2122,44 @@ int unmerged_index(const struct index_state *istate)
        return 0;
 }
 
+int index_has_changes(const struct index_state *istate,
+                     struct tree *tree,
+                     struct strbuf *sb)
+{
+       struct object_id cmp;
+       int i;
+
+       if (istate != &the_index) {
+               BUG("index_has_changes cannot yet accept istate != &the_index; do_diff_cache needs updating first.");
+       }
+       if (tree)
+               cmp = tree->object.oid;
+       if (tree || !get_oid_tree("HEAD", &cmp)) {
+               struct diff_options opt;
+
+               diff_setup(&opt);
+               opt.flags.exit_with_status = 1;
+               if (!sb)
+                       opt.flags.quick = 1;
+               do_diff_cache(&cmp, &opt);
+               diffcore_std(&opt);
+               for (i = 0; sb && i < diff_queued_diff.nr; i++) {
+                       if (i)
+                               strbuf_addch(sb, ' ');
+                       strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path);
+               }
+               diff_flush(&opt);
+               return opt.flags.has_changes != 0;
+       } else {
+               for (i = 0; sb && i < istate->cache_nr; i++) {
+                       if (i)
+                               strbuf_addch(sb, ' ');
+                       strbuf_addstr(sb, istate->cache[i]->name);
+               }
+               return !!istate->cache_nr;
+       }
+}
+
 #define WRITE_BUFFER_SIZE 8192
 static unsigned char write_buffer[WRITE_BUFFER_SIZE];
 static unsigned long write_buffer_len;
@@ -2878,8 +2953,25 @@ struct cache_entry *dup_cache_entry(const struct cache_entry *ce,
 
 void discard_cache_entry(struct cache_entry *ce)
 {
+       if (ce && should_validate_cache_entries())
+               memset(ce, 0xCD, cache_entry_size(ce->ce_namelen));
+
        if (ce && ce->mem_pool_allocated)
                return;
 
        free(ce);
 }
+
+int should_validate_cache_entries(void)
+{
+       static int validate_index_cache_entries = -1;
+
+       if (validate_index_cache_entries < 0) {
+               if (getenv("GIT_TEST_VALIDATE_INDEX_CACHE_ENTRIES"))
+                       validate_index_cache_entries = 1;
+               else
+                       validate_index_cache_entries = 0;
+       }
+
+       return validate_index_cache_entries;
+}