From 336108c1563c23e1af5b7b7e6fbe52f511c21748 Mon Sep 17 00:00:00 2001 From: Paul Tan Date: Tue, 4 Aug 2015 21:52:01 +0800 Subject: [PATCH] builtin-am: support and auto-detect StGit series files Since c574e68 (git-am foreign patch support: StGIT support, 2009-05-27), git-am.sh is able to read a single StGit series file and, for each StGit patch listed in the file, convert the StGit patch into a RFC2822 mail patch suitable for parsing with git-mailinfo, and queue them in the state directory for applying. Since 15ced75 (git-am foreign patch support: autodetect some patch formats, 2009-05-27), git-am.sh is able to auto-detect StGit series files by checking to see if the file starts with the string: # This series applies on GIT commit Re-implement the above in builtin/am.c. Signed-off-by: Paul Tan Signed-off-by: Junio C Hamano --- builtin/am.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/builtin/am.c b/builtin/am.c index d82d07edaa..3c2ec15570 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -80,7 +80,8 @@ static int str_isspace(const char *str) enum patch_format { PATCH_FORMAT_UNKNOWN = 0, PATCH_FORMAT_MBOX, - PATCH_FORMAT_STGIT + PATCH_FORMAT_STGIT, + PATCH_FORMAT_STGIT_SERIES }; enum keep_type { @@ -650,6 +651,11 @@ static int detect_patch_format(const char **paths) goto done; } + if (starts_with(l1.buf, "# This series applies on GIT commit")) { + ret = PATCH_FORMAT_STGIT_SERIES; + goto done; + } + strbuf_reset(&l2); strbuf_getline_crlf(&l2, fp); strbuf_reset(&l3); @@ -801,6 +807,53 @@ static int stgit_patch_to_mail(FILE *out, FILE *in, int keep_cr) } /** + * This function only supports a single StGit series file in `paths`. + * + * Given an StGit series file, converts the StGit patches in the series into + * RFC2822 messages suitable for parsing with git-mailinfo, and queues them in + * the state directory. + * + * Returns 0 on success, -1 on failure. + */ +static int split_mail_stgit_series(struct am_state *state, const char **paths, + int keep_cr) +{ + const char *series_dir; + char *series_dir_buf; + FILE *fp; + struct argv_array patches = ARGV_ARRAY_INIT; + struct strbuf sb = STRBUF_INIT; + int ret; + + if (!paths[0] || paths[1]) + return error(_("Only one StGIT patch series can be applied at once")); + + series_dir_buf = xstrdup(*paths); + series_dir = dirname(series_dir_buf); + + fp = fopen(*paths, "r"); + if (!fp) + return error(_("could not open '%s' for reading: %s"), *paths, + strerror(errno)); + + while (!strbuf_getline(&sb, fp, '\n')) { + if (*sb.buf == '#') + continue; /* skip comment lines */ + + argv_array_push(&patches, mkpath("%s/%s", series_dir, sb.buf)); + } + + fclose(fp); + strbuf_release(&sb); + free(series_dir_buf); + + ret = split_mail_conv(stgit_patch_to_mail, state, patches.argv, keep_cr); + + argv_array_clear(&patches); + return ret; +} + +/** * 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`. @@ -830,6 +883,8 @@ static int split_mail(struct am_state *state, enum patch_format patch_format, return split_mail_mbox(state, paths, keep_cr); case PATCH_FORMAT_STGIT: 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); default: die("BUG: invalid patch_format"); } @@ -1880,6 +1935,8 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int *opt_value = PATCH_FORMAT_MBOX; else if (!strcmp(arg, "stgit")) *opt_value = PATCH_FORMAT_STGIT; + else if (!strcmp(arg, "stgit-series")) + *opt_value = PATCH_FORMAT_STGIT_SERIES; else return error(_("Invalid value for --patch-format: %s"), arg); return 0; -- 2.11.4.GIT