mirror of
https://github.com/git/git.git
synced 2026-03-13 18:33:25 +01:00
pack-objects: use of version 3 delta is now optional.
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@cox.net>
This commit is contained in:
@@ -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_entry *entry)
|
||||
/* 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
|
||||
@@ -1101,6 +1104,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
|
||||
* on an earlier try, but only when reusing delta data.
|
||||
*/
|
||||
if (!no_reuse_delta && trg_entry->in_pack &&
|
||||
trg_entry->in_pack->pack_version <= delta_version &&
|
||||
trg_entry->in_pack == src_entry->in_pack)
|
||||
return 0;
|
||||
|
||||
@@ -1326,10 +1330,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);
|
||||
}
|
||||
|
||||
|
||||
1
cache.h
1
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 */
|
||||
|
||||
2
delta.h
2
delta.h
@@ -1,6 +1,8 @@
|
||||
#ifndef DELTA_H
|
||||
#define DELTA_H
|
||||
|
||||
extern int delta_version;
|
||||
|
||||
/* opaque object for delta index */
|
||||
struct delta_index;
|
||||
|
||||
|
||||
15
diff-delta.c
15
diff-delta.c
@@ -253,10 +253,13 @@ create_delta(const struct delta_index *index,
|
||||
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 *index,
|
||||
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 *index,
|
||||
/* 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 *index,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++;
|
||||
|
||||
Reference in New Issue
Block a user