Extract a struct stat_data from cache_entry

Add public functions fill_stat_data() and match_stat_data() to work with it. This infrastructure will later be used to check the validity of other types of file. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Jun 20, 2013 at 10:37 UTC c21d39d7c7eb07eed0be301a72856bff65201256
3 files changed +116 -80
builtin/ls-files.c
+7 -5
@@ -165,11 +165,13 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
165 }
166 write_name(ce->name, ce_namelen(ce));
167 if (debug_mode) {
168 - printf(" ctime: %d:%d\n", ce->ce_ctime.sec, ce->ce_ctime.nsec);
169 - printf(" mtime: %d:%d\n", ce->ce_mtime.sec, ce->ce_mtime.nsec);
170 - printf(" dev: %d\tino: %d\n", ce->ce_dev, ce->ce_ino);
171 - printf(" uid: %d\tgid: %d\n", ce->ce_uid, ce->ce_gid);
172 - printf(" size: %d\tflags: %x\n", ce->ce_size, ce->ce_flags);
168 + struct stat_data *sd = &ce->ce_stat_data;
169 +
170 + printf(" ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
171 + printf(" mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
172 + printf(" dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino);
173 + printf(" uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid);
174 + printf(" size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags);
175 }
176 }
177
cache.h
+26 -7
@@ -119,15 +119,19 @@ struct cache_time {
119 unsigned int nsec;
120 };
121
122 +struct stat_data {
123 + struct cache_time sd_ctime;
124 + struct cache_time sd_mtime;
125 + unsigned int sd_dev;
126 + unsigned int sd_ino;
127 + unsigned int sd_uid;
128 + unsigned int sd_gid;
129 + unsigned int sd_size;
130 +};
131 +
132 struct cache_entry {
123 - struct cache_time ce_ctime;
124 - struct cache_time ce_mtime;
125 - unsigned int ce_dev;
126 - unsigned int ce_ino;
133 + struct stat_data ce_stat_data;
134 unsigned int ce_mode;
128 - unsigned int ce_uid;
129 - unsigned int ce_gid;
130 - unsigned int ce_size;
135 unsigned int ce_flags;
136 unsigned int ce_namelen;
137 unsigned char sha1[20];
@@ -511,6 +515,21 @@ extern int limit_pathspec_to_literal(void);
515 #define HASH_FORMAT_CHECK 2
516 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
517 extern int index_path(unsigned char *sha1, const char *path, struct stat *st, unsigned flags);
518 +
519 +/*
520 + * Record to sd the data from st that we use to check whether a file
521 + * might have changed.
522 + */
523 +extern void fill_stat_data(struct stat_data *sd, struct stat *st);
524 +
525 +/*
526 + * Return 0 if st is consistent with a file not having been changed
527 + * since sd was filled. If there are differences, return a
528 + * combination of MTIME_CHANGED, CTIME_CHANGED, OWNER_CHANGED,
529 + * INODE_CHANGED, and DATA_CHANGED.
530 + */
531 +extern int match_stat_data(const struct stat_data *sd, struct stat *st);
532 +
533 extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
534
535 #define REFRESH_REALLY 0x0001 /* ignore_valid */
read-cache.c
+83 -68
@@ -67,6 +67,61 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
67 add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
68 }
69
70 +void fill_stat_data(struct stat_data *sd, struct stat *st)
71 +{
72 + sd->sd_ctime.sec = (unsigned int)st->st_ctime;
73 + sd->sd_mtime.sec = (unsigned int)st->st_mtime;
74 + sd->sd_ctime.nsec = ST_CTIME_NSEC(*st);
75 + sd->sd_mtime.nsec = ST_MTIME_NSEC(*st);
76 + sd->sd_dev = st->st_dev;
77 + sd->sd_ino = st->st_ino;
78 + sd->sd_uid = st->st_uid;
79 + sd->sd_gid = st->st_gid;
80 + sd->sd_size = st->st_size;
81 +}
82 +
83 +int match_stat_data(const struct stat_data *sd, struct stat *st)
84 +{
85 + int changed = 0;
86 +
87 + if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
88 + changed |= MTIME_CHANGED;
89 + if (trust_ctime && check_stat &&
90 + sd->sd_ctime.sec != (unsigned int)st->st_ctime)
91 + changed |= CTIME_CHANGED;
92 +
93 +#ifdef USE_NSEC
94 + if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
95 + changed |= MTIME_CHANGED;
96 + if (trust_ctime && check_stat &&
97 + sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
98 + changed |= CTIME_CHANGED;
99 +#endif
100 +
101 + if (check_stat) {
102 + if (sd->sd_uid != (unsigned int) st->st_uid ||
103 + sd->sd_gid != (unsigned int) st->st_gid)
104 + changed |= OWNER_CHANGED;
105 + if (sd->sd_ino != (unsigned int) st->st_ino)
106 + changed |= INODE_CHANGED;
107 + }
108 +
109 +#ifdef USE_STDEV
110 + /*
111 + * st_dev breaks on network filesystems where different
112 + * clients will have different views of what "device"
113 + * the filesystem is on
114 + */
115 + if (check_stat && sd->sd_dev != (unsigned int) st->st_dev)
116 + changed |= INODE_CHANGED;
117 +#endif
118 +
119 + if (sd->sd_size != (unsigned int) st->st_size)
120 + changed |= DATA_CHANGED;
121 +
122 + return changed;
123 +}
124 +
125 /*
126 * This only updates the "non-critical" parts of the directory
127 * cache, ie the parts that aren't tracked by GIT, and only used
@@ -74,15 +129,7 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
129 */
130 void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
131 {
77 - ce->ce_ctime.sec = (unsigned int)st->st_ctime;
78 - ce->ce_mtime.sec = (unsigned int)st->st_mtime;
79 - ce->ce_ctime.nsec = ST_CTIME_NSEC(*st);
80 - ce->ce_mtime.nsec = ST_MTIME_NSEC(*st);
81 - ce->ce_dev = st->st_dev;
82 - ce->ce_ino = st->st_ino;
83 - ce->ce_uid = st->st_uid;
84 - ce->ce_gid = st->st_gid;
85 - ce->ce_size = st->st_size;
132 + fill_stat_data(&ce->ce_stat_data, st);
133
134 if (assume_unchanged)
135 ce->ce_flags |= CE_VALID;
@@ -195,43 +242,11 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
242 default:
243 die("internal error: ce_mode is %o", ce->ce_mode);
244 }
198 - if (ce->ce_mtime.sec != (unsigned int)st->st_mtime)
199 - changed |= MTIME_CHANGED;
200 - if (trust_ctime && check_stat &&
201 - ce->ce_ctime.sec != (unsigned int)st->st_ctime)
202 - changed |= CTIME_CHANGED;
245
204 -#ifdef USE_NSEC
205 - if (check_stat && ce->ce_mtime.nsec != ST_MTIME_NSEC(*st))
206 - changed |= MTIME_CHANGED;
207 - if (trust_ctime && check_stat &&
208 - ce->ce_ctime.nsec != ST_CTIME_NSEC(*st))
209 - changed |= CTIME_CHANGED;
210 -#endif
211 -
212 - if (check_stat) {
213 - if (ce->ce_uid != (unsigned int) st->st_uid ||
214 - ce->ce_gid != (unsigned int) st->st_gid)
215 - changed |= OWNER_CHANGED;
216 - if (ce->ce_ino != (unsigned int) st->st_ino)
217 - changed |= INODE_CHANGED;
218 - }
219 -
220 -#ifdef USE_STDEV
221 - /*
222 - * st_dev breaks on network filesystems where different
223 - * clients will have different views of what "device"
224 - * the filesystem is on
225 - */
226 - if (check_stat && ce->ce_dev != (unsigned int) st->st_dev)
227 - changed |= INODE_CHANGED;
228 -#endif
229 -
230 - if (ce->ce_size != (unsigned int) st->st_size)
231 - changed |= DATA_CHANGED;
246 + changed |= match_stat_data(&ce->ce_stat_data, st);
247
248 /* Racily smudged entry? */
234 - if (!ce->ce_size) {
249 + if (!ce->ce_stat_data.sd_size) {
250 if (!is_empty_blob_sha1(ce->sha1))
251 changed |= DATA_CHANGED;
252 }
@@ -246,11 +261,11 @@ static int is_racy_timestamp(const struct index_state *istate,
261 istate->timestamp.sec &&
262 #ifdef USE_NSEC
263 /* nanosecond timestamped files can also be racy! */
249 - (istate->timestamp.sec < ce->ce_mtime.sec ||
250 - (istate->timestamp.sec == ce->ce_mtime.sec &&
251 - istate->timestamp.nsec <= ce->ce_mtime.nsec))
264 + (istate->timestamp.sec < ce->ce_stat_data.sd_mtime.sec ||
265 + (istate->timestamp.sec == ce->ce_stat_data.sd_mtime.sec &&
266 + istate->timestamp.nsec <= ce->ce_stat_data.sd_mtime.nsec))
267 #else
253 - istate->timestamp.sec <= ce->ce_mtime.sec
268 + istate->timestamp.sec <= ce->ce_stat_data.sd_mtime.sec
269 #endif
270 );
271 }
@@ -342,7 +357,7 @@ int ie_modified(const struct index_state *istate,
357 * then we know it is.
358 */
359 if ((changed & DATA_CHANGED) &&
345 - (S_ISGITLINK(ce->ce_mode) || ce->ce_size != 0))
360 + (S_ISGITLINK(ce->ce_mode) || ce->ce_stat_data.sd_size != 0))
361 return changed;
362
363 changed_fs = ce_modified_check_fs(ce, st);
@@ -1324,16 +1339,16 @@ static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *on
1339 {
1340 struct cache_entry *ce = xmalloc(cache_entry_size(len));
1341
1327 - ce->ce_ctime.sec = ntoh_l(ondisk->ctime.sec);
1328 - ce->ce_mtime.sec = ntoh_l(ondisk->mtime.sec);
1329 - ce->ce_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
1330 - ce->ce_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
1331 - ce->ce_dev = ntoh_l(ondisk->dev);
1332 - ce->ce_ino = ntoh_l(ondisk->ino);
1342 + ce->ce_stat_data.sd_ctime.sec = ntoh_l(ondisk->ctime.sec);
1343 + ce->ce_stat_data.sd_mtime.sec = ntoh_l(ondisk->mtime.sec);
1344 + ce->ce_stat_data.sd_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
1345 + ce->ce_stat_data.sd_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
1346 + ce->ce_stat_data.sd_dev = ntoh_l(ondisk->dev);
1347 + ce->ce_stat_data.sd_ino = ntoh_l(ondisk->ino);
1348 ce->ce_mode = ntoh_l(ondisk->mode);
1334 - ce->ce_uid = ntoh_l(ondisk->uid);
1335 - ce->ce_gid = ntoh_l(ondisk->gid);
1336 - ce->ce_size = ntoh_l(ondisk->size);
1349 + ce->ce_stat_data.sd_uid = ntoh_l(ondisk->uid);
1350 + ce->ce_stat_data.sd_gid = ntoh_l(ondisk->gid);
1351 + ce->ce_stat_data.sd_size = ntoh_l(ondisk->size);
1352 ce->ce_flags = flags & ~CE_NAMEMASK;
1353 ce->ce_namelen = len;
1354 hashcpy(ce->sha1, ondisk->sha1);
@@ -1610,7 +1625,7 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
1625 * The only thing we care about in this function is to smudge the
1626 * falsely clean entry due to touch-update-touch race, so we leave
1627 * everything else as they are. We are called for entries whose
1613 - * ce_mtime match the index file mtime.
1628 + * ce_stat_data.sd_mtime match the index file mtime.
1629 *
1630 * Note that this actually does not do much for gitlinks, for
1631 * which ce_match_stat_basic() always goes to the actual
@@ -1649,7 +1664,7 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
1664 * file, and never calls us, so the cached size information
1665 * for "frotz" stays 6 which does not match the filesystem.
1666 */
1652 - ce->ce_size = 0;
1667 + ce->ce_stat_data.sd_size = 0;
1668 }
1669 }
1670
@@ -1659,16 +1674,16 @@ static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
1674 {
1675 short flags;
1676
1662 - ondisk->ctime.sec = htonl(ce->ce_ctime.sec);
1663 - ondisk->mtime.sec = htonl(ce->ce_mtime.sec);
1664 - ondisk->ctime.nsec = htonl(ce->ce_ctime.nsec);
1665 - ondisk->mtime.nsec = htonl(ce->ce_mtime.nsec);
1666 - ondisk->dev = htonl(ce->ce_dev);
1667 - ondisk->ino = htonl(ce->ce_ino);
1677 + ondisk->ctime.sec = htonl(ce->ce_stat_data.sd_ctime.sec);
1678 + ondisk->mtime.sec = htonl(ce->ce_stat_data.sd_mtime.sec);
1679 + ondisk->ctime.nsec = htonl(ce->ce_stat_data.sd_ctime.nsec);
1680 + ondisk->mtime.nsec = htonl(ce->ce_stat_data.sd_mtime.nsec);
1681 + ondisk->dev = htonl(ce->ce_stat_data.sd_dev);
1682 + ondisk->ino = htonl(ce->ce_stat_data.sd_ino);
1683 ondisk->mode = htonl(ce->ce_mode);
1669 - ondisk->uid = htonl(ce->ce_uid);
1670 - ondisk->gid = htonl(ce->ce_gid);
1671 - ondisk->size = htonl(ce->ce_size);
1684 + ondisk->uid = htonl(ce->ce_stat_data.sd_uid);
1685 + ondisk->gid = htonl(ce->ce_stat_data.sd_gid);
1686 + ondisk->size = htonl(ce->ce_stat_data.sd_size);
1687 hashcpy(ondisk->sha1, ce->sha1);
1688
1689 flags = ce->ce_flags;