send-email: try to order messages in email clients more correctly
[git.git] / diffcore-break.c
index 8cbb99f..0fc2b86 100644 (file)
@@ -4,8 +4,6 @@
 #include "cache.h"
 #include "diff.h"
 #include "diffcore.h"
-#include "delta.h"
-#include "count-delta.h"
 
 static int should_break(struct diff_filespec *src,
                        struct diff_filespec *dst,
@@ -47,7 +45,6 @@ static int should_break(struct diff_filespec *src,
         * The value we return is 1 if we want the pair to be broken,
         * or 0 if we do not.
         */
-       void *delta;
        unsigned long delta_size, base_size, src_copied, literal_added;
        int to_break = 0;
 
@@ -58,29 +55,22 @@ static int should_break(struct diff_filespec *src,
        if (!S_ISREG(src->mode) || !S_ISREG(dst->mode))
                return 0; /* leave symlink rename alone */
 
+       if (src->sha1_valid && dst->sha1_valid &&
+           !memcmp(src->sha1, dst->sha1, 20))
+               return 0; /* they are the same */
+
        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);
-
-       delta = diff_delta(src->data, src->size,
-                          dst->data, dst->size,
-                          &delta_size);
+       base_size = ((src->size < dst->size) ? src->size : dst->size);
+       if (base_size < MINIMUM_BREAK_SIZE)
+               return 0; /* we do not break too small filepair */
 
-       /* Estimate the edit size by interpreting delta. */
-       if (count_delta(delta, delta_size,
-                       &src_copied, &literal_added)) {
-               free(delta);
-               return 0; /* we cannot tell */
-       }
-       free(delta);
+       if (diffcore_count_changes(src->data, src->size,
+                                  dst->data, dst->size,
+                                  0,
+                                  &src_copied, &literal_added))
+               return 0;
 
        /* Compute merge-score, which is "how much is removed
         * from the source material".  The clean-up stage will
@@ -88,10 +78,11 @@ static int should_break(struct diff_filespec *src,
         * 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.
@@ -185,8 +176,7 @@ void diffcore_break(int break_score)
                                 * 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 */
@@ -220,7 +210,7 @@ static void merge_broken(struct diff_filepair *p,
                         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;
@@ -235,7 +225,8 @@ static void merge_broken(struct diff_filepair *p,
        if (!DIFF_FILE_VALID(c->two))
                die("internal error in merge #4");
 
-       diff_queue(outq, d->one, c->two);
+       dp = diff_queue(outq, d->one, c->two);
+       dp->score = p->score;
        diff_free_filespec_data(d->two);
        diff_free_filespec_data(c->one);
        free(d);
@@ -257,7 +248,6 @@ void diffcore_merge_broken(void)
                        /* 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.
@@ -265,7 +255,6 @@ void diffcore_merge_broken(void)
                        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 */