mirror of
https://github.com/git/git.git
synced 2024-11-18 17:23:49 +01:00
Add a "max_size" parameter to diff_delta()
Anything that generates a delta to see if two objects are close usually isn't interested in the delta ends up being bigger than some specified size, and this allows us to stop delta generation early when that happens.
This commit is contained in:
parent
78817c15de
commit
75c42d8cc3
2
delta.h
2
delta.h
@ -4,7 +4,7 @@
|
||||
/* handling of delta buffers */
|
||||
extern void *diff_delta(void *from_buf, unsigned long from_size,
|
||||
void *to_buf, unsigned long to_size,
|
||||
unsigned long *delta_size);
|
||||
unsigned long *delta_size, unsigned long max_size);
|
||||
extern void *patch_delta(void *src_buf, unsigned long src_size,
|
||||
void *delta_buf, unsigned long delta_size,
|
||||
unsigned long *dst_size);
|
||||
|
@ -203,7 +203,8 @@ static void delta_cleanup(bdfile_t *bdf)
|
||||
|
||||
void *diff_delta(void *from_buf, unsigned long from_size,
|
||||
void *to_buf, unsigned long to_size,
|
||||
unsigned long *delta_size)
|
||||
unsigned long *delta_size,
|
||||
unsigned long max_size)
|
||||
{
|
||||
int i, outpos, outsize, inscnt, csize, msize, moff;
|
||||
unsigned int fp;
|
||||
@ -312,6 +313,11 @@ void *diff_delta(void *from_buf, unsigned long from_size,
|
||||
}
|
||||
|
||||
/* next time around the largest possible output is 1 + 4 + 3 */
|
||||
if (max_size && outpos > max_size) {
|
||||
free(out);
|
||||
delta_cleanup(&bdf);
|
||||
return NULL;
|
||||
}
|
||||
if (outpos > outsize - 8) {
|
||||
void *tmp = out;
|
||||
outsize = outsize * 3 / 2;
|
||||
|
@ -65,7 +65,7 @@ static int should_break(struct diff_filespec *src,
|
||||
|
||||
delta = diff_delta(src->data, src->size,
|
||||
dst->data, dst->size,
|
||||
&delta_size);
|
||||
&delta_size, ~0UL);
|
||||
|
||||
/* Estimate the edit size by interpreting delta. */
|
||||
if (count_delta(delta, delta_size,
|
||||
|
@ -165,7 +165,7 @@ static int estimate_similarity(struct diff_filespec *src,
|
||||
|
||||
delta = diff_delta(src->data, src->size,
|
||||
dst->data, dst->size,
|
||||
&delta_size);
|
||||
&delta_size, ~0UL);
|
||||
|
||||
/* A delta that has a lot of literal additions would have
|
||||
* big delta_size no matter what else it does.
|
||||
|
@ -278,7 +278,8 @@ int main(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
delta_buf = diff_delta(ref[r].buf, ref[r].size,
|
||||
trg.buf, trg.size, &delta_size);
|
||||
trg.buf, trg.size,
|
||||
&delta_size, ~0UL);
|
||||
if (!delta_buf)
|
||||
die("out of memory");
|
||||
if (trg.depth < max_depth &&
|
||||
|
@ -83,8 +83,8 @@ static void *delta_against(void *buf, unsigned long size, struct object_entry *e
|
||||
|
||||
if (!otherbuf)
|
||||
die("unable to read %s", sha1_to_hex(entry->delta->sha1));
|
||||
delta_buf = diff_delta(buf, size, otherbuf, othersize, &delta_size);
|
||||
if (delta_size != entry->delta_size)
|
||||
delta_buf = diff_delta(buf, size, otherbuf, othersize, &delta_size, ~0UL);
|
||||
if (!delta_buf || delta_size != entry->delta_size)
|
||||
die("delta size changed");
|
||||
free(buf);
|
||||
free(otherbuf);
|
||||
@ -292,6 +292,7 @@ static int try_delta(struct unpacked *cur, struct unpacked *old)
|
||||
struct object_entry *cur_entry = cur->entry;
|
||||
struct object_entry *old_entry = old->entry;
|
||||
unsigned long size, oldsize, delta_size;
|
||||
long max_size;
|
||||
void *delta_buf;
|
||||
|
||||
/* Don't bother doing diffs between different types */
|
||||
@ -300,6 +301,8 @@ static int try_delta(struct unpacked *cur, struct unpacked *old)
|
||||
|
||||
/* Size is guaranteed to be larger than or equal to oldsize */
|
||||
size = cur_entry->size;
|
||||
if (size < 50)
|
||||
return -1;
|
||||
oldsize = old_entry->size;
|
||||
if (size - oldsize > oldsize / 4)
|
||||
return -1;
|
||||
@ -311,15 +314,14 @@ static int try_delta(struct unpacked *cur, struct unpacked *old)
|
||||
* more space-efficient (deletes don't have to say _what_ they
|
||||
* delete).
|
||||
*/
|
||||
delta_buf = diff_delta(cur->data, size, old->data, oldsize, &delta_size);
|
||||
max_size = size / 2 - 20;
|
||||
if (cur_entry->delta)
|
||||
max_size = cur_entry->delta_size-1;
|
||||
delta_buf = diff_delta(cur->data, size, old->data, oldsize, &delta_size, max_size);
|
||||
if (!delta_buf)
|
||||
die("unable to create delta");
|
||||
if (delta_size + 20 < size / 2) {
|
||||
if (!cur_entry->delta || cur_entry->delta_size > delta_size) {
|
||||
cur_entry->delta = old_entry;
|
||||
cur_entry->delta_size = delta_size;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
cur_entry->delta = old_entry;
|
||||
cur_entry->delta_size = delta_size;
|
||||
free(delta_buf);
|
||||
return 0;
|
||||
}
|
||||
|
@ -60,10 +60,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (argv[1][1] == 'd')
|
||||
out_buf = diff_delta(from_buf, from_size,
|
||||
data_buf, data_size, &out_size);
|
||||
data_buf, data_size,
|
||||
&out_size, ~0UL);
|
||||
else
|
||||
out_buf = patch_delta(from_buf, from_size,
|
||||
data_buf, data_size, &out_size);
|
||||
data_buf, data_size,
|
||||
&out_size);
|
||||
if (!out_buf) {
|
||||
fprintf(stderr, "delta operation failed (returned NULL)\n");
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user