Skip to content

Commit

Permalink
Merge branch 'lt/in-core-index'
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Junio C Hamano committed Feb 12, 2008
2 parents 3960a95 + 9cb76b8 commit e0197c9
Show file tree
Hide file tree
Showing 25 changed files with 566 additions and 296 deletions.
10 changes: 5 additions & 5 deletions builtin-apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -1946,7 +1946,7 @@ static int read_file_or_gitlink(struct cache_entry *ce, struct strbuf *buf)
if (!ce)
return 0;

if (S_ISGITLINK(ntohl(ce->ce_mode))) {
if (S_ISGITLINK(ce->ce_mode)) {
strbuf_grow(buf, 100);
strbuf_addf(buf, "Subproject commit %s\n", sha1_to_hex(ce->sha1));
} else {
Expand Down Expand Up @@ -2023,7 +2023,7 @@ static int check_to_create_blob(const char *new_name, int ok_if_exists)

static int verify_index_match(struct cache_entry *ce, struct stat *st)
{
if (S_ISGITLINK(ntohl(ce->ce_mode))) {
if (S_ISGITLINK(ce->ce_mode)) {
if (!S_ISDIR(st->st_mode))
return -1;
return 0;
Expand Down Expand Up @@ -2082,12 +2082,12 @@ static int check_patch(struct patch *patch, struct patch *prev_patch)
return error("%s: does not match index",
old_name);
if (cached)
st_mode = ntohl(ce->ce_mode);
st_mode = ce->ce_mode;
} else if (stat_ret < 0)
return error("%s: %s", old_name, strerror(errno));

if (!cached)
st_mode = ntohl(ce_mode_from_stat(ce, st.st_mode));
st_mode = ce_mode_from_stat(ce, st.st_mode);

if (patch->is_new < 0)
patch->is_new = 0;
Expand Down Expand Up @@ -2388,7 +2388,7 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
ce = xcalloc(1, ce_size);
memcpy(ce->name, path, namelen);
ce->ce_mode = create_ce_mode(mode);
ce->ce_flags = htons(namelen);
ce->ce_flags = namelen;
if (S_ISGITLINK(mode)) {
const char *s = buf;

Expand Down
2 changes: 1 addition & 1 deletion builtin-blame.c
Original file line number Diff line number Diff line change
Expand Up @@ -2092,7 +2092,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
if (!mode) {
int pos = cache_name_pos(path, len);
if (0 <= pos)
mode = ntohl(active_cache[pos]->ce_mode);
mode = active_cache[pos]->ce_mode;
else
/* Let's not bother reading from HEAD tree */
mode = S_IFREG | 0644;
Expand Down
2 changes: 1 addition & 1 deletion builtin-commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ static int list_paths(struct path_list *list, const char *with_tree,

for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
if (ce->ce_flags & htons(CE_UPDATE))
if (ce->ce_flags & CE_UPDATE)
continue;
if (!pathspec_match(pattern, m, ce->name, 0))
continue;
Expand Down
2 changes: 1 addition & 1 deletion builtin-fsck.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
struct blob *blob;
struct object *obj;

mode = ntohl(active_cache[i]->ce_mode);
mode = active_cache[i]->ce_mode;
if (S_ISGITLINK(mode))
continue;
blob = lookup_blob(active_cache[i]->sha1);
Expand Down
4 changes: 2 additions & 2 deletions builtin-grep.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
struct cache_entry *ce = active_cache[i];
char *name;
int kept;
if (!S_ISREG(ntohl(ce->ce_mode)))
if (!S_ISREG(ce->ce_mode))
continue;
if (!pathspec_matches(paths, ce->name))
continue;
Expand Down Expand Up @@ -387,7 +387,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)

for (nr = 0; nr < active_nr; nr++) {
struct cache_entry *ce = active_cache[nr];
if (!S_ISREG(ntohl(ce->ce_mode)))
if (!S_ISREG(ce->ce_mode))
continue;
if (!pathspec_matches(paths, ce->name))
continue;
Expand Down
10 changes: 5 additions & 5 deletions builtin-ls-files.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
return;

if (tag && *tag && show_valid_bit &&
(ce->ce_flags & htons(CE_VALID))) {
(ce->ce_flags & CE_VALID)) {
static char alttag[4];
memcpy(alttag, tag, 3);
if (isalpha(tag[0]))
Expand All @@ -210,7 +210,7 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
} else {
printf("%s%06o %s %d\t",
tag,
ntohl(ce->ce_mode),
ce->ce_mode,
abbrev ? find_unique_abbrev(ce->sha1,abbrev)
: sha1_to_hex(ce->sha1),
ce_stage(ce));
Expand Down Expand Up @@ -242,7 +242,7 @@ static void show_files(struct dir_struct *dir, const char *prefix)
continue;
if (show_unmerged && !ce_stage(ce))
continue;
if (ce->ce_flags & htons(CE_UPDATE))
if (ce->ce_flags & CE_UPDATE)
continue;
show_ce_entry(ce_stage(ce) ? tag_unmerged : tag_cached, ce);
}
Expand Down Expand Up @@ -350,7 +350,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
struct cache_entry *ce = active_cache[i];
if (!ce_stage(ce))
continue;
ce->ce_flags |= htons(CE_STAGEMASK);
ce->ce_flags |= CE_STAGEMASK;
}

if (prefix) {
Expand Down Expand Up @@ -379,7 +379,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
*/
if (last_stage0 &&
!strcmp(last_stage0->name, ce->name))
ce->ce_flags |= htons(CE_UPDATE);
ce->ce_flags |= CE_UPDATE;
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions builtin-read-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ static int read_cache_unmerged(void)
continue;
cache_tree_invalidate_path(active_cache_tree, ce->name);
last = ce;
ce->ce_mode = 0;
ce->ce_flags &= ~htons(CE_STAGEMASK);
ce->ce_flags |= CE_REMOVE;
}
*dst++ = ce;
}
Expand Down
4 changes: 2 additions & 2 deletions builtin-rerere.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ static int find_conflict(struct path_list *conflict)
if (ce_stage(e2) == 2 &&
ce_stage(e3) == 3 &&
ce_same_name(e2, e3) &&
S_ISREG(ntohl(e2->ce_mode)) &&
S_ISREG(ntohl(e3->ce_mode))) {
S_ISREG(e2->ce_mode) &&
S_ISREG(e3->ce_mode)) {
path_list_insert((const char *)e2->name, conflict);
i++; /* skip over both #2 and #3 */
}
Expand Down
18 changes: 9 additions & 9 deletions builtin-update-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ static int mark_valid(const char *path)
if (0 <= pos) {
switch (mark_valid_only) {
case MARK_VALID:
active_cache[pos]->ce_flags |= htons(CE_VALID);
active_cache[pos]->ce_flags |= CE_VALID;
break;
case UNMARK_VALID:
active_cache[pos]->ce_flags &= ~htons(CE_VALID);
active_cache[pos]->ce_flags &= ~CE_VALID;
break;
}
cache_tree_invalidate_path(active_cache_tree, path);
Expand Down Expand Up @@ -95,7 +95,7 @@ static int add_one_path(struct cache_entry *old, const char *path, int len, stru
size = cache_entry_size(len);
ce = xcalloc(1, size);
memcpy(ce->name, path, len);
ce->ce_flags = htons(len);
ce->ce_flags = len;
fill_stat_cache_info(ce, st);
ce->ce_mode = ce_mode_from_stat(old, st->st_mode);

Expand Down Expand Up @@ -139,7 +139,7 @@ static int process_directory(const char *path, int len, struct stat *st)
/* Exact match: file or existing gitlink */
if (pos >= 0) {
struct cache_entry *ce = active_cache[pos];
if (S_ISGITLINK(ntohl(ce->ce_mode))) {
if (S_ISGITLINK(ce->ce_mode)) {

/* Do nothing to the index if there is no HEAD! */
if (resolve_gitlink_ref(path, "HEAD", sha1) < 0)
Expand Down Expand Up @@ -183,7 +183,7 @@ static int process_file(const char *path, int len, struct stat *st)
int pos = cache_name_pos(path, len);
struct cache_entry *ce = pos < 0 ? NULL : active_cache[pos];

if (ce && S_ISGITLINK(ntohl(ce->ce_mode)))
if (ce && S_ISGITLINK(ce->ce_mode))
return error("%s is already a gitlink, not replacing", path);

return add_one_path(ce, path, len, st);
Expand Down Expand Up @@ -226,7 +226,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
ce->ce_flags = create_ce_flags(len, stage);
ce->ce_mode = create_ce_mode(mode);
if (assume_unchanged)
ce->ce_flags |= htons(CE_VALID);
ce->ce_flags |= CE_VALID;
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
if (add_cache_entry(ce, option))
Expand All @@ -246,14 +246,14 @@ static void chmod_path(int flip, const char *path)
if (pos < 0)
goto fail;
ce = active_cache[pos];
mode = ntohl(ce->ce_mode);
mode = ce->ce_mode;
if (!S_ISREG(mode))
goto fail;
switch (flip) {
case '+':
ce->ce_mode |= htonl(0111); break;
ce->ce_mode |= 0111; break;
case '-':
ce->ce_mode &= htonl(~0111); break;
ce->ce_mode &= ~0111; break;
default:
goto fail;
}
Expand Down
4 changes: 2 additions & 2 deletions cache-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,13 @@ static int update_one(struct cache_tree *it,
}
else {
sha1 = ce->sha1;
mode = ntohl(ce->ce_mode);
mode = ce->ce_mode;
entlen = pathlen - baselen;
}
if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1))
return error("invalid object %s", sha1_to_hex(sha1));

if (!ce->ce_mode)
if (ce->ce_flags & CE_REMOVE)
continue; /* entry being removed */

strbuf_grow(&buffer, entlen + 100);
Expand Down
69 changes: 55 additions & 14 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "git-compat-util.h"
#include "strbuf.h"
#include "hash.h"

#include SHA1_HEADER
#include <zlib.h>
Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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 */
Expand Down
Loading

0 comments on commit e0197c9

Please sign in to comment.