Skip to content

Commit

Permalink
Enable textconv in the blame view and fix blame -L (#1190)
Browse files Browse the repository at this point in the history
Change the blame view to use the porcelain output rather than loading
the file and adding blame information based on the incremental output.

Fixes #978
Fixes #1189

Reviewed-by: Johannes Altmanninger <aclopte@gmail.com>
  • Loading branch information
koutcher authored Jun 3, 2022
1 parent ce9d325 commit 2280734
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 95 deletions.
1 change: 1 addition & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Bug fixes:
- Fix cursor behaviour during staging. (#842, #1028)
- Fix navigation in split tree view.
- Enable textconv in the stage view.
- Enable textconv in the blame view and fix blame -L. (#978, #1189)

tig-2.5.5
---------
Expand Down
3 changes: 2 additions & 1 deletion include/tig/git.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"git", "diff-files", (output_arg), "%(cmdlineargs)", NULL

#define GIT_DIFF_BLAME(encoding_arg, context_arg, space_arg, new_name) \
GIT_DIFF_UNSTAGED(encoding_arg, context_arg, space_arg, "", new_name)
"git", "diff-files", (encoding_arg), "--root", "--textconv", "--patch-with-stat", "-C", "-M", \
(context_arg), (space_arg), "--", (new_name), NULL

#define GIT_DIFF_BLAME_NO_PARENT(encoding_arg, context_arg, space_arg, new_name) \
GIT_DIFF_INITIAL(encoding_arg, "", context_arg, space_arg, "/dev/null", new_name)
Expand Down
2 changes: 1 addition & 1 deletion include/tig/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct blame_header {
size_t group;
};

bool parse_blame_header(struct blame_header *header, const char *text, size_t max_lineno);
bool parse_blame_header(struct blame_header *header, const char *text);
bool parse_blame_info(struct blame_commit *commit, char author[SIZEOF_STR], char *line);

/* Parse author lines where the name may be empty:
Expand Down
115 changes: 30 additions & 85 deletions src/blame.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ struct blame {

struct blame_state {
struct blame_commit *commit;
struct blame_header header;
char author[SIZEOF_STR];
int blamed;
bool done_reading;
bool auto_filename_display;
const char *filename;
/* The history state for the current view is cached in the view
Expand All @@ -78,7 +77,11 @@ static enum status_code
blame_open(struct view *view, enum open_flags flags)
{
struct blame_state *state = view->private;
const char *file_argv[] = { repo.exec_dir, view->env->file , NULL };
const char *blame_argv[] = {
"git", "blame", encoding_arg, "%(blameargs)", "-p",
view->env->ref, "--", view->env->file, NULL
};
enum status_code code;
size_t i;

if (!(repo.is_inside_work_tree || *repo.worktree))
Expand Down Expand Up @@ -145,15 +148,9 @@ blame_open(struct view *view, enum open_flags flags)
return error("No file chosen, press %s to open tree view",
get_view_key(view, REQ_VIEW_TREE));

if (*view->env->ref || begin_update(view, repo.exec_dir, file_argv, flags) != SUCCESS) {
const char *blame_cat_file_argv[] = {
"git", "cat-file", "blob", "%(ref):%(file)", NULL
};
enum status_code code = begin_update(view, repo.exec_dir, blame_cat_file_argv, flags);

if (code != SUCCESS)
return code;
}
code = begin_update(view, repo.exec_dir, blame_argv, flags);
if (code != SUCCESS)
return code;

/* First pass: remove multiple references to the same commit. */
for (i = 0; i < view->lines; i++) {
Expand Down Expand Up @@ -210,77 +207,27 @@ get_blame_commit(struct view *view, const char *id)
static struct blame_commit *
read_blame_commit(struct view *view, const char *text, struct blame_state *state)
{
struct blame_header header;
struct blame_commit *commit;
struct blame *blame;

if (!parse_blame_header(&header, text, view->lines))
if (!parse_blame_header(&state->header, text))
return NULL;

commit = get_blame_commit(view, text);
if (!commit)
return NULL;

state->blamed += header.group;
while (header.group--) {
struct line *line = &view->line[header.lineno + header.group - 1];

blame = line->data;
blame->commit = commit;
blame->lineno = header.orig_lineno + header.group - 1;
line->dirty = 1;
}

return commit;
}

static bool
blame_read_file(struct view *view, struct buffer *buf, struct blame_state *state)
{
if (!buf) {
const char *blame_argv[] = {
"git", "blame", encoding_arg, "%(blameargs)", "--incremental",
*view->env->ref ? view->env->ref : "--incremental", "--", view->env->file, NULL
};

if (failed_to_load_initial_view(view))
die("No blame exist for %s", view->vid);

if (view->lines == 0 || begin_update(view, repo.exec_dir, blame_argv, OPEN_EXTRA) != SUCCESS) {
report("Failed to load blame data");
return true;
}

if (view->env->goto_lineno > 0) {
select_view_line(view, view->env->goto_lineno);
view->env->goto_lineno = 0;
}

state->done_reading = true;
return false;

} else {
struct blame *blame;

if (!add_line_alloc(view, &blame, LINE_DEFAULT, buf->size, false))
return false;

blame->commit = NULL;
strncpy(blame->text, buf->data, buf->size);
blame->text[buf->size] = 0;
return true;
}
}

static bool
blame_read(struct view *view, struct buffer *buf, bool force_stop)
{
struct blame_state *state = view->private;

if (!state->done_reading)
return blame_read_file(view, buf, state);

if (!buf) {
if (failed_to_load_initial_view(view))
die("No blame exist for %s", view->vid);

string_format(view->ref, "%s", view->vid);
if (view_is_displayed(view)) {
update_view_title(view);
Expand All @@ -291,13 +238,24 @@ blame_read(struct view *view, struct buffer *buf, bool force_stop)

if (!state->commit) {
state->commit = read_blame_commit(view, buf->data, state);
string_format(view->ref, "%s %2zu%%", view->vid,
view->lines ? 5 * (size_t) (state->blamed * 20 / view->lines) : 0);

} else if (parse_blame_info(state->commit, state->author, buf->data)) {
bool update_view_columns = true;
int i;
} else if (*buf->data == '\t') {
struct blame *blame;
struct line *line = add_line_alloc(view, &blame, LINE_DEFAULT, buf->size - 1, false);

if (!line)
return false;

blame->commit = state->commit;
blame->lineno = state->header.orig_lineno;
strncpy(blame->text, buf->data + 1, buf->size - 1);
blame->text[buf->size - 1] = 0;

view_column_info_update(view, line);

state->commit = NULL;

} else if (parse_blame_info(state->commit, state->author, buf->data)) {
if (!state->commit->filename)
return false;

Expand All @@ -309,19 +267,6 @@ blame_read(struct view *view, struct buffer *buf, bool force_stop)
blame_update_file_name_visibility(view);
}

for (i = 0; i < view->lines; i++) {
struct line *line = &view->line[i];
struct blame *blame = line->data;

if (blame && blame->commit == state->commit) {
line->dirty = 1;
if (update_view_columns)
view_column_info_update(view, line);
update_view_columns = false;
}
}

state->commit = NULL;
}

return true;
Expand Down Expand Up @@ -363,7 +308,7 @@ setup_blame_parent_line(struct view *view, struct blame *blame)
char from[SIZEOF_REF + SIZEOF_STR];
char to[SIZEOF_REF + SIZEOF_STR];
const char *diff_tree_argv[] = {
"git", "diff", encoding_arg, "--no-textconv", "--no-ext-diff",
"git", "diff", encoding_arg, "--no-ext-diff",
"--no-color", "-U0", from, to, "--", NULL
};
struct io io;
Expand Down
2 changes: 1 addition & 1 deletion src/diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ diff_blame_line(const char *ref, const char *file, unsigned long lineno,

while (io_get(&io, &buf, '\n', true)) {
if (header) {
if (!parse_blame_header(header, buf.data, 9999999))
if (!parse_blame_header(header, buf.data))
break;
header = NULL;

Expand Down
13 changes: 6 additions & 7 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ parse_author_line(char *ident, const struct ident **author, struct time *time)
*/

static bool
parse_number(const char **posref, size_t *number, size_t min, size_t max)
parse_number(const char **posref, size_t *number)
{
const char *pos = *posref;

Expand All @@ -101,15 +101,13 @@ parse_number(const char **posref, size_t *number, size_t min, size_t max)
if (!pos || !isdigit(pos[1]))
return false;
*number = atoi(pos + 1);
if (*number < min || *number > max)
return false;

*posref = pos;
return true;
}

bool
parse_blame_header(struct blame_header *header, const char *text, size_t max_lineno)
parse_blame_header(struct blame_header *header, const char *text)
{
const char *pos = text + SIZEOF_REV - 2;

Expand All @@ -118,10 +116,11 @@ parse_blame_header(struct blame_header *header, const char *text, size_t max_lin

string_ncopy(header->id, text, SIZEOF_REV);

if (!parse_number(&pos, &header->orig_lineno, 1, 9999999) ||
!parse_number(&pos, &header->lineno, 1, max_lineno) ||
!parse_number(&pos, &header->group, 1, max_lineno - header->lineno + 1))
if (!parse_number(&pos, &header->orig_lineno) ||
!parse_number(&pos, &header->lineno))
return false;
if (!parse_number(&pos, &header->group))
header->group = 0;

return true;
}
Expand Down

0 comments on commit 2280734

Please sign in to comment.