blame: wrap blame_sort and compare_blame_final
[gitweb.git] / builtin / blame.c
index 8e676fb933d06ff7d2112f56cc1f3070fd47a6b5..61fd5b477acb729856ebfd1a6395af8d4e4955fa 100644 (file)
@@ -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)
@@ -386,8 +380,22 @@ struct blame_scoreboard {
        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 *);
 
 /*
@@ -411,7 +419,7 @@ static void blame_coalesce(struct blame_scoreboard *sb)
                }
        }
 
-       if (DEBUG) /* sanity */
+       if (sb->debug) /* sanity */
                sanity_check_refcnt(sb);
 }
 
@@ -1370,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;
@@ -1411,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;
 
@@ -1724,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;
 
@@ -1749,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;
@@ -1795,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;
@@ -1808,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,
@@ -2147,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)
@@ -2541,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;
@@ -2887,13 +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();
 
@@ -2902,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);