This introduces a new configuration item, pack.deltaversion, to control whether pack-objects is allowed to use version 3 delta. By default, we keep generating version 2 delta (and version 2 packfile format) to be compatible with git earlier than v1.2.0. This configuration affects the command in the following ways: - the resulting packfile will have the specified version; - when generating delta, larger copies are allowed only when deltaversion is 3; - the logic to reuse delta from existing packs refuses to reuse delta from packs that uses delta version 3 when the configuration is set to 2. Signed-off-by: Junio C Hamano <junkio@xxxxxxx> --- * Nico, I'd really appreciate it if you can eyeball this patch. For the upcoming v1.4.3, we'd at least want to revert: commit 16854571aae6302f457c5fbee41ac64669b09595 Author: Nicolas Pitre <nico@xxxxxxx> Date: Thu Sep 21 00:11:59 2006 -0400 move pack creation to version 3 It's been quite a while now that GIT is able to read version 3 packs. Let's create them at last. Signed-off-by: Nicolas Pitre <nico@xxxxxxx> Signed-off-by: Junio C Hamano <junkio@xxxxxxx> but I'd like to allow people to explicitly tell what version is to be created by default per repository to avoid future problems. For now it would be advised to leave this configuration empty in public repositories, which would cause them to have version 2 packs. People who know their repositories are only used with git v1.2.0 or newer can use the configuration to allow version 3 packs. We should later add a command line override to pack-objects to explicitly say which delta version to be used, so that pack protocol can negotiate the allowed delta version between client and the server and pass that command line option when upload-pack runs pack-objects. builtin-pack-objects.c | 16 ++++++++++++---- cache.h | 1 + delta.h | 2 ++ diff-delta.c | 15 +++++++++++++-- environment.c | 3 +++ sha1_file.c | 1 + 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 96c069a..4d2147b 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -456,7 +456,7 @@ static void write_pack_file(void) fprintf(stderr, "Writing %d objects.\n", nr_result); hdr.hdr_signature = htonl(PACK_SIGNATURE); - hdr.hdr_version = htonl(PACK_VERSION); + hdr.hdr_version = htonl(delta_version); hdr.hdr_entries = htonl(nr_result); sha1write(f, &hdr, sizeof(hdr)); offset = sizeof(hdr); @@ -914,12 +914,15 @@ static void check_object(struct object_e /* Check if it is delta, and the base is also an object * we are going to pack. If so we will reuse the existing * delta. + * + * Also make sure that we do not reuse delta from an existing + * pack that uses higher delta version than allowed. */ if (!no_reuse_delta && entry->in_pack_type == OBJ_DELTA && (base_entry = locate_object_entry(base)) && - (!base_entry->preferred_base)) { - + (!base_entry->preferred_base) && + entry->in_pack->pack_version <= delta_version) { /* Depth value does not matter - find_deltas() * will never consider reused delta as the * base object to deltify other objects @@ -1326,10 +1329,15 @@ static void setup_progress_signal(void) static int git_pack_config(const char *k, const char *v) { - if(!strcmp(k, "pack.window")) { + if (!strcmp(k, "pack.window")) { window = git_config_int(k, v); return 0; } + if (!strcmp(k, "pack.deltaversion")) { + delta_version = git_config_int(k, v); + if (!pack_version_ok(htonl(delta_version))) + die("value %s for '%s' not allowed", v, k); + } return git_default_config(k, v); } diff --git a/cache.h b/cache.h index c354701..724c09a 100644 --- a/cache.h +++ b/cache.h @@ -337,6 +337,7 @@ extern struct packed_git { unsigned int pack_last_used; unsigned int pack_use_cnt; int pack_local; + int pack_version; unsigned char sha1[20]; /* something like ".git/objects/pack/xxxxx.pack" */ char pack_name[FLEX_ARRAY]; /* more */ diff --git a/delta.h b/delta.h index 7b3f86d..55af3d2 100644 --- a/delta.h +++ b/delta.h @@ -1,6 +1,8 @@ #ifndef DELTA_H #define DELTA_H +extern int delta_version; + /* opaque object for delta index */ struct delta_index; diff --git a/diff-delta.c b/diff-delta.c index fa16d06..2f6dcfb 100644 --- a/diff-delta.c +++ b/diff-delta.c @@ -253,10 +253,13 @@ create_delta(const struct delta_index *i int inscnt; const unsigned char *ref_data, *ref_top, *data, *top; unsigned char *out; + unsigned int ref_size_limit; if (!trg_buf || !trg_size) return NULL; + ref_size_limit = (delta_version > 2) ? 0xffffff : 0x10000; + outpos = 0; outsize = 8192; if (max_size && outsize >= max_size) @@ -308,8 +311,8 @@ create_delta(const struct delta_index *i continue; if (ref_size > top - src) ref_size = top - src; - if (ref_size > 0x10000) - ref_size = 0x10000; + if (ref_size > ref_size_limit) + ref_size = ref_size_limit; if (ref_size <= msize) break; while (ref_size-- && *src++ == *ref) @@ -318,6 +321,8 @@ create_delta(const struct delta_index *i /* this is our best match so far */ msize = ref - entry->ptr; moff = entry->ptr - ref_data; + if (delta_version > 2 && msize >= 0x10000) + break; /* this is good enough */ } } @@ -381,6 +386,12 @@ create_delta(const struct delta_index *i if (msize & 0xff) { out[outpos++] = msize; i |= 0x10; } msize >>= 8; if (msize & 0xff) { out[outpos++] = msize; i |= 0x20; } + if (delta_version > 2) { + msize >>= 8; + if (msize & 0xff) { + out[outpos++] = msize; i |= 0x40; + } + } *op = i; } diff --git a/environment.c b/environment.c index 63b1d15..e266f83 100644 --- a/environment.c +++ b/environment.c @@ -8,6 +8,7 @@ * are. */ #include "cache.h" +#include "pack.h" char git_default_email[MAX_GITNAME]; char git_default_name[MAX_GITNAME]; @@ -25,6 +26,8 @@ const char *apply_default_whitespace; int zlib_compression_level = Z_DEFAULT_COMPRESSION; int pager_in_use; int pager_use_color = 1; +/* by default we allow 2 but up to PACK_VERSION is allowed */ +int delta_version = 2; static const char *git_dir; static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file; diff --git a/sha1_file.c b/sha1_file.c index d111be7..6653182 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -527,6 +527,7 @@ int use_packed_git(struct packed_git *p) p->pack_size - 20)) { die("packfile %s does not match index.", p->pack_name); } + p->pack_version = ntohl(hdr->hdr_version); } p->pack_last_used = pack_used_ctr++; p->pack_use_cnt++; -- 1.4.3.rc3.ga5ce - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html