gout

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

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 }