{"thread":{"id":"8251","subject":"[PATCH] Teach mailsplit about Maildir's","startedAt":"2007-05-20T18:14:47Z","lastAt":"2007-05-24T22:15:36Z","messageCount":21,"participants":["Fernando J. Pereda","Junio C Hamano","Alex Riesen","Johan Herland","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"42754","messageId":"20070520181447.GA10638@ferdyx.org","threadId":"8251","inReplyTo":null,"subject":"[PATCH] Teach mailsplit about Maildir's","fromName":"Fernando J. Pereda","fromEmail":"ferdy@gentoo.org","sentAt":"2007-05-20T18:14:47Z","receivedAt":"2007-05-20T18:14:47Z","isPatch":true,"sender":{"key":"ferdy@gentoo.org","avatar":null},"body":"Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>\n---\n\n\tI never got ACK or NACK when I sent it the first time, that's why\n\tI'm resending this one with (almost) no changes.\n\n Documentation/git-am.txt        |    8 ++-\n Documentation/git-mailsplit.txt |   13 +++-\n builtin-mailsplit.c             |  122 ++++++++++++++++++++++++++++++++------\n builtin.h                       |    2 +-\n 4 files changed, 118 insertions(+), 27 deletions(-)\n\ndiff --git a/Documentation/git-am.txt b/Documentation/git-am.txt\nindex ba79773..25cf84a 100644\n--- a/Documentation/git-am.txt\n+++ b/Documentation/git-am.txt\n@@ -12,7 +12,8 @@ SYNOPSIS\n 'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]\n          [--3way] [--interactive] [--binary]\n          [--whitespace=<option>] [-C<n>] [-p<n>]\n-         <mbox>...\n+         <mbox>|<Maildir>...\n+\n 'git-am' [--skip | --resolved]\n \n DESCRIPTION\n@@ -23,9 +24,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..abb0903 100644\n--- a/Documentation/git-mailsplit.txt\n+++ b/Documentation/git-mailsplit.txt\n@@ -7,12 +7,15 @@ 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+IMPORTANT: Maildir splitting relies upon filenames being sorted to output\n+patches in the correct order.\n \n OPTIONS\n -------\n@@ -20,6 +23,10 @@ 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.\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.2\n\n\n-- \nFernando J. Pereda Garcimartín\n20BB BDC3 761A 4781 E6ED  ED0B 0A48 5B0C 60BD 28D4\n"},{"id":"42757","messageId":"7v7ir3mjfa.fsf@assigned-by-dhcp.cox.net","threadId":"8251","inReplyTo":"20070520181447.GA10638@ferdyx.org","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-05-20T18:36:25Z","receivedAt":"2007-05-20T18:36:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Fernando J. Pereda\" <ferdy@gentoo.org> writes:\n\n> Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>\n> ---\n>\n> \tI never got ACK or NACK when I sent it the first time, that's why\n> \tI'm resending this one with (almost) no changes.\n\nSorry, I had a (n obviously false) impression that you retracted\nthis patch due to this:\n\n> ...\n> +IMPORTANT: Maildir splitting relies upon filenames being sorted to output\n> +patches in the correct order.\n\nI am sure there are many users who uses Maildir layout on this\nlist.  Happy with this patch?  Please speak out.\n"},{"id":"42760","messageId":"20070520184959.GA25462@steel.home","threadId":"8251","inReplyTo":"7v7ir3mjfa.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-20T18:49:59Z","receivedAt":"2007-05-20T18:49:59Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Junio C Hamano, Sun, May 20, 2007 20:36:25 +0200:\n> > +IMPORTANT: Maildir splitting relies upon filenames being sorted to output\n> > +patches in the correct order.\n> \n> I am sure there are many users who uses Maildir layout on this\n> list.  Happy with this patch?  Please speak out.\n\nI do use maildirs, but I have a suggestion: --maildir or something, to\ncreate a non-existing maildir and split into it, so that the user does\nnot have to pre-create it.\n"},{"id":"42761","messageId":"200705202053.32291.johan@herland.net","threadId":"8251","inReplyTo":"7v7ir3mjfa.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2007-05-20T18:53:32Z","receivedAt":"2007-05-20T18:53:32Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Sunday 20 May 2007, Junio C Hamano wrote:\n> \"Fernando J. Pereda\" <ferdy@gentoo.org> writes:\n> \n> > Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>\n> > ---\n> >\n> > \tI never got ACK or NACK when I sent it the first time, that's why\n> > \tI'm resending this one with (almost) no changes.\n> \n> Sorry, I had a (n obviously false) impression that you retracted\n> this patch due to this:\n> \n> > ...\n> > +IMPORTANT: Maildir splitting relies upon filenames being sorted to output\n> > +patches in the correct order.\n> \n> I am sure there are many users who uses Maildir layout on this\n> list.  Happy with this patch?  Please speak out.\n\nI use KMail with Maildir for all my mail, except for my \"patches\" mail folder \nwhere I copy patches to import into my repos (which is in mbox format). \nKMail makes it easy to mix mbox and Maildir folders, so it's not really a \nbig deal for me, but I would of course prefer Maildir support if it's \npossible to get it right.\n\nNot sure how I feel about the usefulness of the patch if it requires correct \nsorting, and most mail clients turn out to _not_ sort correctly. Of course \nI have no idea what most mail clients do, but KMail seems to get it about \nright, AFAICS (mail filename starts with timestamp, so they're at least \nsorted roughly on (arrival) date).\n\n\nHave fun!\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"42763","messageId":"20070520190024.GE13197@ferdyx.org","threadId":"8251","inReplyTo":"20070520184959.GA25462@steel.home","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Fernando J. Pereda","fromEmail":"ferdy@ferdyx.org","sentAt":"2007-05-20T19:00:24Z","receivedAt":"2007-05-20T19:00:24Z","isPatch":true,"sender":{"key":"ferdy@ferdyx.org","avatar":"https://gravatar.com/avatar/96bf7c1ddf7ccd430255bd12d9d42b212dbc033b28c668a2bdf9c3995aa81e61?d=mp&s=160"},"body":"On Sun, May 20, 2007 at 08:49:59PM +0200, Alex Riesen wrote:\n> Junio C Hamano, Sun, May 20, 2007 20:36:25 +0200:\n> > > +IMPORTANT: Maildir splitting relies upon filenames being sorted to output\n> > > +patches in the correct order.\n> > \n> > I am sure there are many users who uses Maildir layout on this\n> > list.  Happy with this patch?  Please speak out.\n> \n> I do use maildirs, but I have a suggestion: --maildir or something, to\n> create a non-existing maildir and split into it, so that the user does\n> not have to pre-create it.\n\nI can't think of a use case for this...\n\n- ferdy\n\n-- \nFernando J. Pereda Garcimartín\n20BB BDC3 761A 4781 E6ED  ED0B 0A48 5B0C 60BD 28D4\n"},{"id":"42768","messageId":"20070520191821.GF13197@ferdyx.org","threadId":"8251","inReplyTo":"200705202053.32291.johan@herland.net","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Fernando J. Pereda","fromEmail":"ferdy@ferdyx.org","sentAt":"2007-05-20T19:18:21Z","receivedAt":"2007-05-20T19:18:21Z","isPatch":true,"sender":{"key":"ferdy@ferdyx.org","avatar":"https://gravatar.com/avatar/96bf7c1ddf7ccd430255bd12d9d42b212dbc033b28c668a2bdf9c3995aa81e61?d=mp&s=160"},"body":"On Sun, May 20, 2007 at 08:53:32PM +0200, Johan Herland wrote:\n> I use KMail with Maildir for all my mail, except for my \"patches\" mail folder \n> where I copy patches to import into my repos (which is in mbox format). \n> KMail makes it easy to mix mbox and Maildir folders, so it's not really a \n> big deal for me, but I would of course prefer Maildir support if it's \n> possible to get it right.\n> \n> Not sure how I feel about the usefulness of the patch if it requires correct \n> sorting, and most mail clients turn out to _not_ sort correctly. Of course \n> I have no idea what most mail clients do, but KMail seems to get it about \n> right, AFAICS (mail filename starts with timestamp, so they're at least \n> sorted roughly on (arrival) date).\n\n[ I sent this only to Johan, re-sending to the rest of the people now.\nSorry Johan for the dupe ]\n\nI discussed this with a pine user in #git and we concluded (looking at\nthe respective code) that both Mutt and Pine generate correct filenames\nbased on when that mail arrived to the Maildir.\n\nI use Mutt, and to test it I picked a thread that didn't arrive in\norder, tagged and copied it to a different Maildir, patches were\nsplitted in correct order.\n\n- ferdy\n\n-- \nFernando J. Pereda Garcimartín\n20BB BDC3 761A 4781 E6ED  ED0B 0A48 5B0C 60BD 28D4\n"},{"id":"42769","messageId":"200705202127.17723.johan@herland.net","threadId":"8251","inReplyTo":"20070520191821.GF13197@ferdyx.org","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2007-05-20T19:27:17Z","receivedAt":"2007-05-20T19:27:17Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Sunday 20 May 2007, Fernando J. Pereda wrote:\n> On Sun, May 20, 2007 at 08:53:32PM +0200, Johan Herland wrote:\n> > I use KMail with Maildir for all my mail, except for my \"patches\" mail folder \n> > where I copy patches to import into my repos (which is in mbox format). \n> > KMail makes it easy to mix mbox and Maildir folders, so it's not really a \n> > big deal for me, but I would of course prefer Maildir support if it's \n> > possible to get it right.\n> > \n> > Not sure how I feel about the usefulness of the patch if it requires correct \n> > sorting, and most mail clients turn out to _not_ sort correctly. Of course \n> > I have no idea what most mail clients do, but KMail seems to get it about \n> > right, AFAICS (mail filename starts with timestamp, so they're at least \n> > sorted roughly on (arrival) date).\n> \n> [ I sent this only to Johan, re-sending to the rest of the people now.\n> Sorry Johan for the dupe ]\n> \n> I discussed this with a pine user in #git and we concluded (looking at\n> the respective code) that both Mutt and Pine generate correct filenames\n> based on when that mail arrived to the Maildir.\n> \n> I use Mutt, and to test it I picked a thread that didn't arrive in\n> order, tagged and copied it to a different Maildir, patches were\n> splitted in correct order.\n\nWell, if Mutt, Pine, and KMail all get it right, then it looks like a \nuseful feature to add.\n\nDoes anybody now of (current versions of) mail clients that do _not_ \nget this right?\n\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"42783","messageId":"20070520203534.GB25462@steel.home","threadId":"8251","inReplyTo":"20070520190024.GE13197@ferdyx.org","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-20T20:35:34Z","receivedAt":"2007-05-20T20:35:34Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Fernando J. Pereda, Sun, May 20, 2007 21:00:24 +0200:\n> On Sun, May 20, 2007 at 08:49:59PM +0200, Alex Riesen wrote:\n> > Junio C Hamano, Sun, May 20, 2007 20:36:25 +0200:\n> > > > +IMPORTANT: Maildir splitting relies upon filenames being sorted to output\n> > > > +patches in the correct order.\n> > > \n> > > I am sure there are many users who uses Maildir layout on this\n> > > list.  Happy with this patch?  Please speak out.\n> > \n> > I do use maildirs, but I have a suggestion: --maildir or something, to\n> > create a non-existing maildir and split into it, so that the user does\n> > not have to pre-create it.\n> \n> I can't think of a use case for this...\n> \n\nYou actually enjoy typing \"mkdir tmp && git mailsplit tmp\"?\n"},{"id":"42786","messageId":"20070520204447.GG13197@ferdyx.org","threadId":"8251","inReplyTo":"20070520203534.GB25462@steel.home","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Fernando J. Pereda","fromEmail":"ferdy@ferdyx.org","sentAt":"2007-05-20T20:44:47Z","receivedAt":"2007-05-20T20:44:47Z","isPatch":true,"sender":{"key":"ferdy@ferdyx.org","avatar":"https://gravatar.com/avatar/96bf7c1ddf7ccd430255bd12d9d42b212dbc033b28c668a2bdf9c3995aa81e61?d=mp&s=160"},"body":"On Sun, May 20, 2007 at 10:35:34PM +0200, Alex Riesen wrote:\n> Fernando J. Pereda, Sun, May 20, 2007 21:00:24 +0200:\n> > On Sun, May 20, 2007 at 08:49:59PM +0200, Alex Riesen wrote:\n> > > Junio C Hamano, Sun, May 20, 2007 20:36:25 +0200:\n> > > > > +IMPORTANT: Maildir splitting relies upon filenames being sorted to output\n> > > > > +patches in the correct order.\n> > > > \n> > > > I am sure there are many users who uses Maildir layout on this\n> > > > list.  Happy with this patch?  Please speak out.\n> > > \n> > > I do use maildirs, but I have a suggestion: --maildir or something, to\n> > > create a non-existing maildir and split into it, so that the user does\n> > > not have to pre-create it.\n> > \n> > I can't think of a use case for this...\n> > \n> \n> You actually enjoy typing \"mkdir tmp && git mailsplit tmp\"?\n\nWell, my mail client creates Maildirs for me... so I still don't see why\nwould you do that. I copy mails with patches to a new maildir and run\ngit am there...\n\nAs I said I can't think of a use case for your suggestion.\n\n\n- ferdy\n\n-- \nFernando J. Pereda Garcimartín\n20BB BDC3 761A 4781 E6ED  ED0B 0A48 5B0C 60BD 28D4\n"},{"id":"42835","messageId":"7vd50uj29r.fsf@assigned-by-dhcp.cox.net","threadId":"8251","inReplyTo":"20070520181447.GA10638@ferdyx.org","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-05-21T03:15:12Z","receivedAt":"2007-05-21T03:15:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Fernando J. Pereda\" <ferdy@gentoo.org> writes:\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>  \n\nNo kidding.  ret |= stuff and then printf(\"%d\\n\", ret) would not\ngive us the number of commit e-mails on the standard output.\n"},{"id":"42891","messageId":"Pine.LNX.4.64.0705211353180.6410@racer.site","threadId":"8251","inReplyTo":"20070520191821.GF13197@ferdyx.org","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-05-21T12:55:05Z","receivedAt":"2007-05-21T12:55:05Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 20 May 2007, Fernando J. Pereda wrote:\n\n> On Sun, May 20, 2007 at 08:53:32PM +0200, Johan Herland wrote:\n> > \n> > Not sure how I feel about the usefulness of the patch if it requires \n> > correct sorting, and most mail clients turn out to _not_ sort \n> > correctly. Of course I have no idea what most mail clients do, but \n> > KMail seems to get it about right, AFAICS (mail filename starts with \n> > timestamp, so they're at least sorted roughly on (arrival) date).\n> \n> I discussed this with a pine user in #git and we concluded (looking at \n> the respective code) that both Mutt and Pine generate correct filenames \n> based on when that mail arrived to the Maildir.\n\nFWIW this pine user was me. Yes, I finally bit the bullet and run pine \nwith the maildir patches.\n\nI cannot think of another sane way for any MUA to sort Maildirs.\n\nCiao,\nDscho\n"},{"id":"42892","messageId":"Pine.LNX.4.64.0705211355181.6410@racer.site","threadId":"8251","inReplyTo":"7vd50uj29r.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-05-21T12:56:31Z","receivedAt":"2007-05-21T12:56:31Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 20 May 2007, Junio C Hamano wrote:\n\n> \"Fernando J. Pereda\" <ferdy@gentoo.org> writes:\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> >  \n> \n> No kidding.  ret |= stuff and then printf(\"%d\\n\", ret) would not\n> give us the number of commit e-mails on the standard output.\n\nShould we not just stop when split_maildir() or split_mbox() returns -1? \nAnd yes, we'd probably need a second variable to do take the return value.\n\nCiao,\nDscho\n"},{"id":"42911","messageId":"20070521181755.GA4696@ferdyx.org","threadId":"8251","inReplyTo":"Pine.LNX.4.64.0705211355181.6410@racer.site","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Fernando J. Pereda","fromEmail":"ferdy@gentoo.org","sentAt":"2007-05-21T18:17:55Z","receivedAt":"2007-05-21T18:17:55Z","isPatch":true,"sender":{"key":"ferdy@gentoo.org","avatar":null},"body":"On Mon, May 21, 2007 at 01:56:31PM +0100, Johannes Schindelin wrote:\n>\n> Should we not just stop when split_maildir() or split_mbox() returns -1? \n> And yes, we'd probably need a second variable to do take the return value.\n>\n\nSure, I'll send a new patch with that.\n\n- ferdy\n\n-- \nFernando J. Pereda Garcimartín\n20BB BDC3 761A 4781 E6ED  ED0B 0A48 5B0C 60BD 28D4\n"},{"id":"42912","messageId":"20070521182052.GB4696@ferdyx.org","threadId":"8251","inReplyTo":"7vd50uj29r.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Fernando J. Pereda","fromEmail":"ferdy@gentoo.org","sentAt":"2007-05-21T18:20:52Z","receivedAt":"2007-05-21T18:20:52Z","isPatch":true,"sender":{"key":"ferdy@gentoo.org","avatar":null},"body":"Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>\n---\n Documentation/git-am.txt        |    8 ++-\n Documentation/git-mailsplit.txt |   13 +++-\n builtin-mailsplit.c             |  139 ++++++++++++++++++++++++++++++++-------\n builtin.h                       |    2 +-\n 4 files changed, 132 insertions(+), 30 deletions(-)\n\ndiff --git a/Documentation/git-am.txt b/Documentation/git-am.txt\nindex ba79773..25cf84a 100644\n--- a/Documentation/git-am.txt\n+++ b/Documentation/git-am.txt\n@@ -12,7 +12,8 @@ SYNOPSIS\n 'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]\n          [--3way] [--interactive] [--binary]\n          [--whitespace=<option>] [-C<n>] [-p<n>]\n-         <mbox>...\n+         <mbox>|<Maildir>...\n+\n 'git-am' [--skip | --resolved]\n \n DESCRIPTION\n@@ -23,9 +24,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..abb0903 100644\n--- a/Documentation/git-mailsplit.txt\n+++ b/Documentation/git-mailsplit.txt\n@@ -7,12 +7,15 @@ 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+IMPORTANT: Maildir splitting relies upon filenames being sorted to output\n+patches in the correct order.\n \n OPTIONS\n -------\n@@ -20,6 +23,10 @@ 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.\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..454f943 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, num = 0;\n \tint allow_bare = 0;\n \tconst char *dir = NULL;\n \tconst char **argp;\n@@ -186,9 +249,39 @@ 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-\tif (ret != -1)\n-\t\tprintf(\"%d\\n\", ret);\n+\twhile (*argp) {\n+\t\tconst char *arg = *argp++;\n+\t\tstruct stat argstat;\n+\t\tint ret = 0;\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\tif (ret < 0) {\n+\t\t\t\terror(\"cannot split patches from stdin\");\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\tnum += ret;\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+\n+\t\tif (ret < 0) {\n+\t\t\terror(\"cannot split patches from %s\", arg);\n+\t\t\treturn 1;\n+\t\t}\n+\t\tnum += ret;\n+\t}\n+\n+\tprintf(\"%d\\n\", num);\n \n-\treturn ret == -1;\n+\treturn 0;\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.2\n"},{"id":"42935","messageId":"20070521230524.GC10890@steel.home","threadId":"8251","inReplyTo":"20070521182052.GB4696@ferdyx.org","subject":"[PATCH] Allow user to specify mailbox format for mailsplit","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-21T23:05:24Z","receivedAt":"2007-05-21T23:05:24Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"If the argument ends with a slash - assume it is a Maildir and try to\ncreate it. Otherwise - it is an mbox.\n\nSigned-off-by: Alex Riesen <raa.lkml@gmail.com>\n---\n Documentation/git-mailsplit.txt |    4 +++-\n builtin-mailsplit.c             |   10 ++++++++++\n 2 files changed, 13 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt\nindex abb0903..2c58e09 100644\n--- a/Documentation/git-mailsplit.txt\n+++ b/Documentation/git-mailsplit.txt\n@@ -25,7 +25,9 @@ OPTIONS\n \n <Maildir>::\n \tRoot of the Maildir to split. This directory should contain the cur, tmp\n-\tand new subdirectories.\n+\tand new subdirectories. If the argument ends with a slash '/'\n+\tthe directory and new, cur and tmp subdirectories will be\n+\tcreated automatically.\n \n <directory>::\n \tDirectory in which to place the individual messages.\ndiff --git a/builtin-mailsplit.c b/builtin-mailsplit.c\nindex 454f943..370f7fa 100644\n--- a/builtin-mailsplit.c\n+++ b/builtin-mailsplit.c\n@@ -253,6 +253,7 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)\n \t\tconst char *arg = *argp++;\n \t\tstruct stat argstat;\n \t\tint ret = 0;\n+\t\tsize_t arglen = strlen(arg);\n \n \t\tif (arg[0] == '-' && arg[1] == 0) {\n \t\t\tret = split_mbox(arg, dir, allow_bare, nr_prec, nr);\n@@ -264,6 +265,15 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)\n \t\t\tcontinue;\n \t\t}\n \n+\t\tif (arglen && arg[arglen-1] == '/') {\n+\t\t\tchar *dir = malloc(arglen + 5);\n+\t\t\tmemcpy(dir, arg, arglen);\n+\t\t\tmkdir(arg, 0777);\n+\t\t\tmkdir(strcpy(dir + arglen, \"new\"), 0777);\n+\t\t\tmkdir(strcpy(dir + arglen, \"cur\"), 0777);\n+\t\t\tmkdir(strcpy(dir + arglen, \"tmp\"), 0777);\n+\t\t\tfree(dir);\n+\t\t}\n \t\tif (stat(arg, &argstat) == -1) {\n \t\t\terror(\"cannot stat %s (%s)\", arg, strerror(errno));\n \t\t\treturn 1;\n-- \n1.5.2.rc3.112.gc1e43\n"},{"id":"42937","messageId":"7vwsz1bw8y.fsf@assigned-by-dhcp.cox.net","threadId":"8251","inReplyTo":"20070521230524.GC10890@steel.home","subject":"Re: [PATCH] Allow user to specify mailbox format for mailsplit","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-05-21T23:19:25Z","receivedAt":"2007-05-21T23:19:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Riesen <raa.lkml@gmail.com> writes:\n\n> If the argument ends with a slash - assume it is a Maildir and try to\n> create it. Otherwise - it is an mbox.\n\nSorry, I am lost here.  git-mailsplit is to read an existing\nmbox and split the pieces of e-mail into the specified output\ndirectory.  The recent Maildir support is to make it read pieces\nof e-mails from an existing Maildir (which presumably have bunch\nof files that store e-mail), isn't it?\n\nIf the patch were about creating a new _output_ directory (that\nis, \"dir\" in cmd_mailsplit), I would understand what you are\ntrying to do, but why would you even want to create the input\nMaildir in that loop (I take that your patch is on top of\nFernando's patch)?\n"},{"id":"43000","messageId":"20070522220443.GK30871@steel.home","threadId":"8251","inReplyTo":"7vwsz1bw8y.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Allow user to specify mailbox format for mailsplit","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-05-22T22:04:43Z","receivedAt":"2007-05-22T22:04:43Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Junio C Hamano, Tue, May 22, 2007 01:19:25 +0200:\n> Alex Riesen <raa.lkml@gmail.com> writes:\n> \n> > If the argument ends with a slash - assume it is a Maildir and try to\n> > create it. Otherwise - it is an mbox.\n> \n> Sorry, I am lost here.  git-mailsplit is to read an existing\n> mbox and split the pieces of e-mail into the specified output\n> directory.  The recent Maildir support is to make it read pieces\n> of e-mails from an existing Maildir (which presumably have bunch\n> of files that store e-mail), isn't it?\n\nOh... Fernando, I'm very sorry. I never used mailsplit and didn't even\ngave a second thought about its name. For reasons unknown, I assumed\nthe mbox/maildir argument is for the output.\nMust be all the ozone depletion and the cosmic rays now causing\nglitches in programmers brains...\n\n> If the patch were about creating a new _output_ directory (that\n> is, \"dir\" in cmd_mailsplit), I would understand what you are\n> trying to do, but why would you even want to create the input\n> Maildir in that loop (I take that your patch is on top of\n> Fernando's patch)?\n\nYes, but don't apply it! :)\n"},{"id":"43175","messageId":"7vd50qvwaz.fsf@assigned-by-dhcp.cox.net","threadId":"8251","inReplyTo":"20070521182052.GB4696@ferdyx.org","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-05-24T19:47:00Z","receivedAt":"2007-05-24T19:47:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Fernando J. Pereda\" <ferdy@gentoo.org> writes:\n\n> Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>\n> ---\n>  Documentation/git-am.txt        |    8 ++-\n>  Documentation/git-mailsplit.txt |   13 +++-\n>  builtin-mailsplit.c             |  139 ++++++++++++++++++++++++++++++++-------\n>  builtin.h                       |    2 +-\n>  4 files changed, 132 insertions(+), 30 deletions(-)\n>\n> diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt\n> index ba79773..25cf84a 100644\n> --- a/Documentation/git-am.txt\n> +++ b/Documentation/git-am.txt\n> @@ -12,7 +12,8 @@ SYNOPSIS\n>  'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]\n>           [--3way] [--interactive] [--binary]\n>           [--whitespace=<option>] [-C<n>] [-p<n>]\n> -         <mbox>...\n> +         <mbox>|<Maildir>...\n> +\n>  'git-am' [--skip | --resolved]\n\nDoes the document still format Ok if you add a blank line there\n(not a rhetorical question -- I haven't checked)?\n\n> diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c\n> index 3bca855..454f943 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\nDidn't you just fail opendir, not diropen?\n\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\nUsually we signal success by returning 0.\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> +\tsnprintf(curdir, sizeof(curdir), \"%s/cur\", maildir);\n> +\tif (populate_maildir_list(&list, curdir) < 0)\n> +\t\tgoto out;\n>  \n> +\tint i;\n\nDecl-after-statement.\n\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\nLikewise.\n\n> @@ -186,9 +249,39 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)\n> ...\n> +\t\tif (ret < 0) {\n> +\t\t\terror(\"cannot split patches from %s\", arg);\n> +\t\t\treturn 1;\n> +\t\t}\n> +\t\tnum += ret;\n> +\t}\n> +\n> +\tprintf(\"%d\\n\", num);\n>  \n> -\treturn ret == -1;\n> +\treturn 0;\n>  }\n\nWe do not signal error anymore from the command?\n"},{"id":"43176","messageId":"20070524195608.GA4714@ferdyx.org","threadId":"8251","inReplyTo":"7vd50qvwaz.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Fernando J. Pereda","fromEmail":"ferdy@gentoo.org","sentAt":"2007-05-24T19:56:08Z","receivedAt":"2007-05-24T19:56:08Z","isPatch":true,"sender":{"key":"ferdy@gentoo.org","avatar":null},"body":"On Thu, May 24, 2007 at 12:47:00PM -0700, Junio C Hamano wrote:\n> \"Fernando J. Pereda\" <ferdy@gentoo.org> writes:\n> >           [--whitespace=<option>] [-C<n>] [-p<n>]\n> > -         <mbox>...\n> > +         <mbox>|<Maildir>...\n> > +\n> >  'git-am' [--skip | --resolved]\n> \n> Does the document still format Ok if you add a blank line there\n> (not a rhetorical question -- I haven't checked)?\n\nI think I tried when I first sent it, will try.\n\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> Didn't you just fail opendir, not diropen?\n\nOuch, will fix\n\n> > +\treturn 1;\n> > +}\n> \n> Usually we signal success by returning 0.\n\nOk. Fair enough.\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> > +\tsnprintf(curdir, sizeof(curdir), \"%s/cur\", maildir);\n> > +\tif (populate_maildir_list(&list, curdir) < 0)\n> > +\t\tgoto out;\n> >  \n> > +\tint i;\n> \n> Decl-after-statement.\n\nI did it because other parts of the file do it too. Do you want me to\nfix the rest of them?\n\n> \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> \n> Likewise.\n\nAgain, because we were already doing it in other parts of the file. Will\nfix.\n\n> \n> > @@ -186,9 +249,39 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)\n> > ...\n> > +\t\tif (ret < 0) {\n> > +\t\t\terror(\"cannot split patches from %s\", arg);\n> > +\t\t\treturn 1;\n> > +\t\t}\n> > +\t\tnum += ret;\n> > +\t}\n> > +\n> > +\tprintf(\"%d\\n\", num);\n> >  \n> > -\treturn ret == -1;\n> > +\treturn 0;\n> >  }\n> \n> We do not signal error anymore from the command?\n\nIf we reached that part of the code, there is no error to signal about.\nWe signal error when either split_mbox or split_maildir fail by\nreturning 1.\n\nWill fix those issues and send a new patch. Thanks for reviewing it.\n\n- ferdy\n\n-- \nFernando J. Pereda Garcimartín\n20BB BDC3 761A 4781 E6ED  ED0B 0A48 5B0C 60BD 28D4\n"},{"id":"43177","messageId":"7v8xbevv41.fsf@assigned-by-dhcp.cox.net","threadId":"8251","inReplyTo":"20070524195608.GA4714@ferdyx.org","subject":"Re: [PATCH] Teach mailsplit about Maildir's","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-05-24T20:12:46Z","receivedAt":"2007-05-24T20:12:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Fernando J. Pereda\" <ferdy@gentoo.org> writes:\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>> > +\tsnprintf(curdir, sizeof(curdir), \"%s/cur\", maildir);\n>> > +\tif (populate_maildir_list(&list, curdir) < 0)\n>> > +\t\tgoto out;\n>> >  \n>> > +\tint i;\n>> \n>> Decl-after-statement.\n>\n> I did it because other parts of the file do it too. Do you want me to\n> fix the rest of them?\n\nMy \"gcc -Werror -Wall -Wdeclaration-after-statement\" does not\nseem to find any in the existing code, but if you found any\nplease fix that in a separate patch.\n\n>> > @@ -186,9 +249,39 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)\n>> > ...\n>> > +\t\tif (ret < 0) {\n>> > +\t\t\terror(\"cannot split patches from %s\", arg);\n>> > +\t\t\treturn 1;\n>> > +\t\t}\n>> > +\t\tnum += ret;\n>> > +\t}\n>> > +\n>> > +\tprintf(\"%d\\n\", num);\n>> >  \n>> > -\treturn ret == -1;\n>> > +\treturn 0;\n>> >  }\n>> \n>> We do not signal error anymore from the command?\n>\n> If we reached that part of the code, there is no error to signal about.\n> We signal error when either split_mbox or split_maildir fail by\n> returning 1.\n\nOk, you are right.\n\nThanks.\n"},{"id":"43187","messageId":"20070524221536.GD4714@ferdyx.org","threadId":"8251","inReplyTo":"7v8xbevv41.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Teach mailsplit about Maildir's","fromName":"Fernando J. Pereda","fromEmail":"ferdy@gentoo.org","sentAt":"2007-05-24T22:15:36Z","receivedAt":"2007-05-24T22:15:36Z","isPatch":true,"sender":{"key":"ferdy@gentoo.org","avatar":null},"body":"Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>\n---\n\n\tI built the documentation again, and formatting looks ok with that\n\tblank line there. I think I fixed those declarations after\n\tstatements too.\n\n Documentation/git-am.txt        |    8 ++-\n Documentation/git-mailsplit.txt |   13 +++-\n builtin-mailsplit.c             |  140 ++++++++++++++++++++++++++++++++-------\n builtin.h                       |    2 +-\n 4 files changed, 133 insertions(+), 30 deletions(-)\n\ndiff --git a/Documentation/git-am.txt b/Documentation/git-am.txt\nindex ba79773..25cf84a 100644\n--- a/Documentation/git-am.txt\n+++ b/Documentation/git-am.txt\n@@ -12,7 +12,8 @@ SYNOPSIS\n 'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]\n          [--3way] [--interactive] [--binary]\n          [--whitespace=<option>] [-C<n>] [-p<n>]\n-         <mbox>...\n+         <mbox>|<Maildir>...\n+\n 'git-am' [--skip | --resolved]\n \n DESCRIPTION\n@@ -23,9 +24,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..abb0903 100644\n--- a/Documentation/git-mailsplit.txt\n+++ b/Documentation/git-mailsplit.txt\n@@ -7,12 +7,15 @@ 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+IMPORTANT: Maildir splitting relies upon filenames being sorted to output\n+patches in the correct order.\n \n OPTIONS\n -------\n@@ -20,6 +23,10 @@ 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.\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..97ae004 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,107 @@ 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 opendir %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 0;\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+\tint i;\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+\tfor (i = 0; i < list.nr; i++) {\n+\t\tFILE *f;\n+\t\tsnprintf(file, sizeof(file), \"%s/%s\", curdir, list.items[i].path);\n+\t\tf = 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, num = 0;\n \tint allow_bare = 0;\n \tconst char *dir = NULL;\n \tconst char **argp;\n@@ -186,9 +250,39 @@ 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-\tif (ret != -1)\n-\t\tprintf(\"%d\\n\", ret);\n+\twhile (*argp) {\n+\t\tconst char *arg = *argp++;\n+\t\tstruct stat argstat;\n+\t\tint ret = 0;\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\tif (ret < 0) {\n+\t\t\t\terror(\"cannot split patches from stdin\");\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\tnum += ret;\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+\n+\t\tif (ret < 0) {\n+\t\t\terror(\"cannot split patches from %s\", arg);\n+\t\t\treturn 1;\n+\t\t}\n+\t\tnum += ret;\n+\t}\n+\n+\tprintf(\"%d\\n\", num);\n \n-\treturn ret == -1;\n+\treturn 0;\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.2\n"}]}