projects
/
git.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
pack-objects: avoid delta chains that are too long.
[git.git]
/
pack-objects.c
diff --git
a/pack-objects.c
b/pack-objects.c
index
38e1c99
..
0c9f4c9
100644
(file)
--- a/
pack-objects.c
+++ b/
pack-objects.c
@@
-10,16
+10,22
@@
static const char pack_usage[] = "git-pack-objects [-q] [--no-reuse-delta] [--no
struct object_entry {
unsigned char sha1[20];
unsigned long size; /* uncompressed size */
struct object_entry {
unsigned char sha1[20];
unsigned long size; /* uncompressed size */
- unsigned long offset; /* offset into the final pack file (nonzero if already written) */
+ unsigned long offset; /* offset into the final pack file;
+ * nonzero if already written.
+ */
unsigned int depth; /* delta depth */
unsigned int depth; /* delta depth */
+ unsigned int delta_limit; /* base adjustment for in-pack delta */
unsigned int hash; /* name hint hash */
enum object_type type;
unsigned int hash; /* name hint hash */
enum object_type type;
- unsigned char edge; /* reused delta chain points at this entry. */
enum object_type in_pack_type; /* could be delta */
unsigned long delta_size; /* delta data size (uncompressed) */
struct object_entry *delta; /* delta base object */
struct packed_git *in_pack; /* already in pack */
unsigned int in_pack_offset;
enum object_type in_pack_type; /* could be delta */
unsigned long delta_size; /* delta data size (uncompressed) */
struct object_entry *delta; /* delta base object */
struct packed_git *in_pack; /* already in pack */
unsigned int in_pack_offset;
+ struct object_entry *delta_child; /* delitified objects who bases me */
+ struct object_entry *delta_sibling; /* other deltified objects who
+ * uses the same base as me
+ */
};
/*
};
/*
@@
-470,7
+476,8
@@
static void check_object(struct object_entry *entry)
entry->delta = base_entry;
entry->type = OBJ_DELTA;
entry->delta = base_entry;
entry->type = OBJ_DELTA;
- base_entry->edge = 1;
+ entry->delta_sibling = base_entry->delta_child;
+ base_entry->delta_child = entry;
return;
}
return;
}
@@
-513,15
+520,32
@@
static void hash_objects(void)
}
}
}
}
+static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
+{
+ struct object_entry *child = me->delta_child;
+ unsigned int m = n;
+ while (child) {
+ unsigned int c = check_delta_limit(child, n + 1);
+ if (m < c)
+ m = c;
+ child = child->delta_sibling;
+ }
+ return m;
+}
+
static void get_object_details(void)
{
int i;
static void get_object_details(void)
{
int i;
- struct object_entry *entry
= objects
;
+ struct object_entry *entry;
hash_objects();
prepare_pack_ix();
hash_objects();
prepare_pack_ix();
- for (i = 0; i < nr_objects; i++)
- check_object(entry++);
+ for (i = 0, entry = objects; i < nr_objects; i++, entry++)
+ check_object(entry);
+ for (i = 0, entry = objects; i < nr_objects; i++, entry++)
+ if (!entry->delta && entry->delta_child)
+ entry->delta_limit =
+ check_delta_limit(entry, 1);
}
typedef int (*entry_sort_t)(const struct object_entry *, const struct object_entry *);
}
typedef int (*entry_sort_t)(const struct object_entry *, const struct object_entry *);
@@
-598,8
+622,11
@@
static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_de
* that depend on the current object into account -- otherwise
* they would become too deep.
*/
* that depend on the current object into account -- otherwise
* they would become too deep.
*/
- if (cur_entry->edge)
- max_depth /= 4;
+ if (cur_entry->delta_child) {
+ if (max_depth <= cur_entry->delta_limit)
+ return 0;
+ max_depth -= cur_entry->delta_limit;
+ }
size = cur_entry->size;
if (size < 50)
size = cur_entry->size;
if (size < 50)