add--interactive: allow custom diff highlighting programs
[gitweb.git] / line-log.c
index 1a6bc5921b4890273e4e9edab4d456cc27fd4064..bbe31ed6fbb7c103c739f7e9a3c45cde5d36fcec 100644 (file)
@@ -14,6 +14,7 @@
 #include "graph.h"
 #include "userdiff.h"
 #include "line-log.h"
+#include "argv-array.h"
 
 static void range_set_grow(struct range_set *rs, size_t extra)
 {
@@ -237,7 +238,7 @@ static void diff_ranges_release(struct diff_ranges *diff)
        range_set_release(&diff->target);
 }
 
-void line_log_data_init(struct line_log_data *r)
+static void line_log_data_init(struct line_log_data *r)
 {
        memset(r, 0, sizeof(struct line_log_data));
        range_set_init(&r->ranges, 0);
@@ -325,7 +326,7 @@ static int collect_diff_cb(long start_a, long count_a,
        return 0;
 }
 
-static void collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges *out)
+static int collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges *out)
 {
        struct collect_diff_cbdata cbdata = {NULL};
        xpparam_t xpp;
@@ -340,7 +341,7 @@ static void collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges
        xecfg.hunk_func = collect_diff_cb;
        memset(&ecb, 0, sizeof(ecb));
        ecb.priv = &cbdata;
-       xdi_diff(parent, target, &xpp, &xecfg, &ecb);
+       return xdi_diff(parent, target, &xpp, &xecfg, &ecb);
 }
 
 /*
@@ -502,7 +503,7 @@ static void fill_blob_sha1(struct commit *commit, struct diff_filespec *spec)
        unsigned mode;
        unsigned char sha1[20];
 
-       if (get_tree_entry(commit->object.sha1, spec->path,
+       if (get_tree_entry(commit->object.oid.hash, spec->path,
                           sha1, &mode))
                die("There is no path %s in the commit", spec->path);
        fill_filespec(spec, sha1, 1, mode);
@@ -521,7 +522,7 @@ static void fill_line_ends(struct diff_filespec *spec, long *lines,
        if (diff_populate_filespec(spec, 0))
                die("Cannot read blob %s", sha1_to_hex(spec->sha1));
 
-       ends = xmalloc(size * sizeof(*ends));
+       ALLOC_ARRAY(ends, size);
        ends[cur++] = 0;
        data = spec->data;
        while (num < spec->size) {
@@ -746,22 +747,17 @@ void line_log_init(struct rev_info *rev, const char *prefix, struct string_list
        add_line_range(rev, commit, range);
 
        if (!rev->diffopt.detect_rename) {
-               int i, count = 0;
-               struct line_log_data *r = range;
+               struct line_log_data *r;
+               struct argv_array array = ARGV_ARRAY_INIT;
                const char **paths;
-               while (r) {
-                       count++;
-                       r = r->next;
-               }
-               paths = xmalloc((count+1)*sizeof(char *));
-               r = range;
-               for (i = 0; i < count; i++) {
-                       paths[i] = xstrdup(r->path);
-                       r = r->next;
-               }
-               paths[count] = NULL;
+
+               for (r = range; r; r = r->next)
+                       argv_array_push(&array, r->path);
+               paths = argv_array_detach(&array);
+
                parse_pathspec(&rev->diffopt.pathspec, 0,
                               PATHSPEC_PREFER_FULL, "", paths);
+               /* strings are now owned by pathspec */
                free(paths);
        }
 }
@@ -824,8 +820,8 @@ static void queue_diffs(struct line_log_data *range,
        assert(commit);
 
        DIFF_QUEUE_CLEAR(&diff_queued_diff);
-       diff_tree_sha1(parent ? parent->tree->object.sha1 : NULL,
-                       commit->tree->object.sha1, "", opt);
+       diff_tree_sha1(parent ? parent->tree->object.oid.hash : NULL,
+                       commit->tree->object.oid.hash, "", opt);
        if (opt->detect_rename) {
                filter_diffs_for_paths(range, 1);
                if (diff_might_be_rename())
@@ -893,7 +889,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
        const char *c_meta = diff_get_color(opt->use_color, DIFF_METAINFO);
        const char *c_old = diff_get_color(opt->use_color, DIFF_FILE_OLD);
        const char *c_new = diff_get_color(opt->use_color, DIFF_FILE_NEW);
-       const char *c_plain = diff_get_color(opt->use_color, DIFF_PLAIN);
+       const char *c_context = diff_get_color(opt->use_color, DIFF_CONTEXT);
 
        if (!pair || !diff)
                return;
@@ -957,7 +953,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
                        int k;
                        for (; t_cur < diff->target.ranges[j].start; t_cur++)
                                print_line(prefix, ' ', t_cur, t_ends, pair->two->data,
-                                          c_plain, c_reset);
+                                          c_context, c_reset);
                        for (k = diff->parent.ranges[j].start; k < diff->parent.ranges[j].end; k++)
                                print_line(prefix, '-', k, p_ends, pair->one->data,
                                           c_old, c_reset);
@@ -968,7 +964,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
                }
                for (; t_cur < t_end; t_cur++)
                        print_line(prefix, ' ', t_cur, t_ends, pair->two->data,
-                                  c_plain, c_reset);
+                                  c_context, c_reset);
        }
 
        free(p_ends);
@@ -1030,7 +1026,8 @@ static int process_diff_filepair(struct rev_info *rev,
        }
 
        diff_ranges_init(&diff);
-       collect_diff(&file_parent, &file_target, &diff);
+       if (collect_diff(&file_parent, &file_target, &diff))
+               die("unable to generate diff for %s", pair->one->path);
 
        /* NEEDSWORK should apply some heuristics to prevent mismatches */
        free(rg->path);
@@ -1099,6 +1096,7 @@ static int process_all_files(struct line_log_data **range_out,
                        rg->pair = diff_filepair_dup(queue->queue[i]);
                        memcpy(&rg->diff, pairdiff, sizeof(struct diff_ranges));
                }
+               free(pairdiff);
        }
 
        return changed;
@@ -1144,9 +1142,9 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
        if (nparents > 1 && rev->first_parent_only)
                nparents = 1;
 
-       diffqueues = xmalloc(nparents * sizeof(*diffqueues));
-       cand = xmalloc(nparents * sizeof(*cand));
-       parents = xmalloc(nparents * sizeof(*parents));
+       ALLOC_ARRAY(diffqueues, nparents);
+       ALLOC_ARRAY(cand, nparents);
+       ALLOC_ARRAY(parents, nparents);
 
        p = commit->parents;
        for (i = 0; i < nparents; i++) {