blame: Notice a wholesale incorporation of an existing file.
[gitweb.git] / builtin-blame.c
index 8919b028e620d573e30203c5bffafce9b5776406..f8843e6340acca5cb46d533135df440166b14293 100644 (file)
@@ -890,6 +890,39 @@ static void copy_split_if_better(struct scoreboard *sb,
        memcpy(best_so_far, this, sizeof(struct blame_entry [3]));
 }
 
+/*
+ * We are looking at a part of the final image represented by
+ * ent (tlno and same are offset by ent->s_lno).
+ * tlno is where we are looking at in the final image.
+ * up to (but not including) same match preimage.
+ * plno is where we are looking at in the preimage.
+ *
+ * <-------------- final image ---------------------->
+ *       <------ent------>
+ *         ^tlno ^same
+ *    <---------preimage----->
+ *         ^plno
+ *
+ * All line numbers are 0-based.
+ */
+static void handle_split(struct scoreboard *sb,
+                        struct blame_entry *ent,
+                        int tlno, int plno, int same,
+                        struct origin *parent,
+                        struct blame_entry *split)
+{
+       if (ent->num_lines <= tlno)
+               return;
+       if (tlno < same) {
+               struct blame_entry this[3];
+               tlno += ent->s_lno;
+               same += ent->s_lno;
+               split_overlap(this, ent, tlno, plno, same, parent);
+               copy_split_if_better(sb, split, this);
+               decref_split(this);
+       }
+}
+
 /*
  * Find the lines from parent that are the same as ent so that
  * we can pass blames to it.  file_p has the blob contents for
@@ -922,26 +955,21 @@ static void find_copy_in_blob(struct scoreboard *sb,
 
        patch = compare_buffer(file_p, &file_o, 1);
 
+       /*
+        * file_o is a part of final image we are annotating.
+        * file_p partially may match that image.
+        */
        memset(split, 0, sizeof(struct blame_entry [3]));
        plno = tlno = 0;
        for (i = 0; i < patch->num; i++) {
                struct chunk *chunk = &patch->chunks[i];
 
-               /* tlno to chunk->same are the same as ent */
-               if (ent->num_lines <= tlno)
-                       break;
-               if (tlno < chunk->same) {
-                       struct blame_entry this[3];
-                       split_overlap(this, ent,
-                                     tlno + ent->s_lno, plno,
-                                     chunk->same + ent->s_lno,
-                                     parent);
-                       copy_split_if_better(sb, split, this);
-                       decref_split(this);
-               }
+               handle_split(sb, ent, tlno, plno, chunk->same, parent, split);
                plno = chunk->p_next;
                tlno = chunk->t_next;
        }
+       /* remainder, if any, all match the preimage */
+       handle_split(sb, ent, tlno, plno, ent->num_lines, parent, split);
        free_patch(patch);
 }