refactor userdiff textconv code
[gitweb.git] / builtin-mailsplit.c
index 46b27cdaea71cba92974480da74ec5922fcf3a7a..71f3b3b8741e505fc652e6c74c75972f19211f71 100644 (file)
@@ -6,10 +6,10 @@
  */
 #include "cache.h"
 #include "builtin.h"
-#include "path-list.h"
+#include "string-list.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)
 {
@@ -45,6 +45,24 @@ static int is_from_line(const char *line, int len)
 /* Could be as small as 64, enough to hold a Unix "From " line. */
 static char buf[4096];
 
+/* We cannot use fgets() because our lines can contain NULs */
+int read_line_with_nul(char *buf, int size, FILE *in)
+{
+       int len = 0, c;
+
+       for (;;) {
+               c = getc(in);
+               if (c == EOF)
+                       break;
+               buf[len++] = c;
+               if (c == '\n' || len + 1 >= size)
+                       break;
+       }
+       buf[len] = '\0';
+
+       return len;
+}
+
 /* Called with the first line (potentially partial)
  * already in buf[] -- normally that should begin with
  * the Unix "From " line.  Write it into the specified
@@ -70,19 +88,19 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)
         * "From " and having something that looks like a date format.
         */
        for (;;) {
-               int is_partial = (buf[len-1] != '\n');
+               int is_partial = len && buf[len-1] != '\n';
 
-               if (fputs(buf, output) == EOF)
+               if (fwrite(buf, 1, len, output) != len)
                        die("cannot write output");
 
-               if (fgets(buf, sizeof(buf), mbox) == NULL) {
+               len = read_line_with_nul(buf, sizeof(buf), mbox);
+               if (len == 0) {
                        if (feof(mbox)) {
                                status = 1;
                                break;
                        }
                        die("cannot read mbox");
                }
-               len = strlen(buf);
                if (!is_partial && !is_bare && is_from_line(buf, len))
                        break; /* done with one message */
        }
@@ -97,7 +115,7 @@ 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;
@@ -118,7 +136,7 @@ static int populate_maildir_list(struct path_list *list, const char *path)
                        if (dent->d_name[0] == '.')
                                continue;
                        snprintf(name, sizeof(name), "%s/%s", *sub, dent->d_name);
-                       path_list_insert(name, list);
+                       string_list_insert(name, list);
                }
 
                closedir(dir);
@@ -134,14 +152,14 @@ static int split_maildir(const char *maildir, const char *dir,
        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};
 
        if (populate_maildir_list(&list, maildir) < 0)
                goto out;
 
        for (i = 0; i < list.nr; i++) {
                FILE *f;
-               snprintf(file, sizeof(file), "%s/%s", maildir, 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));
@@ -161,7 +179,7 @@ static int split_maildir(const char *maildir, const char *dir,
 
        ret = skip;
 out:
-       path_list_clear(&list, 1);
+       string_list_clear(&list, 1);
        return ret;
 }