summaryrefslogtreecommitdiff
path: root/pack-write.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2013-12-05 15:28:07 -0500
committerJunio C Hamano <gitster@pobox.com>2013-12-05 15:40:11 -0800
commit1190a1acf800acdcfd7569f87ac1560e2d077414 (patch)
tree6870ff8f5238d694fa70ebf3f9b6b54993dc0c54 /pack-write.c
parente74435a5169b56be901196ad172b4dbda124254d (diff)
downloadgit-1190a1acf800acdcfd7569f87ac1560e2d077414.tar.gz
pack-objects: name pack files after trailer hash
Our current scheme for naming packfiles is to calculate the sha1 hash of the sorted list of objects contained in the packfile. This gives us a unique name, so we are reasonably sure that two packs with the same name will contain the same objects. It does not, however, tell us that two such packs have the exact same bytes. This makes things awkward if we repack the same set of objects. Due to run-to-run variations, the bytes may not be identical (e.g., changed zlib or git versions, different source object reuse due to new packs in the repository, or even different deltas due to races during a multi-threaded delta search). In theory, this could be helpful to a program that cares that the packfile contains a certain set of objects, but does not care about the particular representation. In practice, no part of git makes use of that, and in many cases it is potentially harmful. For example, if a dumb http client fetches the .idx file, it must be sure to get the exact .pack that matches it. Similarly, a partial transfer of a .pack file cannot be safely resumed, as the actual bytes may have changed. This could also affect a local client which opened the .idx and .pack files, closes the .pack file (due to memory or file descriptor limits), and then re-opens a changed packfile. In all of these cases, git can detect the problem, as we have the sha1 of the bytes themselves in the pack trailer (which we verify on transfer), and the .idx file references the trailer from the matching packfile. But it would be simpler and more efficient to actually get the correct bytes, rather than noticing the problem and having to restart the operation. This patch simply uses the pack trailer sha1 as the pack name. It should be similarly unique, but covers the exact representation of the objects. Other parts of git should not care, as the pack name is returned by pack-objects and is essentially opaque. One test needs to be updated, because it actually corrupts a pack and expects that re-packing the corrupted bytes will use the same name. It won't anymore, but we can easily just use the name that pack-objects hands back. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'pack-write.c')
-rw-r--r--pack-write.c8
1 files changed, 1 insertions, 7 deletions
diff --git a/pack-write.c b/pack-write.c
index ca9e63be18..ddc174e1ad 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -44,14 +44,13 @@ static int need_large_offset(off_t offset, const struct pack_idx_option *opts)
*/
const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects,
int nr_objects, const struct pack_idx_option *opts,
- unsigned char *sha1)
+ const unsigned char *sha1)
{
struct sha1file *f;
struct pack_idx_entry **sorted_by_sha, **list, **last;
off_t last_obj_offset = 0;
uint32_t array[256];
int i, fd;
- git_SHA_CTX ctx;
uint32_t index_version;
if (nr_objects) {
@@ -114,9 +113,6 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec
}
sha1write(f, array, 256 * 4);
- /* compute the SHA1 hash of sorted object names. */
- git_SHA1_Init(&ctx);
-
/*
* Write the actual SHA1 entries..
*/
@@ -128,7 +124,6 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec
sha1write(f, &offset, 4);
}
sha1write(f, obj->sha1, 20);
- git_SHA1_Update(&ctx, obj->sha1, 20);
if ((opts->flags & WRITE_IDX_STRICT) &&
(i && !hashcmp(list[-2]->sha1, obj->sha1)))
die("The same object %s appears twice in the pack",
@@ -178,7 +173,6 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec
sha1write(f, sha1, 20);
sha1close(f, NULL, ((opts->flags & WRITE_IDX_VERIFY)
? CSUM_CLOSE : CSUM_FSYNC));
- git_SHA1_Final(sha1, &ctx);
return index_name;
}