diff --git a/NEWS.adoc b/NEWS.adoc index 7dbea85eb..1b5d44147 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -8,6 +8,10 @@ Bug fixes: - Fix wrapping of lines with multibyte characters. (#988) +Improvements: + + - Start blame on deleted lines in the stage view from HEAD so the line's origin can be traced. (#1008) + tig-2.5.1 --------- diff --git a/include/tig/diff.h b/include/tig/diff.h index f7cb97507..eca80ec35 100644 --- a/include/tig/diff.h +++ b/include/tig/diff.h @@ -41,6 +41,7 @@ enum status_code diff_init_highlight(struct view *view, struct diff_state *state bool diff_done_highlight(struct diff_state *state); unsigned int diff_get_lineno(struct view *view, struct line *line); +unsigned int diff_get_old_lineno(struct view *view, struct line *line); const char *diff_get_pathname(struct view *view, struct line *line); extern struct view diff_view; diff --git a/src/diff.c b/src/diff.c index e38162c12..6d2ea740d 100644 --- a/src/diff.c +++ b/src/diff.c @@ -635,6 +635,39 @@ diff_get_lineno(struct view *view, struct line *line) return lineno; } +unsigned int +diff_get_old_lineno(struct view *view, struct line *line) +{ + const struct line *header, *chunk; + unsigned int lineno; + struct chunk_header chunk_header; + + /* Verify that we are after a diff header and one of its chunks */ + header = find_prev_line_by_type(view, line, LINE_DIFF_HEADER); + chunk = find_prev_line_by_type(view, line, LINE_DIFF_CHUNK); + if (!header || !chunk || chunk < header) { + return 0; + } + + /* + * In a chunk header, the number after the '-' sign is the number of its + * following line, in the old version of the file. We increment this + * number for each non-addition line, until the given line position. + */ + if (!parse_chunk_header(&chunk_header, box_text(chunk))) { + return 0; + } + + lineno = chunk_header.old.position; + + for (chunk++; chunk < line; chunk++) + if (chunk->type != LINE_DIFF_ADD && + chunk->type != LINE_DIFF_ADD2) + lineno++; + + return lineno; +} + static enum request diff_trace_origin(struct view *view, struct line *line) { diff --git a/src/stage.c b/src/stage.c index 565c946a0..c1ce01ca9 100644 --- a/src/stage.c +++ b/src/stage.c @@ -444,8 +444,13 @@ stage_request(struct view *view, enum request request, struct line *line) string_ncopy(view->env->file, file, strlen(file)); } - view->env->ref[0] = 0; - view->env->goto_lineno = diff_get_lineno(view, line); + if (!is_initial_commit() && line->type == LINE_DIFF_DEL) { + string_copy(view->env->ref, "HEAD"); + view->env->goto_lineno = diff_get_old_lineno(view, line); + } else { + view->env->ref[0] = 0; + view->env->goto_lineno = diff_get_lineno(view, line); + } if (view->env->goto_lineno > 0) view->env->goto_lineno--; return request;