]> gitweb.ps.run Git - ps-cgit/blobdiff - ui-blame.c
ui-snapshot: pass repo into get_ref_from_filename()
[ps-cgit] / ui-blame.c
index bbaad1c2b33ed6e1488786f9dcdecfbf1d648a38..b118a81521a5d0a11f45ca3e58edc19988691212 100644 (file)
@@ -45,11 +45,17 @@ static void emit_blame_entry_hash(struct blame_entry *ent)
 {
        struct blame_origin *suspect = ent->suspect;
        struct object_id *oid = &suspect->commit->object.oid;
+       unsigned long line = 0;
 
        char *detail = emit_suspect_detail(suspect);
+       html("<span class='sha1'>");
        cgit_commit_link(find_unique_abbrev(oid->hash, DEFAULT_ABBREV), detail,
                         NULL, ctx.qry.head, oid_to_hex(oid), suspect->path);
+       html("</span>");
        free(detail);
+
+       while (line++ < ent->num_lines)
+               html("\n");
 }
 
 static void emit_blame_entry_linenumber(struct blame_entry *ent)
@@ -61,33 +67,29 @@ static void emit_blame_entry_linenumber(struct blame_entry *ent)
                htmlf(numberfmt, ++lineno);
 }
 
-static void emit_blame_entry_line(struct blame_scoreboard *sb,
-                                 struct blame_entry *ent)
-{
-       const char *cp, *cpend;
-
-       cp = blame_nth_line(sb, ent->lno);
-       cpend = blame_nth_line(sb, ent->lno + ent->num_lines);
-
-       html_ntxt(cp, cpend - cp);
-}
-
-static void emit_blame_entry(struct blame_scoreboard *sb,
-                            struct blame_entry *ent)
+static void emit_blame_entry_line_background(struct blame_scoreboard *sb,
+                                            struct blame_entry *ent)
 {
-       html("<tr><td class='sha1 hashes'>");
-       emit_blame_entry_hash(ent);
-       html("</td>\n");
-
-       if (ctx.cfg.enable_tree_linenumbers) {
-               html("<td class='linenumbers'><pre>");
-               emit_blame_entry_linenumber(ent);
-               html("</pre></td>\n");
+       unsigned long line;
+       size_t len, maxlen = 2;
+       const char* pos, *endpos;
+
+       for (line = ent->lno; line < ent->lno + ent->num_lines; line++) {
+               html("\n");
+               pos = blame_nth_line(sb, line);
+               endpos = blame_nth_line(sb, line + 1);
+               len = 0;
+               while (pos < endpos) {
+                       len++;
+                       if (*pos++ == '\t')
+                               len = (len + 7) & ~7;
+               }
+               if (len > maxlen)
+                       maxlen = len;
        }
 
-       html("<td class='lines'><pre><code>");
-       emit_blame_entry_line(sb, ent);
-       html("</code></pre></td></tr>\n");
+       for (len = 0; len < maxlen - 1; len++)
+               html(" ");
 }
 
 struct walk_tree_context {
@@ -100,6 +102,7 @@ static void print_object(const unsigned char *sha1, const char *path,
                         const char *basename, const char *rev)
 {
        enum object_type type;
+       char *buf;
        unsigned long size;
        struct argv_array rev_argv = ARGV_ARRAY_INIT;
        struct rev_info revs;
@@ -114,6 +117,13 @@ static void print_object(const unsigned char *sha1, const char *path,
                return;
        }
 
+       buf = read_sha1_file(sha1, &type, &size);
+       if (!buf) {
+               cgit_print_error_page(500, "Internal server error",
+                       "Error reading object %s", sha1_to_hex(sha1));
+               return;
+       }
+
        argv_array_push(&rev_argv, "blame");
        argv_array_push(&rev_argv, rev);
        init_revisions(&revs, NULL);
@@ -144,20 +154,68 @@ static void print_object(const unsigned char *sha1, const char *path,
                htmlf("<div class='error'>blob size (%ldKB)"
                      " exceeds display size limit (%dKB).</div>",
                      size / 1024, ctx.cfg.max_blob_size);
-               return;
+               goto cleanup;
        }
 
-       html("<table class='blame blob'>");
+       html("<table class='blame blob'>\n<tr>\n");
+
+       /* Commit hashes */
+       html("<td class='hashes'>");
+       for (ent = sb.ent; ent; ent = ent->next) {
+               html("<div class='alt'><pre>");
+               emit_blame_entry_hash(ent);
+               html("</pre></div>");
+       }
+       html("</td>\n");
+
+       /* Line numbers */
+       if (ctx.cfg.enable_tree_linenumbers) {
+               html("<td class='linenumbers'>");
+               for (ent = sb.ent; ent; ent = ent->next) {
+                       html("<div class='alt'><pre>");
+                       emit_blame_entry_linenumber(ent);
+                       html("</pre></div>");
+               }
+               html("</td>\n");
+       }
+
+       html("<td class='lines'><div>");
+
+       /* Colored bars behind lines */
+       html("<div>");
        for (ent = sb.ent; ent; ) {
                struct blame_entry *e = ent->next;
-               emit_blame_entry(&sb, ent);
+               html("<div class='alt'><pre>");
+               emit_blame_entry_line_background(&sb, ent);
+               html("</pre></div>");
                free(ent);
                ent = e;
        }
-       html("</table>\n");
+       html("</div>");
+
        free((void *)sb.final_buf);
 
+       /* Lines */
+       html("<pre><code>");
+       if (ctx.repo->source_filter) {
+               char *filter_arg = xstrdup(basename);
+               cgit_open_filter(ctx.repo->source_filter, filter_arg);
+               html_raw(buf, size);
+               cgit_close_filter(ctx.repo->source_filter);
+               free(filter_arg);
+       } else {
+               html_txt(buf);
+       }
+       html("</code></pre>");
+
+       html("</div></td>\n");
+
+       html("</tr>\n</table>\n");
+
        cgit_print_layout_end();
+
+cleanup:
+       free(buf);
 }
 
 static int walk_tree(const unsigned char *sha1, struct strbuf *base,