gout

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

repo_writer.c (5112B)


      1 #include "writer/gemini/repo_writer.h"
      2 
      3 #include <assert.h>
      4 #include <err.h>
      5 #include <limits.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <sys/stat.h>
      9 #include <sys/types.h>
     10 
     11 #include "git/commit.h"
     12 #include "git/file.h"
     13 #include "git/reference.h"
     14 #include "utils.h"
     15 #include "writer/atom/atom.h"
     16 #include "writer/gemini/commit.h"
     17 #include "writer/gemini/fileblob.h"
     18 #include "writer/gemini/files.h"
     19 #include "writer/gemini/log.h"
     20 #include "writer/gemini/refs.h"
     21 
     22 struct GeminiRepoWriter {
     23   const GitRepo* repo;
     24   const FileSystem* fs;
     25   GeminiRefs* refs;
     26   GeminiLog* log;
     27   Atom* atom;
     28   FILE* atom_out;
     29   Atom* tags;
     30   FILE* tags_out;
     31   GeminiFiles* files;
     32 };
     33 
     34 GeminiRepoWriter* gemini_repowriter_create(const GitRepo* repo,
     35                                            const FileSystem* fs) {
     36   assert(repo != NULL);
     37   assert(fs != NULL);
     38   GeminiRepoWriter* writer = ecalloc(1, sizeof(GeminiRepoWriter));
     39   writer->repo = repo;
     40   writer->fs = fs;
     41   writer->refs = gemini_refs_create(repo, fs);
     42   writer->log = gemini_log_create(repo, fs);
     43   writer->atom_out = fs->fopen("atom.xml", "w");
     44   if (!writer->atom_out) {
     45     err(1, "fopen: atom.xml");
     46   }
     47   writer->atom = atom_create(repo, writer->atom_out);
     48   writer->tags_out = fs->fopen("tags.xml", "w");
     49   if (!writer->tags_out) {
     50     err(1, "fopen: tags.xml");
     51   }
     52   writer->tags = atom_create(repo, writer->tags_out);
     53   writer->files = gemini_files_create(repo, fs);
     54   return writer;
     55 }
     56 
     57 void gemini_repowriter_free(GeminiRepoWriter* writer) {
     58   if (!writer) {
     59     return;
     60   }
     61   gemini_refs_free(writer->refs);
     62   gemini_log_free(writer->log);
     63   atom_free(writer->atom);
     64   if (writer->atom_out) {
     65     writer->fs->fclose(writer->atom_out);
     66   }
     67   atom_free(writer->tags);
     68   if (writer->tags_out) {
     69     writer->fs->fclose(writer->tags_out);
     70   }
     71   gemini_files_free(writer->files);
     72   free(writer);
     73 }
     74 
     75 void gemini_repowriter_set_log_cachefile(GeminiRepoWriter* writer,
     76                                          const char* cachefile) {
     77   assert(writer != NULL);
     78   assert(cachefile != NULL);
     79   gemini_log_set_cachefile(writer->log, cachefile);
     80 }
     81 
     82 void gemini_repowriter_set_log_commit_limit(GeminiRepoWriter* writer,
     83                                             size_t count) {
     84   assert(writer != NULL);
     85   gemini_log_set_commit_limit(writer->log, count);
     86 }
     87 
     88 void gemini_repowriter_set_baseurl(GeminiRepoWriter* writer,
     89                                    const char* baseurl) {
     90   assert(writer != NULL);
     91   assert(baseurl != NULL);
     92   atom_set_baseurl(writer->atom, baseurl);
     93   atom_set_baseurl(writer->tags, baseurl);
     94 }
     95 
     96 void gemini_repowriter_begin(GeminiRepoWriter* writer) {
     97   assert(writer != NULL);
     98   writer->fs->mkdir("commit", S_IRWXU | S_IRWXG | S_IRWXO);
     99   writer->fs->mkdir("file", S_IRWXU | S_IRWXG | S_IRWXO);
    100 
    101   gemini_refs_begin(writer->refs);
    102   gemini_log_begin(writer->log);
    103   atom_begin(writer->atom);
    104   atom_begin(writer->tags);
    105   gemini_files_begin(writer->files);
    106 }
    107 
    108 void gemini_repowriter_add_commit(GeminiRepoWriter* writer,
    109                                   const GitCommit* git_commit) {
    110   assert(writer != NULL);
    111   assert(git_commit != NULL);
    112   char filename[PATH_MAX];
    113   int r = snprintf(filename, sizeof(filename), "%s.gmi", git_commit->oid);
    114   if (r < 0 || (size_t)r >= sizeof(filename)) {
    115     errx(1, "snprintf: filename truncated or error");
    116   }
    117   char* path = path_concat("commit", filename);
    118   atom_add_commit(writer->atom, git_commit, path, "", "");
    119   free(path);
    120 
    121   if (gemini_log_can_add_commits(writer->log)) {
    122     gemini_log_add_commit(writer->log, git_commit);
    123     GeminiCommit* commit = gemini_commit_create(
    124         writer->repo, writer->fs, git_commit->oid, git_commit->summary);
    125     gemini_commit_begin(commit);
    126     gemini_commit_add_commit(commit, git_commit);
    127     gemini_commit_end(commit);
    128     gemini_commit_free(commit);
    129   }
    130 }
    131 
    132 void gemini_repowriter_add_reference(GeminiRepoWriter* writer,
    133                                      const GitReference* ref) {
    134   assert(writer != NULL);
    135   assert(ref != NULL);
    136   gemini_refs_add_ref(writer->refs, ref);
    137   if (ref->type == kReftypeTag) {
    138     GitCommit* commit = ref->commit;
    139     char filename[PATH_MAX];
    140     int r = snprintf(filename, sizeof(filename), "%s.gmi", commit->oid);
    141     if (r < 0 || (size_t)r >= sizeof(filename)) {
    142       errx(1, "snprintf: filename truncated or error");
    143     }
    144     char* path = path_concat("commit", filename);
    145     atom_add_commit(writer->tags, commit, path, "", ref->shorthand);
    146     free(path);
    147   }
    148 }
    149 
    150 void gemini_repowriter_add_file(GeminiRepoWriter* writer, const GitFile* file) {
    151   assert(writer != NULL);
    152   assert(file != NULL);
    153   gemini_files_add_file(writer->files, file);
    154 
    155   GeminiFileBlob* blob =
    156       gemini_fileblob_create(writer->repo, writer->fs, file->repo_path);
    157   gemini_fileblob_begin(blob);
    158   gemini_fileblob_add_file(blob, file);
    159   gemini_fileblob_end(blob);
    160   gemini_fileblob_free(blob);
    161 }
    162 
    163 void gemini_repowriter_end(GeminiRepoWriter* writer) {
    164   assert(writer != NULL);
    165   gemini_refs_end(writer->refs);
    166   gemini_log_end(writer->log);
    167   atom_end(writer->atom);
    168   atom_end(writer->tags);
    169   gemini_files_end(writer->files);
    170 }