refs.c (3975B)
1 #include "writer/gemini/refs.h" 2 3 #include <assert.h> 4 #include <err.h> 5 #include <stdbool.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 9 #include "format.h" 10 #include "git/commit.h" 11 #include "utils.h" 12 #include "writer/gemini/page.h" 13 14 typedef struct { 15 char* title; 16 FILE* out; 17 } GeminiRefsTable; 18 19 struct GeminiRefs { 20 const GitRepo* repo; 21 const FileSystem* fs; 22 FILE* out; 23 GeminiPage* page; 24 GeminiRefsTable* branches; 25 GeminiRefsTable* tags; 26 }; 27 28 static GeminiRefsTable* gemini_refstable_create(const char* title, FILE* out); 29 static void gemini_refstable_free(GeminiRefsTable* table); 30 static void gemini_refstable_begin(GeminiRefsTable* table); 31 static void gemini_refstable_add_ref(GeminiRefsTable* table, 32 const GitReference* ref); 33 static void gemini_refstable_end(GeminiRefsTable* table); 34 35 static GeminiRefsTable* gemini_refstable_create(const char* title, FILE* out) { 36 assert(title != NULL); 37 assert(out != NULL); 38 GeminiRefsTable* table = ecalloc(1, sizeof(GeminiRefsTable)); 39 table->title = estrdup(title); 40 table->out = out; 41 return table; 42 } 43 44 static void gemini_refstable_free(GeminiRefsTable* table) { 45 if (!table) { 46 return; 47 } 48 free(table->title); 49 free(table); 50 } 51 52 static void gemini_refstable_begin(GeminiRefsTable* table) { 53 assert(table != NULL); 54 fprintf(table->out, "## %s\n\n", table->title); 55 fprintf(table->out, "```\n"); 56 print_utf8_padded(table->out, "Name", 32, ' '); 57 fprintf(table->out, " "); 58 print_utf8_padded(table->out, "Last commit date", 16, ' '); 59 fprintf(table->out, " Author\n"); 60 } 61 62 static void gemini_refstable_add_ref(GeminiRefsTable* table, 63 const GitReference* ref) { 64 assert(table != NULL); 65 assert(ref != NULL); 66 GitCommit* commit = ref->commit; 67 FILE* out = table->out; 68 69 print_utf8_padded(out, ref->shorthand, 32, ' '); 70 fprintf(out, " "); 71 print_time_short(out, commit->author_time); 72 fprintf(out, " %s\n", commit->author_name); 73 } 74 75 static void gemini_refstable_end(GeminiRefsTable* table) { 76 assert(table != NULL); 77 fprintf(table->out, "```\n\n"); 78 } 79 80 GeminiRefs* gemini_refs_create(const GitRepo* repo, const FileSystem* fs) { 81 assert(repo != NULL); 82 assert(fs != NULL); 83 GeminiRefs* refs = ecalloc(1, sizeof(GeminiRefs)); 84 refs->repo = repo; 85 refs->fs = fs; 86 refs->out = fs->fopen("refs.gmi", "w"); 87 if (!refs->out) { 88 err(1, "fopen: refs.gmi"); 89 } 90 refs->page = gemini_page_create(refs->out, repo, fs, "Refs", ""); 91 return refs; 92 } 93 94 void gemini_refs_free(GeminiRefs* refs) { 95 if (!refs) { 96 return; 97 } 98 refs->fs->fclose(refs->out); 99 gemini_page_free(refs->page); 100 gemini_refstable_free(refs->branches); 101 gemini_refstable_free(refs->tags); 102 free(refs); 103 } 104 105 void gemini_refs_begin(GeminiRefs* refs) { 106 assert(refs != NULL); 107 gemini_page_begin(refs->page); 108 } 109 110 void gemini_refs_add_ref(GeminiRefs* refs, const GitReference* ref) { 111 assert(refs != NULL); 112 assert(ref != NULL); 113 switch (ref->type) { 114 case kReftypeBranch: 115 if (!refs->branches) { 116 refs->branches = gemini_refstable_create("Branches", refs->out); 117 gemini_refstable_begin(refs->branches); 118 } 119 gemini_refstable_add_ref(refs->branches, ref); 120 break; 121 case kReftypeTag: 122 if (refs->branches) { 123 gemini_refstable_end(refs->branches); 124 gemini_refstable_free(refs->branches); 125 refs->branches = NULL; 126 } 127 if (!refs->tags) { 128 refs->tags = gemini_refstable_create("Tags", refs->out); 129 gemini_refstable_begin(refs->tags); 130 } 131 gemini_refstable_add_ref(refs->tags, ref); 132 break; 133 } 134 } 135 136 void gemini_refs_end(GeminiRefs* refs) { 137 assert(refs != NULL); 138 if (refs->branches) { 139 gemini_refstable_end(refs->branches); 140 gemini_refstable_free(refs->branches); 141 refs->branches = NULL; 142 } 143 if (refs->tags) { 144 gemini_refstable_end(refs->tags); 145 gemini_refstable_free(refs->tags); 146 refs->tags = NULL; 147 } 148 gemini_page_end(refs->page); 149 }