split-index: strip pathname of on-disk replaced entries
We know the positions of replaced entries via the replace bitmap in "link" extension, so the "name" path does not have to be stored (it's still in the shared index). With this, we also have a way to distinguish additions vs replacements at load time and can catch broken "link" extensions. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Nguyễn Thái Ngọc Duy committed
Jun 13, 2014 at 19:19 UTC
b3c96fb158f05152336f167076f5d81d23c3a5e5
3 files changed
+23
-2
cache.h
+1
@@ -170,6 +170,7 @@ struct cache_entry {
170
#define CE_MATCHED (1 << 26)
171
172
#define CE_UPDATE_IN_BASE (1 << 27)
173
+#define CE_STRIP_NAME (1 << 28)
174
175
/*
176
* Extended on-disk flags
read-cache.c
+10
@@ -1787,9 +1787,15 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
1787
{
1788
int size;
1789
struct ondisk_cache_entry *ondisk;
1790
+ int saved_namelen = saved_namelen; /* compiler workaround */
1791
char *name;
1792
int result;
1793
1794
+ if (ce->ce_flags & CE_STRIP_NAME) {
1795
+ saved_namelen = ce_namelen(ce);
1796
+ ce->ce_namelen = 0;
1797
+ }
1798
+
1799
if (!previous_name) {
1800
size = ondisk_ce_size(ce);
1801
ondisk = xcalloc(1, size);
@@ -1821,6 +1827,10 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
1827
strbuf_splice(previous_name, common, to_remove,
1828
ce->name + common, ce_namelen(ce) - common);
1829
}
1830
+ if (ce->ce_flags & CE_STRIP_NAME) {
1831
+ ce->ce_namelen = saved_namelen;
1832
+ ce->ce_flags &= ~CE_STRIP_NAME;
1833
+ }
1834
1835
result = ce_write(c, fd, ondisk, size);
1836
free(ondisk);
split-index.c
+12
-2
@@ -89,6 +89,7 @@ static void replace_entry(size_t pos, void *data)
89
struct index_state *istate = data;
90
struct split_index *si = istate->split_index;
91
struct cache_entry *dst, *src;
92
+
93
if (pos >= istate->cache_nr)
94
die("position for replacement %d exceeds base index size %d",
95
(int)pos, istate->cache_nr);
@@ -100,10 +101,14 @@ static void replace_entry(size_t pos, void *data)
101
die("entry %d is marked as both replaced and deleted",
102
(int)pos);
103
src = si->saved_cache[si->nr_replacements];
104
+ if (ce_namelen(src))
105
+ die("corrupt link extension, entry %d should have "
106
+ "zero length name", (int)pos);
107
src->index = pos + 1;
108
src->ce_flags |= CE_UPDATE_IN_BASE;
105
- free(dst);
106
- dst = src;
109
+ src->ce_namelen = dst->ce_namelen;
110
+ copy_cache_entry(dst, src);
111
+ free(src);
112
si->nr_replacements++;
113
}
114
@@ -131,6 +136,9 @@ void merge_base_index(struct index_state *istate)
136
remove_marked_cache_entries(istate);
137
138
for (i = si->nr_replacements; i < si->saved_cache_nr; i++) {
139
+ if (!ce_namelen(si->saved_cache[i]))
140
+ die("corrupt link extension, entry %d should "
141
+ "have non-zero length name", i);
142
add_index_entry(istate, si->saved_cache[i],
143
ADD_CACHE_OK_TO_ADD |
144
ADD_CACHE_KEEP_CACHE_TREE |
@@ -213,6 +221,7 @@ void prepare_to_write_split_index(struct index_state *istate)
221
ewah_set(si->delete_bitmap, i);
222
else if (ce->ce_flags & CE_UPDATE_IN_BASE) {
223
ewah_set(si->replace_bitmap, i);
224
+ ce->ce_flags |= CE_STRIP_NAME;
225
ALLOC_GROW(entries, nr_entries+1, nr_alloc);
226
entries[nr_entries++] = ce;
227
}
@@ -222,6 +231,7 @@ void prepare_to_write_split_index(struct index_state *istate)
231
for (i = 0; i < istate->cache_nr; i++) {
232
ce = istate->cache[i];
233
if ((!si->base || !ce->index) && !(ce->ce_flags & CE_REMOVE)) {
234
+ assert(!(ce->ce_flags & CE_STRIP_NAME));
235
ALLOC_GROW(entries, nr_entries+1, nr_alloc);
236
entries[nr_entries++] = ce;
237
}