| -rw-r--r-- | parsing.c | 112 |
1 files changed, 71 insertions, 41 deletions
@@ -118,50 +118,45 @@ static const char *reencode(char **txt, const char *src_enc, const char *dst_enc } #endif -static const char *next_header_line(const char *p) -{ - p = strchr(p, '\n'); - if (!p) - return NULL; - return p + 1; -} - -static int end_of_header(const char *p) -{ - return !p || (*p == '\n'); -} - struct commitinfo *cgit_parse_commit(struct commit *commit) { - const int sha1hex_len = 40; struct commitinfo *ret; const char *p = get_cached_commit_buffer(commit, NULL); const char *t; - ret = xcalloc(1, sizeof(struct commitinfo)); + ret = xmalloc(sizeof(*ret)); ret->commit = commit; + ret->author = NULL; + ret->author_email = NULL; + ret->committer = NULL; + ret->committer_email = NULL; + ret->subject = NULL; + ret->msg = NULL; + ret->msg_encoding = NULL; - if (!p) + if (p == NULL) return ret; - if (!skip_prefix(p, "tree ", &p)) + if (!starts_with(p, "tree ")) die("Bad commit: %s", sha1_to_hex(commit->object.sha1)); - p += sha1hex_len + 1; + else + p += 46; // "tree " + hex[40] + "\n" - while (skip_prefix(p, "parent ", &p)) - p += sha1hex_len + 1; + while (starts_with(p, "parent ")) + p += 48; // "parent " + hex[40] + "\n" - if (p && skip_prefix(p, "author ", &p)) { - p = parse_user(p, &ret->author, &ret->author_email, + if (p && starts_with(p, "author ")) { + p = parse_user(p + 7, &ret->author, &ret->author_email, &ret->author_date); } - if (p && skip_prefix(p, "committer ", &p)) { - p = parse_user(p, &ret->committer, &ret->committer_email, + if (p && starts_with(p, "committer ")) { + p = parse_user(p + 10, &ret->committer, &ret->committer_email, &ret->committer_date); } - if (p && skip_prefix(p, "encoding ", &p)) { + if (p && starts_with(p, "encoding ")) { + p += 9; t = strchr(p, '\n'); if (t) { ret->msg_encoding = substr(p, t + 1); @@ -169,21 +164,38 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) } } + /* if no special encoding is found, assume UTF-8 */ if (!ret->msg_encoding) ret->msg_encoding = xstrdup("UTF-8"); - while (!end_of_header(p)) - p = next_header_line(p); + // skip unknown header fields + while (p && *p && (*p != '\n')) { + p = strchr(p, '\n'); + if (p) + p++; + } + + // skip empty lines between headers and message while (p && *p == '\n') p++; + if (!p) return ret; - t = strchrnul(p, '\n'); - ret->subject = substr(p, t); - while (*t == '\n') - t++; - ret->msg = xstrdup(t); + t = strchr(p, '\n'); + if (t) { + ret->subject = substr(p, t); + p = t + 1; + + while (p && *p == '\n') { + p = strchr(p, '\n'); + if (p) + p++; + } + if (p) + ret->msg = xstrdup(p); + } else + ret->subject = xstrdup(p); reencode(&ret->author, ret->msg_encoding, PAGE_ENCODING); reencode(&ret->author_email, ret->msg_encoding, PAGE_ENCODING); @@ -195,31 +207,49 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) return ret; } + struct taginfo *cgit_parse_tag(struct tag *tag) { void *data; enum object_type type; unsigned long size; const char *p; - struct taginfo *ret = NULL; + struct taginfo *ret; data = read_sha1_file(tag->object.sha1, &type, &size); - if (!data || type != OBJ_TAG) - goto cleanup; + if (!data || type != OBJ_TAG) { + free(data); + return 0; + } + + ret = xmalloc(sizeof(*ret)); + ret->tagger = NULL; + ret->tagger_email = NULL; + ret->tagger_date = 0; + ret->msg = NULL; - ret = xcalloc(1, sizeof(struct taginfo)); + p = data; - for (p = data; !end_of_header(p); p = next_header_line(p)) { - if (skip_prefix(p, "tagger ", &p)) { - p = parse_user(p, &ret->tagger, &ret->tagger_email, + while (p && *p) { + if (*p == '\n') + break; + + if (starts_with(p, "tagger ")) { + p = parse_user(p + 7, &ret->tagger, &ret->tagger_email, &ret->tagger_date); + } else { + p = strchr(p, '\n'); + if (p) + p++; } } + // skip empty lines between headers and message + while (p && *p == '\n') + p++; + if (p && *p) ret->msg = xstrdup(p); - -cleanup: free(data); return ret; } |