summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
authorPaul Tan <pyokagan@gmail.com>2015-08-04 21:52:01 +0800
committerJunio C Hamano <gitster@pobox.com>2015-08-04 22:02:11 -0700
commit336108c1563c23e1af5b7b7e6fbe52f511c21748 (patch)
tree859c7ec9f1d1e595b97d09aa4a669365b1fac61e /builtin
parent5ae41c79b81a5c73939749bee19c1d1075cc0cdf (diff)
downloadgit-336108c1563c23e1af5b7b7e6fbe52f511c21748.tar.gz
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 <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin')
-rw-r--r--builtin/am.c59
1 files changed, 58 insertions, 1 deletions
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;