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:
Junio C Hamano
2008-02-11 16:46:20 -08:00
25 changed files with 568 additions and 298 deletions

69
cache.h
View File

@ -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 */