Skip to content

Commit 9d22778

Browse files
committed
read-cache.c: write prefix-compressed names in the index
Teach the code to write the index in the v4 on-disk format. Record the format version of the on-disk index we read from in the index_state, and use the format when writing the new index out. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6c9cd16 commit 9d22778

File tree

2 files changed

+58
-10
lines changed

2 files changed

+58
-10
lines changed

cache.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ struct cache_header {
105105
unsigned int hdr_entries;
106106
};
107107

108+
#define INDEX_FORMAT_LB 2
109+
#define INDEX_FORMAT_UB 4
110+
108111
/*
109112
* The "cache_time" is just the low 32 bits of the
110113
* time. It doesn't matter if it overflows - we only
@@ -265,6 +268,7 @@ static inline unsigned int canon_mode(unsigned int mode)
265268

266269
struct index_state {
267270
struct cache_entry **cache;
271+
unsigned int version;
268272
unsigned int cache_nr, cache_alloc, cache_changed;
269273
struct string_list *resolve_undo;
270274
struct cache_tree *cache_tree;

read-cache.c

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,8 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int reall
11961196
* Index File I/O
11971197
*****************************************************************/
11981198

1199+
#define INDEX_FORMAT_DEFAULT 3
1200+
11991201
/*
12001202
* dev/ino/uid/gid/size are also just tracked to the low 32 bits
12011203
* Again - this is just a (very strong in practice) heuristic that
@@ -1443,12 +1445,13 @@ int read_index_from(struct index_state *istate, const char *path)
14431445
if (verify_hdr(hdr, mmap_size) < 0)
14441446
goto unmap;
14451447

1448+
istate->version = ntohl(hdr->hdr_version);
14461449
istate->cache_nr = ntohl(hdr->hdr_entries);
14471450
istate->cache_alloc = alloc_nr(istate->cache_nr);
14481451
istate->cache = xcalloc(istate->cache_alloc, sizeof(struct cache_entry *));
14491452
istate->initialized = 1;
14501453

1451-
if (hdr->hdr_version == htonl(4))
1454+
if (istate->version == 4)
14521455
previous_name = &previous_name_buf;
14531456
else
14541457
previous_name = NULL;
@@ -1676,15 +1679,45 @@ static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
16761679
}
16771680
}
16781681

1679-
static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
1682+
static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
1683+
struct strbuf *previous_name)
16801684
{
1681-
int size = ondisk_ce_size(ce);
1682-
struct ondisk_cache_entry *ondisk = xcalloc(1, size);
1685+
int size;
1686+
struct ondisk_cache_entry *ondisk;
16831687
char *name;
16841688
int result;
16851689

1686-
name = copy_cache_entry_to_ondisk(ondisk, ce);
1687-
memcpy(name, ce->name, ce_namelen(ce));
1690+
if (!previous_name) {
1691+
size = ondisk_ce_size(ce);
1692+
ondisk = xcalloc(1, size);
1693+
name = copy_cache_entry_to_ondisk(ondisk, ce);
1694+
memcpy(name, ce->name, ce_namelen(ce));
1695+
} else {
1696+
int common, to_remove, prefix_size;
1697+
unsigned char to_remove_vi[16];
1698+
for (common = 0;
1699+
(ce->name[common] &&
1700+
common < previous_name->len &&
1701+
ce->name[common] == previous_name->buf[common]);
1702+
common++)
1703+
; /* still matching */
1704+
to_remove = previous_name->len - common;
1705+
prefix_size = encode_varint(to_remove, to_remove_vi);
1706+
1707+
if (ce->ce_flags & CE_EXTENDED)
1708+
size = offsetof(struct ondisk_cache_entry_extended, name);
1709+
else
1710+
size = offsetof(struct ondisk_cache_entry, name);
1711+
size += prefix_size + (ce_namelen(ce) - common + 1);
1712+
1713+
ondisk = xcalloc(1, size);
1714+
name = copy_cache_entry_to_ondisk(ondisk, ce);
1715+
memcpy(name, to_remove_vi, prefix_size);
1716+
memcpy(name + prefix_size, ce->name + common, ce_namelen(ce) - common);
1717+
1718+
strbuf_splice(previous_name, common, to_remove,
1719+
ce->name + common, ce_namelen(ce) - common);
1720+
}
16881721

16891722
result = ce_write(c, fd, ondisk, size);
16901723
free(ondisk);
@@ -1720,10 +1753,11 @@ int write_index(struct index_state *istate, int newfd)
17201753
{
17211754
git_SHA_CTX c;
17221755
struct cache_header hdr;
1723-
int i, err, removed, extended;
1756+
int i, err, removed, extended, hdr_version;
17241757
struct cache_entry **cache = istate->cache;
17251758
int entries = istate->cache_nr;
17261759
struct stat st;
1760+
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
17271761

17281762
for (i = removed = extended = 0; i < entries; i++) {
17291763
if (cache[i]->ce_flags & CE_REMOVE)
@@ -1737,24 +1771,34 @@ int write_index(struct index_state *istate, int newfd)
17371771
}
17381772
}
17391773

1774+
if (!istate->version)
1775+
istate->version = INDEX_FORMAT_DEFAULT;
1776+
1777+
/* demote version 3 to version 2 when the latter suffices */
1778+
if (istate->version == 3 || istate->version == 2)
1779+
istate->version = extended ? 3 : 2;
1780+
1781+
hdr_version = istate->version;
1782+
17401783
hdr.hdr_signature = htonl(CACHE_SIGNATURE);
1741-
/* for extended format, increase version so older git won't try to read it */
1742-
hdr.hdr_version = htonl(extended ? 3 : 2);
1784+
hdr.hdr_version = htonl(hdr_version);
17431785
hdr.hdr_entries = htonl(entries - removed);
17441786

17451787
git_SHA1_Init(&c);
17461788
if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
17471789
return -1;
17481790

1791+
previous_name = (hdr_version == 4) ? &previous_name_buf : NULL;
17491792
for (i = 0; i < entries; i++) {
17501793
struct cache_entry *ce = cache[i];
17511794
if (ce->ce_flags & CE_REMOVE)
17521795
continue;
17531796
if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
17541797
ce_smudge_racily_clean_entry(ce);
1755-
if (ce_write_entry(&c, newfd, ce) < 0)
1798+
if (ce_write_entry(&c, newfd, ce, previous_name) < 0)
17561799
return -1;
17571800
}
1801+
strbuf_release(&previous_name_buf);
17581802

17591803
/* Write extension data here */
17601804
if (istate->cache_tree) {

0 commit comments

Comments
 (0)