log.c (3646B)
1 #include "writer/html/log.h" 2 3 #include <assert.h> 4 #include <stdbool.h> 5 #include <stdint.h> 6 #include <stdlib.h> 7 8 #include "format.h" 9 #include "utils.h" 10 #include "writer/cache/cache.h" 11 #include "writer/html/page.h" 12 13 #include <err.h> 14 #include <sys/stat.h> 15 #include <unistd.h> 16 17 struct HtmlLog { 18 const GitRepo* repo; 19 const FileSystem* fs; 20 FILE* out; 21 Cache* cache; 22 HtmlPage* page; 23 size_t remaining_commits; 24 size_t unlogged_commits; 25 }; 26 27 static void write_commit_row(FILE* out, const GitCommit* commit); 28 29 HtmlLog* html_log_create(const GitRepo* repo, const FileSystem* fs) { 30 assert(repo != NULL); 31 assert(fs != NULL); 32 HtmlLog* log = ecalloc(1, sizeof(HtmlLog)); 33 log->repo = repo; 34 log->fs = fs; 35 log->out = fs->fopen("log.html", "w"); 36 if (!log->out) { 37 err(1, "fopen: log.html"); 38 } 39 log->page = html_page_create(log->out, repo, fs, "Log", ""); 40 log->remaining_commits = SIZE_MAX; 41 log->unlogged_commits = 0; 42 return log; 43 } 44 45 void html_log_free(HtmlLog* log) { 46 if (!log) { 47 return; 48 } 49 log->fs->fclose(log->out); 50 cache_free(log->cache); 51 html_page_free(log->page); 52 free(log); 53 } 54 55 void html_log_set_cachefile(HtmlLog* log, const char* cachefile) { 56 assert(log != NULL); 57 assert(cachefile != NULL); 58 log->cache = cache_open(log->fs, cachefile, write_commit_row); 59 } 60 61 void html_log_set_commit_limit(HtmlLog* log, size_t count) { 62 assert(log != NULL); 63 log->remaining_commits = count; 64 } 65 66 bool html_log_can_add_commits(const HtmlLog* log) { 67 assert(log != NULL); 68 return !log->cache || cache_can_add_commits(log->cache); 69 } 70 71 void html_log_begin(HtmlLog* log) { 72 assert(log != NULL); 73 html_page_begin(log->page); 74 fprintf(log->out, 75 "<table id=\"log\"><thead>\n" 76 "<tr>" 77 "<td><b>Date</b></td>" 78 "<td><b>Commit message</b></td>" 79 "<td><b>Author</b></td>" 80 "<td class=\"num\" align=\"right\"><b>Files</b></td>" 81 "<td class=\"num\" align=\"right\"><b>+</b></td>" 82 "<td class=\"num\" align=\"right\"><b>-</b></td>" 83 "</tr>\n" 84 "</thead><tbody>\n"); 85 } 86 87 void html_log_add_commit(HtmlLog* log, const GitCommit* commit) { 88 assert(log != NULL); 89 assert(commit != NULL); 90 if (log->cache) { 91 cache_add_commit_row(log->cache, commit); 92 } else if (log->remaining_commits > 0) { 93 write_commit_row(log->out, commit); 94 log->remaining_commits--; 95 } else { 96 log->unlogged_commits++; 97 } 98 } 99 100 void html_log_end(HtmlLog* log) { 101 assert(log != NULL); 102 FILE* out = log->out; 103 if (log->cache) { 104 cache_close_and_replace(log->cache, log->out); 105 } else if (log->unlogged_commits > 0) { 106 size_t count = log->unlogged_commits; 107 fprintf(out, "<tr><td></td><td colspan=\"5\">"); 108 fprintf(out, "%zu more commits remaining, fetch the repository", count); 109 fprintf(out, "</td></tr>\n"); 110 } 111 fprintf(out, "</tbody></table>"); 112 html_page_end(log->page); 113 } 114 115 static void write_commit_row(FILE* out, const GitCommit* commit) { 116 assert(out != NULL); 117 assert(commit != NULL); 118 fprintf(out, "<tr><td>"); 119 print_time_short(out, commit->author_time); 120 fprintf(out, "</td><td>"); 121 const char* summary = commit->summary; 122 if (summary) { 123 fprintf(out, "<a href=\"commit/%s.html\">", commit->oid); 124 print_xml_encoded(out, summary); 125 fprintf(out, "</a>"); 126 } 127 fprintf(out, "</td><td>"); 128 print_xml_encoded(out, commit->author_name); 129 fprintf(out, 130 "</td>" 131 "<td class=\"num\" align=\"right\">%zu</td>" 132 "<td class=\"num\" align=\"right\">+%zu</td>" 133 "<td class=\"num\" align=\"right\">-%zu</td></tr>\n", 134 commit->filecount, commit->addcount, commit->delcount); 135 }