+ tmp = reencode_string(*txt, src_enc, dst_enc);
+ if (tmp) {
+ free(*txt);
+ *txt = tmp;
+ }
+ return *txt;
+}
+#endif
+
+struct commitinfo *cgit_parse_commit(struct commit *commit)
+{
+ struct commitinfo *ret;
+ char *p = commit->buffer, *t = commit->buffer;
+
+ 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 == NULL)
+ return ret;
+
+ if (strncmp(p, "tree ", 5))
+ die("Bad commit: %s", sha1_to_hex(commit->object.sha1));
+ else
+ p += 46; // "tree " + hex[40] + "\n"
+
+ while (!strncmp(p, "parent ", 7))
+ p += 48; // "parent " + hex[40] + "\n"
+
+ if (p && !strncmp(p, "author ", 7)) {
+ p = parse_user(p + 7, &ret->author, &ret->author_email,
+ &ret->author_date);
+ }
+
+ if (p && !strncmp(p, "committer ", 9)) {
+ p = parse_user(p + 9, &ret->committer, &ret->committer_email,
+ &ret->committer_date);
+ }
+
+ if (p && !strncmp(p, "encoding ", 9)) {
+ p += 9;
+ t = strchr(p, '\n');
+ if (t) {
+ ret->msg_encoding = substr(p, t + 1);
+ p = t + 1;
+ }
+ }
+
+ // 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 = 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);
+
+ if (ret->msg_encoding) {
+ reencode(&ret->subject, PAGE_ENCODING, ret->msg_encoding);
+ reencode(&ret->msg, PAGE_ENCODING, ret->msg_encoding);
+ }