if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
return 0; /* error but caught downstream */
- delta_size = ((src->size < dst->size) ?
- (dst->size - src->size) : (src->size - dst->size));
-
- /* Notice that we use max of src and dst as the base size,
- * unlike rename similarity detection. This is so that we do
- * not mistake a large addition as a complete rewrite.
- */
- base_size = ((src->size < dst->size) ? dst->size : src->size);
+ base_size = ((src->size < dst->size) ? src->size : dst->size);
delta = diff_delta(src->data, src->size,
dst->data, dst->size,
- &delta_size);
+ &delta_size, 0);
/* Estimate the edit size by interpreting delta. */
if (count_delta(delta, delta_size,
* less than the minimum, after rename/copy runs.
*/
if (src->size <= src_copied)
- delta_size = 0; /* avoid wrapping around */
- else
+ ; /* all copied, nothing removed */
+ else {
delta_size = src->size - src_copied;
- *merge_score_p = delta_size * MAX_SCORE / src->size;
+ *merge_score_p = delta_size * MAX_SCORE / src->size;
+ }
/* Extent of damage, which counts both inserts and
* deletes.
!S_ISDIR(p->one->mode) && !S_ISDIR(p->two->mode) &&
!strcmp(p->one->path, p->two->path)) {
if (should_break(p->one, p->two,
- break_score, &score)) {
+ break_score, &score) &&
+ MINIMUM_BREAK_SIZE <= p->one->size) {
/* Split this into delete and create */
struct diff_filespec *null_one, *null_two;
struct diff_filepair *dp;
* Also we do not want to break very
* small files.
*/
- if ((score < merge_score) ||
- (p->one->size < MINIMUM_BREAK_SIZE))
+ if (score < merge_score)
score = 0;
/* deletion of one */
struct diff_queue_struct *outq)
{
/* p and pp are broken pairs we want to merge */
- struct diff_filepair *c = p, *d = pp;
+ struct diff_filepair *c = p, *d = pp, *dp;
if (DIFF_FILE_VALID(p->one)) {
/* this must be a delete half */
d = p; c = pp;
if (!DIFF_FILE_VALID(c->two))
die("internal error in merge #4");
- diff_queue(outq, d->one, c->two);
- diff_free_filespec_data(d->two);
- diff_free_filespec_data(c->one);
+ dp = diff_queue(outq, d->one, c->two);
+ dp->score = p->score;
+ diff_free_filespec(d->two);
+ diff_free_filespec(c->one);
free(d);
free(c);
}
/* we already merged this with its peer */
continue;
else if (p->broken_pair &&
- p->score == 0 &&
!strcmp(p->one->path, p->two->path)) {
/* If the peer also survived rename/copy, then
* we merge them back together.
for (j = i + 1; j < q->nr; j++) {
struct diff_filepair *pp = q->queue[j];
if (pp->broken_pair &&
- p->score == 0 &&
!strcmp(pp->one->path, pp->two->path) &&
!strcmp(p->one->path, pp->two->path)) {
/* Peer survived. Merge them */