Teach mailsplit about Maildir's

Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Fernando J. Pereda 2007-05-25 00:15:36 +02:00 committed by Junio C Hamano
parent 98ee8187e4
commit d63bd9a217
4 changed files with 134 additions and 31 deletions

View File

@ -12,7 +12,8 @@ SYNOPSIS
'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8] 'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]
[--3way] [--interactive] [--binary] [--3way] [--interactive] [--binary]
[--whitespace=<option>] [-C<n>] [-p<n>] [--whitespace=<option>] [-C<n>] [-p<n>]
<mbox>... <mbox>|<Maildir>...
'git-am' [--skip | --resolved] 'git-am' [--skip | --resolved]
DESCRIPTION DESCRIPTION
@ -23,9 +24,10 @@ current branch.
OPTIONS OPTIONS
------- -------
<mbox>...:: <mbox>|<Maildir>...::
The list of mailbox files to read patches from. If you do not 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:: -s, --signoff::
Add `Signed-off-by:` line to the commit message, using Add `Signed-off-by:` line to the commit message, using

View File

@ -7,12 +7,15 @@ git-mailsplit - Simple UNIX mbox splitter program
SYNOPSIS SYNOPSIS
-------- --------
'git-mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>...] 'git-mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>|<Maildir>...]
DESCRIPTION DESCRIPTION
----------- -----------
Splits a mbox file into a list of files: "0001" "0002" .. in the specified Splits a mbox file or a Maildir into a list of files: "0001" "0002" .. in the
directory so you can process them further from there. specified directory so you can process them further from there.
IMPORTANT: Maildir splitting relies upon filenames being sorted to output
patches in the correct order.
OPTIONS OPTIONS
------- -------
@ -20,6 +23,10 @@ OPTIONS
Mbox file to split. If not given, the mbox is read from Mbox file to split. If not given, the mbox is read from
the standard input. the standard input.
<Maildir>::
Root of the Maildir to split. This directory should contain the cur, tmp
and new subdirectories.
<directory>:: <directory>::
Directory in which to place the individual messages. Directory in which to place the individual messages.

View File

@ -6,9 +6,10 @@
*/ */
#include "cache.h" #include "cache.h"
#include "builtin.h" #include "builtin.h"
#include "path-list.h"
static const char git_mailsplit_usage[] = 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) static int is_from_line(const char *line, int len)
{ {
@ -96,44 +97,107 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)
exit(1); 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 opendir %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 0;
}
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; int ret = -1;
int i;
struct path_list list = {NULL, 0, 0, 1};
while (*mbox) { snprintf(curdir, sizeof(curdir), "%s/cur", maildir);
const char *file = *mbox++; if (populate_maildir_list(&list, curdir) < 0)
FILE *f = !strcmp(file, "-") ? stdin : fopen(file, "r"); goto out;
int file_done = 0;
if ( !f ) { for (i = 0; i < list.nr; i++) {
error("cannot open mbox %s", file); FILE *f;
snprintf(file, sizeof(file), "%s/%s", curdir, list.items[i].path);
f = fopen(file, "r");
if (!f) {
error("cannot open mail %s (%s)", file, strerror(errno));
goto out; goto out;
} }
if (fgets(buf, sizeof(buf), f) == NULL) { if (fgets(buf, sizeof(buf), f) == NULL) {
if (f == stdin) error("cannot read mail %s (%s)", file, strerror(errno));
break; /* empty stdin is OK */
error("cannot read mbox %s", file);
goto out; goto out;
} }
while (!file_done) { sprintf(name, "%s/%0*d", dir, nr_prec, ++skip);
sprintf(name, "%s/%0*d", dir, nr_prec, ++skip); split_one(f, name, 1);
file_done = split_one(f, name, allow_bare);
}
if (f != stdin) fclose(f);
fclose(f);
} }
path_list_clear(&list, 1);
ret = skip; ret = skip;
out: out:
free(name);
return ret; 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;
}
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:
return ret;
}
int cmd_mailsplit(int argc, const char **argv, const char *prefix) int cmd_mailsplit(int argc, const char **argv, const char *prefix)
{ {
int nr = 0, nr_prec = 4, ret; int nr = 0, nr_prec = 4, num = 0;
int allow_bare = 0; int allow_bare = 0;
const char *dir = NULL; const char *dir = NULL;
const char **argp; const char **argp;
@ -186,9 +250,39 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
argp = stdin_only; argp = stdin_only;
} }
ret = split_mbox(argp, dir, allow_bare, nr_prec, nr); while (*argp) {
if (ret != -1) const char *arg = *argp++;
printf("%d\n", ret); struct stat argstat;
int ret = 0;
return ret == -1; if (arg[0] == '-' && arg[1] == 0) {
ret = split_mbox(arg, dir, allow_bare, nr_prec, nr);
if (ret < 0) {
error("cannot split patches from stdin");
return 1;
}
num += ret;
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 < 0) {
error("cannot split patches from %s", arg);
return 1;
}
num += ret;
}
printf("%d\n", num);
return 0;
} }

View File

@ -8,7 +8,7 @@ extern const char git_usage_string[];
extern void help_unknown_cmd(const char *cmd); 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 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 void stripspace(FILE *in, FILE *out);
extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix); extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);
extern void prune_packed_objects(int); extern void prune_packed_objects(int);