gout

A static git page generator
git clone https://git.bracken.jp/gout.git
Log | Files | Refs | README | LICENSE

refs.c (5220B)


      1 #include "writer/html/refs.h"
      2 
      3 #include <assert.h>
      4 #include <err.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 
      8 #include "format.h"
      9 #include "git/commit.h"
     10 #include "third_party/openbsd/reallocarray.h"
     11 #include "utils.h"
     12 #include "writer/html/page.h"
     13 
     14 typedef struct {
     15   char* title;
     16   char* id;
     17   FILE* out;
     18 } HtmlRefsTable;
     19 
     20 typedef struct {
     21   char* shorthand;
     22   time_t author_time;
     23   char* author_name;
     24 } RefData;
     25 
     26 typedef struct {
     27   RefData* items;
     28   size_t count;
     29   size_t capacity;
     30 } RefList;
     31 
     32 struct HtmlRefs {
     33   const GitRepo* repo;
     34   const FileSystem* fs;
     35   FILE* out;
     36   HtmlPage* page;
     37   RefList branches;
     38   RefList tags;
     39 };
     40 
     41 static HtmlRefsTable* html_refstable_create(const char* title,
     42                                             const char* id,
     43                                             FILE* out);
     44 static void html_refstable_free(HtmlRefsTable* table);
     45 static void html_refstable_begin(HtmlRefsTable* table);
     46 static void html_refstable_add_ref(HtmlRefsTable* table, const RefData* ref);
     47 static void html_refstable_end(HtmlRefsTable* table);
     48 
     49 static HtmlRefsTable* html_refstable_create(const char* title,
     50                                             const char* id,
     51                                             FILE* out) {
     52   assert(title != NULL);
     53   assert(id != NULL);
     54   assert(out != NULL);
     55   HtmlRefsTable* table = ecalloc(1, sizeof(HtmlRefsTable));
     56   table->title = estrdup(title);
     57   table->id = estrdup(id);
     58   table->out = out;
     59   return table;
     60 }
     61 
     62 static void html_refstable_free(HtmlRefsTable* table) {
     63   if (!table) {
     64     return;
     65   }
     66   free(table->title);
     67   free(table->id);
     68   free(table);
     69 }
     70 
     71 static void html_refstable_begin(HtmlRefsTable* table) {
     72   assert(table != NULL);
     73   fprintf(table->out, "<h2>%s</h2>", table->title);
     74   fprintf(table->out, "<table id=\"%s\">", table->id);
     75   fprintf(table->out,
     76           "<thead>\n"
     77           "<tr>"
     78           "<td><b>Name</b></td>"
     79           "<td><b>Last commit date</b></td>"
     80           "<td><b>Author</b></td>\n"
     81           "</tr>\n"
     82           "</thead><tbody>\n");
     83 }
     84 
     85 static void html_refstable_add_ref(HtmlRefsTable* table, const RefData* ref) {
     86   assert(table != NULL);
     87   assert(ref != NULL);
     88   fprintf(table->out, "<tr><td>");
     89   print_xml_encoded(table->out, ref->shorthand);
     90   fprintf(table->out, "</td><td>");
     91   print_time_short(table->out, ref->author_time);
     92   fprintf(table->out, "</td><td>");
     93   print_xml_encoded(table->out, ref->author_name);
     94   fprintf(table->out, "</td></tr>\n");
     95 }
     96 
     97 static void html_refstable_end(HtmlRefsTable* table) {
     98   assert(table != NULL);
     99   fprintf(table->out, "</tbody></table><br/>\n");
    100 }
    101 
    102 static void reflist_add(RefList* list, const GitReference* ref) {
    103   if (list->count >= list->capacity) {
    104     list->capacity = list->capacity == 0 ? 16 : list->capacity * 2;
    105     list->items = reallocarray(list->items, list->capacity, sizeof(RefData));
    106     if (!list->items) {
    107       err(1, "reallocarray");
    108     }
    109   }
    110   RefData* item = &list->items[list->count++];
    111   item->shorthand = estrdup(ref->shorthand);
    112   if (ref->commit) {
    113     item->author_time = ref->commit->author_time;
    114     item->author_name = estrdup(ref->commit->author_name);
    115   } else {
    116     item->author_time = 0;
    117     item->author_name = estrdup("");
    118   }
    119 }
    120 
    121 static void reflist_clear(RefList* list) {
    122   for (size_t i = 0; i < list->count; i++) {
    123     free(list->items[i].shorthand);
    124     free(list->items[i].author_name);
    125   }
    126   free(list->items);
    127   list->items = NULL;
    128   list->count = 0;
    129   list->capacity = 0;
    130 }
    131 
    132 HtmlRefs* html_refs_create(const GitRepo* repo, const FileSystem* fs) {
    133   assert(repo != NULL);
    134   assert(fs != NULL);
    135   HtmlRefs* refs = ecalloc(1, sizeof(HtmlRefs));
    136   refs->repo = repo;
    137   refs->fs = fs;
    138   refs->out = fs->fopen("refs.html", "w");
    139   if (!refs->out) {
    140     err(1, "fopen: refs.html");
    141   }
    142   refs->page = html_page_create(refs->out, repo, fs, "Refs", "");
    143   return refs;
    144 }
    145 
    146 void html_refs_free(HtmlRefs* refs) {
    147   if (!refs) {
    148     return;
    149   }
    150   refs->fs->fclose(refs->out);
    151   html_page_free(refs->page);
    152   reflist_clear(&refs->branches);
    153   reflist_clear(&refs->tags);
    154   free(refs);
    155 }
    156 
    157 void html_refs_begin(HtmlRefs* refs) {
    158   assert(refs != NULL);
    159   html_page_begin(refs->page);
    160 }
    161 
    162 void html_refs_add_ref(HtmlRefs* refs, const GitReference* ref) {
    163   assert(refs != NULL);
    164   assert(ref != NULL);
    165   switch (ref->type) {
    166     case kReftypeBranch:
    167       reflist_add(&refs->branches, ref);
    168       break;
    169     case kReftypeTag:
    170       reflist_add(&refs->tags, ref);
    171       break;
    172   }
    173 }
    174 
    175 void html_refs_end(HtmlRefs* refs) {
    176   assert(refs != NULL);
    177   if (refs->branches.count > 0) {
    178     HtmlRefsTable* table =
    179         html_refstable_create("Branches", "branches", refs->out);
    180     html_refstable_begin(table);
    181     for (size_t i = 0; i < refs->branches.count; i++) {
    182       html_refstable_add_ref(table, &refs->branches.items[i]);
    183     }
    184     html_refstable_end(table);
    185     html_refstable_free(table);
    186   }
    187   if (refs->tags.count > 0) {
    188     HtmlRefsTable* table = html_refstable_create("Tags", "tags", refs->out);
    189     html_refstable_begin(table);
    190     for (size_t i = 0; i < refs->tags.count; i++) {
    191       html_refstable_add_ref(table, &refs->tags.items[i]);
    192     }
    193     html_refstable_end(table);
    194     html_refstable_free(table);
    195   }
    196   html_page_end(refs->page);
    197 }