| 563 | } |
| 564 | |
| 565 | static struct line_log_data * |
| 566 | parse_lines(struct repository *r, struct commit *commit, |
| 567 | const char *prefix, struct string_list *args) |
| 568 | { |
| 569 | long lines = 0; |
| 570 | unsigned long *ends = NULL; |
| 571 | struct nth_line_cb cb_data; |
| 572 | struct string_list_item *item; |
| 573 | struct line_log_data *ranges = NULL; |
| 574 | struct line_log_data *p; |
| 575 | |
| 576 | for_each_string_list_item(item, args) { |
| 577 | const char *name_part; |
| 578 | char *range_part; |
| 579 | char *full_name; |
| 580 | struct diff_filespec *spec; |
| 581 | long begin = 0, end = 0; |
| 582 | long anchor; |
| 583 | |
| 584 | name_part = skip_range_arg(item->string, r->index); |
| 585 | if (!name_part || *name_part != ':' || !name_part[1]) |
| 586 | die("-L argument not 'start,end:file' or ':funcname:file': %s", |
| 587 | item->string); |
| 588 | range_part = xstrndup(item->string, name_part - item->string); |
| 589 | name_part++; |
| 590 | |
| 591 | full_name = prefix_path(r, prefix, prefix ? strlen(prefix) : 0, |
| 592 | name_part); |
| 593 | |
| 594 | spec = alloc_filespec(full_name); |
| 595 | fill_blob_sha1(r, commit, spec); |
| 596 | fill_line_ends(r, spec, &lines, &ends); |
| 597 | cb_data.spec = spec; |
| 598 | cb_data.lines = lines; |
| 599 | cb_data.line_ends = ends; |
| 600 | |
| 601 | p = search_line_log_data(ranges, full_name, NULL); |
| 602 | if (p && p->ranges.nr) |
| 603 | anchor = p->ranges.ranges[p->ranges.nr - 1].end + 1; |
| 604 | else |
| 605 | anchor = 1; |
| 606 | |
| 607 | if (parse_range_arg(range_part, nth_line, &cb_data, |
| 608 | lines, anchor, &begin, &end, |
| 609 | full_name, r->index)) |
| 610 | die("malformed -L argument '%s'", range_part); |
| 611 | if ((!lines && (begin || end)) || lines < begin) |
| 612 | die("file %s has only %lu lines", name_part, lines); |
| 613 | if (begin < 1) |
| 614 | begin = 1; |
| 615 | if (end < 1 || lines < end) |
| 616 | end = lines; |
| 617 | begin--; |
| 618 | line_log_data_insert(&ranges, full_name, begin, end); |
| 619 | |
| 620 | free_filespec(spec); |
| 621 | FREE_AND_NULL(ends); |
| 622 | free(range_part); |
no test coverage detected