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>
This commit is contained in:

committed by
Junio C Hamano

parent
4f6b83e370
commit
c21d39d7c7
@ -165,11 +165,13 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
|
|||||||
}
|
}
|
||||||
write_name(ce->name, ce_namelen(ce));
|
write_name(ce->name, ce_namelen(ce));
|
||||||
if (debug_mode) {
|
if (debug_mode) {
|
||||||
printf(" ctime: %d:%d\n", ce->ce_ctime.sec, ce->ce_ctime.nsec);
|
struct stat_data *sd = &ce->ce_stat_data;
|
||||||
printf(" mtime: %d:%d\n", ce->ce_mtime.sec, ce->ce_mtime.nsec);
|
|
||||||
printf(" dev: %d\tino: %d\n", ce->ce_dev, ce->ce_ino);
|
printf(" ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
|
||||||
printf(" uid: %d\tgid: %d\n", ce->ce_uid, ce->ce_gid);
|
printf(" mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
|
||||||
printf(" size: %d\tflags: %x\n", ce->ce_size, ce->ce_flags);
|
printf(" dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino);
|
||||||
|
printf(" uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid);
|
||||||
|
printf(" size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
cache.h
33
cache.h
@ -119,15 +119,19 @@ struct cache_time {
|
|||||||
unsigned int nsec;
|
unsigned int nsec;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct stat_data {
|
||||||
|
struct cache_time sd_ctime;
|
||||||
|
struct cache_time sd_mtime;
|
||||||
|
unsigned int sd_dev;
|
||||||
|
unsigned int sd_ino;
|
||||||
|
unsigned int sd_uid;
|
||||||
|
unsigned int sd_gid;
|
||||||
|
unsigned int sd_size;
|
||||||
|
};
|
||||||
|
|
||||||
struct cache_entry {
|
struct cache_entry {
|
||||||
struct cache_time ce_ctime;
|
struct stat_data ce_stat_data;
|
||||||
struct cache_time ce_mtime;
|
|
||||||
unsigned int ce_dev;
|
|
||||||
unsigned int ce_ino;
|
|
||||||
unsigned int ce_mode;
|
unsigned int ce_mode;
|
||||||
unsigned int ce_uid;
|
|
||||||
unsigned int ce_gid;
|
|
||||||
unsigned int ce_size;
|
|
||||||
unsigned int ce_flags;
|
unsigned int ce_flags;
|
||||||
unsigned int ce_namelen;
|
unsigned int ce_namelen;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
@ -511,6 +515,21 @@ extern int limit_pathspec_to_literal(void);
|
|||||||
#define HASH_FORMAT_CHECK 2
|
#define HASH_FORMAT_CHECK 2
|
||||||
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
|
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
|
||||||
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, unsigned flags);
|
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, unsigned flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record to sd the data from st that we use to check whether a file
|
||||||
|
* might have changed.
|
||||||
|
*/
|
||||||
|
extern void fill_stat_data(struct stat_data *sd, struct stat *st);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 0 if st is consistent with a file not having been changed
|
||||||
|
* since sd was filled. If there are differences, return a
|
||||||
|
* combination of MTIME_CHANGED, CTIME_CHANGED, OWNER_CHANGED,
|
||||||
|
* INODE_CHANGED, and DATA_CHANGED.
|
||||||
|
*/
|
||||||
|
extern int match_stat_data(const struct stat_data *sd, struct stat *st);
|
||||||
|
|
||||||
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
|
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
|
||||||
|
|
||||||
#define REFRESH_REALLY 0x0001 /* ignore_valid */
|
#define REFRESH_REALLY 0x0001 /* ignore_valid */
|
||||||
|
151
read-cache.c
151
read-cache.c
@ -67,6 +67,61 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
|
|||||||
add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
|
add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fill_stat_data(struct stat_data *sd, struct stat *st)
|
||||||
|
{
|
||||||
|
sd->sd_ctime.sec = (unsigned int)st->st_ctime;
|
||||||
|
sd->sd_mtime.sec = (unsigned int)st->st_mtime;
|
||||||
|
sd->sd_ctime.nsec = ST_CTIME_NSEC(*st);
|
||||||
|
sd->sd_mtime.nsec = ST_MTIME_NSEC(*st);
|
||||||
|
sd->sd_dev = st->st_dev;
|
||||||
|
sd->sd_ino = st->st_ino;
|
||||||
|
sd->sd_uid = st->st_uid;
|
||||||
|
sd->sd_gid = st->st_gid;
|
||||||
|
sd->sd_size = st->st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int match_stat_data(const struct stat_data *sd, struct stat *st)
|
||||||
|
{
|
||||||
|
int changed = 0;
|
||||||
|
|
||||||
|
if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
|
||||||
|
changed |= MTIME_CHANGED;
|
||||||
|
if (trust_ctime && check_stat &&
|
||||||
|
sd->sd_ctime.sec != (unsigned int)st->st_ctime)
|
||||||
|
changed |= CTIME_CHANGED;
|
||||||
|
|
||||||
|
#ifdef USE_NSEC
|
||||||
|
if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
|
||||||
|
changed |= MTIME_CHANGED;
|
||||||
|
if (trust_ctime && check_stat &&
|
||||||
|
sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
|
||||||
|
changed |= CTIME_CHANGED;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (check_stat) {
|
||||||
|
if (sd->sd_uid != (unsigned int) st->st_uid ||
|
||||||
|
sd->sd_gid != (unsigned int) st->st_gid)
|
||||||
|
changed |= OWNER_CHANGED;
|
||||||
|
if (sd->sd_ino != (unsigned int) st->st_ino)
|
||||||
|
changed |= INODE_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_STDEV
|
||||||
|
/*
|
||||||
|
* st_dev breaks on network filesystems where different
|
||||||
|
* clients will have different views of what "device"
|
||||||
|
* the filesystem is on
|
||||||
|
*/
|
||||||
|
if (check_stat && sd->sd_dev != (unsigned int) st->st_dev)
|
||||||
|
changed |= INODE_CHANGED;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sd->sd_size != (unsigned int) st->st_size)
|
||||||
|
changed |= DATA_CHANGED;
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This only updates the "non-critical" parts of the directory
|
* This only updates the "non-critical" parts of the directory
|
||||||
* cache, ie the parts that aren't tracked by GIT, and only used
|
* 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
|
|||||||
*/
|
*/
|
||||||
void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
|
void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
|
||||||
{
|
{
|
||||||
ce->ce_ctime.sec = (unsigned int)st->st_ctime;
|
fill_stat_data(&ce->ce_stat_data, st);
|
||||||
ce->ce_mtime.sec = (unsigned int)st->st_mtime;
|
|
||||||
ce->ce_ctime.nsec = ST_CTIME_NSEC(*st);
|
|
||||||
ce->ce_mtime.nsec = ST_MTIME_NSEC(*st);
|
|
||||||
ce->ce_dev = st->st_dev;
|
|
||||||
ce->ce_ino = st->st_ino;
|
|
||||||
ce->ce_uid = st->st_uid;
|
|
||||||
ce->ce_gid = st->st_gid;
|
|
||||||
ce->ce_size = st->st_size;
|
|
||||||
|
|
||||||
if (assume_unchanged)
|
if (assume_unchanged)
|
||||||
ce->ce_flags |= CE_VALID;
|
ce->ce_flags |= CE_VALID;
|
||||||
@ -195,43 +242,11 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
|
|||||||
default:
|
default:
|
||||||
die("internal error: ce_mode is %o", ce->ce_mode);
|
die("internal error: ce_mode is %o", ce->ce_mode);
|
||||||
}
|
}
|
||||||
if (ce->ce_mtime.sec != (unsigned int)st->st_mtime)
|
|
||||||
changed |= MTIME_CHANGED;
|
|
||||||
if (trust_ctime && check_stat &&
|
|
||||||
ce->ce_ctime.sec != (unsigned int)st->st_ctime)
|
|
||||||
changed |= CTIME_CHANGED;
|
|
||||||
|
|
||||||
#ifdef USE_NSEC
|
changed |= match_stat_data(&ce->ce_stat_data, st);
|
||||||
if (check_stat && ce->ce_mtime.nsec != ST_MTIME_NSEC(*st))
|
|
||||||
changed |= MTIME_CHANGED;
|
|
||||||
if (trust_ctime && check_stat &&
|
|
||||||
ce->ce_ctime.nsec != ST_CTIME_NSEC(*st))
|
|
||||||
changed |= CTIME_CHANGED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (check_stat) {
|
|
||||||
if (ce->ce_uid != (unsigned int) st->st_uid ||
|
|
||||||
ce->ce_gid != (unsigned int) st->st_gid)
|
|
||||||
changed |= OWNER_CHANGED;
|
|
||||||
if (ce->ce_ino != (unsigned int) st->st_ino)
|
|
||||||
changed |= INODE_CHANGED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_STDEV
|
|
||||||
/*
|
|
||||||
* st_dev breaks on network filesystems where different
|
|
||||||
* clients will have different views of what "device"
|
|
||||||
* the filesystem is on
|
|
||||||
*/
|
|
||||||
if (check_stat && ce->ce_dev != (unsigned int) st->st_dev)
|
|
||||||
changed |= INODE_CHANGED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ce->ce_size != (unsigned int) st->st_size)
|
|
||||||
changed |= DATA_CHANGED;
|
|
||||||
|
|
||||||
/* Racily smudged entry? */
|
/* Racily smudged entry? */
|
||||||
if (!ce->ce_size) {
|
if (!ce->ce_stat_data.sd_size) {
|
||||||
if (!is_empty_blob_sha1(ce->sha1))
|
if (!is_empty_blob_sha1(ce->sha1))
|
||||||
changed |= DATA_CHANGED;
|
changed |= DATA_CHANGED;
|
||||||
}
|
}
|
||||||
@ -246,11 +261,11 @@ static int is_racy_timestamp(const struct index_state *istate,
|
|||||||
istate->timestamp.sec &&
|
istate->timestamp.sec &&
|
||||||
#ifdef USE_NSEC
|
#ifdef USE_NSEC
|
||||||
/* nanosecond timestamped files can also be racy! */
|
/* nanosecond timestamped files can also be racy! */
|
||||||
(istate->timestamp.sec < ce->ce_mtime.sec ||
|
(istate->timestamp.sec < ce->ce_stat_data.sd_mtime.sec ||
|
||||||
(istate->timestamp.sec == ce->ce_mtime.sec &&
|
(istate->timestamp.sec == ce->ce_stat_data.sd_mtime.sec &&
|
||||||
istate->timestamp.nsec <= ce->ce_mtime.nsec))
|
istate->timestamp.nsec <= ce->ce_stat_data.sd_mtime.nsec))
|
||||||
#else
|
#else
|
||||||
istate->timestamp.sec <= ce->ce_mtime.sec
|
istate->timestamp.sec <= ce->ce_stat_data.sd_mtime.sec
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -342,7 +357,7 @@ int ie_modified(const struct index_state *istate,
|
|||||||
* then we know it is.
|
* then we know it is.
|
||||||
*/
|
*/
|
||||||
if ((changed & DATA_CHANGED) &&
|
if ((changed & DATA_CHANGED) &&
|
||||||
(S_ISGITLINK(ce->ce_mode) || ce->ce_size != 0))
|
(S_ISGITLINK(ce->ce_mode) || ce->ce_stat_data.sd_size != 0))
|
||||||
return changed;
|
return changed;
|
||||||
|
|
||||||
changed_fs = ce_modified_check_fs(ce, st);
|
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
|
|||||||
{
|
{
|
||||||
struct cache_entry *ce = xmalloc(cache_entry_size(len));
|
struct cache_entry *ce = xmalloc(cache_entry_size(len));
|
||||||
|
|
||||||
ce->ce_ctime.sec = ntoh_l(ondisk->ctime.sec);
|
ce->ce_stat_data.sd_ctime.sec = ntoh_l(ondisk->ctime.sec);
|
||||||
ce->ce_mtime.sec = ntoh_l(ondisk->mtime.sec);
|
ce->ce_stat_data.sd_mtime.sec = ntoh_l(ondisk->mtime.sec);
|
||||||
ce->ce_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
|
ce->ce_stat_data.sd_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
|
||||||
ce->ce_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
|
ce->ce_stat_data.sd_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
|
||||||
ce->ce_dev = ntoh_l(ondisk->dev);
|
ce->ce_stat_data.sd_dev = ntoh_l(ondisk->dev);
|
||||||
ce->ce_ino = ntoh_l(ondisk->ino);
|
ce->ce_stat_data.sd_ino = ntoh_l(ondisk->ino);
|
||||||
ce->ce_mode = ntoh_l(ondisk->mode);
|
ce->ce_mode = ntoh_l(ondisk->mode);
|
||||||
ce->ce_uid = ntoh_l(ondisk->uid);
|
ce->ce_stat_data.sd_uid = ntoh_l(ondisk->uid);
|
||||||
ce->ce_gid = ntoh_l(ondisk->gid);
|
ce->ce_stat_data.sd_gid = ntoh_l(ondisk->gid);
|
||||||
ce->ce_size = ntoh_l(ondisk->size);
|
ce->ce_stat_data.sd_size = ntoh_l(ondisk->size);
|
||||||
ce->ce_flags = flags & ~CE_NAMEMASK;
|
ce->ce_flags = flags & ~CE_NAMEMASK;
|
||||||
ce->ce_namelen = len;
|
ce->ce_namelen = len;
|
||||||
hashcpy(ce->sha1, ondisk->sha1);
|
hashcpy(ce->sha1, ondisk->sha1);
|
||||||
@ -1610,7 +1625,7 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
|
|||||||
* The only thing we care about in this function is to smudge the
|
* The only thing we care about in this function is to smudge the
|
||||||
* falsely clean entry due to touch-update-touch race, so we leave
|
* falsely clean entry due to touch-update-touch race, so we leave
|
||||||
* everything else as they are. We are called for entries whose
|
* everything else as they are. We are called for entries whose
|
||||||
* ce_mtime match the index file mtime.
|
* ce_stat_data.sd_mtime match the index file mtime.
|
||||||
*
|
*
|
||||||
* Note that this actually does not do much for gitlinks, for
|
* Note that this actually does not do much for gitlinks, for
|
||||||
* which ce_match_stat_basic() always goes to the actual
|
* 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)
|
|||||||
* file, and never calls us, so the cached size information
|
* file, and never calls us, so the cached size information
|
||||||
* for "frotz" stays 6 which does not match the filesystem.
|
* for "frotz" stays 6 which does not match the filesystem.
|
||||||
*/
|
*/
|
||||||
ce->ce_size = 0;
|
ce->ce_stat_data.sd_size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1659,16 +1674,16 @@ static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
|
|||||||
{
|
{
|
||||||
short flags;
|
short flags;
|
||||||
|
|
||||||
ondisk->ctime.sec = htonl(ce->ce_ctime.sec);
|
ondisk->ctime.sec = htonl(ce->ce_stat_data.sd_ctime.sec);
|
||||||
ondisk->mtime.sec = htonl(ce->ce_mtime.sec);
|
ondisk->mtime.sec = htonl(ce->ce_stat_data.sd_mtime.sec);
|
||||||
ondisk->ctime.nsec = htonl(ce->ce_ctime.nsec);
|
ondisk->ctime.nsec = htonl(ce->ce_stat_data.sd_ctime.nsec);
|
||||||
ondisk->mtime.nsec = htonl(ce->ce_mtime.nsec);
|
ondisk->mtime.nsec = htonl(ce->ce_stat_data.sd_mtime.nsec);
|
||||||
ondisk->dev = htonl(ce->ce_dev);
|
ondisk->dev = htonl(ce->ce_stat_data.sd_dev);
|
||||||
ondisk->ino = htonl(ce->ce_ino);
|
ondisk->ino = htonl(ce->ce_stat_data.sd_ino);
|
||||||
ondisk->mode = htonl(ce->ce_mode);
|
ondisk->mode = htonl(ce->ce_mode);
|
||||||
ondisk->uid = htonl(ce->ce_uid);
|
ondisk->uid = htonl(ce->ce_stat_data.sd_uid);
|
||||||
ondisk->gid = htonl(ce->ce_gid);
|
ondisk->gid = htonl(ce->ce_stat_data.sd_gid);
|
||||||
ondisk->size = htonl(ce->ce_size);
|
ondisk->size = htonl(ce->ce_stat_data.sd_size);
|
||||||
hashcpy(ondisk->sha1, ce->sha1);
|
hashcpy(ondisk->sha1, ce->sha1);
|
||||||
|
|
||||||
flags = ce->ce_flags;
|
flags = ce->ce_flags;
|
||||||
|
Reference in New Issue
Block a user