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