Signed-off-by: Fernando J. Pereda <ferdy@xxxxxxxxxx> --- This time I changed the documentation of git-am and git-mailsplit to state that it can also split Maildirs. Instead of taking an arbitrary order (like my last patch) it now relies on filenames to be sorted. Although the Maildir 'spec' prohibits it, at leas Documentation/git-am.txt | 7 +- Documentation/git-mailsplit.txt | 11 +++- builtin-mailsplit.c | 122 ++++++++++++++++++++++++++++++++------ builtin.h | 2 +- 4 files changed, 115 insertions(+), 27 deletions(-) diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index f0405a3..3b392f0 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -11,7 +11,7 @@ SYNOPSIS [verse] 'git-am' [--signoff] [--dotest=<dir>] [--utf8 | --no-utf8] [--binary] [--3way] [--interactive] [--whitespace=<option>] [-C<n>] [-p<n>] - <mbox>... + <mbox>|<Maildir>... 'git-am' [--skip | --resolved] DESCRIPTION @@ -22,9 +22,10 @@ current branch. OPTIONS ------- -<mbox>...:: +<mbox>|<Maildir>...:: The list of mailbox files to read patches from. If you do not - supply this argument, reads from the standard input. + supply this argument, reads from the standard input. If you supply + directories, they'll be treated as Maildirs. -s, --signoff:: Add `Signed-off-by:` line to the commit message, using diff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt index c11d6a5..35a74b8 100644 --- a/Documentation/git-mailsplit.txt +++ b/Documentation/git-mailsplit.txt @@ -7,12 +7,12 @@ git-mailsplit - Simple UNIX mbox splitter program SYNOPSIS -------- -'git-mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>...] +'git-mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>|<Maildir>...] DESCRIPTION ----------- -Splits a mbox file into a list of files: "0001" "0002" .. in the specified -directory so you can process them further from there. +Splits a mbox file or a Maildir into a list of files: "0001" "0002" .. in the +specified directory so you can process them further from there. OPTIONS ------- @@ -20,6 +20,11 @@ OPTIONS Mbox file to split. If not given, the mbox is read from the standard input. +<Maildir>:: + Root of the Maildir to split. This directory should contain the cur, tmp + and new subdirectories. git-mailsplit relies on filenames being sorted to + output patches in the correct order. + <directory>:: Directory in which to place the individual messages. diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c index 3bca855..1d096d6 100644 --- a/builtin-mailsplit.c +++ b/builtin-mailsplit.c @@ -6,9 +6,10 @@ */ #include "cache.h" #include "builtin.h" +#include "path-list.h" static const char git_mailsplit_usage[] = -"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>..."; +"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>|<Maildir>..."; static int is_from_line(const char *line, int len) { @@ -96,44 +97,106 @@ static int split_one(FILE *mbox, const char *name, int allow_bare) exit(1); } -int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip) +static int populate_maildir_list(struct path_list *list, const char *path) { - char *name = xmalloc(strlen(dir) + 2 + 3 * sizeof(skip)); + DIR *dir; + struct dirent *dent; + + if ((dir = opendir(path)) == NULL) { + error("cannot diropen %s (%s)", path, strerror(errno)); + return -1; + } + + while ((dent = readdir(dir)) != NULL) { + if (dent->d_name[0] == '.') + continue; + path_list_insert(dent->d_name, list); + } + + closedir(dir); + + return 1; +} + +static int split_maildir(const char *maildir, const char *dir, + int nr_prec, int skip) +{ + char file[PATH_MAX]; + char curdir[PATH_MAX]; + char name[PATH_MAX]; int ret = -1; + struct path_list list = {NULL, 0, 0, 1}; - while (*mbox) { - const char *file = *mbox++; - FILE *f = !strcmp(file, "-") ? stdin : fopen(file, "r"); - int file_done = 0; + snprintf(curdir, sizeof(curdir), "%s/cur", maildir); + if (populate_maildir_list(&list, curdir) < 0) + goto out; - if ( !f ) { - error("cannot open mbox %s", file); + int i; + for (i = 0; i < list.nr; i++) { + snprintf(file, sizeof(file), "%s/%s", curdir, list.items[i].path); + FILE *f = fopen(file, "r"); + if (!f) { + error("cannot open mail %s (%s)", file, strerror(errno)); goto out; } if (fgets(buf, sizeof(buf), f) == NULL) { - if (f == stdin) - break; /* empty stdin is OK */ - error("cannot read mbox %s", file); + error("cannot read mail %s (%s)", file, strerror(errno)); goto out; } - while (!file_done) { - sprintf(name, "%s/%0*d", dir, nr_prec, ++skip); - file_done = split_one(f, name, allow_bare); + sprintf(name, "%s/%0*d", dir, nr_prec, ++skip); + split_one(f, name, 1); + + fclose(f); + } + + path_list_clear(&list, 1); + + ret = skip; +out: + return ret; +} + +int split_mbox(const char *file, const char *dir, int allow_bare, + int nr_prec, int skip) +{ + char name[PATH_MAX]; + int ret = -1; + + FILE *f = !strcmp(file, "-") ? stdin : fopen(file, "r"); + int file_done = 0; + + if (!f) { + error("cannot open mbox %s", file); + goto out; + } + + if (fgets(buf, sizeof(buf), f) == NULL) { + /* empty stdin is OK */ + if (f != stdin) { + error("cannot read mbox %s", file); + goto out; } + file_done = 1; + } - if (f != stdin) - fclose(f); + while (!file_done) { + sprintf(name, "%s/%0*d", dir, nr_prec, ++skip); + file_done = split_one(f, name, allow_bare); } + + if (f != stdin) + fclose(f); + ret = skip; out: - free(name); return ret; } + int cmd_mailsplit(int argc, const char **argv, const char *prefix) { - int nr = 0, nr_prec = 4, ret; + int nr = 0, nr_prec = 4, ret = 0; int allow_bare = 0; const char *dir = NULL; const char **argp; @@ -186,7 +249,26 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix) argp = stdin_only; } - ret = split_mbox(argp, dir, allow_bare, nr_prec, nr); + while (*argp) { + const char *arg = *argp++; + struct stat argstat; + + if (arg[0] == '-' && arg[1] == 0) { + ret |= split_mbox(arg, dir, allow_bare, nr_prec, nr); + continue; + } + + if (stat(arg, &argstat) == -1) { + error("cannot stat %s (%s)", arg, strerror(errno)); + return 1; + } + + if (S_ISDIR(argstat.st_mode)) + ret |= split_maildir(arg, dir, nr_prec, nr); + else + ret |= split_mbox(arg, dir, allow_bare, nr_prec, nr); + } + if (ret != -1) printf("%d\n", ret); diff --git a/builtin.h b/builtin.h index d3f3a74..39290d1 100644 --- a/builtin.h +++ b/builtin.h @@ -8,7 +8,7 @@ extern const char git_usage_string[]; extern void help_unknown_cmd(const char *cmd); extern int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, const char *msg, const char *patch); -extern int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip); +extern int split_mbox(const char *file, const char *dir, int allow_bare, int nr_prec, int skip); extern void stripspace(FILE *in, FILE *out); extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix); extern void prune_packed_objects(int); -- 1.5.1.2 - 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