gout

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

atom.c (4008B)


      1 #include "atom.h"
      2 
      3 #include <assert.h>
      4 #include <err.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 
      9 #include "format.h"
     10 #include "utils.h"
     11 
     12 struct Atom {
     13   const GitRepo* repo;
     14   const char* baseurl;
     15   FILE* out;
     16   size_t remaining_commits;
     17 };
     18 
     19 Atom* atom_create(const GitRepo* repo, FILE* out) {
     20   assert(repo != NULL);
     21   assert(out != NULL);
     22   Atom* atom = ecalloc(1, sizeof(Atom));
     23   atom->repo = repo;
     24   atom->baseurl = "";
     25   atom->out = out;
     26   atom->remaining_commits = 100;
     27   return atom;
     28 }
     29 
     30 void atom_free(Atom* atom) {
     31   if (!atom) {
     32     return;
     33   }
     34   atom->out = NULL;
     35   free(atom);
     36 }
     37 
     38 void atom_set_baseurl(Atom* atom, const char* baseurl) {
     39   assert(atom != NULL);
     40   assert(baseurl != NULL);
     41   atom->baseurl = baseurl;
     42 }
     43 
     44 void atom_begin(Atom* atom) {
     45   assert(atom != NULL);
     46   fprintf(atom->out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
     47   fprintf(atom->out, "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n");
     48   fprintf(atom->out, "<title>");
     49   if (atom->repo->short_name) {
     50     print_xml_encoded(atom->out, atom->repo->short_name);
     51   }
     52   fprintf(atom->out, ", branch HEAD</title>\n");
     53   fprintf(atom->out, "<subtitle>");
     54   if (atom->repo->description) {
     55     print_xml_encoded(atom->out, atom->repo->description);
     56   }
     57   fprintf(atom->out, "</subtitle>\n");
     58 }
     59 
     60 void atom_add_commit(Atom* atom,
     61                      const GitCommit* commit,
     62                      const char* path,
     63                      const char* content_type,
     64                      const char* tag) {
     65   assert(atom != NULL);
     66   assert(commit != NULL);
     67   assert(path != NULL);
     68   assert(path[0] != '\0');
     69   assert(content_type != NULL);
     70 
     71   FILE* out = atom->out;
     72   if (atom->remaining_commits == 0) {
     73     return;
     74   }
     75   if (commit->oid[0] == '\0') {
     76     warnx("atom: processed commit with missing/empty object ID");
     77     return;
     78   }
     79   atom->remaining_commits--;
     80 
     81   fprintf(out, "<entry>\n");
     82   fprintf(out, "<id>%s</id>\n", commit->oid);
     83 
     84   fprintf(out, "<published>");
     85   print_time_z(out, commit->author_time);
     86   fprintf(out, "</published>\n");
     87 
     88   fprintf(out, "<updated>");
     89   print_time_z(out, commit->commit_time);
     90   fprintf(out, "</updated>\n");
     91 
     92   if (commit->summary) {
     93     fprintf(out, "<title>");
     94     if (tag && tag[0] != '\0') {
     95       fprintf(out, "[");
     96       print_xml_encoded(out, tag);
     97       fprintf(out, "]");
     98     }
     99     print_xml_encoded(out, commit->summary);
    100     fprintf(out, "</title>\n");
    101   }
    102   fprintf(out, "<link rel=\"alternate\" ");
    103   if (strlen(content_type) > 0) {
    104     fprintf(out, "type=\"%s\" ", content_type);
    105   }
    106   size_t baseurl_len = strlen(atom->baseurl);
    107   const char* p = path;
    108   if (baseurl_len > 0 && atom->baseurl[baseurl_len - 1] == '/' && p[0] == '/') {
    109     p++;
    110   }
    111   bool needs_slash =
    112       (baseurl_len > 0 && atom->baseurl[baseurl_len - 1] != '/' && p[0] != '/');
    113   fprintf(out, "href=\"%s%s%s\" />\n", atom->baseurl, needs_slash ? "/" : "",
    114           p);
    115 
    116   fprintf(out, "<author>\n<name>");
    117   if (commit->author_name) {
    118     print_xml_encoded(out, commit->author_name);
    119   }
    120   fprintf(out, "</name>\n<email>");
    121   if (commit->author_email) {
    122     print_xml_encoded(out, commit->author_email);
    123   }
    124   fprintf(out, "</email>\n</author>\n");
    125 
    126   fprintf(out, "<content>");
    127   fprintf(out, "commit %s\n", commit->oid);
    128   const char* parentoid = commit->parentoid;
    129   if (parentoid && parentoid[0] != '\0') {
    130     fprintf(out, "parent %s\n", parentoid);
    131   }
    132   fprintf(out, "Author: ");
    133   if (commit->author_name) {
    134     print_xml_encoded(out, commit->author_name);
    135   }
    136   fprintf(out, " &lt;");
    137   if (commit->author_email) {
    138     print_xml_encoded(out, commit->author_email);
    139   }
    140   fprintf(out, "&gt;\n");
    141   fprintf(out, "Date:   ");
    142   print_time(out, commit->author_time, commit->author_timezone_offset);
    143   fprintf(out, "\n");
    144   const char* message = commit->message;
    145   if (message) {
    146     fprintf(out, "\n");
    147     print_xml_encoded(out, message);
    148   }
    149   fprintf(out, "\n</content>\n</entry>\n");
    150 }
    151 
    152 void atom_end(Atom* atom) {
    153   assert(atom != NULL);
    154   fprintf(atom->out, "</feed>\n");
    155 }