shortlog: warn the user when there is no input
[gitweb.git] / builtin-mailsplit.c
index 74b04706f36128711719fff3e1423b3fb454af4c..207e358ed19cecb8cf7b57d59a9149619909459d 100644 (file)
@@ -6,10 +6,11 @@
  */
 #include "cache.h"
 #include "builtin.h"
-#include "path-list.h"
+#include "string-list.h"
+#include "strbuf.h"
 
 static const char git_mailsplit_usage[] =
-"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>|<Maildir>...";
+"git mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]";
 
 static int is_from_line(const char *line, int len)
 {
@@ -42,8 +43,8 @@ static int is_from_line(const char *line, int len)
        return 1;
 }
 
-/* Could be as small as 64, enough to hold a Unix "From " line. */
-static char buf[4096];
+static struct strbuf buf = STRBUF_INIT;
+static int keep_cr;
 
 /* Called with the first line (potentially partial)
  * already in buf[] -- normally that should begin with
@@ -53,37 +54,39 @@ static char buf[4096];
 static int split_one(FILE *mbox, const char *name, int allow_bare)
 {
        FILE *output = NULL;
-       int len = strlen(buf);
        int fd;
        int status = 0;
-       int is_bare = !is_from_line(buflen);
+       int is_bare = !is_from_line(buf.buf, buf.len);
 
        if (is_bare && !allow_bare)
                goto corrupt;
 
        fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666);
        if (fd < 0)
-               die("cannot open output file %s", name);
-       output = fdopen(fd, "w");
+               die_errno("cannot open output file '%s'", name);
+       output = xfdopen(fd, "w");
 
        /* Copy it out, while searching for a line that begins with
         * "From " and having something that looks like a date format.
         */
        for (;;) {
-               int is_partial = (buf[len-1] != '\n');
+               if (!keep_cr && buf.len > 1 && buf.buf[buf.len-1] == '\n' &&
+                       buf.buf[buf.len-2] == '\r') {
+                       strbuf_setlen(&buf, buf.len-2);
+                       strbuf_addch(&buf, '\n');
+               }
 
-               if (fputs(buf, output) == EOF)
-                       die("cannot write output");
+               if (fwrite(buf.buf, 1, buf.len, output) != buf.len)
+                       die_errno("cannot write output");
 
-               if (fgets(buf, sizeof(buf), mbox) == NULL) {
+               if (strbuf_getwholeline(&buf, mbox, '\n')) {
                        if (feof(mbox)) {
                                status = 1;
                                break;
                        }
-                       die("cannot read mbox");
+                       die_errno("cannot read mbox");
                }
-               len = strlen(buf);
-               if (!is_partial && !is_bare && is_from_line(buf, len))
+               if (!is_bare && is_from_line(buf.buf, buf.len))
                        break; /* done with one message */
        }
        fclose(output);
@@ -97,24 +100,33 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)
        exit(1);
 }
 
-static int populate_maildir_list(struct path_list *list, const char *path)
+static int populate_maildir_list(struct string_list *list, const char *path)
 {
        DIR *dir;
        struct dirent *dent;
+       char name[PATH_MAX];
+       char *subs[] = { "cur", "new", NULL };
+       char **sub;
+
+       for (sub = subs; *sub; ++sub) {
+               snprintf(name, sizeof(name), "%s/%s", path, *sub);
+               if ((dir = opendir(name)) == NULL) {
+                       if (errno == ENOENT)
+                               continue;
+                       error("cannot opendir %s (%s)", name, strerror(errno));
+                       return -1;
+               }
 
-       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;
+                       snprintf(name, sizeof(name), "%s/%s", *sub, dent->d_name);
+                       string_list_insert(name, list);
+               }
 
-       while ((dent = readdir(dir)) != NULL) {
-               if (dent->d_name[0] == '.')
-                       continue;
-               path_list_insert(dent->d_name, list);
+               closedir(dir);
        }
 
-       closedir(dir);
-
        return 0;
 }
 
@@ -122,26 +134,24 @@ 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};
+       struct string_list list = {NULL, 0, 0, 1};
 
-       snprintf(curdir, sizeof(curdir), "%s/cur", maildir);
-       if (populate_maildir_list(&list, curdir) < 0)
+       if (populate_maildir_list(&list, maildir) < 0)
                goto out;
 
        for (i = 0; i < list.nr; i++) {
                FILE *f;
-               snprintf(file, sizeof(file), "%s/%s", curdir, list.items[i].path);
+               snprintf(file, sizeof(file), "%s/%s", maildir, list.items[i].string);
                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 (strbuf_getwholeline(&buf, f, '\n')) {
                        error("cannot read mail %s (%s)", file, strerror(errno));
                        goto out;
                }
@@ -152,10 +162,9 @@ static int split_maildir(const char *maildir, const char *dir,
                fclose(f);
        }
 
-       path_list_clear(&list, 1);
-
        ret = skip;
 out:
+       string_list_clear(&list, 1);
        return ret;
 }
 
@@ -179,7 +188,7 @@ static int split_mbox(const char *file, const char *dir, int allow_bare,
        } while (isspace(peek));
        ungetc(peek, f);
 
-       if (fgets(buf, sizeof(buf), f) == NULL) {
+       if (strbuf_getwholeline(&buf, f, '\n')) {
                /* empty stdin is OK */
                if (f != stdin) {
                        error("cannot read mbox %s", file);
@@ -222,8 +231,12 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
                        continue;
                } else if ( arg[1] == 'f' ) {
                        nr = strtol(arg+2, NULL, 10);
+               } else if ( arg[1] == 'h' ) {
+                       usage(git_mailsplit_usage);
                } else if ( arg[1] == 'b' && !arg[2] ) {
                        allow_bare = 1;
+               } else if (!strcmp(arg, "--keep-cr")) {
+                       keep_cr = 1;
                } else if ( arg[1] == 'o' && arg[2] ) {
                        dir = arg+2;
                } else if ( arg[1] == '-' && !arg[2] ) {