summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--line-log.c45
-rw-r--r--line-log.h8
-rwxr-xr-xt/t4211-line-log.sh2
3 files changed, 31 insertions, 24 deletions
diff --git a/line-log.c b/line-log.c
index 85c7c249f4..44d1cd510d 100644
--- a/line-log.c
+++ b/line-log.c
@@ -265,7 +265,7 @@ search_line_log_data(struct line_log_data *list, const char *path,
if (insertion_point)
*insertion_point = NULL;
while (p) {
- int cmp = strcmp(p->spec->path, path);
+ int cmp = strcmp(p->path, path);
if (!cmp)
return p;
if (insertion_point && cmp < 0)
@@ -275,22 +275,26 @@ search_line_log_data(struct line_log_data *list, const char *path,
return NULL;
}
+/*
+ * Note: takes ownership of 'path', which happens to be what the only
+ * caller needs.
+ */
static void line_log_data_insert(struct line_log_data **list,
- struct diff_filespec *spec,
+ char *path,
long begin, long end)
{
struct line_log_data *ip;
- struct line_log_data *p = search_line_log_data(*list, spec->path, &ip);
+ struct line_log_data *p = search_line_log_data(*list, path, &ip);
if (p) {
range_set_append_unsafe(&p->ranges, begin, end);
sort_and_merge_range_set(&p->ranges);
- free_filespec(spec);
+ free(path);
return;
}
p = xcalloc(1, sizeof(struct line_log_data));
- p->spec = spec;
+ p->path = path;
range_set_append(&p->ranges, begin, end);
if (ip) {
p->next = ip->next;
@@ -354,7 +358,7 @@ static void dump_line_log_data(struct line_log_data *r)
{
char buf[4096];
while (r) {
- snprintf(buf, 4096, "file %s\n", r->spec->path);
+ snprintf(buf, 4096, "file %s\n", r->path);
dump_range_set(&r->ranges, buf);
r = r->next;
}
@@ -561,7 +565,7 @@ parse_lines(struct commit *commit, const char *prefix, struct string_list *args)
for_each_string_list_item(item, args) {
const char *name_part, *range_part;
- const char *full_name;
+ char *full_name;
struct diff_filespec *spec;
long begin = 0, end = 0;
@@ -584,7 +588,7 @@ parse_lines(struct commit *commit, const char *prefix, struct string_list *args)
if (parse_range_arg(range_part, nth_line, &cb_data,
lines, &begin, &end,
- spec->path))
+ full_name))
die("malformed -L argument '%s'", range_part);
if (begin < 1)
begin = 1;
@@ -593,8 +597,9 @@ parse_lines(struct commit *commit, const char *prefix, struct string_list *args)
begin--;
if (lines < end || lines < begin)
die("file %s has only %ld lines", name_part, lines);
- line_log_data_insert(&ranges, spec, begin, end);
+ line_log_data_insert(&ranges, full_name, begin, end);
+ free_filespec(spec);
free(ends);
ends = NULL;
}
@@ -610,9 +615,7 @@ static struct line_log_data *line_log_data_copy_one(struct line_log_data *r)
line_log_data_init(ret);
range_set_copy(&ret->ranges, &r->ranges);
- ret->spec = r->spec;
- assert(ret->spec);
- ret->spec->count++;
+ ret->path = xstrdup(r->path);
return ret;
}
@@ -652,7 +655,7 @@ static struct line_log_data *line_log_data_merge(struct line_log_data *a,
else if (!b)
cmp = -1;
else
- cmp = strcmp(a->spec->path, b->spec->path);
+ cmp = strcmp(a->path, b->path);
if (cmp < 0) {
src = a;
a = a->next;
@@ -667,8 +670,7 @@ static struct line_log_data *line_log_data_merge(struct line_log_data *a,
}
d = xmalloc(sizeof(struct line_log_data));
line_log_data_init(d);
- d->spec = src->spec;
- d->spec->count++;
+ d->path = xstrdup(src->path);
*pp = d;
pp = &d->next;
if (src2)
@@ -741,7 +743,7 @@ void line_log_init(struct rev_info *rev, const char *prefix, struct string_list
paths = xmalloc((count+1)*sizeof(char *));
r = range;
for (i = 0; i < count; i++) {
- paths[i] = xstrdup(r->spec->path);
+ paths[i] = xstrdup(r->path);
r = r->next;
}
paths[count] = NULL;
@@ -797,7 +799,7 @@ static void filter_diffs_for_paths(struct line_log_data *range, int keep_deletio
continue;
}
for (rg = range; rg; rg = rg->next) {
- if (!strcmp(rg->spec->path, p->two->path))
+ if (!strcmp(rg->path, p->two->path))
break;
}
if (rg)
@@ -1021,8 +1023,8 @@ static int process_diff_filepair(struct rev_info *rev,
assert(pair->two->path);
while (rg) {
- assert(rg->spec->path);
- if (!strcmp(rg->spec->path, pair->two->path))
+ assert(rg->path);
+ if (!strcmp(rg->path, pair->two->path))
break;
rg = rg->next;
}
@@ -1050,7 +1052,8 @@ static int process_diff_filepair(struct rev_info *rev,
collect_diff(&file_parent, &file_target, &diff);
/* NEEDSWORK should apply some heuristics to prevent mismatches */
- rg->spec->path = xstrdup(pair->one->path);
+ free(rg->path);
+ rg->path = xstrdup(pair->one->path);
range_set_init(&tmp, 0);
range_set_map_across_diff(&tmp, &rg->ranges, &diff, diff_out);
@@ -1096,7 +1099,7 @@ static int process_all_files(struct line_log_data **range_out,
struct line_log_data *rg = range;
changed++;
/* NEEDSWORK tramples over data structures not owned here */
- while (rg && strcmp(rg->spec->path, queue->queue[i]->two->path))
+ while (rg && strcmp(rg->path, queue->queue[i]->two->path))
rg = rg->next;
assert(rg);
rg->pair = diff_filepair_dup(queue->queue[i]);
diff --git a/line-log.h b/line-log.h
index 9acd12361a..8bea45fd78 100644
--- a/line-log.h
+++ b/line-log.h
@@ -26,10 +26,14 @@ struct diff_ranges {
};
/* Linked list of interesting files and their associated ranges. The
- * list must be kept sorted by spec->path */
+ * list must be kept sorted by path.
+ *
+ * For simplicity, even though this is highly redundant, each
+ * line_log_data owns its 'path'.
+ */
struct line_log_data {
struct line_log_data *next;
- struct diff_filespec *spec;
+ char *path;
char status;
struct range_set ranges;
int arg_alloc, arg_nr;
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index bba0b093d5..7776f93e3d 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -45,7 +45,7 @@ canned_test "-L '/long f/',/^}/:a.c -L /main/,/^}/:a.c simple" two-ranges
canned_test "-L 24,+1:a.c simple" vanishes-early
canned_test "-M -L '/long f/,/^}/:b.c' move-support" move-support-f
-canned_test_failure "-M -L ':f:b.c' parallel-change" parallel-change-f-to-main
+canned_test "-M -L ':f:b.c' parallel-change" parallel-change-f-to-main
canned_test "-L 4,12:a.c -L :main:a.c simple" multiple
canned_test "-L 4,18:a.c -L :main:a.c simple" multiple-overlapping