Make git-mailsplit a builtin
authorLukas Sandström <lukass@etek.chalmers.se>
Tue, 13 Jun 2006 20:21:46 +0000 (22:21 +0200)
committerJunio C Hamano <junkio@cox.net>
Mon, 19 Jun 2006 04:58:20 +0000 (21:58 -0700)
Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Makefile
builtin-mailsplit.c [new file with mode: 0644]
builtin.h
git.c
mailsplit.c [deleted file]
index 6e9ab57999089095ba9eb5b05296347f0cb5d13c..8febf6905421401d42a2e0cb81d41b9828dc7a82 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -144,7 +144,6 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
 
 # The ones that do not have to link with lcrypto, lz nor xdiff.
 SIMPLE_PROGRAMS = \
-       git-mailsplit$X \
        git-stripspace$X git-daemon$X
 
 # ... and all the rest that could be moved out of bindir to gitexecdir
@@ -165,7 +164,7 @@ PROGRAMS = \
        git-describe$X git-merge-tree$X git-blame$X git-imap-send$X
 
 BUILT_INS = git-log$X git-whatchanged$X git-show$X \
-       git-count-objects$X git-diff$X git-push$X \
+       git-count-objects$X git-diff$X git-push$X git-mailsplit$X \
        git-grep$X git-add$X git-rm$X git-rev-list$X \
        git-check-ref-format$X git-rev-parse$X \
        git-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \
@@ -227,7 +226,7 @@ BUILTIN_OBJS = \
        builtin-read-tree.o builtin-commit-tree.o \
        builtin-apply.o builtin-show-branch.o builtin-diff-files.o \
        builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \
-       builtin-cat-file.o
+       builtin-cat-file.o builtin-mailsplit.o
 
 GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
 LIBS = $(GITLIBS) -lz
diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c
new file mode 100644 (file)
index 0000000..e2a0058
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Totally braindamaged mbox splitter program.
+ *
+ * It just splits a mbox into a list of files: "0001" "0002" ..
+ * so you can process them further from there.
+ */
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include "cache.h"
+#include "builtin.h"
+
+static const char git_mailsplit_usage[] =
+"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>...";
+
+static int is_from_line(const char *line, int len)
+{
+       const char *colon;
+
+       if (len < 20 || memcmp("From ", line, 5))
+               return 0;
+
+       colon = line + len - 2;
+       line += 5;
+       for (;;) {
+               if (colon < line)
+                       return 0;
+               if (*--colon == ':')
+                       break;
+       }
+
+       if (!isdigit(colon[-4]) ||
+           !isdigit(colon[-2]) ||
+           !isdigit(colon[-1]) ||
+           !isdigit(colon[ 1]) ||
+           !isdigit(colon[ 2]))
+               return 0;
+
+       /* year */
+       if (strtol(colon+3, NULL, 10) <= 90)
+               return 0;
+
+       /* Ok, close enough */
+       return 1;
+}
+
+/* Could be as small as 64, enough to hold a Unix "From " line. */
+static char buf[4096];
+
+/* Called with the first line (potentially partial)
+ * already in buf[] -- normally that should begin with
+ * the Unix "From " line.  Write it into the specified
+ * file.
+ */
+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(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");
+
+       /* 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 (fputs(buf, output) == EOF)
+                       die("cannot write output");
+
+               if (fgets(buf, sizeof(buf), mbox) == NULL) {
+                       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 */
+       }
+       fclose(output);
+       return status;
+
+ corrupt:
+       if (output)
+               fclose(output);
+       unlink(name);
+       fprintf(stderr, "corrupt mailbox\n");
+       exit(1);
+}
+
+int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip)
+{
+       char *name = xmalloc(strlen(dir) + 2 + 3 * sizeof(skip));
+       int ret = -1;
+
+       while (*mbox) {
+               const char *file = *mbox++;
+               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) {
+                       if (f == stdin)
+                               break; /* empty stdin is OK */
+                       error("cannot read mbox %s", file);
+                       goto out;
+               }
+
+               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, char **envp)
+{
+       int nr = 0, nr_prec = 4, ret;
+       int allow_bare = 0;
+       const char *dir = NULL;
+       const char **argp;
+       static const char *stdin_only[] = { "-", NULL };
+
+       for (argp = argv+1; *argp; argp++) {
+               const char *arg = *argp;
+
+               if (arg[0] != '-')
+                       break;
+               /* do flags here */
+               if ( arg[1] == 'd' ) {
+                       nr_prec = strtol(arg+2, NULL, 10);
+                       if (nr_prec < 3 || 10 <= nr_prec)
+                               usage(git_mailsplit_usage);
+                       continue;
+               } else if ( arg[1] == 'f' ) {
+                       nr = strtol(arg+2, NULL, 10);
+               } else if ( arg[1] == 'b' && !arg[2] ) {
+                       allow_bare = 1;
+               } else if ( arg[1] == 'o' && arg[2] ) {
+                       dir = arg+2;
+               } else if ( arg[1] == '-' && !arg[2] ) {
+                       argp++; /* -- marks end of options */
+                       break;
+               } else {
+                       die("unknown option: %s", arg);
+               }
+       }
+
+       if ( !dir ) {
+               /* Backwards compatibility: if no -o specified, accept
+                  <mbox> <dir> or just <dir> */
+               switch (argc - (argp-argv)) {
+               case 1:
+                       dir = argp[0];
+                       argp = stdin_only;
+                       break;
+               case 2:
+                       stdin_only[0] = argp[0];
+                       dir = argp[1];
+                       argp = stdin_only;
+                       break;
+               default:
+                       usage(git_mailsplit_usage);
+               }
+       } else {
+               /* New usage: if no more argument, parse stdin */
+               if ( !*argp )
+                       argp = stdin_only;
+       }
+
+       ret = split_mbox(argp, dir, allow_bare, nr_prec, nr);
+       if (ret != -1)
+               printf("%d\n", ret);
+
+       return ret == -1;
+}
index 885422e9f84b02d5146657e58af76bea322e8649..92e1e1b51cde7a72104a9917dba3a3d7561b373e 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -49,4 +49,6 @@ extern int cmd_rev_parse(int argc, const char **argv, char **envp);
 extern int cmd_write_tree(int argc, const char **argv, char **envp);
 extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);
 
