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>
Paul Tan committed
Aug 4, 2015 at 21:52 UTC
336108c1563c23e1af5b7b7e6fbe52f511c21748
1 file changed
+58
-1
builtin/am.c
+58
-1
@@ -80,7 +80,8 @@ static int str_isspace(const char *str)
80
enum patch_format {
81
PATCH_FORMAT_UNKNOWN = 0,
82
PATCH_FORMAT_MBOX,
83
- PATCH_FORMAT_STGIT
83
+ PATCH_FORMAT_STGIT,
84
+ PATCH_FORMAT_STGIT_SERIES
85
};
86
87
enum keep_type {
@@ -650,6 +651,11 @@ static int detect_patch_format(const char **paths)
651
goto done;
652
}
653
654
+ if (starts_with(l1.buf, "# This series applies on GIT commit")) {
655
+ ret = PATCH_FORMAT_STGIT_SERIES;
656
+ goto done;
657
+ }
658
+
659
strbuf_reset(&l2);
660
strbuf_getline_crlf(&l2, fp);
661
strbuf_reset(&l3);
@@ -800,6 +806,53 @@ static int stgit_patch_to_mail(FILE *out, FILE *in, int keep_cr)
806
return 0;
807
}
808
809
+/**
810
+ * This function only supports a single StGit series file in `paths`.
811
+ *
812
+ * Given an StGit series file, converts the StGit patches in the series into
813
+ * RFC2822 messages suitable for parsing with git-mailinfo, and queues them in
814
+ * the state directory.
815
+ *
816
+ * Returns 0 on success, -1 on failure.
817
+ */
818
+static int split_mail_stgit_series(struct am_state *state, const char **paths,
819
+ int keep_cr)
820
+{
821
+ const char *series_dir;
822
+ char *series_dir_buf;
823
+ FILE *fp;
824
+ struct argv_array patches = ARGV_ARRAY_INIT;
825
+ struct strbuf sb = STRBUF_INIT;
826
+ int ret;
827
+
828
+ if (!paths[0] || paths[1])
829
+ return error(_("Only one StGIT patch series can be applied at once"));
830
+
831
+ series_dir_buf = xstrdup(*paths);
832
+ series_dir = dirname(series_dir_buf);
833
+
834
+ fp = fopen(*paths, "r");
835
+ if (!fp)
836
+ return error(_("could not open '%s' for reading: %s"), *paths,
837
+ strerror(errno));
838
+
839
+ while (!strbuf_getline(&sb, fp, '\n')) {
840
+ if (*sb.buf == '#')
841
+ continue; /* skip comment lines */
842
+
843
+ argv_array_push(&patches, mkpath("%s/%s", series_dir, sb.buf));
844
+ }
845
+
846
+ fclose(fp);
847
+ strbuf_release(&sb);
848
+ free(series_dir_buf);
849
+
850
+ ret = split_mail_conv(stgit_patch_to_mail, state, patches.argv, keep_cr);
851
+
852
+ argv_array_clear(&patches);
853
+ return ret;
854
+}
855
+
856
/**
857
* Splits a list of files/directories into individual email patches. Each path
858
* in `paths` must be a file/directory that is formatted according to
@@ -830,6 +883,8 @@ static int split_mail(struct am_state *state, enum patch_format patch_format,
883
return split_mail_mbox(state, paths, keep_cr);
884
case PATCH_FORMAT_STGIT:
885
return split_mail_conv(stgit_patch_to_mail, state, paths, keep_cr);
886
+ case PATCH_FORMAT_STGIT_SERIES:
887
+ return split_mail_stgit_series(state, paths, keep_cr);
888
default:
889
die("BUG: invalid patch_format");
890
}
@@ -1880,6 +1935,8 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
1935
*opt_value = PATCH_FORMAT_MBOX;
1936
else if (!strcmp(arg, "stgit"))
1937
*opt_value = PATCH_FORMAT_STGIT;
1938
+ else if (!strcmp(arg, "stgit-series"))
1939
+ *opt_value = PATCH_FORMAT_STGIT_SERIES;
1940
else
1941
return error(_("Invalid value for --patch-format: %s"), arg);
1942
return 0;