Skip to content

Commit

Permalink
Teach mailsplit about Maildir's
Browse files Browse the repository at this point in the history
Signed-off-by: Fernando J. Pereda <ferdy@gentoo.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Fernando J. Pereda authored and Junio C Hamano committed May 25, 2007
1 parent 98ee818 commit d63bd9a
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 30 deletions.
8 changes: 5 additions & 3 deletions Documentation/git-am.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ SYNOPSIS
'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]
[--3way] [--interactive] [--binary]
[--whitespace=<option>] [-C<n>] [-p<n>]
<mbox>...
<mbox>|<Maildir>...

'git-am' [--skip | --resolved]

DESCRIPTION
Expand All @@ -23,9 +24,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
Expand Down
13 changes: 10 additions & 3 deletions Documentation/git-mailsplit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,26 @@ 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.

IMPORTANT: Maildir splitting relies upon filenames being sorted to output
patches in the correct order.

OPTIONS
-------
<mbox>::
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.

<directory>::
Directory in which to place the individual messages.

Expand Down
140 changes: 117 additions & 23 deletions builtin-mailsplit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -96,44 +97,107 @@ 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 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 i;
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);
for (i = 0; i < list.nr; i++) {
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;
}

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, num = 0;
int allow_bare = 0;
const char *dir = NULL;
const char **argp;
Expand Down Expand Up @@ -186,9 +250,39 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
argp = stdin_only;
}

ret = split_mbox(argp, dir, allow_bare, nr_prec, nr);
if (ret != -1)
printf("%d\n", ret);
while (*argp) {
const char *arg = *argp++;
struct stat argstat;
int ret = 0;

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 ret == -1;
return 0;
}
2 changes: 1 addition & 1 deletion builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit d63bd9a

Please sign in to comment.