It can sometimes be useful to know whether a path in the
filesystem has been updated without going to the work of
opening and re-reading its content. We trust the stat()
information on disk already to handle index updates, and we
can use the same trick here.

This patch introduces a "stat_validity" struct which
encapsulates the concept of checking the stat-freshness of a
file. It is implemented on top of "struct cache_entry" to
reuse the logic about which stat entries to trust for a
particular platform, but hides the complexity behind two
simple functions: check and update.

Signed-off-by: Jeff King <p...@peff.net>
---
This one is prep for the next patch. I'm not super-happy with the way it
builds around cache_entry, just because cache entries may end up
following different rules in the long run. But I at least tried to
encapsulate the grossness, so if it turns out to be a problem, we can
factor out the relevant bits from ce_match_stat_basic into a shared
function.

 cache.h      | 27 +++++++++++++++++++++++++++
 read-cache.c | 31 +++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/cache.h b/cache.h
index 94ca1ac..adf2874 100644
--- a/cache.h
+++ b/cache.h
@@ -1326,4 +1326,31 @@ int sane_execvp(const char *file, char *const argv[]);
 
 int sane_execvp(const char *file, char *const argv[]);
 
+/*
+ * A struct to encapsulate the concept of whether a file has changed
+ * since we last checked it. This is a simplified version of the up-to-date
+ * checks we use for the index. The implementation is built on an index entry,
+ * but we shield the callers from that ugliness with our struct.
+ */
+struct stat_validity {
+       struct cache_entry *ce;
+};
+
+void stat_validity_clear(struct stat_validity *sv);
+
+/*
+ * Returns 1 if the path matches the saved stat_validity, 0 otherwise.
+ * A missing or inaccessible file is considered a match if the struct was just
+ * initialized, or if the previous update found an inaccessible file.
+ */
+int stat_validity_check(struct stat_validity *sv, const char *path);
+
+/*
+ * Update the stat_validity from a file opened at descriptor fd (if the file
+ * is missing or inaccessible, the validity will reflect that, and future
+ * calls to stat_validity_check will match only if it continues to be
+ * inaccessible).
+ */
+void stat_validity_update(struct stat_validity *sv, int fd);
+
 #endif /* CACHE_H */
diff --git a/read-cache.c b/read-cache.c
index 04ed561..a0bd06c 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1933,3 +1933,34 @@ void *read_blob_data_from_index(struct index_state 
*istate, const char *path, un
                *size = sz;
        return data;
 }
+
+void stat_validity_clear(struct stat_validity *sv)
+{
+       free(sv->ce);
+       sv->ce = NULL;
+}
+
+int stat_validity_check(struct stat_validity *sv, const char *path)
+{
+       struct stat st;
+
+       if (stat(path, &st) < 0)
+               return sv->ce == NULL;
+       if (!sv->ce)
+               return 0;
+       return !ce_match_stat_basic(sv->ce, &st);
+}
+
+void stat_validity_update(struct stat_validity *sv, int fd)
+{
+       struct stat st;
+
+       if (fstat(fd, &st) < 0)
+               stat_validity_clear(sv);
+       else {
+               if (!sv->ce)
+                       sv->ce = xcalloc(1, cache_entry_size(0));
+               fill_stat_cache_info(sv->ce, &st);
+               sv->ce->ce_mode = create_ce_mode(st.st_mode);
+       }
+}
-- 
1.8.3.rc1.2.g12db477

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

Reply via email to