Diff options
Diffstat (limited to '')
| -rw-r--r-- | source/ui-blame.c | 123 |
1 file changed, 33 insertions, 90 deletions
diff --git a/source/ui-blame.c b/source/ui-blame.c index 48cbf8e..eef8602 100644 --- a/source/ui-blame.c +++ b/source/ui-blame.c @@ -24,7 +24,7 @@ enum blame_target { }; struct walk_tree_context { - char *rev; + const char *rev; int match_baselen; enum blame_target found; }; @@ -34,15 +34,6 @@ struct walk_tree_context { // detail is cached here and looked up by object id. static struct string_list suspect_details = STRING_LIST_INIT_DUP; -static void free_suspect_details(void) -{ - struct string_list_item *item; - - for_each_string_list_item(item, &suspect_details) - free(item->util); - string_list_clear(&suspect_details, 0); -} - /* * The scoreboard keeps a pointer to revs, so the caller owns both and has to * keep them alive together. @@ -57,7 +48,8 @@ static void run_blame(struct blame_scoreboard *sb, struct rev_info *revs, strvec_push(&argv, rev); repo_init_revisions(the_repository, revs, NULL); revs->diffopt.flags.allow_textconv = 1; - setup_revisions(argv.nr, argv.v, revs, NULL); + setup_revisions_from_strvec(&argv, revs, NULL); + strvec_clear(&argv); init_scoreboard(sb); sb->revs = revs; sb->repo = the_repository; @@ -67,7 +59,6 @@ static void run_blame(struct blame_scoreboard *sb, struct rev_info *revs, prio_queue_put(&sb->commits, origin->commit); blame_origin_decref(origin); sb->ent = NULL; - sb->path = path; assign_blame(sb, 0); blame_sort_final(sb); blame_coalesce(sb); @@ -161,44 +152,20 @@ static void emit_entry_hash(struct blame_entry *ent) emit_chars('\n', ent->num_lines); } -static void emit_hashes(struct blame_scoreboard *sb) -{ - struct blame_entry *ent; - - html("<td class='hashes'>"); - for (ent = sb->ent; ent; ent = ent->next) { - html("<div class='alt'><pre>"); - emit_entry_hash(ent); - html("</pre></div>"); - } - html("</td>\n"); -} - static void emit_entry_linenumbers(struct blame_entry *ent) { - struct strbuf numbers = STRBUF_INIT; - int lineno = ent->lno; - - while (lineno < ent->lno + ent->num_lines) { - lineno++; - strbuf_addf(&numbers, "<a id='n%d' href='#n%d'>%d</a>\n", lineno, lineno, lineno); - if (numbers.len >= HTML_BATCH) { - html_raw(numbers.buf, numbers.len); - strbuf_reset(&numbers); - } - } - html_raw(numbers.buf, numbers.len); - strbuf_release(&numbers); + cgit_print_line_anchors((size_t)ent->lno + 1, (size_t)ent->lno + ent->num_lines); } -static void emit_linenumbers(struct blame_scoreboard *sb) +static void emit_column(struct blame_scoreboard *sb, const char *class, + void (*emit_entry)(struct blame_entry *ent)) { struct blame_entry *ent; - html("<td class='linenumbers'>"); + htmlf("<td class='%s'>", class); for (ent = sb->ent; ent; ent = ent->next) { html("<div class='alt'><pre>"); - emit_entry_linenumbers(ent); + emit_entry(ent); html("</pre></div>"); } html("</td>\n"); @@ -220,9 +187,10 @@ static size_t line_width(struct blame_scoreboard *sb, int line) pos += len; continue; } - width++; if (*pos++ == '\t') - width = (width + TAB_WIDTH - 1) & ~(TAB_WIDTH - 1); + width += TAB_WIDTH - width % TAB_WIDTH; + else + width++; } return width; } @@ -275,8 +243,9 @@ static void print_blame_page(const struct object_id *oid, const char *path, enum object_type type; char *buf; size_t size; - struct rev_info revs; + struct rev_info revs = REV_INFO_INIT; struct blame_scoreboard sb; + int binary; type = odb_read_object_info(the_repository->objects, oid, &size); if (type == OBJ_BAD) { @@ -295,7 +264,13 @@ static void print_blame_page(const struct object_id *oid, const char *path, return; } - run_blame(&sb, &revs, path, rev); + // A NUL past the window buffer_is_binary sniffs would end a Lua + // filter's output early while the hash and line number columns still + // cover the whole file, so a blob holding one anywhere is treated as + // binary too. + binary = buffer_is_binary(buf, size) || memchr(buf, 0, size); + if (!binary) + run_blame(&sb, &revs, path, rev); cgit_set_title_from_path(path); cgit_prefix_title("blame"); @@ -307,29 +282,16 @@ static void print_blame_page(const struct object_id *oid, const char *path, cgit_tree_link("tree", NULL, NULL, ctx.qry.head, rev, path); html(")</div>\n"); - // A NUL past the window buffer_is_binary sniffs would end a Lua - // filter's output early while the hash and line number columns still - // cover the whole file, so a blob holding one anywhere is treated as - // binary too. - if (buffer_is_binary(buf, size) || memchr(buf, 0, size)) { - struct blame_entry *ent = sb.ent, *next; - - // The scoreboard is normally consumed by the column passes, - // so this early exit has to release it itself. - for (; ent; ent = next) { - next = ent->next; - free(ent); - } - free((void *)sb.final_buf); + if (binary) { html("<div class='error'>Blob is binary</div>"); goto cleanup; } html("<table class='blame blob'>\n<tr>\n"); - emit_hashes(&sb); + emit_column(&sb, "hashes", emit_entry_hash); if (ctx.cfg.enable_tree_linenumbers) - emit_linenumbers(&sb); + emit_column(&sb, "linenumbers", emit_entry_linenumbers); html("<td class='lines'><div>"); emit_line_backgrounds(&sb); @@ -338,12 +300,9 @@ static void print_blame_page(const struct object_id *oid, const char *path, html("<pre><code>"); if (ctx.repo->source_filter) { - char *filter_arg = xstrdup(filename); - - cgit_open_filter(ctx.repo->source_filter, filter_arg); + cgit_open_filter(ctx.repo->source_filter, filename); html_raw(buf, size); cgit_close_filter(ctx.repo->source_filter); - free(filter_arg); } else { html_blob_txt(buf, size); } @@ -355,8 +314,9 @@ static void print_blame_page(const struct object_id *oid, const char *path, cleanup: cgit_print_layout_end(); - free_suspect_details(); + string_list_clear(&suspect_details, 1); free(buf); + release_revisions(&revs); } static int walk_tree(const struct object_id *oid, struct strbuf *base, @@ -399,18 +359,8 @@ void cgit_print_blame(void) const char *rev = ctx.qry.oid; struct object_id oid; struct commit *commit; - int path_len = ctx.qry.path ? strlen(ctx.qry.path) : 0; - // nowildcard_len matches len so git treats the path as literal rather - // than as a glob, which is what a request naming one file means. - struct pathspec_item path_items = { - .match = ctx.qry.path, - .len = path_len, - .nowildcard_len = path_len - }; - struct pathspec paths = { - .nr = 1, - .items = &path_items - }; + struct pathspec_item path_item; + struct pathspec paths = { 0 }; struct walk_tree_context walk = { .found = TARGET_MISSING }; @@ -418,24 +368,17 @@ void cgit_print_blame(void) if (!rev) rev = ctx.qry.head; - if (repo_get_oid(the_repository, rev, &oid)) { - cgit_print_error_page(404, "Not Found", "Bad object id: %s", rev); + commit = cgit_get_commit(rev, &oid); + if (!commit) return; - } - commit = lookup_commit_reference(the_repository, &oid); - if (!commit || repo_parse_commit(the_repository, commit)) { - cgit_print_error_page(404, "Not Found", "Not a commit: %s", rev); - return; - } - walk.rev = xstrdup(rev); - walk.match_baselen = path_items.match ? basedir_len(path_items.match) : -1; + walk.rev = rev; + walk.match_baselen = ctx.qry.path ? basedir_len(ctx.qry.path) : -1; + cgit_literal_pathspec(&paths, &path_item, ctx.qry.path); read_tree(the_repository, repo_get_commit_tree(the_repository, commit), &paths, walk_tree, &walk); if (walk.found == TARGET_MISSING) cgit_print_error_page(404, "Not Found", "Not found"); else if (walk.found == TARGET_FOLDER) cgit_print_error_page(404, "Not Found", "Blame is not available for a directory"); - - free(walk.rev); } |
