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, " <"); 137 if (commit->author_email) { 138 print_xml_encoded(out, commit->author_email); 139 } 140 fprintf(out, ">\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 }