When reading the watchman extension, invalidate the listed
untracked-cache entries.

We don't clear these entries yet; we can only do that once we know
that they came from a live watchman (rather than from disk).

Signed-off-by: David Turner <[email protected]>
---
 dir.c        | 11 +++++---
 dir.h        |  3 ++
 read-cache.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 94 insertions(+), 9 deletions(-)

diff --git a/dir.c b/dir.c
index 69e0be6..9b659e6 100644
--- a/dir.c
+++ b/dir.c
@@ -597,9 +597,9 @@ static void trim_trailing_spaces(char *buf)
  *
  * If "name" has the trailing slash, it'll be excluded in the search.
  */
-static struct untracked_cache_dir *lookup_untracked(struct untracked_cache *uc,
-                                                   struct untracked_cache_dir 
*dir,
-                                                   const char *name, int len)
+struct untracked_cache_dir *lookup_untracked(struct untracked_cache *uc,
+                                            struct untracked_cache_dir *dir,
+                                            const char *name, int len)
 {
        int first, last;
        struct untracked_cache_dir *d;
@@ -2625,8 +2625,10 @@ static void free_untracked(struct untracked_cache_dir 
*ucd)
 
 void free_untracked_cache(struct untracked_cache *uc)
 {
-       if (uc)
+       if (uc) {
                free_untracked(uc->root);
+               string_list_clear(&uc->invalid_untracked, 0);
+       }
        free(uc);
 }
 
@@ -2775,6 +2777,7 @@ struct untracked_cache *read_untracked_extension(const 
void *data, unsigned long
                return NULL;
 
        uc = xcalloc(1, sizeof(*uc));
+       string_list_init(&uc->invalid_untracked, 1);
        strbuf_init(&uc->ident, ident_len);
        strbuf_add(&uc->ident, ident, ident_len);
        load_sha1_stat(&uc->ss_info_exclude, &ouc->info_exclude_stat,
diff --git a/dir.h b/dir.h
index 3d540de..8fd3f9e 100644
--- a/dir.h
+++ b/dir.h
@@ -315,4 +315,7 @@ struct untracked_cache *read_untracked_extension(const void 
*data, unsigned long
 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);
+struct untracked_cache_dir *lookup_untracked(struct untracked_cache *uc,
+                                            struct untracked_cache_dir *dir,
+                                            const char *name, int len);
 #endif
diff --git a/read-cache.c b/read-cache.c
index 6d5e871..b4bd15c 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1373,11 +1373,76 @@ static int verify_hdr(const struct cache_header *hdr, 
unsigned long size)
        return 0;
 }
 
+static struct untracked_cache_dir *find_untracked_cache_dir(
+       struct untracked_cache *uc, struct untracked_cache_dir *ucd,
+       const char *name)
+{
+       int component_len;
+       const char *end;
+       struct untracked_cache_dir *dir;
+
+       if (!*name)
+               return ucd;
+
+       end = strchr(name, '/');
+       if (end)
+               component_len = end - name;
+       else
+               component_len = strlen(name);
+
+       dir = lookup_untracked(uc, ucd, name, component_len);
+       if (dir)
+               return find_untracked_cache_dir(uc, dir, name + component_len + 
1);
+
+       return NULL;
+}
+
 static void mark_no_watchman(size_t pos, void *data)
 {
        struct index_state *istate = data;
+       struct cache_entry *ce = istate->cache[pos];
+       struct strbuf sb = STRBUF_INIT;
+       char *c;
+       struct untracked_cache_dir *dir;
+
        assert(pos < istate->cache_nr);
-       istate->cache[pos]->ce_flags |= CE_WATCHMAN_DIRTY;
+       ce->ce_flags |= CE_WATCHMAN_DIRTY;
+
+       if (!istate->untracked || !istate->untracked->root)
+               return;
+
+       strbuf_add(&sb, ce->name, ce_namelen(ce));
+
+       for (c = sb.buf + sb.len - 1; c > sb.buf; c--) {
+               if (*c == '/') {
+                       strbuf_setlen(&sb, c - sb.buf);
+                       break;
+               }
+       }
+
+       if (c == sb.buf) {
+               strbuf_setlen(&sb, 0);
+       }
+
+       dir = find_untracked_cache_dir(istate->untracked,
+                                      istate->untracked->root, sb.buf);
+       if (dir)
+               dir->valid = 0;
+
+       strbuf_release(&sb);
+}
+
+static int mark_untracked_invalid(struct string_list_item *item, void *uc)
+{
+       struct untracked_cache *untracked = uc;
+       struct untracked_cache_dir *dir;
+
+       dir = find_untracked_cache_dir(untracked, untracked->root,
+                                      item->string);
+       if (dir)
+               dir->valid = 0;
+
+       return 0;
 }
 
 static int read_watchman_ext(struct index_state *istate, const void *data,
@@ -1407,10 +1472,24 @@ static int read_watchman_ext(struct index_state 
*istate, const void *data,
        ewah_each_bit(bitmap, mark_no_watchman, istate);
        ewah_free(bitmap);
 
-       /*
-        * TODO: update the untracked cache from the untracked data in this
-        * extension.
-        */
+       if (istate->untracked && istate->untracked->root) {
+               int i;
+               const char *untracked;
+
+               untracked = data + len + 8 + bitmap_size;
+               for (i = 0; i < untracked_nr; ++i) {
+                       int len = strlen(untracked);
+                       
string_list_append(&istate->untracked->invalid_untracked,
+                                          untracked);
+                       untracked += len + 1;
+               }
+
+               for_each_string_list(&istate->untracked->invalid_untracked,
+                        mark_untracked_invalid, istate->untracked);
+
+               if (untracked_nr)
+                       istate->cache_changed |= WATCHMAN_CHANGED;
+       }
        return 0;
 }
 
-- 
2.4.2.767.g62658d5-twtrsrc

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to