Merge branch 'lt/in-core-index'
* lt/in-core-index: lazy index hashing Create pathname-based hash-table lookup into index read-cache.c: introduce is_racy_timestamp() helper read-cache.c: fix a couple more CE_REMOVE conversion Also use unpack_trees() in do_diff_cache() Make run_diff_index() use unpack_trees(), not read_tree() Avoid running lstat(2) on the same cache entry. index: be careful when handling long names Make on-disk index representation separate from in-core one
This commit is contained in:
69
cache.h
69
cache.h
@ -3,6 +3,7 @@
|
||||
|
||||
#include "git-compat-util.h"
|
||||
#include "strbuf.h"
|
||||
#include "hash.h"
|
||||
|
||||
#include SHA1_HEADER
|
||||
#include <zlib.h>
|
||||
@ -94,48 +95,84 @@ struct cache_time {
|
||||
* We save the fields in big-endian order to allow using the
|
||||
* index file over NFS transparently.
|
||||
*/
|
||||
struct ondisk_cache_entry {
|
||||
struct cache_time ctime;
|
||||
struct cache_time mtime;
|
||||
unsigned int dev;
|
||||
unsigned int ino;
|
||||
unsigned int mode;
|
||||
unsigned int uid;
|
||||
unsigned int gid;
|
||||
unsigned int size;
|
||||
unsigned char sha1[20];
|
||||
unsigned short flags;
|
||||
char name[FLEX_ARRAY]; /* more */
|
||||
};
|
||||
|
||||
struct cache_entry {
|
||||
struct cache_time ce_ctime;
|
||||
struct cache_time ce_mtime;
|
||||
struct cache_entry *next;
|
||||
unsigned int ce_ctime;
|
||||
unsigned int ce_mtime;
|
||||
unsigned int ce_dev;
|
||||
unsigned int ce_ino;
|
||||
unsigned int ce_mode;
|
||||
unsigned int ce_uid;
|
||||
unsigned int ce_gid;
|
||||
unsigned int ce_size;
|
||||
unsigned int ce_flags;
|
||||
unsigned char sha1[20];
|
||||
unsigned short ce_flags;
|
||||
char name[FLEX_ARRAY]; /* more */
|
||||
};
|
||||
|
||||
#define CE_NAMEMASK (0x0fff)
|
||||
#define CE_STAGEMASK (0x3000)
|
||||
#define CE_UPDATE (0x4000)
|
||||
#define CE_VALID (0x8000)
|
||||
#define CE_STAGESHIFT 12
|
||||
|
||||
#define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT))
|
||||
#define ce_namelen(ce) (CE_NAMEMASK & ntohs((ce)->ce_flags))
|
||||
/* In-memory only */
|
||||
#define CE_UPDATE (0x10000)
|
||||
#define CE_REMOVE (0x20000)
|
||||
#define CE_UPTODATE (0x40000)
|
||||
#define CE_UNHASHED (0x80000)
|
||||
|
||||
static inline unsigned create_ce_flags(size_t len, unsigned stage)
|
||||
{
|
||||
if (len >= CE_NAMEMASK)
|
||||
len = CE_NAMEMASK;
|
||||
return (len | (stage << CE_STAGESHIFT));
|
||||
}
|
||||
|
||||
static inline size_t ce_namelen(const struct cache_entry *ce)
|
||||
{
|
||||
size_t len = ce->ce_flags & CE_NAMEMASK;
|
||||
if (len < CE_NAMEMASK)
|
||||
return len;
|
||||
return strlen(ce->name + CE_NAMEMASK) + CE_NAMEMASK;
|
||||
}
|
||||
|
||||
#define ce_size(ce) cache_entry_size(ce_namelen(ce))
|
||||
#define ce_stage(ce) ((CE_STAGEMASK & ntohs((ce)->ce_flags)) >> CE_STAGESHIFT)
|
||||
#define ondisk_ce_size(ce) ondisk_cache_entry_size(ce_namelen(ce))
|
||||
#define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT)
|
||||
#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
|
||||
#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
|
||||
|
||||
#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
|
||||
static inline unsigned int create_ce_mode(unsigned int mode)
|
||||
{
|
||||
if (S_ISLNK(mode))
|
||||
return htonl(S_IFLNK);
|
||||
return S_IFLNK;
|
||||
if (S_ISDIR(mode) || S_ISGITLINK(mode))
|
||||
return htonl(S_IFGITLINK);
|
||||
return htonl(S_IFREG | ce_permissions(mode));
|
||||
return S_IFGITLINK;
|
||||
return S_IFREG | ce_permissions(mode);
|
||||
}
|
||||
static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode)
|
||||
{
|
||||
extern int trust_executable_bit, has_symlinks;
|
||||
if (!has_symlinks && S_ISREG(mode) &&
|
||||
ce && S_ISLNK(ntohl(ce->ce_mode)))
|
||||
ce && S_ISLNK(ce->ce_mode))
|
||||
return ce->ce_mode;
|
||||
if (!trust_executable_bit && S_ISREG(mode)) {
|
||||
if (ce && S_ISREG(ntohl(ce->ce_mode)))
|
||||
if (ce && S_ISREG(ce->ce_mode))
|
||||
return ce->ce_mode;
|
||||
return create_ce_mode(0666);
|
||||
}
|
||||
@ -146,14 +183,16 @@ static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned in
|
||||
S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK)
|
||||
|
||||
#define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)
|
||||
#define ondisk_cache_entry_size(len) ((offsetof(struct ondisk_cache_entry,name) + (len) + 8) & ~7)
|
||||
|
||||
struct index_state {
|
||||
struct cache_entry **cache;
|
||||
unsigned int cache_nr, cache_alloc, cache_changed;
|
||||
struct cache_tree *cache_tree;
|
||||
time_t timestamp;
|
||||
void *mmap;
|
||||
size_t mmap_size;
|
||||
void *alloc;
|
||||
unsigned name_hash_initialized : 1;
|
||||
struct hash_table name_hash;
|
||||
};
|
||||
|
||||
extern struct index_state the_index;
|
||||
@ -177,6 +216,7 @@ extern struct index_state the_index;
|
||||
#define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)
|
||||
#define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
|
||||
#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
|
||||
#define cache_name_exists(name, namelen) index_name_exists(&the_index, (name), (namelen))
|
||||
#endif
|
||||
|
||||
enum object_type {
|
||||
@ -263,6 +303,7 @@ extern int read_index_from(struct index_state *, const char *path);
|
||||
extern int write_index(struct index_state *, int newfd);
|
||||
extern int discard_index(struct index_state *);
|
||||
extern int verify_path(const char *path);
|
||||
extern int index_name_exists(struct index_state *istate, const char *name, int namelen);
|
||||
extern int index_name_pos(struct index_state *, const char *name, int namelen);
|
||||
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
|
||||
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
|
||||
|
||||
Reference in New Issue
Block a user