{"thread":{"id":"7871","subject":"[PATCH] Teach mailsplit about Maildir","startedAt":"2007-04-27T13:23:13Z","lastAt":"2007-04-27T13:26:59Z","messageCount":2,"participants":["Fernando J. Pereda"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"40592","messageId":"20070427132313.GA5237@ferdyx.org","threadId":"7871","inReplyTo":null,"subject":"[PATCH] Teach mailsplit about Maildir","fromName":"Fernando J. Pereda","fromEmail":"ferdy@gentoo.org","sentAt":"2007-04-27T13:23:13Z","receivedAt":"2007-04-27T13:23:13Z","isPatch":true,"sender":{"key":"ferdy@gentoo.org","avatar":null},"body":"Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>\n---\n\n\tThis time I changed the documentation of git-am and git-mailsplit to\n\tstate that it can also split Maildirs.\n\n\tInstead of taking an arbitrary order (like my last patch) it now\n\trelies on filenames to be sorted. Although the Maildir 'spec'\n\tprohibits it, at leas\n\n Documentation/git-am.txt        |    7 +-\n Documentation/git-mailsplit.txt |   11 +++-\n builtin-mailsplit.c             |  122 ++++++++++++++++++++++++++++++++------\n builtin.h                       |    2 +-\n 4 files changed, 115 insertions(+), 27 deletions(-)\n\ndiff --git a/Documentation/git-am.txt b/Documentation/git-am.txt\nindex f0405a3..3b392f0 100644\n--- a/Documentation/git-am.txt\n+++ b/Documentation/git-am.txt\n@@ -11,7 +11,7 @@ SYNOPSIS\n [verse]\n 'git-am' [--signoff] [--dotest=<dir>] [--utf8 | --no-utf8] [--binary] [--3way]\n          [--interactive] [--whitespace=<option>] [-C<n>] [-p<n>]\n-\t <mbox>...\n+\t <mbox>|<Maildir>...\n 'git-am' [--skip | --resolved]\n \n DESCRIPTION\n@@ -22,9 +22,10 @@ current branch.\n \n OPTIONS\n -------\n-<mbox>...::\n+<mbox>|<Maildir>...::\n \tThe list of mailbox files to read patches from. If you do not\n-\tsupply this argument, reads from the standard input.\n+\tsupply this argument, reads from the standard input. If you supply\n+\tdirectories, they'll be treated as Maildirs.\n \n -s, --signoff::\n \tAdd `Signed-off-by:` line to the commit message, using\ndiff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt\nindex c11d6a5..35a74b8 100644\n--- a/Documentation/git-mailsplit.txt\n+++ b/Documentation/git-mailsplit.txt\n@@ -7,12 +7,12 @@ git-mailsplit - Simple UNIX mbox splitter program\n \n SYNOPSIS\n --------\n-'git-mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>...]\n+'git-mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>|<Maildir>...]\n \n DESCRIPTION\n -----------\n-Splits a mbox file into a list of files: \"0001\" \"0002\" ..  in the specified\n-directory so you can process them further from there.\n+Splits a mbox file or a Maildir into a list of files: \"0001\" \"0002\" ..  in the\n+specified directory so you can process them further from there.\n \n OPTIONS\n -------\n@@ -20,6 +20,11 @@ OPTIONS\n \tMbox file to split.  If not given, the mbox is read from\n \tthe standard input.\n \n+<Maildir>::\n+\tRoot of the Maildir to split. This directory should contain the cur, tmp\n+\tand new subdirectories. git-mailsplit relies on filenames being sorted to\n+\toutput patches in the correct order.\n+\n <directory>::\n \tDirectory in which to place the individual messages.\n \ndiff --git a/builtin-mailsplit.c b/builtin-mailsplit.c\nindex 3bca855..1d096d6 100644\n--- a/builtin-mailsplit.c\n+++ b/builtin-mailsplit.c\n@@ -6,9 +6,10 @@\n  */\n #include \"cache.h\"\n #include \"builtin.h\"\n+#include \"path-list.h\"\n \n static const char git_mailsplit_usage[] =\n-\"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>...\";\n+\"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>|<Maildir>...\";\n \n static int is_from_line(const char *line, int len)\n {\n@@ -96,44 +97,106 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)\n \texit(1);\n }\n \n-int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip)\n+static int populate_maildir_list(struct path_list *list, const char *path)\n {\n-\tchar *name = xmalloc(strlen(dir) + 2 + 3 * sizeof(skip));\n+\tDIR *dir;\n+\tstruct dirent *dent;\n+\n+\tif ((dir = opendir(path)) == NULL) {\n+\t\terror(\"cannot diropen %s (%s)\", path, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\twhile ((dent = readdir(dir)) != NULL) {\n+\t\tif (dent->d_name[0] == '.')\n+\t\t\tcontinue;\n+\t\tpath_list_insert(dent->d_name, list);\n+\t}\n+\n+\tclosedir(dir);\n+\n+\treturn 1;\n+}\n+\n+static int split_maildir(const char *maildir, const char *dir,\n+\tint nr_prec, int skip)\n+{\n+\tchar file[PATH_MAX];\n+\tchar curdir[PATH_MAX];\n+\tchar name[PATH_MAX];\n \tint ret = -1;\n+\tstruct path_list list = {NULL, 0, 0, 1};\n \n-\twhile (*mbox) {\n-\t\tconst char *file = *mbox++;\n-\t\tFILE *f = !strcmp(file, \"-\") ? stdin : fopen(file, \"r\");\n-\t\tint file_done = 0;\n+\tsnprintf(curdir, sizeof(curdir), \"%s/cur\", maildir);\n+\tif (populate_maildir_list(&list, curdir) < 0)\n+\t\tgoto out;\n \n-\t\tif ( !f ) {\n-\t\t\terror(\"cannot open mbox %s\", file);\n+\tint i;\n+\tfor (i = 0; i < list.nr; i++) {\n+\t\tsnprintf(file, sizeof(file), \"%s/%s\", curdir, list.items[i].path);\n+\t\tFILE *f = fopen(file, \"r\");\n+\t\tif (!f) {\n+\t\t\terror(\"cannot open mail %s (%s)\", file, strerror(errno));\n \t\t\tgoto out;\n \t\t}\n \n \t\tif (fgets(buf, sizeof(buf), f) == NULL) {\n-\t\t\tif (f == stdin)\n-\t\t\t\tbreak; /* empty stdin is OK */\n-\t\t\terror(\"cannot read mbox %s\", file);\n+\t\t\terror(\"cannot read mail %s (%s)\", file, strerror(errno));\n \t\t\tgoto out;\n \t\t}\n \n-\t\twhile (!file_done) {\n-\t\t\tsprintf(name, \"%s/%0*d\", dir, nr_prec, ++skip);\n-\t\t\tfile_done = split_one(f, name, allow_bare);\n+\t\tsprintf(name, \"%s/%0*d\", dir, nr_prec, ++skip);\n+\t\tsplit_one(f, name, 1);\n+\n+\t\tfclose(f);\n+\t}\n+\n+\tpath_list_clear(&list, 1);\n+\n+\tret = skip;\n+out:\n+\treturn ret;\n+}\n+\n+int split_mbox(const char *file, const char *dir, int allow_bare,\n+\t\tint nr_prec, int skip)\n+{\n+\tchar name[PATH_MAX];\n+\tint ret = -1;\n+\n+\tFILE *f = !strcmp(file, \"-\") ? stdin : fopen(file, \"r\");\n+\tint file_done = 0;\n+\n+\tif (!f) {\n+\t\terror(\"cannot open mbox %s\", file);\n+\t\tgoto out;\n+\t}\n+\n+\tif (fgets(buf, sizeof(buf), f) == NULL) {\n+\t\t/* empty stdin is OK */\n+\t\tif (f != stdin) {\n+\t\t\terror(\"cannot read mbox %s\", file);\n+\t\t\tgoto out;\n \t\t}\n+\t\tfile_done = 1;\n+\t}\n \n-\t\tif (f != stdin)\n-\t\t\tfclose(f);\n+\twhile (!file_done) {\n+\t\tsprintf(name, \"%s/%0*d\", dir, nr_prec, ++skip);\n+\t\tfile_done = split_one(f, name, allow_bare);\n \t}\n+\n+\tif (f != stdin)\n+\t\tfclose(f);\n+\n \tret = skip;\n out:\n-\tfree(name);\n \treturn ret;\n }\n+\n int cmd_mailsplit(int argc, const char **argv, const char *prefix)\n {\n-\tint nr = 0, nr_prec = 4, ret;\n+\tint nr = 0, nr_prec = 4, ret = 0;\n \tint allow_bare = 0;\n \tconst char *dir = NULL;\n \tconst char **argp;\n@@ -186,7 +249,26 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)\n \t\t\targp = stdin_only;\n \t}\n \n-\tret = split_mbox(argp, dir, allow_bare, nr_prec, nr);\n+\twhile (*argp) {\n+\t\tconst char *arg = *argp++;\n+\t\tstruct stat argstat;\n+\n+\t\tif (arg[0] == '-' && arg[1] == 0) {\n+\t\t\tret |= split_mbox(arg, dir, allow_bare, nr_prec, nr);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (stat(arg, &argstat) == -1) {\n+\t\t\terror(\"cannot stat %s (%s)\", arg, strerror(errno));\n+\t\t\treturn 1;\n+\t\t}\n+\n+\t\tif (S_ISDIR(argstat.st_mode))\n+\t\t\tret |= split_maildir(arg, dir, nr_prec, nr);\n+\t\telse\n+\t\t\tret |= split_mbox(arg, dir, allow_bare, nr_prec, nr);\n+\t}\n+\n \tif (ret != -1)\n \t\tprintf(\"%d\\n\", ret);\n \ndiff --git a/builtin.h b/builtin.h\nindex d3f3a74..39290d1 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -8,7 +8,7 @@ extern const char git_usage_string[];\n \n extern void help_unknown_cmd(const char *cmd);\n extern int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, const char *msg, const char *patch);\n-extern int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip);\n+extern int split_mbox(const char *file, const char *dir, int allow_bare, int nr_prec, int skip);\n extern void stripspace(FILE *in, FILE *out);\n extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);\n extern void prune_packed_objects(int);\n-- \n1.5.1.2\n"},{"id":"40593","messageId":"20070427132659.GD4690@ferdyx.org","threadId":"7871","inReplyTo":"20070427132313.GA5237@ferdyx.org","subject":"Re: [PATCH] Teach mailsplit about Maildir","fromName":"Fernando J. Pereda","fromEmail":"ferdy@ferdyx.org","sentAt":"2007-04-27T13:26:59Z","receivedAt":"2007-04-27T13:26:59Z","isPatch":true,"sender":{"key":"ferdy@ferdyx.org","avatar":"https://gravatar.com/avatar/96bf7c1ddf7ccd430255bd12d9d42b212dbc033b28c668a2bdf9c3995aa81e61?d=mp&s=160"},"body":"On Fri, Apr 27, 2007 at 03:23:13PM +0200, Fernando J. Pereda wrote:\n> Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>\n> ---\n> \n> \tThis time I changed the documentation of git-am and git-mailsplit to\n> \tstate that it can also split Maildirs.\n> \n> \tInstead of taking an arbitrary order (like my last patch) it now\n> \trelies on filenames to be sorted. Although the Maildir 'spec'\n> \tprohibits it, at leas\n\n... at least we found that Pine and Mutt are generating 'sorted\nfilenames'.\n\nHit 'send' too early.\n\n- ferdy\n"}]}