diff options
| author | Lukas Fleischer | 2015-03-03 13:00:07 +0100 |
|---|---|---|
| committer | Jason A. Donenfeld | 2015-03-03 16:47:30 +0100 |
| commit | 936295c4e4de8da83701c67377a911a0aefbcbd6 (patch) | |
| tree | 8a7d0f56bc0faaca7f68eab0037bb2bb7dd4579c | |
| parent | 911d574250d3a2ae97f282fb8f466db2afa1cd64 (diff) | |
| download | cgit-936295c4e4de8da83701c67377a911a0aefbcbd6.tar.gz cgit-936295c4e4de8da83701c67377a911a0aefbcbd6.tar.bz2 cgit-936295c4e4de8da83701c67377a911a0aefbcbd6.zip | |
Simplify commit and tag parsing
* Use skip_prefix to avoid magic numbers in the code.
* Use xcalloc() instead of xmalloc(), followed by manual initialization.
* Split out line splitting.
Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de>
| -rw-r--r-- | parsing.c | 114 |
1 files changed, 42 insertions, 72 deletions
| @@ -118,45 +118,50 @@ static const char *reencode(char **txt, const char *src_enc, const char *dst_enc | |||
| 118 | } | 118 | } |
| 119 | #endif | 119 | #endif |
| 120 | 120 | ||
| 121 | static const char *next_header_line(const char *p) | ||
| 122 | { | ||
| 123 | p = strchr(p, '\n'); | ||
| 124 | if (!p) | ||
| 125 | return NULL; | ||
| 126 | return p + 1; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int end_of_header(const char *p) | ||
| 130 | { | ||
| 131 | return !p || (*p == '\n'); | ||
| 132 | } | ||
| 133 | |||
| 121 | struct commitinfo *cgit_parse_commit(struct commit *commit) | 134 | struct commitinfo *cgit_parse_commit(struct commit *commit) |
| 122 | { | 135 | { |
| 136 | const int sha1hex_len = 40; | ||
| 123 | struct commitinfo *ret; | 137 | struct commitinfo *ret; |
| 124 | const char *p = get_cached_commit_buffer(commit, NULL); | 138 | const char *p = get_cached_commit_buffer(commit, NULL); |
| 125 | const char *t; | 139 | const char *t; |
| 126 | 140 | ||
| 127 | ret = xmalloc(sizeof(*ret)); | 141 | ret = xcalloc(1, sizeof(struct commitinfo)); |
| 128 | ret->commit = commit; | 142 | ret->commit = commit; |
| 129 | ret->author = NULL; | 143 | |
| 130 | ret->author_email = NULL; | 144 | if (!p) |
| 131 | ret->committer = NULL; | ||
| 132 | ret->committer_email = NULL; | ||
| 133 | ret->subject = NULL; | ||
| 134 | ret->msg = NULL; | ||
| 135 | ret->msg_encoding = NULL; | ||
| 136 | |||
| 137 | if (p == NULL) | ||
| 138 | return ret; | 145 | return ret; |
| 139 | 146 | ||
| 140 | if (!starts_with(p, "tree ")) | 147 | if (!skip_prefix(p, "tree ", &p)) |
| 141 | die("Bad commit: %s", sha1_to_hex(commit->object.sha1)); | 148 | die("Bad commit: %s", sha1_to_hex(commit->object.sha1)); |
| 142 | else | 149 | p += sha1hex_len + 1; |
| 143 | p += 46; // "tree " + hex[40] + "\n" | ||
| 144 | 150 | ||
| 145 | while (starts_with(p, "parent ")) | 151 | while (skip_prefix(p, "parent ", &p)) |
| 146 | p += 48; // "parent " + hex[40] + "\n" | 152 | p += sha1hex_len + 1; |
| 147 | 153 | ||
| 148 | if (p && starts_with(p, "author ")) { | 154 | if (p && skip_prefix(p, "author ", &p)) { |
| 149 | p = parse_user(p + 7, &ret->author, &ret->author_email, | 155 | p = parse_user(p, &ret->author, &ret->author_email, |
| 150 | &ret->author_date); | 156 | &ret->author_date); |
| 151 | } | 157 | } |
| 152 | 158 | ||
| 153 | if (p && starts_with(p, "committer ")) { | 159 | if (p && skip_prefix(p, "committer ", &p)) { |
| 154 | p = parse_user(p + 10, &ret->committer, &ret->committer_email, | 160 | p = parse_user(p, &ret->committer, &ret->committer_email, |
| 155 | &ret->committer_date); | 161 | &ret->committer_date); |
| 156 | } | 162 | } |
| 157 | 163 | ||
| 158 | if (p && starts_with(p, "encoding ")) { | 164 | if (p && skip_prefix(p, "encoding ", &p)) { |
| 159 | p += 9; | ||
| 160 | t = strchr(p, '\n'); | 165 | t = strchr(p, '\n'); |
| 161 | if (t) { | 166 | if (t) { |
| 162 | ret->msg_encoding = substr(p, t + 1); | 167 | ret->msg_encoding = substr(p, t + 1); |
| @@ -164,38 +169,21 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) | |||
| 164 | } | 169 | } |
| 165 | } | 170 | } |
| 166 | 171 | ||
| 167 | /* if no special encoding is found, assume UTF-8 */ | ||
| 168 | if (!ret->msg_encoding) | 172 | if (!ret->msg_encoding) |
| 169 | ret->msg_encoding = xstrdup("UTF-8"); | 173 | ret->msg_encoding = xstrdup("UTF-8"); |
| 170 | 174 | ||
| 171 | // skip unknown header fields | 175 | while (!end_of_header(p)) |
| 172 | while (p && *p && (*p != '\n')) { | 176 | p = next_header_line(p); |
| 173 | p = strchr(p, '\n'); | ||
| 174 | if (p) | ||
| 175 | p++; | ||
| 176 | } | ||
| 177 | |||
| 178 | // skip empty lines between headers and message | ||
| 179 | while (p && *p == '\n') | 177 | while (p && *p == '\n') |
| 180 | p++; | 178 | p++; |
| 181 | |||
| 182 | if (!p) | 179 | if (!p) |
| 183 | return ret; | 180 | return ret; |
| 184 | 181 | ||
| 185 | t = strchr(p, '\n'); | 182 | t = strchrnul(p, '\n'); |
| 186 | if (t) { | 183 | ret->subject = substr(p, t); |
| 187 | ret->subject = substr(p, t); | 184 | while (*t == '\n') |
| 188 | p = t + 1; | 185 | t++; |
| 189 | 186 | ret->msg = xstrdup(t); | |
| 190 | while (p && *p == '\n') { | ||
| 191 | p = strchr(p, '\n'); | ||
| 192 | if (p) | ||
| 193 | p++; | ||
| 194 | } | ||
| 195 | if (p) | ||
| 196 | ret->msg = xstrdup(p); | ||
| 197 | } else | ||
| 198 | ret->subject = xstrdup(p); | ||
| 199 | 187 | ||
| 200 | reencode(&ret->author, ret->msg_encoding, PAGE_ENCODING); | 188 | reencode(&ret->author, ret->msg_encoding, PAGE_ENCODING); |
| 201 | reencode(&ret->author_email, ret->msg_encoding, PAGE_ENCODING); | 189 | reencode(&ret->author_email, ret->msg_encoding, PAGE_ENCODING); |
| @@ -207,49 +195,31 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) | |||
| 207 | return ret; | 195 | return ret; |
| 208 | } | 196 | } |
| 209 | 197 | ||
| 210 | |||
| 211 | struct taginfo *cgit_parse_tag(struct tag *tag) | 198 | struct taginfo *cgit_parse_tag(struct tag *tag) |
| 212 | { | 199 | { |
| 213 | void *data; | 200 | void *data; |
| 214 | enum object_type type; | 201 | enum object_type type; |
| 215 | unsigned long size; | 202 | unsigned long size; |
| 216 | const char *p; | 203 | const char *p; |
| 217 | struct taginfo *ret; | 204 | struct taginfo *ret = NULL; |
| 218 | 205 | ||
| 219 | data = read_sha1_file(tag->object.sha1, &type, &size); | 206 | data = read_sha1_file(tag->object.sha1, &type, &size); |
| 220 | if (!data || type != OBJ_TAG) { | 207 | if (!data || type != OBJ_TAG) |
| 221 | free(data); | 208 | goto cleanup; |
| 222 | return 0; | ||
| 223 | } | ||
| 224 | 209 | ||
| 225 | ret = xmalloc(sizeof(*ret)); | 210 | ret = xcalloc(1, sizeof(struct taginfo)); |
| 226 | ret->tagger = NULL; | ||
| 227 | ret->tagger_email = NULL; | ||
| 228 | ret->tagger_date = 0; | ||
| 229 | ret->msg = NULL; | ||
| 230 | 211 | ||
| 231 | p = data; | 212 | for (p = data; !end_of_header(p); p = next_header_line(p)) { |
| 232 | 213 | if (skip_prefix(p, "tagger ", &p)) { | |
| 233 | while (p && *p) { | 214 | p = parse_user(p, &ret->tagger, &ret->tagger_email, |
| 234 | if (*p == '\n') | ||
| 235 | break; | ||
| 236 | |||
| 237 | if (starts_with(p, "tagger ")) { | ||
| 238 | p = parse_user(p + 7, &ret->tagger, &ret->tagger_email, | ||
| 239 | &ret->tagger_date); | 215 | &ret->tagger_date); |
| 240 | } else { | ||
| 241 | p = strchr(p, '\n'); | ||
| 242 | if (p) | ||
| 243 | p++; | ||
| 244 | } | 216 | } |
| 245 | } | 217 | } |
| 246 | 218 | ||
| 247 | // skip empty lines between headers and message | ||
| 248 | while (p && *p == '\n') | ||
| 249 | p++; | ||
| 250 | |||
| 251 | if (p && *p) | 219 | if (p && *p) |
| 252 | ret->msg = xstrdup(p); | 220 | ret->msg = xstrdup(p); |
| 221 | |||
| 222 | cleanup: | ||
| 253 | free(data); | 223 | free(data); |
| 254 | return ret; | 224 | return ret; |
| 255 | } | 225 | } |