+extern int cmd_mailsplit(int argc, const char **argv, char **envp);
+extern int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip);
 #endif
diff --git a/git.c b/git.c
index b4b01326a9b683a00ee196bea15f805d70b57f26..39dc40a691c06bbb082dd863b4664a0965cded9c 100644 (file)
--- a/git.c
+++ b/git.c
@@ -179,7 +179,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
                { "diff-tree", cmd_diff_tree },
                { "cat-file", cmd_cat_file },
                { "rev-parse", cmd_rev_parse },
-               { "write-tree", cmd_write_tree }
+               { "write-tree", cmd_write_tree },
+               { "mailsplit", cmd_mailsplit }
        };
        int i;
 
diff --git a/mailsplit.c b/mailsplit.c
deleted file mode 100644 (file)
index 70a569c..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Totally braindamaged mbox splitter program.
- *
- * It just splits a mbox into a list of files: "0001" "0002" ..
- * so you can process them further from there.
- */
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <stdio.h>
-#include "cache.h"
-
-static const char git_mailsplit_usage[] =
-"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>...";
-
-static int is_from_line(const char *line, int len)
-{
-       const char *colon;
-
-       if (len < 20 || memcmp("From ", line, 5))
-               return 0;
-
-       colon = line + len - 2;
-       line += 5;
-       for (;;) {
-               if (colon < line)
-                       return 0;
-               if (*--colon == ':')
-                       break;
-       }
-
-       if (!isdigit(colon[-4]) ||
-           !isdigit(colon[-2]) ||
-           !isdigit(colon[-1]) ||
-           !isdigit(colon[ 1]) ||
-           !isdigit(colon[ 2]))
-               return 0;
-
-       /* year */
-       if (strtol(colon+3, NULL, 10) <= 90)
-               return 0;
-
-       /* Ok, close enough */
-       return 1;
-}
-
-/* Could be as small as 64, enough to hold a Unix "From " line. */
-static char buf[4096];
-
-/* Called with the first line (potentially partial)
- * already in buf[] -- normally that should begin with
- * the Unix "From " line.  Write it into the specified
- * file.
- */
-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(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");
-
-       /* 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 (fputs(buf, output) == EOF)
-                       die("cannot write output");
-
-               if (fgets(buf, sizeof(buf), mbox) == NULL) {
-                       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 */
-       }
-       fclose(output);
-       return status;
-
- corrupt:
-       if (output)
-               fclose(output);
-       unlink(name);
-       fprintf(stderr, "corrupt mailbox\n");
-       exit(1);
-}
-
-int main(int argc, const char **argv)
-{
-       int nr = 0, nr_prec = 4;
-       int allow_bare = 0;
-       const char *dir = NULL;
-       const char **argp;
-       static const char *stdin_only[] = { "-", NULL };
-       char *name;
-
-       for (argp = argv+1; *argp; argp++) {
-               const char *arg = *argp;
-
-               if (arg[0] != '-')
-                       break;
-               /* do flags here */
-               if ( arg[1] == 'd' ) {
-                       nr_prec = strtol(arg+2, NULL, 10);
-                       if (nr_prec < 3 || 10 <= nr_prec)
-                               usage(git_mailsplit_usage);
-                       continue;
-               } else if ( arg[1] == 'f' ) {
-                       nr = strtol(arg+2, NULL, 10);
-               } else if ( arg[1] == 'b' && !arg[2] ) {
-                       allow_bare = 1;
-               } else if ( arg[1] == 'o' && arg[2] ) {
-                       dir = arg+2;
-               } else if ( arg[1] == '-' && !arg[2] ) {
-                       argp++; /* -- marks end of options */
-                       break;
-               } else {
-                       die("unknown option: %s", arg);
-               }
-       }
-
-       if ( !dir ) {
-               /* Backwards compatibility: if no -o specified, accept
-                  <mbox> <dir> or just <dir> */
-               switch (argc - (argp-argv)) {
-               case 1:
-                       dir = argp[0];
-                       argp = stdin_only;
-                       break;
-               case 2:
-                       stdin_only[0] = argp[0];
-                       dir = argp[1];
-                       argp = stdin_only;
-                       break;
-               default:
-                       usage(git_mailsplit_usage);
-               }
-       } else {
-               /* New usage: if no more argument, parse stdin */
-               if ( !*argp )
-                       argp = stdin_only;
-       }
-
-       name = xmalloc(strlen(dir) + 2 + 3 * sizeof(nr));
-
-       while (*argp) {
-               const char *file = *argp++;
-               FILE *f = !strcmp(file, "-") ? stdin : fopen(file, "r");
-               int file_done = 0;
-
-               if ( !f )
-                       die ("cannot open mbox %s", file);
-
-               if (fgets(buf, sizeof(buf), f) == NULL) {
-                       if (f == stdin)
-                               break; /* empty stdin is OK */
-                       die("cannot read mbox %s", file);
-               }
-
-               while (!file_done) {
-                       sprintf(name, "%s/%0*d", dir, nr_prec, ++nr);
-                       file_done = split_one(f, name, allow_bare);
-               }
-
-               if (f != stdin)
-                       fclose(f);
-       }
-
-       printf("%d\n", nr);
-       return 0;
-}