+/**
+ * Callback signature for split_mail_conv(). The foreign patch should be
+ * read from `in`, and the converted patch (in RFC2822 mail format) should be
+ * written to `out`. Return 0 on success, or -1 on failure.
+ */
+typedef int (*mail_conv_fn)(FILE *out, FILE *in, int keep_cr);
+
+/**
+ * Calls `fn` for each file in `paths` to convert the foreign patch to the
+ * RFC2822 mail format suitable for parsing with git-mailinfo.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
+ const char **paths, int keep_cr)
+{
+ static const char *stdin_only[] = {"-", NULL};
+ int i;
+
+ if (!*paths)
+ paths = stdin_only;
+
+ for (i = 0; *paths; paths++, i++) {
+ FILE *in, *out;
+ const char *mail;
+ int ret;
+
+ if (!strcmp(*paths, "-"))
+ in = stdin;
+ else
+ in = fopen(*paths, "r");
+
+ if (!in)
+ return error(_("could not open '%s' for reading: %s"),
+ *paths, strerror(errno));
+
+ mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1);
+
+ out = fopen(mail, "w");
+ if (!out)
+ return error(_("could not open '%s' for writing: %s"),
+ mail, strerror(errno));
+
+ ret = fn(out, in, keep_cr);
+
+ fclose(out);
+ fclose(in);
+
+ if (ret)
+ return error(_("could not parse patch '%s'"), *paths);
+ }
+
+ state->cur = 1;
+ state->last = i;
+ return 0;
+}
+
+/**
+ * A split_mail_conv() callback that converts an StGit patch to an RFC2822
+ * message suitable for parsing with git-mailinfo.
+ */
+static int stgit_patch_to_mail(FILE *out, FILE *in, int keep_cr)
+{
+ struct strbuf sb = STRBUF_INIT;
+ int subject_printed = 0;
+
+ while (!strbuf_getline(&sb, in, '\n')) {
+ const char *str;
+
+ if (str_isspace(sb.buf))
+ continue;
+ else if (skip_prefix(sb.buf, "Author:", &str))
+ fprintf(out, "From:%s\n", str);
+ else if (starts_with(sb.buf, "From") || starts_with(sb.buf, "Date"))
+ fprintf(out, "%s\n", sb.buf);
+ else if (!subject_printed) {
+ fprintf(out, "Subject: %s\n", sb.buf);
+ subject_printed = 1;
+ } else {
+ fprintf(out, "\n%s\n", sb.buf);
+ break;
+ }
+ }
+
+ strbuf_reset(&sb);
+ while (strbuf_fread(&sb, 8192, in) > 0) {
+ fwrite(sb.buf, 1, sb.len, out);
+ strbuf_reset(&sb);
+ }
+
+ strbuf_release(&sb);
+ return 0;
+}
+