log.c (3140B)
1 #include "writer/gopher/log.h" 2 3 #include <assert.h> 4 #include <err.h> 5 #include <stdbool.h> 6 #include <stdint.h> 7 #include <stdlib.h> 8 9 #include "format.h" 10 #include "utils.h" 11 #include "writer/cache/cache.h" 12 #include "writer/gopher/page.h" 13 14 #include <sys/stat.h> 15 #include <unistd.h> 16 17 struct GopherLog { 18 const GitRepo* repo; 19 const FileSystem* fs; 20 FILE* out; 21 Cache* cache; 22 GopherPage* 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 GopherLog* gopher_log_create(const GitRepo* repo, const FileSystem* fs) { 30 assert(repo != NULL); 31 assert(fs != NULL); 32 GopherLog* log = ecalloc(1, sizeof(GopherLog)); 33 log->repo = repo; 34 log->fs = fs; 35 log->out = fs->fopen("log.gph", "w"); 36 if (!log->out) { 37 err(1, "fopen: log.gph"); 38 } 39 log->page = gopher_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 gopher_log_free(GopherLog* log) { 46 if (!log) { 47 return; 48 } 49 log->fs->fclose(log->out); 50 cache_free(log->cache); 51 gopher_page_free(log->page); 52 free(log); 53 } 54 55 void gopher_log_set_cachefile(GopherLog* 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 gopher_log_set_commit_limit(GopherLog* log, size_t count) { 62 assert(log != NULL); 63 log->remaining_commits = count; 64 } 65 66 bool gopher_log_can_add_commits(const GopherLog* log) { 67 assert(log != NULL); 68 return !log->cache || cache_can_add_commits(log->cache); 69 } 70 71 void gopher_log_begin(GopherLog* log) { 72 assert(log != NULL); 73 FILE* out = log->out; 74 gopher_page_begin(log->page); 75 fprintf(out, "%-16.16s ", "Date"); 76 fprintf(out, "%-40.40s ", "Commit message"); 77 fprintf(out, "%s\n", "Author"); 78 } 79 80 void gopher_log_add_commit(GopherLog* log, const GitCommit* commit) { 81 assert(log != NULL); 82 assert(commit != NULL); 83 if (log->cache) { 84 cache_add_commit_row(log->cache, commit); 85 } else if (log->remaining_commits > 0) { 86 write_commit_row(log->out, commit); 87 log->remaining_commits--; 88 } else { 89 log->unlogged_commits++; 90 } 91 } 92 93 void gopher_log_end(GopherLog* log) { 94 assert(log != NULL); 95 FILE* out = log->out; 96 if (log->cache) { 97 cache_close_and_replace(log->cache, log->out); 98 } else if (log->unlogged_commits > 0) { 99 size_t count = log->unlogged_commits; 100 fprintf(out, "%16.16s %zu more commits remaining, fetch the repository\n", 101 "", count); 102 } 103 fprintf(out, "\n[0|Atom feed|atom.xml|server|port]\n"); 104 fprintf(out, "[0|Atom feed (tags)|tags.xml|server|port]\n"); 105 gopher_page_end(log->page); 106 } 107 108 static void write_commit_row(FILE* out, const GitCommit* commit) { 109 assert(out != NULL); 110 assert(commit != NULL); 111 fprintf(out, "[1|"); 112 print_time_short(out, commit->author_time); 113 fprintf(out, " "); 114 const char* summary = commit->summary; 115 if (summary) { 116 print_gopher_link_padded(out, summary, 40, ' '); 117 fprintf(out, " "); 118 } 119 print_gopher_link(out, commit->author_name); 120 fprintf(out, "|commit/%s.gph|server|port]\n", commit->oid); 121 }