On Sun, Jun 28, 2015 at 7:06 AM, Paul Tan <pyokagan@xxxxxxxxx> wrote: > Since 0cfd112 (am: preliminary support for hg patches, 2011-08-29), > git-am.sh could convert mercurial patches to an RFC2822 mail patch > suitable for parsing with git-mailinfo, and queue them in the state > directory for application. > > Since 15ced75 (git-am foreign patch support: autodetect some patch > formats, 2009-05-27), git-am.sh was able to auto-detect mercurial > patches by checking if the file begins with the line: > > # HG changeset patch > > Re-implement the above in builtin/am.c. > > Signed-off-by: Paul Tan <pyokagan@xxxxxxxxx> > --- > builtin/am.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 72 insertions(+), 1 deletion(-) > > diff --git a/builtin/am.c b/builtin/am.c > index 1576bd4..5c86e6f 100644 > --- a/builtin/am.c > +++ b/builtin/am.c > @@ -81,7 +81,8 @@ enum patch_format { > PATCH_FORMAT_UNKNOWN = 0, > PATCH_FORMAT_MBOX, > PATCH_FORMAT_STGIT, > - PATCH_FORMAT_STGIT_SERIES > + PATCH_FORMAT_STGIT_SERIES, > + PATCH_FORMAT_HG > }; > > enum keep_type { > @@ -697,6 +698,11 @@ static int detect_patch_format(const char **paths) > goto done; > } > > + if (!strcmp(l1.buf, "# HG changeset patch")) { > + ret = PATCH_FORMAT_HG; > + goto done; > + } > + > strbuf_reset(&l2); > strbuf_getline_crlf(&l2, fp); > strbuf_reset(&l3); > @@ -895,6 +901,67 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths, > } > > /** > + * A split_patches_conv() callback that converts a mercurial patch to a RFC2822 > + * message suitable for parsing with git-mailinfo. > + */ > +static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr) > +{ > + struct strbuf sb = STRBUF_INIT; > + > + while (!strbuf_getline(&sb, in, '\n')) { > + const char *str; > + > + if (skip_prefix(sb.buf, "# User ", &str)) > + fprintf(out, "From: %s\n", str); > + else if (skip_prefix(sb.buf, "# Date ", &str)) { > + unsigned long timestamp; > + long tz; > + char *end; > + > + errno = 0; > + timestamp = strtoul(str, &end, 10); > + if (errno) > + return error(_("invalid timestamp")); > + > + if (!skip_prefix(end, " ", &str)) > + return error(_("invalid Date line")); > + > + errno = 0; > + tz = strtol(str, &end, 10); > + if (errno) > + return error(_("invalid timezone offset")); > + > + if (*end) > + return error(_("invalid Date line")); > + > + /* > + * mercurial's timezone is in seconds west of UTC, > + * however git's timezone is in hours + minutes east of > + * UTC. Convert it. > + */ > + tz = tz / (60 * 60) * 100 + tz % (60 * 60); What happens if we have a negative input not matching a full hour, say -5400 ? (would equate to 0130 in git) for calculating the minutes we would only need to take % 3600 (which you do), but then we still need to divide by 60 to convert seconds to minutes? > + tz = -tz; > + > + fprintf(out, "Date: %s\n", show_date(timestamp, tz, DATE_RFC2822)); > + } else if (starts_with(sb.buf, "# ")) { > + continue; > + } 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; > +} > + > +/** > * Splits a list of files/directories into individual email patches. Each path > * in `paths` must be a file/directory that is formatted according to > * `patch_format`. > @@ -926,6 +993,8 @@ static int split_mail(struct am_state *state, enum patch_format patch_format, > return split_mail_conv(stgit_patch_to_mail, state, paths, keep_cr); > case PATCH_FORMAT_STGIT_SERIES: > return split_mail_stgit_series(state, paths, keep_cr); > + case PATCH_FORMAT_HG: > + return split_mail_conv(hg_patch_to_mail, state, paths, keep_cr); > default: > die("BUG: invalid patch_format"); > } > @@ -1960,6 +2029,8 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int > *opt_value = PATCH_FORMAT_STGIT; > else if (!strcmp(arg, "stgit-series")) > *opt_value = PATCH_FORMAT_STGIT_SERIES; > + else if (!strcmp(arg, "hg")) > + *opt_value = PATCH_FORMAT_HG; > else > return error(_("Invalid value for --patch-format: %s"), arg); > return 0; > -- > 2.5.0.rc0.76.gb2c6e93 > -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html