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 <gitster@pobox.com>
Junio C Hamano committed
Apr 4, 2012 at 09:12 UTC
9d227781b688707f64ee1703a1156b0c83247c33
2 files changed
+58
-10
cache.h
+4
@@ -105,6 +105,9 @@ struct cache_header {
105
unsigned int hdr_entries;
106
};
107
108
+#define INDEX_FORMAT_LB 2
109
+#define INDEX_FORMAT_UB 4
110
+
111
/*
112
* The "cache_time" is just the low 32 bits of the
113
* time. It doesn't matter if it overflows - we only
@@ -265,6 +268,7 @@ static inline unsigned int canon_mode(unsigned int mode)
268
269
struct index_state {
270
struct cache_entry **cache;
271
+ unsigned int version;
272
unsigned int cache_nr, cache_alloc, cache_changed;
273
struct string_list *resolve_undo;
274
struct cache_tree *cache_tree;
read-cache.c
+54
-10
@@ -1196,6 +1196,8 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int reall
1196
* Index File I/O
1197
*****************************************************************/
1198
1199
+#define INDEX_FORMAT_DEFAULT 3
1200
+
1201
/*
1202
* dev/ino/uid/gid/size are also just tracked to the low 32 bits
1203
* 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)
1445
if (verify_hdr(hdr, mmap_size) < 0)
1446
goto unmap;
1447
1448
+ istate->version = ntohl(hdr->hdr_version);
1449
istate->cache_nr = ntohl(hdr->hdr_entries);
1450
istate->cache_alloc = alloc_nr(istate->cache_nr);
1451
istate->cache = xcalloc(istate->cache_alloc, sizeof(struct cache_entry *));
1452
istate->initialized = 1;
1453
1451
- if (hdr->hdr_version == htonl(4))
1454
+ if (istate->version == 4)
1455
previous_name = &previous_name_buf;
1456
else
1457
previous_name = NULL;
@@ -1676,15 +1679,45 @@ static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
1679
}
1680
}
1681
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)
1684
{
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;
1687
char *name;
1688
int result;
1689
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
+ }
1721
1722
result = ce_write(c, fd, ondisk, size);
1723
free(ondisk);
@@ -1720,10 +1753,11 @@ int write_index(struct index_state *istate, int newfd)
1753
{
1754
git_SHA_CTX c;
1755
struct cache_header hdr;
1723
- int i, err, removed, extended;
1756
+ int i, err, removed, extended, hdr_version;
1757
struct cache_entry **cache = istate->cache;
1758
int entries = istate->cache_nr;
1759
struct stat st;
1760
+ struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
1761
1762
for (i = removed = extended = 0; i < entries; i++) {
1763
if (cache[i]->ce_flags & CE_REMOVE)
@@ -1737,24 +1771,34 @@ int write_index(struct index_state *istate, int newfd)
1771
}
1772
}
1773
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
+
1783
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);
1785
hdr.hdr_entries = htonl(entries - removed);
1786
1787
git_SHA1_Init(&c);
1788
if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
1789
return -1;
1790
1791
+ previous_name = (hdr_version == 4) ? &previous_name_buf : NULL;
1792
for (i = 0; i < entries; i++) {
1793
struct cache_entry *ce = cache[i];
1794
if (ce->ce_flags & CE_REMOVE)
1795
continue;
1796
if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
1797
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)
1799
return -1;
1800
}
1801
+ strbuf_release(&previous_name_buf);
1802
1803
/* Write extension data here */
1804
if (istate->cache_tree) {