Re: [PATCH/WIP 4/8] am: split out mbox/maildir patches with git-mailsplit

2015-06-02 Thread Paul Tan
On Fri, May 29, 2015 at 7:05 AM, Eric Sunshine  wrote:
> On Wed, May 27, 2015 at 9:33 AM, Paul Tan  wrote:
>> @@ -128,13 +190,32 @@ static void am_next(struct am_state *state)
>>   */
>> +/**
>> + * parse_options() callback that validates and sets opt->value to the
>> + * PATCH_FORMAT_* enum value corresponding to `arg`.
>> + */
>> +static int parse_opt_patchformat(const struct option *opt, const char *arg, 
>> int unset)
>> +{
>> +   int *opt_value = opt->value;
>> +
>> +   if (!strcmp(arg, "mbox"))
>> +   *opt_value = PATCH_FORMAT_MBOX;
>> +   else
>> +   return -1;
>> +   return 0;
>> +}
>> +
>>  struct am_state state;
>> +int opt_patch_format;
>
> Should these two variables be static?

Whoops. Yes, they should.

Thanks,
Paul
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/WIP 4/8] am: split out mbox/maildir patches with git-mailsplit

2015-05-28 Thread Eric Sunshine
On Wed, May 27, 2015 at 9:33 AM, Paul Tan  wrote:
> git-am.sh supports mbox, stgit and mercurial patches. Re-implement
> support for splitting out mbox/maildirs using git-mailsplit, while also
> implementing the framework required to support other patch formats in
> the future.
>
> Re-implement support for the --patch-format option (since a5a6755
> (git-am foreign patch support: introduce patch_format, 2009-05-27)) to
> allow the user to choose between the different patch formats.
>
> Signed-off-by: Paul Tan 
> ---
> @@ -128,13 +190,32 @@ static void am_next(struct am_state *state)
>   */
> +/**
> + * parse_options() callback that validates and sets opt->value to the
> + * PATCH_FORMAT_* enum value corresponding to `arg`.
> + */
> +static int parse_opt_patchformat(const struct option *opt, const char *arg, 
> int unset)
> +{
> +   int *opt_value = opt->value;
> +
> +   if (!strcmp(arg, "mbox"))
> +   *opt_value = PATCH_FORMAT_MBOX;
> +   else
> +   return -1;
> +   return 0;
> +}
> +
>  struct am_state state;
> +int opt_patch_format;

Should these two variables be static?

>  static const char * const am_usage[] = {
> N_("git am [options] [(|)...]"),
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH/WIP 4/8] am: split out mbox/maildir patches with git-mailsplit

2015-05-27 Thread Paul Tan
git-am.sh supports mbox, stgit and mercurial patches. Re-implement
support for splitting out mbox/maildirs using git-mailsplit, while also
implementing the framework required to support other patch formats in
the future.

Re-implement support for the --patch-format option (since a5a6755
(git-am foreign patch support: introduce patch_format, 2009-05-27)) to
allow the user to choose between the different patch formats.

Signed-off-by: Paul Tan 
---
 builtin/am.c | 104 ---
 1 file changed, 100 insertions(+), 4 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index 6c9..9c7b058 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -6,11 +6,18 @@
 #include "cache.h"
 #include "parse-options.h"
 #include "dir.h"
+#include "run-command.h"
+
+enum patch_format {
+   PATCH_FORMAT_UNKNOWN = 0,
+   PATCH_FORMAT_MBOX
+};
 
 struct am_state {
struct strbuf dir;/* state directory path */
int cur;  /* current patch number */
int last; /* last patch number */
+   int prec; /* number of digits in patch filename */
 };
 
 /**
@@ -21,6 +28,7 @@ static void am_state_init(struct am_state *state)
memset(state, 0, sizeof(*state));
 
strbuf_init(&state->dir, 0);
+   state->prec = 4;
 }
 
 /**
@@ -101,13 +109,67 @@ static void am_destroy(const struct am_state *state)
 }
 
 /**
+ * Splits out individual patches from `paths`, where each path is either a mbox
+ * file or a Maildir. Return 0 on success, -1 on failure.
+ */
+static int split_patches_mbox(struct am_state *state, struct string_list 
*paths)
+{
+   struct child_process cp = CHILD_PROCESS_INIT;
+   struct string_list_item *item;
+   struct strbuf last = STRBUF_INIT;
+
+   cp.git_cmd = 1;
+   argv_array_push(&cp.args, "mailsplit");
+   argv_array_pushf(&cp.args, "-d%d", state->prec);
+   argv_array_pushf(&cp.args, "-o%s", state->dir.buf);
+   argv_array_push(&cp.args, "-b");
+   argv_array_push(&cp.args, "--");
+
+   for_each_string_list_item(item, paths)
+   argv_array_push(&cp.args, item->string);
+
+   if (capture_command(&cp, &last, 8))
+   return -1;
+
+   state->cur = 1;
+   state->last = strtol(last.buf, NULL, 10);
+
+   return 0;
+}
+
+/**
+ * Splits out individual patches, of patch_format, contained within paths.
+ * These patches will be stored in the state directory, with each patch's
+ * filename being its index, padded to state->prec digits. state->cur will be
+ * set to the index of the first patch, and state->last will be set to the
+ * index of the last patch. Returns 0 on success, -1 on failure.
+ */
+static int split_patches(struct am_state *state, enum patch_format 
patch_format,
+   struct string_list *paths)
+{
+   switch (patch_format) {
+   case PATCH_FORMAT_MBOX:
+   return split_patches_mbox(state, paths);
+   default:
+   die("BUG: invalid patch_format");
+   }
+   return -1;
+}
+
+/**
  * Setup a new am session for applying patches
  */
-static void am_setup(struct am_state *state)
+static void am_setup(struct am_state *state, enum patch_format patch_format,
+   struct string_list *paths)
 {
if (mkdir(state->dir.buf, 0777) < 0 && errno != EEXIST)
die_errno(_("failed to create directory '%s'"), state->dir.buf);
 
+   if (split_patches(state, patch_format, paths) < 0) {
+   am_destroy(state);
+   die(_("Failed to split patches."));
+   }
+
write_file(am_path(state, "next"), 1, "%d", state->cur);
 
write_file(am_path(state, "last"), 1, "%d", state->last);
@@ -128,13 +190,32 @@ static void am_next(struct am_state *state)
  */
 static void am_run(struct am_state *state)
 {
-   while (state->cur <= state->last)
+   while (state->cur <= state->last) {
+   /* patch application not implemented yet */
+
am_next(state);
+   }
 
am_destroy(state);
 }
 
+/**
+ * parse_options() callback that validates and sets opt->value to the
+ * PATCH_FORMAT_* enum value corresponding to `arg`.
+ */
+static int parse_opt_patchformat(const struct option *opt, const char *arg, 
int unset)
+{
+   int *opt_value = opt->value;
+
+   if (!strcmp(arg, "mbox"))
+   *opt_value = PATCH_FORMAT_MBOX;
+   else
+   return -1;
+   return 0;
+}
+
 struct am_state state;
+int opt_patch_format;
 
 static const char * const am_usage[] = {
N_("git am [options] [(|)...]"),
@@ -142,6 +223,8 @@ static const char * const am_usage[] = {
 };
 
 static struct option am_options[] = {
+   OPT_CALLBACK(0, "patch-format", &opt_patch_format, N_("format"),
+   N_("format the patch(es) are in"), parse_opt_patchformat),
OPT_END()
 };
 
@@ -156,8 +239,21 @@ in