diff options
Diffstat (limited to 'line-log.c')
-rw-r--r-- | line-log.c | 145 |
1 files changed, 55 insertions, 90 deletions
diff --git a/line-log.c b/line-log.c index 717638b333..65f3558b3b 100644 --- a/line-log.c +++ b/line-log.c @@ -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) { @@ -112,7 +113,7 @@ void sort_and_merge_range_set(struct range_set *rs) int i; int o = 0; /* output cursor */ - qsort(rs->ranges, rs->nr, sizeof(struct range), range_cmp); + QSORT(rs->ranges, rs->nr, range_cmp); for (i = 0; i < rs->nr; i++) { if (rs->ranges[i].start == rs->ranges[i].end) @@ -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); } /* @@ -479,8 +480,7 @@ static struct commit *check_single_commit(struct rev_info *revs) struct object *obj = revs->pending.objects[i].item; if (obj->flags & UNINTERESTING) continue; - while (obj->type == OBJ_TAG) - obj = deref_tag(obj, NULL, 0); + obj = deref_tag(obj, NULL, 0); if (obj->type != OBJ_COMMIT) die("Non commit %s?", revs->pending.objects[i].name); if (commit) @@ -502,7 +502,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); @@ -519,9 +519,9 @@ static void fill_line_ends(struct diff_filespec *spec, long *lines, char *data = NULL; if (diff_populate_filespec(spec, 0)) - die("Cannot read blob %s", sha1_to_hex(spec->sha1)); + die("Cannot read blob %s", oid_to_hex(&spec->oid)); - ends = xmalloc(size * sizeof(*ends)); + ALLOC_ARRAY(ends, size); ends[cur++] = 0; data = spec->data; while (num < spec->size) { @@ -533,7 +533,7 @@ static void fill_line_ends(struct diff_filespec *spec, long *lines, } /* shrink the array to fit the elements */ - ends = xrealloc(ends, cur * sizeof(*ends)); + REALLOC_ARRAY(ends, cur); *lines = cur-1; *line_ends = ends; } @@ -575,7 +575,7 @@ parse_lines(struct commit *commit, const char *prefix, struct string_list *args) name_part = skip_range_arg(item->string); if (!name_part || *name_part != ':' || !name_part[1]) - die("-L argument '%s' not of the form start,end:file", + die("-L argument not 'start,end:file' or ':funcname:file': %s", item->string); range_part = xstrndup(item->string, name_part - item->string); name_part++; @@ -746,47 +746,21 @@ 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); } } -static void load_tree_desc(struct tree_desc *desc, void **tree, - const unsigned char *sha1) -{ - unsigned long size; - *tree = read_object_with_reference(sha1, tree_type, &size, NULL); - if (!*tree) - die("Unable to read tree (%s)", sha1_to_hex(sha1)); - init_tree_desc(desc, *tree, size); -} - -static int count_parents(struct commit *commit) -{ - struct commit_list *parents = commit->parents; - int count = 0; - while (parents) { - count++; - parents = parents->next; - } - return count; -} - static void move_diff_queue(struct diff_queue_struct *dst, struct diff_queue_struct *src) { @@ -842,18 +816,11 @@ static void queue_diffs(struct line_log_data *range, struct diff_queue_struct *queue, struct commit *commit, struct commit *parent) { - void *tree1 = NULL, *tree2 = NULL; - struct tree_desc desc1, desc2; - assert(commit); - load_tree_desc(&desc2, &tree2, commit->tree->object.sha1); - if (parent) - load_tree_desc(&desc1, &tree1, parent->tree->object.sha1); - else - init_tree_desc(&desc1, "", 0); DIFF_QUEUE_CLEAR(&diff_queued_diff); - diff_tree(&desc1, &desc2, "", 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()) @@ -861,11 +828,6 @@ static void queue_diffs(struct line_log_data *range, filter_diffs_for_paths(range, 0); } move_diff_queue(queue, &diff_queued_diff); - - if (tree1) - free(tree1); - if (tree2) - free(tree2); } static char *get_nth_line(long line, unsigned long *ends, void *data) @@ -878,7 +840,7 @@ static char *get_nth_line(long line, unsigned long *ends, void *data) static void print_line(const char *prefix, char first, long line, unsigned long *ends, void *data, - const char *color, const char *reset) + const char *color, const char *reset, FILE *file) { char *begin = get_nth_line(line, ends, data); char *end = get_nth_line(line+1, ends, data); @@ -889,14 +851,14 @@ static void print_line(const char *prefix, char first, had_nl = 1; } - fputs(prefix, stdout); - fputs(color, stdout); - putchar(first); - fwrite(begin, 1, end-begin, stdout); - fputs(reset, stdout); - putchar('\n'); + fputs(prefix, file); + fputs(color, file); + putc(first, file); + fwrite(begin, 1, end-begin, file); + fputs(reset, file); + putc('\n', file); if (!had_nl) - fputs("\\ No newline at end of file\n", stdout); + fputs("\\ No newline at end of file\n", file); } static char *output_prefix(struct diff_options *opt) @@ -926,21 +888,21 @@ 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; - if (pair->one->sha1_valid) + if (pair->one->oid_valid) fill_line_ends(pair->one, &p_lines, &p_ends); fill_line_ends(pair->two, &t_lines, &t_ends); - printf("%s%sdiff --git a/%s b/%s%s\n", prefix, c_meta, pair->one->path, pair->two->path, c_reset); - printf("%s%s--- %s%s%s\n", prefix, c_meta, - pair->one->sha1_valid ? "a/" : "", - pair->one->sha1_valid ? pair->one->path : "/dev/null", + fprintf(opt->file, "%s%sdiff --git a/%s b/%s%s\n", prefix, c_meta, pair->one->path, pair->two->path, c_reset); + fprintf(opt->file, "%s%s--- %s%s%s\n", prefix, c_meta, + pair->one->oid_valid ? "a/" : "", + pair->one->oid_valid ? pair->one->path : "/dev/null", c_reset); - printf("%s%s+++ b/%s%s\n", prefix, c_meta, pair->two->path, c_reset); + fprintf(opt->file, "%s%s+++ b/%s%s\n", prefix, c_meta, pair->two->path, c_reset); for (i = 0; i < range->ranges.nr; i++) { long p_start, p_end; long t_start = range->ranges.ranges[i].start; @@ -982,7 +944,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang } /* Now output a diff hunk for this range */ - printf("%s%s@@ -%ld,%ld +%ld,%ld @@%s\n", + fprintf(opt->file, "%s%s@@ -%ld,%ld +%ld,%ld @@%s\n", prefix, c_frag, p_start+1, p_end-p_start, t_start+1, t_end-t_start, c_reset); @@ -990,18 +952,18 @@ 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, opt->file); 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); + c_old, c_reset, opt->file); for (; t_cur < diff->target.ranges[j].end && t_cur < t_end; t_cur++) print_line(prefix, '+', t_cur, t_ends, pair->two->data, - c_new, c_reset); + c_new, c_reset, opt->file); j++; } 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, opt->file); } free(p_ends); @@ -1014,7 +976,7 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang */ static void dump_diff_hacky(struct rev_info *rev, struct line_log_data *range) { - puts(output_prefix(&rev->diffopt)); + fprintf(rev->diffopt.file, "%s\n", output_prefix(&rev->diffopt)); while (range) { dump_diff_hacky_one(rev, range); range = range->next; @@ -1048,12 +1010,12 @@ static int process_diff_filepair(struct rev_info *rev, if (rg->ranges.nr == 0) return 0; - assert(pair->two->sha1_valid); + assert(pair->two->oid_valid); diff_populate_filespec(pair->two, 0); file_target.ptr = pair->two->data; file_target.size = pair->two->size; - if (pair->one->sha1_valid) { + if (pair->one->oid_valid) { diff_populate_filespec(pair->one, 0); file_parent.ptr = pair->one->data; file_parent.size = pair->one->size; @@ -1063,7 +1025,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); @@ -1132,6 +1095,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; @@ -1172,11 +1136,14 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm struct commit **parents; struct commit_list *p; int i; - int nparents = count_parents(commit); + int nparents = commit_list_count(commit->parents); + + 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++) { @@ -1196,9 +1163,7 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm */ add_line_range(rev, parents[i], cand[i]); clear_commit_line_range(rev, commit); - commit->parents = xmalloc(sizeof(struct commit_list)); - commit->parents->item = parents[i]; - commit->parents->next = NULL; + commit_list_append(parents[i], &commit->parents); free(parents); free(cand); free_diffqueues(nparents, diffqueues); |