diff options
Diffstat (limited to 'read-cache.c')
-rw-r--r-- | read-cache.c | 70 |
1 files changed, 42 insertions, 28 deletions
diff --git a/read-cache.c b/read-cache.c index ef355cc9a8..fda78bc353 100644 --- a/read-cache.c +++ b/read-cache.c @@ -17,6 +17,10 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really); +/* Mask for the name length in ce_flags in the on-disk index */ + +#define CE_NAMEMASK (0x0fff) + /* Index extensions. * * The first letter should be 'A'..'Z' for extensions that are not @@ -54,8 +58,8 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n new = xmalloc(cache_entry_size(namelen)); copy_cache_entry(new, old); - new->ce_flags &= ~(CE_STATE_MASK | CE_NAMEMASK); - new->ce_flags |= (namelen >= CE_NAMEMASK ? CE_NAMEMASK : namelen); + new->ce_flags &= ~CE_STATE_MASK; + new->ce_namelen = namelen; memcpy(new->name, new_name, namelen + 1); cache_tree_invalidate_path(istate->cache_tree, old->name); @@ -395,10 +399,8 @@ int df_name_compare(const char *name1, int len1, int mode1, return c1 - c2; } -int cache_name_compare(const char *name1, int flags1, const char *name2, int flags2) +int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2) { - int len1 = flags1 & CE_NAMEMASK; - int len2 = flags2 & CE_NAMEMASK; int len = len1 < len2 ? len1 : len2; int cmp; @@ -410,18 +412,19 @@ int cache_name_compare(const char *name1, int flags1, const char *name2, int fla if (len1 > len2) return 1; - /* Compare stages */ - flags1 &= CE_STAGEMASK; - flags2 &= CE_STAGEMASK; - - if (flags1 < flags2) + if (stage1 < stage2) return -1; - if (flags1 > flags2) + if (stage1 > stage2) return 1; return 0; } -int index_name_pos(const struct index_state *istate, const char *name, int namelen) +int cache_name_compare(const char *name1, int len1, const char *name2, int len2) +{ + return cache_name_stage_compare(name1, len1, 0, name2, len2, 0); +} + +static int index_name_stage_pos(const struct index_state *istate, const char *name, int namelen, int stage) { int first, last; @@ -430,7 +433,7 @@ int index_name_pos(const struct index_state *istate, const char *name, int namel while (last > first) { int next = (last + first) >> 1; struct cache_entry *ce = istate->cache[next]; - int cmp = cache_name_compare(name, namelen, ce->name, ce->ce_flags); + int cmp = cache_name_stage_compare(name, namelen, stage, ce->name, ce_namelen(ce), ce_stage(ce)); if (!cmp) return next; if (cmp < 0) { @@ -442,6 +445,11 @@ int index_name_pos(const struct index_state *istate, const char *name, int namel return -first-1; } +int index_name_pos(const struct index_state *istate, const char *name, int namelen) +{ + return index_name_stage_pos(istate, name, namelen, 0); +} + /* Remove entry, return true if there are more entries to go.. */ int remove_index_entry_at(struct index_state *istate, int pos) { @@ -581,7 +589,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, size = cache_entry_size(namelen); ce = xcalloc(1, size); memcpy(ce->name, path, namelen); - ce->ce_flags = namelen; + ce->ce_namelen = namelen; if (!intent_only) fill_stat_cache_info(ce, st); else @@ -683,7 +691,8 @@ struct cache_entry *make_cache_entry(unsigned int mode, hashcpy(ce->sha1, sha1); memcpy(ce->name, path, len); - ce->ce_flags = create_ce_flags(len, stage); + ce->ce_flags = create_ce_flags(stage); + ce->ce_namelen = len; ce->ce_mode = create_ce_mode(mode); if (refresh) @@ -820,7 +829,7 @@ static int has_dir_name(struct index_state *istate, } len = slash - name; - pos = index_name_pos(istate, name, create_ce_flags(len, stage)); + pos = index_name_stage_pos(istate, name, len, stage); if (pos >= 0) { /* * Found one, but not so fast. This could @@ -910,7 +919,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e int new_only = option & ADD_CACHE_NEW_ONLY; cache_tree_invalidate_path(istate->cache_tree, ce->name); - pos = index_name_pos(istate, ce->name, ce->ce_flags); + pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce)); /* existing match? Just replace it. */ if (pos >= 0) { @@ -942,7 +951,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e if (!ok_to_replace) return error("'%s' appears as both a file and as a directory", ce->name); - pos = index_name_pos(istate, ce->name, ce->ce_flags); + pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce)); pos = -pos-1; } return pos + 1; @@ -1119,7 +1128,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p continue; if (pathspec && - !match_pathspec(pathspec, ce->name, strlen(ce->name), 0, seen)) + !match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen)) filtered = 1; if (ce_stage(ce)) { @@ -1319,7 +1328,8 @@ static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *on ce->ce_uid = ntoh_l(ondisk->uid); ce->ce_gid = ntoh_l(ondisk->gid); ce->ce_size = ntoh_l(ondisk->size); - ce->ce_flags = flags; + ce->ce_flags = flags & ~CE_NAMEMASK; + ce->ce_namelen = len; hashcpy(ce->sha1, ondisk->sha1); memcpy(ce->name, name, len); ce->name[len] = '\0'; @@ -1404,11 +1414,9 @@ int read_index_from(struct index_state *istate, const char *path) size_t mmap_size; struct strbuf previous_name_buf = STRBUF_INIT, *previous_name; - errno = EBUSY; if (istate->initialized) return istate->cache_nr; - errno = ENOENT; istate->timestamp.sec = 0; istate->timestamp.nsec = 0; fd = open(path, O_RDONLY); @@ -1421,15 +1429,14 @@ int read_index_from(struct index_state *istate, const char *path) if (fstat(fd, &st)) die_errno("cannot stat the open index"); - errno = EINVAL; mmap_size = xsize_t(st.st_size); if (mmap_size < sizeof(struct cache_header) + 20) die("index file smaller than expected"); mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - close(fd); if (mmap == MAP_FAILED) die_errno("unable to map index file"); + close(fd); hdr = mmap; if (verify_hdr(hdr, mmap_size) < 0) @@ -1485,7 +1492,6 @@ int read_index_from(struct index_state *istate, const char *path) unmap: munmap(mmap, mmap_size); - errno = EINVAL; die("index file corrupt"); } @@ -1646,6 +1652,8 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce) static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk, struct cache_entry *ce) { + short flags; + ondisk->ctime.sec = htonl(ce->ce_ctime.sec); ondisk->mtime.sec = htonl(ce->ce_mtime.sec); ondisk->ctime.nsec = htonl(ce->ce_ctime.nsec); @@ -1657,7 +1665,10 @@ static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk, ondisk->gid = htonl(ce->ce_gid); ondisk->size = htonl(ce->ce_size); hashcpy(ondisk->sha1, ce->sha1); - ondisk->flags = htons(ce->ce_flags); + + flags = ce->ce_flags; + flags |= (ce_namelen(ce) >= CE_NAMEMASK ? CE_NAMEMASK : ce_namelen(ce)); + ondisk->flags = htons(flags); if (ce->ce_flags & CE_EXTENDED) { struct ondisk_cache_entry_extended *ondisk2; ondisk2 = (struct ondisk_cache_entry_extended *)ondisk; @@ -1785,6 +1796,8 @@ int write_index(struct index_state *istate, int newfd) continue; if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce)) ce_smudge_racily_clean_entry(ce); + if (is_null_sha1(ce->sha1)) + return error("cache entry has null sha1: %s", ce->name); if (ce_write_entry(&c, newfd, ce, previous_name) < 0) return -1; } @@ -1841,11 +1854,12 @@ int read_index_unmerged(struct index_state *istate) if (!ce_stage(ce)) continue; unmerged = 1; - len = strlen(ce->name); + len = ce_namelen(ce); size = cache_entry_size(len); new_ce = xcalloc(1, size); memcpy(new_ce->name, ce->name, len); - new_ce->ce_flags = create_ce_flags(len, 0) | CE_CONFLICTED; + new_ce->ce_flags = create_ce_flags(0) | CE_CONFLICTED; + new_ce->ce_namelen = len; new_ce->ce_mode = ce->ce_mode; if (add_index_entry(istate, new_ce, 0)) return error("%s: cannot drop to stage #0", |