statinfo: move stat_{data,validity} functions from cache/read-cache

These functions do not depend upon struct cache_entry or struct index_state in any way, and it seems more logical to break them out into this file, especially since statinfo.h already has the struct stat_data declaration. Diff best viewed with `--color-moved`. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed May 16, 2023 at 06:33 UTC 90cbae9ce5d22df29867be9026c514b8c79e3d31
8 files changed +142 -132
Makefile
+1
@@ -1142,6 +1142,7 @@ LIB_OBJS += sigchain.o
1142 LIB_OBJS += sparse-index.o
1143 LIB_OBJS += split-index.o
1144 LIB_OBJS += stable-qsort.o
1145 +LIB_OBJS += statinfo.o
1146 LIB_OBJS += strbuf.o
1147 LIB_OBJS += streaming.o
1148 LIB_OBJS += string-list.o
cache.h
-48
@@ -488,19 +488,6 @@ int has_racy_timestamp(struct index_state *istate);
488 int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
489 int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
490
491 -/*
492 - * Record to sd the data from st that we use to check whether a file
493 - * might have changed.
494 - */
495 -void fill_stat_data(struct stat_data *sd, struct stat *st);
496 -
497 -/*
498 - * Return 0 if st is consistent with a file not having been changed
499 - * since sd was filled. If there are differences, return a
500 - * combination of MTIME_CHANGED, CTIME_CHANGED, OWNER_CHANGED,
501 - * INODE_CHANGED, and DATA_CHANGED.
502 - */
503 -int match_stat_data(const struct stat_data *sd, struct stat *st);
491 int match_stat_data_racy(const struct index_state *istate,
492 const struct stat_data *sd, struct stat *st);
493
@@ -539,14 +526,6 @@ void set_alternate_index_output(const char *);
526 extern int verify_index_checksum;
527 extern int verify_ce_order;
528
542 -#define MTIME_CHANGED 0x0001
543 -#define CTIME_CHANGED 0x0002
544 -#define OWNER_CHANGED 0x0004
545 -#define MODE_CHANGED 0x0008
546 -#define INODE_CHANGED 0x0010
547 -#define DATA_CHANGED 0x0020
548 -#define TYPE_CHANGED 0x0040
549 -
529 int cmp_cache_name_compare(const void *a_, const void *b_);
530
531 /* add */
@@ -579,31 +558,4 @@ int checkout_fast_forward(struct repository *r,
558
559 int sane_execvp(const char *file, char *const argv[]);
560
582 -/*
583 - * A struct to encapsulate the concept of whether a file has changed
584 - * since we last checked it. This uses criteria similar to those used
585 - * for the index.
586 - */
587 -struct stat_validity {
588 - struct stat_data *sd;
589 -};
590 -
591 -void stat_validity_clear(struct stat_validity *sv);
592 -
593 -/*
594 - * Returns 1 if the path is a regular file (or a symlink to a regular
595 - * file) and matches the saved stat_validity, 0 otherwise. A missing
596 - * or inaccessible file is considered a match if the struct was just
597 - * initialized, or if the previous update found an inaccessible file.
598 - */
599 -int stat_validity_check(struct stat_validity *sv, const char *path);
600 -
601 -/*
602 - * Update the stat_validity from a file opened at descriptor fd. If
603 - * the file is missing, inaccessible, or not a regular file, then
604 - * future calls to stat_validity_check will match iff one of those
605 - * conditions continues to be true.
606 - */
607 -void stat_validity_update(struct stat_validity *sv, int fd);
608 -
561 #endif /* CACHE_H */
object.c
+1
@@ -6,6 +6,7 @@
6 #include "object-file.h"
7 #include "object-store.h"
8 #include "blob.h"
9 +#include "statinfo.h"
10 #include "tree.h"
11 #include "commit.h"
12 #include "tag.h"
read-cache.c
-84
@@ -177,61 +177,6 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
177 add_index_entry(istate, new_entry, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
178 }
179
180 -void fill_stat_data(struct stat_data *sd, struct stat *st)
181 -{
182 - sd->sd_ctime.sec = (unsigned int)st->st_ctime;
183 - sd->sd_mtime.sec = (unsigned int)st->st_mtime;
184 - sd->sd_ctime.nsec = ST_CTIME_NSEC(*st);
185 - sd->sd_mtime.nsec = ST_MTIME_NSEC(*st);
186 - sd->sd_dev = st->st_dev;
187 - sd->sd_ino = st->st_ino;
188 - sd->sd_uid = st->st_uid;
189 - sd->sd_gid = st->st_gid;
190 - sd->sd_size = st->st_size;
191 -}
192 -
193 -int match_stat_data(const struct stat_data *sd, struct stat *st)
194 -{
195 - int changed = 0;
196 -
197 - if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
198 - changed |= MTIME_CHANGED;
199 - if (trust_ctime && check_stat &&
200 - sd->sd_ctime.sec != (unsigned int)st->st_ctime)
201 - changed |= CTIME_CHANGED;
202 -
203 -#ifdef USE_NSEC
204 - if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
205 - changed |= MTIME_CHANGED;
206 - if (trust_ctime && check_stat &&
207 - sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
208 - changed |= CTIME_CHANGED;
209 -#endif
210 -
211 - if (check_stat) {
212 - if (sd->sd_uid != (unsigned int) st->st_uid ||
213 - sd->sd_gid != (unsigned int) st->st_gid)
214 - changed |= OWNER_CHANGED;
215 - if (sd->sd_ino != (unsigned int) st->st_ino)
216 - changed |= INODE_CHANGED;
217 - }
218 -
219 -#ifdef USE_STDEV
220 - /*
221 - * st_dev breaks on network filesystems where different
222 - * clients will have different views of what "device"
223 - * the filesystem is on
224 - */
225 - if (check_stat && sd->sd_dev != (unsigned int) st->st_dev)
226 - changed |= INODE_CHANGED;
227 -#endif
228 -
229 - if (sd->sd_size != (unsigned int) st->st_size)
230 - changed |= DATA_CHANGED;
231 -
232 - return changed;
233 -}
234 -
180 /*
181 * This only updates the "non-critical" parts of the directory
182 * cache, ie the parts that aren't tracked by GIT, and only used
@@ -3536,35 +3481,6 @@ void *read_blob_data_from_index(struct index_state *istate,
3481 return data;
3482 }
3483
3539 -void stat_validity_clear(struct stat_validity *sv)
3540 -{
3541 - FREE_AND_NULL(sv->sd);
3542 -}
3543 -
3544 -int stat_validity_check(struct stat_validity *sv, const char *path)
3545 -{
3546 - struct stat st;
3547 -
3548 - if (stat(path, &st) < 0)
3549 - return sv->sd == NULL;
3550 - if (!sv->sd)
3551 - return 0;
3552 - return S_ISREG(st.st_mode) && !match_stat_data(sv->sd, &st);
3553 -}
3554 -
3555 -void stat_validity_update(struct stat_validity *sv, int fd)
3556 -{
3557 - struct stat st;
3558 -
3559 - if (fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))
3560 - stat_validity_clear(sv);
3561 - else {
3562 - if (!sv->sd)
3563 - CALLOC_ARRAY(sv->sd, 1);
3564 - fill_stat_data(sv->sd, &st);
3565 - }
3566 -}
3567 -
3484 void move_index_extensions(struct index_state *dst, struct index_state *src)
3485 {
3486 dst->untracked = src->untracked;
refs/packed-backend.c
+1
@@ -10,6 +10,7 @@
10 #include "../iterator.h"
11 #include "../lockfile.h"
12 #include "../chdir-notify.h"
13 +#include "../statinfo.h"
14 #include "../wrapper.h"
15 #include "../write-or-die.h"
16
shallow.c
+1
@@ -17,6 +17,7 @@
17 #include "list-objects.h"
18 #include "commit-reach.h"
19 #include "shallow.h"
20 +#include "statinfo.h"
21 #include "trace.h"
22 #include "wrapper.h"
23
statinfo.c new
+87
@@ -0,0 +1,87 @@
1 +#include "git-compat-util.h"
2 +#include "environment.h"
3 +#include "statinfo.h"
4 +
5 +void fill_stat_data(struct stat_data *sd, struct stat *st)
6 +{
7 + sd->sd_ctime.sec = (unsigned int)st->st_ctime;
8 + sd->sd_mtime.sec = (unsigned int)st->st_mtime;
9 + sd->sd_ctime.nsec = ST_CTIME_NSEC(*st);
10 + sd->sd_mtime.nsec = ST_MTIME_NSEC(*st);
11 + sd->sd_dev = st->st_dev;
12 + sd->sd_ino = st->st_ino;
13 + sd->sd_uid = st->st_uid;
14 + sd->sd_gid = st->st_gid;
15 + sd->sd_size = st->st_size;
16 +}
17 +
18 +int match_stat_data(const struct stat_data *sd, struct stat *st)
19 +{
20 + int changed = 0;
21 +
22 + if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
23 + changed |= MTIME_CHANGED;
24 + if (trust_ctime && check_stat &&
25 + sd->sd_ctime.sec != (unsigned int)st->st_ctime)
26 + changed |= CTIME_CHANGED;
27 +
28 +#ifdef USE_NSEC
29 + if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
30 + changed |= MTIME_CHANGED;
31 + if (trust_ctime && check_stat &&
32 + sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
33 + changed |= CTIME_CHANGED;
34 +#endif
35 +
36 + if (check_stat) {
37 + if (sd->sd_uid != (unsigned int) st->st_uid ||
38 + sd->sd_gid != (unsigned int) st->st_gid)
39 + changed |= OWNER_CHANGED;
40 + if (sd->sd_ino != (unsigned int) st->st_ino)
41 + changed |= INODE_CHANGED;
42 + }
43 +
44 +#ifdef USE_STDEV
45 + /*
46 + * st_dev breaks on network filesystems where different
47 + * clients will have different views of what "device"
48 + * the filesystem is on
49 + */
50 + if (check_stat && sd->sd_dev != (unsigned int) st->st_dev)
51 + changed |= INODE_CHANGED;
52 +#endif
53 +
54 + if (sd->sd_size != (unsigned int) st->st_size)
55 + changed |= DATA_CHANGED;
56 +
57 + return changed;
58 +}
59 +
60 +void stat_validity_clear(struct stat_validity *sv)
61 +{
62 + FREE_AND_NULL(sv->sd);
63 +}
64 +
65 +int stat_validity_check(struct stat_validity *sv, const char *path)
66 +{
67 + struct stat st;
68 +
69 + if (stat(path, &st) < 0)
70 + return sv->sd == NULL;
71 + if (!sv->sd)
72 + return 0;
73 + return S_ISREG(st.st_mode) && !match_stat_data(sv->sd, &st);
74 +}
75 +
76 +void stat_validity_update(struct stat_validity *sv, int fd)
77 +{
78 + struct stat st;
79 +
80 + if (fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))
81 + stat_validity_clear(sv);
82 + else {
83 + if (!sv->sd)
84 + CALLOC_ARRAY(sv->sd, 1);
85 + fill_stat_data(sv->sd, &st);
86 + }
87 +}
statinfo.h
+51
@@ -1,6 +1,8 @@
1 #ifndef STATINFO_H
2 #define STATINFO_H
3
4 +struct index_state;
5 +
6 /*
7 * The "cache_time" is just the low 32 bits of the
8 * time. It doesn't matter if it overflows - we only
@@ -21,4 +23,53 @@ struct stat_data {
23 unsigned int sd_size;
24 };
25
26 +/*
27 + * A struct to encapsulate the concept of whether a file has changed
28 + * since we last checked it. This uses criteria similar to those used
29 + * for the index.
30 + */
31 +struct stat_validity {
32 + struct stat_data *sd;
33 +};
34 +
35 +#define MTIME_CHANGED 0x0001
36 +#define CTIME_CHANGED 0x0002
37 +#define OWNER_CHANGED 0x0004
38 +#define MODE_CHANGED 0x0008
39 +#define INODE_CHANGED 0x0010
40 +#define DATA_CHANGED 0x0020
41 +#define TYPE_CHANGED 0x0040
42 +
43 +/*
44 + * Record to sd the data from st that we use to check whether a file
45 + * might have changed.
46 + */
47 +void fill_stat_data(struct stat_data *sd, struct stat *st);
48 +
49 +/*
50 + * Return 0 if st is consistent with a file not having been changed
51 + * since sd was filled. If there are differences, return a
52 + * combination of MTIME_CHANGED, CTIME_CHANGED, OWNER_CHANGED,
53 + * INODE_CHANGED, and DATA_CHANGED.
54 + */
55 +int match_stat_data(const struct stat_data *sd, struct stat *st);
56 +
57 +void stat_validity_clear(struct stat_validity *sv);
58 +
59 +/*
60 + * Returns 1 if the path is a regular file (or a symlink to a regular
61 + * file) and matches the saved stat_validity, 0 otherwise. A missing
62 + * or inaccessible file is considered a match if the struct was just
63 + * initialized, or if the previous update found an inaccessible file.
64 + */
65 +int stat_validity_check(struct stat_validity *sv, const char *path);
66 +
67 +/*
68 + * Update the stat_validity from a file opened at descriptor fd. If
69 + * the file is missing, inaccessible, or not a regular file, then
70 + * future calls to stat_validity_check will match iff one of those
71 + * conditions continues to be true.
72 + */
73 +void stat_validity_update(struct stat_validity *sv, int fd);
74 +
75 #endif