Skip to content

Packed-refs v2 Part I: Optionally hash the index #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Documentation/config/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,11 @@ index.version::
Specify the version with which new index files should be
initialized. This does not affect existing repositories.
If `feature.manyFiles` is enabled, then the default is 4.

index.computeHash::
When enabled, compute the hash of the index file as it is written
and store the hash at the end of the content. This is enabled by
default.
+
If you disable `index.computHash`, then older Git clients may report that
your index is corrupt during `git fsck`.
14 changes: 11 additions & 3 deletions csum-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ void hashflush(struct hashfile *f)
unsigned offset = f->offset;

if (offset) {
the_hash_algo->update_fn(&f->ctx, f->buffer, offset);
if (!f->skip_hash)
the_hash_algo->update_fn(&f->ctx, f->buffer, offset);
flush(f, f->buffer, offset);
f->offset = 0;
}
Expand All @@ -64,7 +65,12 @@ int finalize_hashfile(struct hashfile *f, unsigned char *result,
int fd;

hashflush(f);
the_hash_algo->final_fn(f->buffer, &f->ctx);

if (f->skip_hash)
memset(f->buffer, 0, the_hash_algo->rawsz);
else
the_hash_algo->final_fn(f->buffer, &f->ctx);

if (result)
hashcpy(result, f->buffer);
if (flags & CSUM_HASH_IN_STREAM)
Expand Down Expand Up @@ -108,7 +114,8 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count)
* the hashfile's buffer. In this block,
* f->offset is necessarily zero.
*/
the_hash_algo->update_fn(&f->ctx, buf, nr);
if (!f->skip_hash)
the_hash_algo->update_fn(&f->ctx, buf, nr);
flush(f, buf, nr);
} else {
/*
Expand Down Expand Up @@ -153,6 +160,7 @@ static struct hashfile *hashfd_internal(int fd, const char *name,
f->tp = tp;
f->name = name;
f->do_crc = 0;
f->skip_hash = 0;
the_hash_algo->init_fn(&f->ctx);

f->buffer_len = buffer_len;
Expand Down
7 changes: 7 additions & 0 deletions csum-file.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ struct hashfile {
size_t buffer_len;
unsigned char *buffer;
unsigned char *check_buffer;

/**
* If set to 1, skip_hash indicates that we should
* not actually compute the hash for this hashfile and
* instead only use it as a buffered write.
*/
unsigned int skip_hash;
};

/* Checkpoint */
Expand Down
22 changes: 21 additions & 1 deletion read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1817,6 +1817,8 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)
git_hash_ctx c;
unsigned char hash[GIT_MAX_RAWSZ];
int hdr_version;
int all_zeroes = 1;
unsigned char *start, *end;

if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
return error(_("bad signature 0x%08x"), hdr->hdr_signature);
Expand All @@ -1827,10 +1829,23 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)
if (!verify_index_checksum)
return 0;

end = (unsigned char *)hdr + size;
start = end - the_hash_algo->rawsz;
while (start < end) {
if (*start != 0) {
all_zeroes = 0;
break;
}
start++;
}

if (all_zeroes)
return 0;

the_hash_algo->init_fn(&c);
the_hash_algo->update_fn(&c, hdr, size - the_hash_algo->rawsz);
the_hash_algo->final_fn(hash, &c);
if (!hasheq(hash, (unsigned char *)hdr + size - the_hash_algo->rawsz))
if (!hasheq(hash, end - the_hash_algo->rawsz))
return error(_("bad index file sha1 signature"));
return 0;
}
Expand Down Expand Up @@ -2917,9 +2932,14 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
int ieot_entries = 1;
struct index_entry_offset_table *ieot = NULL;
int nr, nr_threads;
int compute_hash;

f = hashfd(tempfile->fd, tempfile->filename.buf);

if (!git_config_get_maybe_bool("index.computehash", &compute_hash) &&
!compute_hash)
f->skip_hash = 1;

for (i = removed = extended = 0; i < entries; i++) {
if (cache[i]->ce_flags & CE_REMOVE)
removed++;
Expand Down
8 changes: 8 additions & 0 deletions t/t1600-index.sh
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,12 @@ test_expect_success 'index version config precedence' '
test_index_version 0 true 2 2
'

test_expect_success 'index.computeHash config option' '
(
rm -f .git/index &&
git -c index.computeHash=false add a &&
git fsck
)
'

test_done