atom.c (4161B)
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 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 = estrdup(""); 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 free(atom->baseurl); 36 atom->out = NULL; 37 free(atom); 38 } 39 40 void atom_set_baseurl(Atom* atom, const char* baseurl) { 41 assert(atom != NULL); 42 assert(baseurl != NULL); 43 free(atom->baseurl); 44 atom->baseurl = estrdup(baseurl); 45 } 46 47 void atom_begin(Atom* atom) { 48 assert(atom != NULL); 49 fprintf(atom->out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 50 fprintf(atom->out, "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n"); 51 fprintf(atom->out, "<title>"); 52 if (atom->repo->short_name) { 53 print_xml_encoded(atom->out, atom->repo->short_name); 54 } 55 fprintf(atom->out, ", branch HEAD</title>\n"); 56 fprintf(atom->out, "<subtitle>"); 57 if (atom->repo->description) { 58 print_xml_encoded(atom->out, atom->repo->description); 59 } 60 fprintf(atom->out, "</subtitle>\n"); 61 } 62 63 void atom_add_commit(Atom* atom, 64 const GitCommit* commit, 65 const char* path, 66 const char* content_type, 67 const char* tag) { 68 assert(atom != NULL); 69 assert(commit != NULL); 70 assert(path != NULL); 71 assert(path[0] != '\0'); 72 assert(content_type != NULL); 73 74 FILE* out = atom->out; 75 if (atom->remaining_commits == 0) { 76 return; 77 } 78 if (commit->oid[0] == '\0') { 79 warnx("atom: processed commit with missing/empty object ID"); 80 return; 81 } 82 atom->remaining_commits--; 83 84 fprintf(out, "<entry>\n"); 85 fprintf(out, "<id>%s</id>\n", commit->oid); 86 87 fprintf(out, "<published>"); 88 print_time_z(out, commit->author_time); 89 fprintf(out, "</published>\n"); 90 91 fprintf(out, "<updated>"); 92 print_time_z(out, commit->commit_time); 93 fprintf(out, "</updated>\n"); 94 95 fprintf(out, "<title>"); 96 if (tag && tag[0] != '\0') { 97 fprintf(out, "["); 98 print_xml_encoded(out, tag); 99 fprintf(out, "] "); 100 } 101 if (commit->summary && commit->summary[0] != '\0') { 102 print_xml_encoded(out, commit->summary); 103 } else { 104 fprintf(out, "Commit %.7s", commit->oid); 105 } 106 fprintf(out, "</title>\n"); 107 fprintf(out, "<link rel=\"alternate\" "); 108 if (strlen(content_type) > 0) { 109 fprintf(out, "type=\"%s\" ", content_type); 110 } 111 size_t baseurl_len = strlen(atom->baseurl); 112 const char* p = path; 113 if (baseurl_len > 0 && atom->baseurl[baseurl_len - 1] == '/' && p[0] == '/') { 114 p++; 115 } 116 bool needs_slash = 117 (baseurl_len > 0 && atom->baseurl[baseurl_len - 1] != '/' && p[0] != '/'); 118 fprintf(out, "href=\"%s%s%s\" />\n", atom->baseurl, needs_slash ? "/" : "", 119 p); 120 121 fprintf(out, "<author>\n<name>"); 122 if (commit->author_name) { 123 print_xml_encoded(out, commit->author_name); 124 } 125 fprintf(out, "</name>\n<email>"); 126 if (commit->author_email) { 127 print_xml_encoded(out, commit->author_email); 128 } 129 fprintf(out, "</email>\n</author>\n"); 130 131 fprintf(out, "<content>"); 132 fprintf(out, "commit %s\n", commit->oid); 133 const char* parentoid = commit->parentoid; 134 if (parentoid && parentoid[0] != '\0') { 135 fprintf(out, "parent %s\n", parentoid); 136 } 137 fprintf(out, "Author: "); 138 if (commit->author_name) { 139 print_xml_encoded(out, commit->author_name); 140 } 141 fprintf(out, " <"); 142 if (commit->author_email) { 143 print_xml_encoded(out, commit->author_email); 144 } 145 fprintf(out, ">\n"); 146 fprintf(out, "Date: "); 147 print_time(out, commit->author_time, commit->author_timezone_offset); 148 fprintf(out, "\n"); 149 const char* message = commit->message; 150 if (message) { 151 fprintf(out, "\n"); 152 print_xml_encoded(out, message); 153 } 154 fprintf(out, "\n</content>\n</entry>\n"); 155 } 156 157 void atom_end(Atom* atom) { 158 assert(atom != NULL); 159 fprintf(atom->out, "</feed>\n"); 160 }