This is complicated slightly by having to remember the previous -L range
for each file specified via -L<range>:file.

The existing implementation coalesces ranges for each file as each -L is
parsed which makes it impossible to refer back to the previous -L range
for any particular file. Re-implement to instead store each file's set
of -L ranges verbatim, and then coalesce the ranges in a post-processing
step.

Signed-off-by: Eric Sunshine <sunsh...@sunshineco.com>
---
 line-log.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/line-log.c b/line-log.c
index 38f827b..d40c79d 100644
--- a/line-log.c
+++ b/line-log.c
@@ -291,7 +291,6 @@ static void line_log_data_insert(struct line_log_data 
**list,
 
        if (p) {
                range_set_append_unsafe(&p->ranges, begin, end);
-               sort_and_merge_range_set(&p->ranges);
                free(path);
                return;
        }
@@ -299,7 +298,6 @@ static void line_log_data_insert(struct line_log_data 
**list,
        p = xcalloc(1, sizeof(struct line_log_data));
        p->path = path;
        range_set_append(&p->ranges, begin, end);
-       sort_and_merge_range_set(&p->ranges);
        if (ip) {
                p->next = ip->next;
                ip->next = p;
@@ -566,12 +564,14 @@ parse_lines(struct commit *commit, const char *prefix, 
struct string_list *args)
        struct nth_line_cb cb_data;
        struct string_list_item *item;
        struct line_log_data *ranges = NULL;
+       struct line_log_data *p;
 
        for_each_string_list_item(item, args) {
                const char *name_part, *range_part;
                char *full_name;
                struct diff_filespec *spec;
                long begin = 0, end = 0;
+               long anchor;
 
                name_part = skip_range_arg(item->string);
                if (!name_part || *name_part != ':' || !name_part[1])
@@ -590,8 +590,14 @@ parse_lines(struct commit *commit, const char *prefix, 
struct string_list *args)
                cb_data.lines = lines;
                cb_data.line_ends = ends;
 
+               p = search_line_log_data(ranges, full_name, NULL);
+               if (p && p->ranges.nr)
+                       anchor = p->ranges.ranges[p->ranges.nr - 1].end + 1;
+               else
+                       anchor = 1;
+
                if (parse_range_arg(range_part, nth_line, &cb_data,
-                                   lines, 1, &begin, &end,
+                                   lines, anchor, &begin, &end,
                                    full_name))
                        die("malformed -L argument '%s'", range_part);
                if (lines < end || ((lines || begin) && lines < begin))
@@ -608,6 +614,9 @@ parse_lines(struct commit *commit, const char *prefix, 
struct string_list *args)
                ends = NULL;
        }
 
+       for (p = ranges; p; p = p->next)
+               sort_and_merge_range_set(&p->ranges);
+
        return ranges;
 }
 
-- 
1.8.4.rc1.409.gbd48715

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to