blame: wrap blame_sort and compare_blame_final
[gitweb.git] / builtin / blame.c
index fdd41b41be019161f798bb676aeadd89ec10b23a..61fd5b477acb729856ebfd1a6395af8d4e4955fa 100644 (file)
@@ -125,7 +125,7 @@ struct progress_info {
 };
 
 static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b,
-                     xdl_emit_hunk_consume_func_t hunk_func, void *cb_data)
+                     xdl_emit_hunk_consume_func_t hunk_func, void *cb_data, int xdl_opts)
 {
        xpparam_t xpp = {0};
        xdemitconf_t xecfg = {0};
@@ -328,12 +328,6 @@ static int compare_blame_suspect(const void *p1, const void *p2)
        return s1->s_lno > s2->s_lno ? 1 : -1;
 }
 
-static struct blame_entry *blame_sort(struct blame_entry *head,
-                                     int (*compare_fn)(const void *, const void *))
-{
-       return llist_mergesort (head, get_next_blame, set_next_blame, compare_fn);
-}
-
 static int compare_commits_by_reverse_commit_date(const void *a,
                                                  const void *b,
                                                  void *c)
@@ -385,8 +379,23 @@ struct blame_scoreboard {
        /* flags */
        int reverse;
        int show_root;
+       int xdl_opts;
+       int no_whole_file_rename;
+       int debug;
+
+       /* callbacks */
+       void(*on_sanity_fail)(struct blame_scoreboard *, int);
+       void(*found_guilty_entry)(struct blame_entry *, void *);
+
+       void *found_guilty_entry_data;
 };
 
+static void blame_sort_final(struct blame_scoreboard *sb)
+{
+       sb->ent = llist_mergesort(sb->ent, get_next_blame, set_next_blame,
+                                 compare_blame_final);
+}
+
 static void sanity_check_refcnt(struct blame_scoreboard *);
 
 /*
@@ -410,7 +419,7 @@ static void blame_coalesce(struct blame_scoreboard *sb)
                }
        }
 
-       if (DEBUG) /* sanity */
+       if (sb->debug) /* sanity */
                sanity_check_refcnt(sb);
 }
 
