1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-11-05 08:47:56 +01:00

count-delta: tweak counting of copied source material.

With the finer grained delta algorithm, count-delta algorithm
started overcounting copied source material, since the new delta
output tends to reuse the same source range more than once and
more aggressively.  This broke an earlier assumption that the
number of bytes copied out from the source buffer is a good
approximation how much source material is actually remaining in
the result.

This uses fairly inefficient algorithm to keep track of ranges
of source material that are actually copied out to the
destination buffer.  With this tweak, the obvious rename/break
detection tests in the testsuite start to work again.

Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Junio C Hamano 2006-02-23 02:58:37 -08:00
parent 6b7d25d97b
commit 907380eeff

View file

@ -3,11 +3,74 @@
* The delta-parsing part is almost straight copy of patch-delta.c * The delta-parsing part is almost straight copy of patch-delta.c
* which is (C) 2005 Nicolas Pitre <nico@cam.org>. * which is (C) 2005 Nicolas Pitre <nico@cam.org>.
*/ */
#include "cache.h"
#include "delta.h"
#include "count-delta.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include "delta.h"
#include "count-delta.h" struct span {
struct span *next;
unsigned long ofs;
unsigned long end;
};
static void touch_range(struct span **span,
unsigned long ofs, unsigned long end)
{
struct span *e = *span;
struct span *p = NULL;
while (e && e->ofs <= ofs) {
again:
if (ofs < e->end) {
while (e->end < end) {
if (e->next) {
e->end = e->next->ofs;
e = e->next;
}
else {
e->end = end;
return;
}
}
return;
}
p = e;
e = e->next;
}
if (e && e->ofs <= end) {
e->ofs = ofs;
goto again;
}
else {
e = xmalloc(sizeof(*e));
e->ofs = ofs;
e->end = end;
if (p) {
e->next = p->next;
p->next = e;
}
else {
e->next = *span;
*span = e;
}
}
}
static unsigned long count_range(struct span *s)
{
struct span *t;
unsigned long sz = 0;
while (s) {
t = s;
sz += s->end - s->ofs;
s = s->next;
free(t);
}
return sz;
}
/* /*
* NOTE. We do not _interpret_ delta fully. As an approximation, we * NOTE. We do not _interpret_ delta fully. As an approximation, we
@ -21,10 +84,11 @@
int count_delta(void *delta_buf, unsigned long delta_size, int count_delta(void *delta_buf, unsigned long delta_size,
unsigned long *src_copied, unsigned long *literal_added) unsigned long *src_copied, unsigned long *literal_added)
{ {
unsigned long copied_from_source, added_literal; unsigned long added_literal;
const unsigned char *data, *top; const unsigned char *data, *top;
unsigned char cmd; unsigned char cmd;
unsigned long src_size, dst_size, out; unsigned long src_size, dst_size, out;
struct span *span = NULL;
if (delta_size < DELTA_SIZE_MIN) if (delta_size < DELTA_SIZE_MIN)
return -1; return -1;
@ -35,7 +99,7 @@ int count_delta(void *delta_buf, unsigned long delta_size,
src_size = get_delta_hdr_size(&data); src_size = get_delta_hdr_size(&data);
dst_size = get_delta_hdr_size(&data); dst_size = get_delta_hdr_size(&data);
added_literal = copied_from_source = out = 0; added_literal = out = 0;
while (data < top) { while (data < top) {
cmd = *data++; cmd = *data++;
if (cmd & 0x80) { if (cmd & 0x80) {
@ -49,7 +113,7 @@ int count_delta(void *delta_buf, unsigned long delta_size,
if (cmd & 0x40) cp_size |= (*data++ << 16); if (cmd & 0x40) cp_size |= (*data++ << 16);
if (cp_size == 0) cp_size = 0x10000; if (cp_size == 0) cp_size = 0x10000;
copied_from_source += cp_size; touch_range(&span, cp_off, cp_off+cp_size);
out += cp_size; out += cp_size;
} else { } else {
/* write literal into dst */ /* write literal into dst */
@ -59,6 +123,8 @@ int count_delta(void *delta_buf, unsigned long delta_size,
} }
} }
*src_copied = count_range(span);
/* sanity check */ /* sanity check */
if (data != top || out != dst_size) if (data != top || out != dst_size)
return -1; return -1;
@ -66,7 +132,6 @@ int count_delta(void *delta_buf, unsigned long delta_size,
/* delete size is what was _not_ copied from source. /* delete size is what was _not_ copied from source.
* edit size is that and literal additions. * edit size is that and literal additions.
*/ */
*src_copied = copied_from_source;
*literal_added = added_literal; *literal_added = added_literal;
return 0; return 0;
} }