Merge branch 'nd/narrow' (early part) into jc/add-i-t-a
* 'nd/narrow' (early part): Extend index to save more flags
This commit is contained in:
commit
fe60dff744
58
cache.h
58
cache.h
@ -115,6 +115,26 @@ struct ondisk_cache_entry {
|
||||
char name[FLEX_ARRAY]; /* more */
|
||||
};
|
||||
|
||||
/*
|
||||
* This struct is used when CE_EXTENDED bit is 1
|
||||
* The struct must match ondisk_cache_entry exactly from
|
||||
* ctime till flags
|
||||
*/
|
||||
struct ondisk_cache_entry_extended {
|
||||
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;
|
||||
unsigned short flags2;
|
||||
char name[FLEX_ARRAY]; /* more */
|
||||
};
|
||||
|
||||
struct cache_entry {
|
||||
unsigned int ce_ctime;
|
||||
unsigned int ce_mtime;
|
||||
@ -136,7 +156,15 @@ struct cache_entry {
|
||||
#define CE_VALID (0x8000)
|
||||
#define CE_STAGESHIFT 12
|
||||
|
||||
/* In-memory only */
|
||||
/*
|
||||
* Range 0xFFFF0000 in ce_flags is divided into
|
||||
* two parts: in-memory flags and on-disk ones.
|
||||
* Flags in CE_EXTENDED_FLAGS will get saved on-disk
|
||||
* if you want to save a new flag, add it in
|
||||
* CE_EXTENDED_FLAGS
|
||||
*
|
||||
* In-memory only flags
|
||||
*/
|
||||
#define CE_UPDATE (0x10000)
|
||||
#define CE_REMOVE (0x20000)
|
||||
#define CE_UPTODATE (0x40000)
|
||||
@ -145,6 +173,24 @@ struct cache_entry {
|
||||
#define CE_HASHED (0x100000)
|
||||
#define CE_UNHASHED (0x200000)
|
||||
|
||||
/*
|
||||
* Extended on-disk flags
|
||||
*/
|
||||
/* CE_EXTENDED2 is for future extension */
|
||||
#define CE_EXTENDED2 0x80000000
|
||||
|
||||
#define CE_EXTENDED_FLAGS (0)
|
||||
|
||||
/*
|
||||
* Safeguard to avoid saving wrong flags:
|
||||
* - CE_EXTENDED2 won't get saved until its semantic is known
|
||||
* - Bits in 0x0000FFFF have been saved in ce_flags already
|
||||
* - Bits in 0x003F0000 are currently in-memory flags
|
||||
*/
|
||||
#if CE_EXTENDED_FLAGS & 0x803FFFFF
|
||||
#error "CE_EXTENDED_FLAGS out of range"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copy the sha1 and stat state of a cache entry from one to
|
||||
* another. But we never change the name, or the hash state!
|
||||
@ -177,7 +223,9 @@ static inline size_t ce_namelen(const struct cache_entry *ce)
|
||||
}
|
||||
|
||||
#define ce_size(ce) cache_entry_size(ce_namelen(ce))
|
||||
#define ondisk_ce_size(ce) ondisk_cache_entry_size(ce_namelen(ce))
|
||||
#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \
|
||||
ondisk_cache_entry_extended_size(ce_namelen(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)
|
||||
@ -220,8 +268,10 @@ static inline int ce_to_dtype(const struct cache_entry *ce)
|
||||
(S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \
|
||||
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)
|
||||
#define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
|
||||
#define cache_entry_size(len) flexible_size(cache_entry,len)
|
||||
#define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len)
|
||||
#define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len)
|
||||
|
||||
struct index_state {
|
||||
struct cache_entry **cache;
|
||||
|
51
read-cache.c
51
read-cache.c
@ -1098,7 +1098,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
|
||||
|
||||
if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
|
||||
return error("bad signature");
|
||||
if (hdr->hdr_version != htonl(2))
|
||||
if (hdr->hdr_version != htonl(2) && hdr->hdr_version != htonl(3))
|
||||
return error("bad index version");
|
||||
git_SHA1_Init(&c);
|
||||
git_SHA1_Update(&c, hdr, size - 20);
|
||||
@ -1133,6 +1133,7 @@ int read_index(struct index_state *istate)
|
||||
static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_entry *ce)
|
||||
{
|
||||
size_t len;
|
||||
const char *name;
|
||||
|
||||
ce->ce_ctime = ntohl(ondisk->ctime.sec);
|
||||
ce->ce_mtime = ntohl(ondisk->mtime.sec);
|
||||
@ -1145,19 +1146,31 @@ static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_en
|
||||
/* On-disk flags are just 16 bits */
|
||||
ce->ce_flags = ntohs(ondisk->flags);
|
||||
|
||||
/* For future extension: we do not understand this entry yet */
|
||||
if (ce->ce_flags & CE_EXTENDED)
|
||||
die("Unknown index entry format");
|
||||
hashcpy(ce->sha1, ondisk->sha1);
|
||||
|
||||
len = ce->ce_flags & CE_NAMEMASK;
|
||||
|
||||
if (ce->ce_flags & CE_EXTENDED) {
|
||||
struct ondisk_cache_entry_extended *ondisk2;
|
||||
int extended_flags;
|
||||
ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
|
||||
extended_flags = ntohs(ondisk2->flags2) << 16;
|
||||
/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
|
||||
if (extended_flags & ~CE_EXTENDED_FLAGS)
|
||||
die("Unknown index entry format %08x", extended_flags);
|
||||
ce->ce_flags |= extended_flags;
|
||||
name = ondisk2->name;
|
||||
}
|
||||
else
|
||||
name = ondisk->name;
|
||||
|
||||
if (len == CE_NAMEMASK)
|
||||
len = strlen(ondisk->name);
|
||||
len = strlen(name);
|
||||
/*
|
||||
* NEEDSWORK: If the original index is crafted, this copy could
|
||||
* go unchecked.
|
||||
*/
|
||||
memcpy(ce->name, ondisk->name, len + 1);
|
||||
memcpy(ce->name, name, len + 1);
|
||||
}
|
||||
|
||||
static inline size_t estimate_cache_size(size_t ondisk_size, unsigned int entries)
|
||||
@ -1422,6 +1435,7 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
|
||||
{
|
||||
int size = ondisk_ce_size(ce);
|
||||
struct ondisk_cache_entry *ondisk = xcalloc(1, size);
|
||||
char *name;
|
||||
|
||||
ondisk->ctime.sec = htonl(ce->ce_ctime);
|
||||
ondisk->ctime.nsec = 0;
|
||||
@ -1435,7 +1449,15 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
|
||||
ondisk->size = htonl(ce->ce_size);
|
||||
hashcpy(ondisk->sha1, ce->sha1);
|
||||
ondisk->flags = htons(ce->ce_flags);
|
||||
memcpy(ondisk->name, ce->name, ce_namelen(ce));
|
||||
if (ce->ce_flags & CE_EXTENDED) {
|
||||
struct ondisk_cache_entry_extended *ondisk2;
|
||||
ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
|
||||
ondisk2->flags2 = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16);
|
||||
name = ondisk2->name;
|
||||
}
|
||||
else
|
||||
name = ondisk->name;
|
||||
memcpy(name, ce->name, ce_namelen(ce));
|
||||
|
||||
return ce_write(c, fd, ondisk, size);
|
||||
}
|
||||
@ -1444,16 +1466,25 @@ int write_index(const struct index_state *istate, int newfd)
|
||||
{
|
||||
git_SHA_CTX c;
|
||||
struct cache_header hdr;
|
||||
int i, err, removed;
|
||||
int i, err, removed, extended;
|
||||
struct cache_entry **cache = istate->cache;
|
||||
int entries = istate->cache_nr;
|
||||
|
||||
for (i = removed = 0; i < entries; i++)
|
||||
for (i = removed = extended = 0; i < entries; i++) {
|
||||
if (cache[i]->ce_flags & CE_REMOVE)
|
||||
removed++;
|
||||
|
||||
/* reduce extended entries if possible */
|
||||
cache[i]->ce_flags &= ~CE_EXTENDED;
|
||||
if (cache[i]->ce_flags & CE_EXTENDED_FLAGS) {
|
||||
extended++;
|
||||
cache[i]->ce_flags |= CE_EXTENDED;
|
||||
}
|
||||
}
|
||||
|
||||
hdr.hdr_signature = htonl(CACHE_SIGNATURE);
|
||||
hdr.hdr_version = htonl(2);
|
||||
/* for extended format, increase version so older git won't try to read it */
|
||||
hdr.hdr_version = htonl(extended ? 3 : 2);
|
||||
hdr.hdr_entries = htonl(entries - removed);
|
||||
|
||||
git_SHA1_Init(&c);
|
||||
|
Loading…
Reference in New Issue
Block a user