@@ -948,7 +957,7 @@ static void pass_blame_to_parent(struct blame_scoreboard *sb,
        fill_origin_blob(&sb->revs->diffopt, target, &file_o, &sb->num_read_blob);
        sb->num_get_patch++;
 
-       if (diff_hunks(&file_p, &file_o, blame_chunk_cb, &d))
+       if (diff_hunks(&file_p, &file_o, blame_chunk_cb, &d, sb->xdl_opts))
                die("unable to generate diff (%s -> %s)",
                    oid_to_hex(&parent->commit->object.oid),
                    oid_to_hex(&target->commit->object.oid));
@@ -1097,7 +1106,7 @@ static void find_copy_in_blob(struct blame_scoreboard *sb,
         * file_p partially may match that image.
         */
        memset(split, 0, sizeof(struct blame_entry [3]));
-       if (diff_hunks(file_p, &file_o, handle_split_cb, &d))
+       if (diff_hunks(file_p, &file_o, handle_split_cb, &d, sb->xdl_opts))
                die("unable to generate diff (%s)",
                    oid_to_hex(&parent->commit->object.oid));
        /* remainder, if any, all match the preimage */
@@ -1369,7 +1378,8 @@ static int num_scapegoats(struct rev_info *revs, struct commit *commit, int reve
  */
 static void distribute_blame(struct blame_scoreboard *sb, struct blame_entry *blamed)
 {
-       blamed = blame_sort(blamed, compare_blame_suspect);
+       blamed = llist_mergesort(blamed, get_next_blame, set_next_blame,
+                                compare_blame_suspect);
        while (blamed)
        {
                struct blame_origin *porigin = blamed->suspect;
@@ -1410,7 +1420,7 @@ static void pass_blame(struct blame_scoreboard *sb, struct blame_origin *origin,
         * The first pass looks for unrenamed path to optimize for
         * common cases, then we look for renames in the second pass.
         */
-       for (pass = 0; pass < 2 - no_whole_file_rename; pass++) {
+       for (pass = 0; pass < 2 - sb->no_whole_file_rename; pass++) {
                struct blame_origin *(*find)(struct commit *, struct blame_origin *);
                find = pass ? find_rename : find_origin;
 
@@ -1723,9 +1733,10 @@ static int emit_one_suspect_detail(struct blame_origin *suspect, int repeat)
  * The blame_entry is found to be guilty for the range.
  * Show it in incremental output.
  */
-static void found_guilty_entry(struct blame_entry *ent,
-                          struct progress_info *pi)
+static void found_guilty_entry(struct blame_entry *ent, void *data)
 {
+       struct progress_info *pi = (struct progress_info *)data;
+
        if (incremental) {
                struct blame_origin *suspect = ent->suspect;
 
@@ -1748,11 +1759,6 @@ static void assign_blame(struct blame_scoreboard *sb, int opt)
 {
        struct rev_info *revs = sb->revs;
        struct commit *commit = prio_queue_get(&sb->commits);
-       struct progress_info pi = { NULL, 0 };
-
-       if (show_progress)
-               pi.progress = start_progress_delay(_("Blaming lines"),
-                                                  sb->num_lines, 50, 1);
 
        while (commit) {
                struct blame_entry *ent;
@@ -1794,7 +1800,8 @@ static void assign_blame(struct blame_scoreboard *sb, int opt)
                        suspect->guilty = 1;
                        for (;;) {
                                struct blame_entry *next = ent->next;
-                               found_guilty_entry(ent, &pi);
+                               if (sb->found_guilty_entry)
+                                       sb->found_guilty_entry(ent, sb->found_guilty_entry_data);
                                if (next) {
                                        ent = next;
                                        continue;
@@ -1807,11 +1814,9 @@ static void assign_blame(struct blame_scoreboard *sb, int opt)
                }
                blame_origin_decref(suspect);
 
-               if (DEBUG) /* sanity */
+               if (sb->debug) /* sanity */
                        sanity_check_refcnt(sb);
        }
-
-       stop_progress(&pi.progress);
 }
 
 static const char *format_time(timestamp_t time, const char *tz_str,
@@ -2146,12 +2151,16 @@ static void sanity_check_refcnt(struct blame_scoreboard *sb)
                        baa = 1;
                }
        }
-       if (baa) {
-               int opt = 0160;
-               find_alignment(sb, &opt);
-               output(sb, opt);
-               die("Baa %d!", baa);
-       }
+       if (baa)
+               sb->on_sanity_fail(sb, baa);
+}
+
+static void sanity_check_on_fail(struct blame_scoreboard *sb, int baa)
+{
+       int opt = OUTPUT_SHOW_SCORE | OUTPUT_SHOW_NUMBER | OUTPUT_SHOW_NAME;
+       find_alignment(sb, &opt);
+       output(sb, opt);
+       die("Baa %d!", baa);
 }
 
 static unsigned parse_score(const char *arg)
@@ -2540,6 +2549,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        char *final_commit_name = NULL;
        enum object_type type;
        struct commit *final_commit = NULL;
+       struct progress_info pi = { NULL, 0 };
 
        struct string_list range_list = STRING_LIST_INIT_NODUP;
        int output_option = 0, opt = 0;
@@ -2886,12 +2896,25 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        if (blame_copy_score)
                sb.copy_score = blame_copy_score;
 
+       sb.debug = DEBUG;
+       sb.on_sanity_fail = &sanity_check_on_fail;
+
        sb.show_root = show_root;
+       sb.xdl_opts = xdl_opts;
+       sb.no_whole_file_rename = no_whole_file_rename;
 
        read_mailmap(&mailmap, NULL);
 
+       sb.found_guilty_entry = &found_guilty_entry;
+       sb.found_guilty_entry_data = &pi;
+       if (show_progress)
+               pi.progress = start_progress_delay(_("Blaming lines"),
+                                                  sb.num_lines, 50, 1);
+
        assign_blame(&sb, opt);
 
+       stop_progress(&pi.progress);
+
        if (!incremental)
                setup_pager();
 
@@ -2900,7 +2923,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        if (incremental)
                return 0;
 
-       sb.ent = blame_sort(sb.ent, compare_blame_final);
+       blame_sort_final(&sb);
 
        blame_coalesce(&sb);