builtin-grep: -w fix
[gitweb.git] / diffcore-break.c
index 06f9a7f0ee25891ff6f4dd9646e39cd4c8b105fd..ed0e14c6d8b1b8347f20c890854972be6c6a234c 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,9 +45,8 @@ 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;
+       unsigned long delta_size, base_size, src_copied, literal_added,
+               src_removed;
 
        *merge_score_p = 0; /* assume no deletion --- "do not break"
                             * is the default.
@@ -58,50 +55,58 @@ 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 */
 
        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 */
 
-       delta = diff_delta(src->data, src->size,
-                          dst->data, dst->size,
-                          &delta_size, 0);
+       if (diffcore_count_changes(src->data, src->size,
+                                  dst->data, dst->size,
+                                  NULL, NULL,
+                                  0,
+                                  &src_copied, &literal_added))
+               return 0;
 
-       /* Estimate the edit size by interpreting delta. */
-       if (count_delta(delta, delta_size,
-                       &src_copied, &literal_added)) {
-               free(delta);
-               return 0; /* we cannot tell */
+       /* sanity */
+       if (src->size < src_copied)
+               src_copied = src->size;
+       if (dst->size < literal_added + src_copied) {
+               if (src_copied < dst->size)
+                       literal_added = dst->size - src_copied;
+               else
+                       literal_added = 0;
        }
-       free(delta);
+       src_removed = src->size - src_copied;
 
        /* Compute merge-score, which is "how much is removed
         * from the source material".  The clean-up stage will
         * merge the surviving pair together if the score is
         * less than the minimum, after rename/copy runs.
         */
-       if (src->size <= src_copied)
-               ; /* all copied, nothing removed */
-       else {
-               delta_size = src->size - src_copied;
-               *merge_score_p = delta_size * MAX_SCORE / src->size;
-       }
-       
+       *merge_score_p = src_removed * MAX_SCORE / src->size;
+
        /* Extent of damage, which counts both inserts and
         * deletes.
         */
-       if (src->size + literal_added <= src_copied)
-               delta_size = 0; /* avoid wrapping around */
-       else
-               delta_size = (src->size - src_copied) + literal_added;
-       
-       /* We break if the edit exceeds the minimum.
-        * i.e. (break_score / MAX_SCORE < delta_size / base_size)
+       delta_size = src_removed + literal_added;
+       if (delta_size * MAX_SCORE / base_size < break_score)
+               return 0;
+
+       /* If you removed a lot without adding new material, that is
+        * not really a rewrite.
         */
-       if (break_score * base_size < delta_size * MAX_SCORE)
-               to_break = 1;
+       if ((src->size * break_score < src_removed * MAX_SCORE) &&
+           (literal_added * 20 < src_removed) &&
+           (literal_added * 20 < src_copied))
+               return 0;
 
-       return to_break;
+       return 1;
 }
 
 void diffcore_break(int break_score)
@@ -168,8 +173,7 @@ void diffcore_break(int break_score)
                    !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) &&
-                           MINIMUM_BREAK_SIZE <= p->one->size) {
+                                        break_score, &score)) {
                                /* Split this into delete and create */
                                struct diff_filespec *null_one, *null_two;
                                struct diff_filepair *dp;