Skip to content

Commit

Permalink
split-index: strip pathname of on-disk replaced entries
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Nguyễn Thái Ngọc Duy authored and Junio C Hamano committed Jun 13, 2014
1 parent ce7c614 commit b3c96fb
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 2 deletions.
1 change: 1 addition & 0 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ struct cache_entry {
#define CE_MATCHED (1 << 26)

#define CE_UPDATE_IN_BASE (1 << 27)
#define CE_STRIP_NAME (1 << 28)

/*
* Extended on-disk flags
Expand Down
10 changes: 10 additions & 0 deletions read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1787,9 +1787,15 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
{
int size;
struct ondisk_cache_entry *ondisk;
int saved_namelen = saved_namelen; /* compiler workaround */
char *name;
int result;

if (ce->ce_flags & CE_STRIP_NAME) {
saved_namelen = ce_namelen(ce);
ce->ce_namelen = 0;
}

if (!previous_name) {
size = ondisk_ce_size(ce);
ondisk = xcalloc(1, size);
Expand Down Expand Up @@ -1821,6 +1827,10 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
strbuf_splice(previous_name, common, to_remove,
ce->name + common, ce_namelen(ce) - common);
}
if (ce->ce_flags & CE_STRIP_NAME) {
ce->ce_namelen = saved_namelen;
ce->ce_flags &= ~CE_STRIP_NAME;
}

result = ce_write(c, fd, ondisk, size);
free(ondisk);
Expand Down
14 changes: 12 additions & 2 deletions split-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ static void replace_entry(size_t pos, void *data)
struct index_state *istate = data;
struct split_index *si = istate->split_index;
struct cache_entry *dst, *src;

if (pos >= istate->cache_nr)
die("position for replacement %d exceeds base index size %d",
(int)pos, istate->cache_nr);
Expand All @@ -100,10 +101,14 @@ static void replace_entry(size_t pos, void *data)
die("entry %d is marked as both replaced and deleted",
(int)pos);
src = si->saved_cache[si->nr_replacements];
if (ce_namelen(src))
die("corrupt link extension, entry %d should have "
"zero length name", (int)pos);
src->index = pos + 1;
src->ce_flags |= CE_UPDATE_IN_BASE;
free(dst);
dst = src;
src->ce_namelen = dst->ce_namelen;
copy_cache_entry(dst, src);
free(src);
si->nr_replacements++;
}

Expand Down Expand Up @@ -131,6 +136,9 @@ void merge_base_index(struct index_state *istate)
remove_marked_cache_entries(istate);

for (i = si->nr_replacements; i < si->saved_cache_nr; i++) {
if (!ce_namelen(si->saved_cache[i]))
die("corrupt link extension, entry %d should "
"have non-zero length name", i);
add_index_entry(istate, si->saved_cache[i],
ADD_CACHE_OK_TO_ADD |
ADD_CACHE_KEEP_CACHE_TREE |
Expand Down Expand Up @@ -213,6 +221,7 @@ void prepare_to_write_split_index(struct index_state *istate)
ewah_set(si->delete_bitmap, i);
else if (ce->ce_flags & CE_UPDATE_IN_BASE) {
ewah_set(si->replace_bitmap, i);
ce->ce_flags |= CE_STRIP_NAME;
ALLOC_GROW(entries, nr_entries+1, nr_alloc);
entries[nr_entries++] = ce;
}
Expand All @@ -222,6 +231,7 @@ void prepare_to_write_split_index(struct index_state *istate)
for (i = 0; i < istate->cache_nr; i++) {
ce = istate->cache[i];
if ((!si->base || !ce->index) && !(ce->ce_flags & CE_REMOVE)) {
assert(!(ce->ce_flags & CE_STRIP_NAME));
ALLOC_GROW(entries, nr_entries+1, nr_alloc);
entries[nr_entries++] = ce;
}
Expand Down

0 comments on commit b3c96fb

Please sign in to comment.