{"thread":{"id":"4501","subject":"[PATCH 2/8] Make git-mailsplit a builtin","startedAt":"2006-06-13T20:21:42Z","lastAt":"2006-06-14T02:22:28Z","messageCount":9,"participants":["Lukas Sandström","Shawn Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":8},"messages":[{"id":"21745","messageId":"448F1E56.8010203@etek.chalmers.se","threadId":"4501","inReplyTo":"448EF791.7070504@etek.chalmers.se","subject":"[PATCH 1/8] Make git-write-tree a builtin","fromName":"Lukas Sandström","fromEmail":"lukass@etek.chalmers.se","sentAt":"2006-06-13T20:21:42Z","receivedAt":"2006-06-13T20:21:42Z","isPatch":true,"sender":{"key":"luksan@gmail.com","avatar":"https://avatars.githubusercontent.com/u/152281?v=4"},"body":"Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n---\n Makefile                             |    6 ++-\n write-tree.c => builtin-write-tree.c |   68 +++++++++++++++++++++-------------\n builtin.h                            |    3 ++\n git.c                                |    3 +-\n 4 files changed, 50 insertions(+), 30 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 2a1e639..37b5e40 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -159,7 +159,7 @@ PROGRAMS = \\\n \tgit-show-index$X git-ssh-fetch$X \\\n \tgit-ssh-upload$X git-unpack-file$X \\\n \tgit-unpack-objects$X git-update-index$X git-update-server-info$X \\\n-\tgit-upload-pack$X git-verify-pack$X git-write-tree$X \\\n+\tgit-upload-pack$X git-verify-pack$X \\\n \tgit-update-ref$X git-symbolic-ref$X \\\n \tgit-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \\\n \tgit-describe$X git-merge-tree$X git-blame$X git-imap-send$X\n@@ -170,7 +170,7 @@ BUILT_INS = git-log$X git-whatchanged$X \n \tgit-check-ref-format$X git-rev-parse$X \\\n \tgit-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \\\n \tgit-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \\\n-\tgit-read-tree$X git-commit-tree$X \\\n+\tgit-read-tree$X git-commit-tree$X git-write-tree$X \\\n \tgit-apply$X git-show-branch$X git-diff-files$X \\\n \tgit-diff-index$X git-diff-stages$X git-diff-tree$X git-cat-file$X\n \n@@ -223,7 +223,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-grep.o builtin-add.o builtin-rev-list.o builtin-check-ref-format.o \\\n \tbuiltin-rm.o builtin-init-db.o builtin-rev-parse.o \\\n \tbuiltin-tar-tree.o builtin-upload-tar.o \\\n-\tbuiltin-ls-files.o builtin-ls-tree.o \\\n+\tbuiltin-ls-files.o builtin-ls-tree.o builtin-write-tree.o \\\n \tbuiltin-read-tree.o builtin-commit-tree.o \\\n \tbuiltin-apply.o builtin-show-branch.o builtin-diff-files.o \\\n \tbuiltin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \\\ndiff --git a/write-tree.c b/builtin-write-tree.c\nsimilarity index 66%\nrename from write-tree.c\nrename to builtin-write-tree.c\nindex bd07da6..c3aac36 100644\n--- a/write-tree.c\n+++ b/builtin-write-tree.c\n@@ -3,41 +3,24 @@\n  *\n  * Copyright (C) Linus Torvalds, 2005\n  */\n+#include \"builtin.h\"\n #include \"cache.h\"\n #include \"tree.h\"\n #include \"cache-tree.h\"\n \n-static int missing_ok = 0;\n-static char *prefix = NULL;\n-\n static const char write_tree_usage[] =\n \"git-write-tree [--missing-ok] [--prefix=<prefix>/]\";\n \n-static struct lock_file lock_file;\n-\n-int main(int argc, char **argv)\n+int write_tree(unsigned char *sha1, int missing_ok, const char *prefix)\n {\n \tint entries, was_valid, newfd;\n \n-\tsetup_git_directory();\n+\t/* We can't free this memory, it becomes part of a linked list parsed atexit() */\n+\tstruct lock_file *lock_file = xmalloc(sizeof(struct lock_file));\n \n-\tnewfd = hold_lock_file_for_update(&lock_file, get_index_file());\n-\tentries = read_cache();\n-\n-\twhile (1 < argc) {\n-\t\tchar *arg = argv[1];\n-\t\tif (!strcmp(arg, \"--missing-ok\"))\n-\t\t\tmissing_ok = 1;\n-\t\telse if (!strncmp(arg, \"--prefix=\", 9))\n-\t\t\tprefix = arg + 9;\n-\t\telse\n-\t\t\tdie(write_tree_usage);\n-\t\targc--; argv++;\n-\t}\n-\n-\tif (argc > 2)\n-\t\tdie(\"too many options\");\n+\tnewfd = hold_lock_file_for_update(lock_file, get_index_file());\n \n+\tentries = read_cache();\n \tif (entries < 0)\n \t\tdie(\"git-write-tree: error reading cache\");\n \n@@ -45,6 +28,7 @@ int main(int argc, char **argv)\n \t\tactive_cache_tree = cache_tree();\n \n \twas_valid = cache_tree_fully_valid(active_cache_tree);\n+\n \tif (!was_valid) {\n \t\tif (cache_tree_update(active_cache_tree,\n \t\t\t\t      active_cache, active_nr,\n@@ -52,7 +36,7 @@ int main(int argc, char **argv)\n \t\t\tdie(\"git-write-tree: error building trees\");\n \t\tif (0 <= newfd) {\n \t\t\tif (!write_cache(newfd, active_cache, active_nr))\n-\t\t\t\tcommit_lock_file(&lock_file);\n+\t\t\t\tcommit_lock_file(lock_file);\n \t\t}\n \t\t/* Not being able to write is fine -- we are only interested\n \t\t * in updating the cache-tree part, and if the next caller\n@@ -61,12 +45,44 @@ int main(int argc, char **argv)\n \t\t * performance penalty and not a big deal.\n \t\t */\n \t}\n+\n \tif (prefix) {\n \t\tstruct cache_tree *subtree =\n \t\t\tcache_tree_find(active_cache_tree, prefix);\n-\t\tprintf(\"%s\\n\", sha1_to_hex(subtree->sha1));\n+\t\tmemcpy(sha1, subtree->sha1, 20);\n \t}\n \telse\n-\t\tprintf(\"%s\\n\", sha1_to_hex(active_cache_tree->sha1));\n+\t\tmemcpy(sha1, active_cache_tree->sha1, 20);\n+\n+\trollback_lock_file(lock_file);\n+\n \treturn 0;\n }\n+\n+int cmd_write_tree(int argc, const char **argv, char **envp)\n+{\n+\tint missing_ok = 0, ret;\n+\tconst char *prefix = NULL;\n+\tunsigned char sha1[20];\n+\n+\tsetup_git_directory();\n+\n+\twhile (1 < argc) {\n+\t\tconst char *arg = argv[1];\n+\t\tif (!strcmp(arg, \"--missing-ok\"))\n+\t\t\tmissing_ok = 1;\n+\t\telse if (!strncmp(arg, \"--prefix=\", 9))\n+\t\t\tprefix = arg + 9;\n+\t\telse\n+\t\t\tdie(write_tree_usage);\n+\t\targc--; argv++;\n+\t}\n+\n+\tif (argc > 2)\n+\t\tdie(\"too many options\");\n+\n+\tret = write_tree(sha1, missing_ok, prefix);\n+\tprintf(\"%s\\n\", sha1_to_hex(sha1));\n+\n+\treturn ret;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex b9f36be..885422e 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -46,4 +46,7 @@ extern int cmd_diff_tree(int argc, const\n extern int cmd_cat_file(int argc, const char **argv, char **envp);\n extern int cmd_rev_parse(int argc, const char **argv, char **envp);\n \n+extern int cmd_write_tree(int argc, const char **argv, char **envp);\n+extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);\n+\n #endif\ndiff --git a/git.c b/git.c\nindex 9469d44..5868fb9 100644\n--- a/git.c\n+++ b/git.c\n@@ -178,7 +178,8 @@ static void handle_internal_command(int \n \t\t{ \"diff-stages\", cmd_diff_stages },\n \t\t{ \"diff-tree\", cmd_diff_tree },\n \t\t{ \"cat-file\", cmd_cat_file },\n-\t\t{ \"rev-parse\", cmd_rev_parse }\n+\t\t{ \"rev-parse\", cmd_rev_parse },\n+\t\t{ \"write-tree\", cmd_write_tree }\n \t};\n \tint i;\n \n-- \n1.4.0\n"},{"id":"21744","messageId":"448F1E5A.7070204@etek.chalmers.se","threadId":"4501","inReplyTo":"448EF791.7070504@etek.chalmers.se","subject":"[PATCH 2/8] Make git-mailsplit a builtin","fromName":"Lukas Sandström","fromEmail":"lukass@etek.chalmers.se","sentAt":"2006-06-13T20:21:46Z","receivedAt":"2006-06-13T20:21:46Z","isPatch":true,"sender":{"key":"luksan@gmail.com","avatar":"https://avatars.githubusercontent.com/u/152281?v=4"},"body":"Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n---\n Makefile                           |    5 +--\n mailsplit.c => builtin-mailsplit.c |   71 +++++++++++++++++++++---------------\n builtin.h                          |    2 +\n git.c                              |    3 +-\n 4 files changed, 48 insertions(+), 33 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 37b5e40..7bee30d 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -144,7 +144,6 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)\n \n # The ones that do not have to link with lcrypto, lz nor xdiff.\n SIMPLE_PROGRAMS = \\\n-\tgit-mailsplit$X \\\n \tgit-stripspace$X git-daemon$X\n \n # ... and all the rest that could be moved out of bindir to gitexecdir\n@@ -165,7 +164,7 @@ PROGRAMS = \\\n \tgit-describe$X git-merge-tree$X git-blame$X git-imap-send$X\n \n BUILT_INS = git-log$X git-whatchanged$X git-show$X \\\n-\tgit-count-objects$X git-diff$X git-push$X \\\n+\tgit-count-objects$X git-diff$X git-push$X git-mailsplit$X \\\n \tgit-grep$X git-add$X git-rm$X git-rev-list$X \\\n \tgit-check-ref-format$X git-rev-parse$X \\\n \tgit-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \\\n@@ -227,7 +226,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-read-tree.o builtin-commit-tree.o \\\n \tbuiltin-apply.o builtin-show-branch.o builtin-diff-files.o \\\n \tbuiltin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \\\n-\tbuiltin-cat-file.o\n+\tbuiltin-cat-file.o builtin-mailsplit.o\n \n GITLIBS = $(LIB_FILE) $(XDIFF_LIB)\n LIBS = $(GITLIBS) -lz\ndiff --git a/mailsplit.c b/builtin-mailsplit.c\nsimilarity index 85%\nrename from mailsplit.c\nrename to builtin-mailsplit.c\nindex 70a569c..e2a0058 100644\n--- a/mailsplit.c\n+++ b/builtin-mailsplit.c\n@@ -12,6 +12,7 @@ #include <sys/stat.h>\n #include <string.h>\n #include <stdio.h>\n #include \"cache.h\"\n+#include \"builtin.h\"\n \n static const char git_mailsplit_usage[] =\n \"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>...\";\n@@ -102,14 +103,48 @@ static int split_one(FILE *mbox, const c\n \texit(1);\n }\n \n-int main(int argc, const char **argv)\n+int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip)\n {\n-\tint nr = 0, nr_prec = 4;\n+\tchar *name = xmalloc(strlen(dir) + 2 + 3 * sizeof(skip));\n+\tint ret = -1;\n+\n+\twhile (*mbox) {\n+\t\tconst char *file = *mbox++;\n+\t\tFILE *f = !strcmp(file, \"-\") ? stdin : fopen(file, \"r\");\n+\t\tint file_done = 0;\n+\n+\t\tif ( !f ) {\n+\t\t\terror(\"cannot open mbox %s\", file);\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tif (fgets(buf, sizeof(buf), f) == NULL) {\n+\t\t\tif (f == stdin)\n+\t\t\t\tbreak; /* empty stdin is OK */\n+\t\t\terror(\"cannot read mbox %s\", file);\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\twhile (!file_done) {\n+\t\t\tsprintf(name, \"%s/%0*d\", dir, nr_prec, ++skip);\n+\t\t\tfile_done = split_one(f, name, allow_bare);\n+\t\t}\n+\n+\t\tif (f != stdin)\n+\t\t\tfclose(f);\n+\t}\n+\tret = skip;\n+out:\n+\tfree(name);\n+\treturn ret;\n+}\n+int cmd_mailsplit(int argc, const char **argv, char **envp)\n+{\n+\tint nr = 0, nr_prec = 4, ret;\n \tint allow_bare = 0;\n \tconst char *dir = NULL;\n \tconst char **argp;\n \tstatic const char *stdin_only[] = { \"-\", NULL };\n-\tchar *name;\n \n \tfor (argp = argv+1; *argp; argp++) {\n \t\tconst char *arg = *argp;\n@@ -158,31 +193,9 @@ int main(int argc, const char **argv)\n \t\t\targp = stdin_only;\n \t}\n \n-\tname = xmalloc(strlen(dir) + 2 + 3 * sizeof(nr));\n-\n-\twhile (*argp) {\n-\t\tconst char *file = *argp++;\n-\t\tFILE *f = !strcmp(file, \"-\") ? stdin : fopen(file, \"r\");\n-\t\tint file_done = 0;\n-\n-\t\tif ( !f )\n-\t\t\tdie (\"cannot open mbox %s\", file);\n-\n-\t\tif (fgets(buf, sizeof(buf), f) == NULL) {\n-\t\t\tif (f == stdin)\n-\t\t\t\tbreak; /* empty stdin is OK */\n-\t\t\tdie(\"cannot read mbox %s\", file);\n-\t\t}\n-\n-\t\twhile (!file_done) {\n-\t\t\tsprintf(name, \"%s/%0*d\", dir, nr_prec, ++nr);\n-\t\t\tfile_done = split_one(f, name, allow_bare);\n-\t\t}\n-\n-\t\tif (f != stdin)\n-\t\t\tfclose(f);\n-\t}\n+\tret = split_mbox(argp, dir, allow_bare, nr_prec, nr);\n+\tif (ret != -1)\n+\t\tprintf(\"%d\\n\", ret);\n \n-\tprintf(\"%d\\n\", nr);\n-\treturn 0;\n+\treturn ret == -1;\n }\ndiff --git a/builtin.h b/builtin.h\nindex 885422e..92e1e1b 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -49,4 +49,6 @@ extern int cmd_rev_parse(int argc, const\n extern int cmd_write_tree(int argc, const char **argv, char **envp);\n extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);\n \n+extern int cmd_mailsplit(int argc, const char **argv, char **envp);\n+extern int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip);\n #endif\ndiff --git a/git.c b/git.c\nindex 5868fb9..3264c65 100644\n--- a/git.c\n+++ b/git.c\n@@ -179,7 +179,8 @@ static void handle_internal_command(int \n \t\t{ \"diff-tree\", cmd_diff_tree },\n \t\t{ \"cat-file\", cmd_cat_file },\n \t\t{ \"rev-parse\", cmd_rev_parse },\n-\t\t{ \"write-tree\", cmd_write_tree }\n+\t\t{ \"write-tree\", cmd_write_tree },\n+\t\t{ \"mailsplit\", cmd_mailsplit }\n \t};\n \tint i;\n \n-- \n1.4.0\n"},{"id":"21746","messageId":"448F1E5E.3060802@etek.chalmers.se","threadId":"4501","inReplyTo":"448EF791.7070504@etek.chalmers.se","subject":"[PATCH 3/8] Make git-mailinfo a builtin","fromName":"Lukas Sandström","fromEmail":"lukass@etek.chalmers.se","sentAt":"2006-06-13T20:21:50Z","receivedAt":"2006-06-13T20:21:50Z","isPatch":true,"sender":{"key":"luksan@gmail.com","avatar":"https://avatars.githubusercontent.com/u/152281?v=4"},"body":"Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n---\n Makefile                         |   12 ++---\n mailinfo.c => builtin-mailinfo.c |   85 ++++++++++++++++++++++----------------\n builtin.h                        |    6 +++\n git.c                            |    3 +\n 4 files changed, 62 insertions(+), 44 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 7bee30d..e64d943 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -151,7 +151,7 @@ PROGRAMS = \\\n \tgit-checkout-index$X git-clone-pack$X \\\n \tgit-convert-objects$X git-fetch-pack$X git-fsck-objects$X \\\n \tgit-hash-object$X git-index-pack$X git-local-fetch$X \\\n-\tgit-mailinfo$X git-merge-base$X \\\n+\tgit-merge-base$X \\\n \tgit-merge-index$X git-mktag$X git-mktree$X git-pack-objects$X git-patch-id$X \\\n \tgit-peek-remote$X git-prune-packed$X git-receive-pack$X \\\n \tgit-send-pack$X git-shell$X \\\n@@ -166,7 +166,7 @@ PROGRAMS = \\\n BUILT_INS = git-log$X git-whatchanged$X git-show$X \\\n \tgit-count-objects$X git-diff$X git-push$X git-mailsplit$X \\\n \tgit-grep$X git-add$X git-rm$X git-rev-list$X \\\n-\tgit-check-ref-format$X git-rev-parse$X \\\n+\tgit-check-ref-format$X git-rev-parse$X git-mailinfo$X \\\n \tgit-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \\\n \tgit-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \\\n \tgit-read-tree$X git-commit-tree$X git-write-tree$X \\\n@@ -223,7 +223,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-rm.o builtin-init-db.o builtin-rev-parse.o \\\n \tbuiltin-tar-tree.o builtin-upload-tar.o \\\n \tbuiltin-ls-files.o builtin-ls-tree.o builtin-write-tree.o \\\n-\tbuiltin-read-tree.o builtin-commit-tree.o \\\n+\tbuiltin-read-tree.o builtin-commit-tree.o builtin-mailinfo.o \\\n \tbuiltin-apply.o builtin-show-branch.o builtin-diff-files.o \\\n \tbuiltin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \\\n \tbuiltin-cat-file.o builtin-mailsplit.o\n@@ -486,7 +486,7 @@ strip: $(PROGRAMS) git$X\n git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS)\n \t$(CC) -DGIT_VERSION='\"$(GIT_VERSION)\"' \\\n \t\t$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \\\n-\t\t$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)\n+\t\t$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) $(LIB_4_ICONV)\n \n builtin-help.o: common-cmds.h\n \n@@ -563,10 +563,6 @@ git-%$X: %.o $(GITLIBS)\n \t$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIB_FILE) $(SIMPLE_LIB)\n \n-git-mailinfo$X: mailinfo.o $(LIB_FILE)\n-\t$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n-\t\t$(LIB_FILE) $(SIMPLE_LIB) $(LIB_4_ICONV)\n-\n git-local-fetch$X: fetch.o\n git-ssh-fetch$X: rsh.o fetch.o\n git-ssh-upload$X: rsh.o\ndiff --git a/mailinfo.c b/builtin-mailinfo.c\nsimilarity index 94%\nrename from mailinfo.c\nrename to builtin-mailinfo.c\nindex 5b6c215..6e30758 100644\n--- a/mailinfo.c\n+++ b/builtin-mailinfo.c\n@@ -12,8 +12,9 @@ #include <iconv.h>\n #endif\n #include \"git-compat-util.h\"\n #include \"cache.h\"\n+#include \"builtin.h\"\n \n-static FILE *cmitmsg, *patchfile;\n+static FILE *cmitmsg, *patchfile, *fin, *fout;\n \n static int keep_subject = 0;\n static char *metainfo_charset = NULL;\n@@ -49,7 +50,7 @@ static int bogus_from(char *line)\n \n \t/* This is fallback, so do not bother if we already have an\n \t * e-mail address.\n-\t */ \n+\t */\n \tif (*email)\n \t\treturn 0;\n \n@@ -311,12 +312,12 @@ static char *cleanup_subject(char *subje\n \t\t\tif (remove <= len *2) {\n \t\t\t\tsubject = p+1;\n \t\t\t\tcontinue;\n-\t\t\t}\t\n+\t\t\t}\n \t\t\tbreak;\n \t\t}\n \t\treturn subject;\n \t}\n-}\t\t\t\n+}\n \n static void cleanup_space(char *buf)\n {\n@@ -638,7 +639,7 @@ static void handle_info(void)\n \tcleanup_space(email);\n \tcleanup_space(sub);\n \n-\tprintf(\"Author: %s\\nEmail: %s\\nSubject: %s\\nDate: %s\\n\\n\",\n+\tfprintf(fout, \"Author: %s\\nEmail: %s\\nSubject: %s\\nDate: %s\\n\\n\",\n \t       name, email, sub, date);\n }\n \n@@ -675,7 +676,7 @@ static int handle_commit_msg(int *seen)\n \t\t\tcontinue;\n \n \t\tfputs(line, cmitmsg);\n-\t} while (fgets(line, sizeof(line), stdin) != NULL);\n+\t} while (fgets(line, sizeof(line), fin) != NULL);\n \tfclose(cmitmsg);\n \tcmitmsg = NULL;\n \treturn 0;\n@@ -696,7 +697,7 @@ static void handle_patch(void)\n \t\tdecode_transfer_encoding(line);\n \t\tfputs(line, patchfile);\n \t\tpatch_lines++;\n-\t} while (fgets(line, sizeof(line), stdin) != NULL);\n+\t} while (fgets(line, sizeof(line), fin) != NULL);\n }\n \n /* multipart boundary and transfer encoding are set up for us, and we\n@@ -709,7 +710,7 @@ static int handle_multipart_one_part(int\n {\n \tint n = 0;\n \n-\twhile (fgets(line, sizeof(line), stdin) != NULL) {\n+\twhile (fgets(line, sizeof(line), fin) != NULL) {\n \tagain:\n \t\tn++;\n \t\tif (is_multipart_boundary(line))\n@@ -730,7 +731,7 @@ static void handle_multipart_body(void)\n \tint part_num = 0;\n \n \t/* Skip up to the first boundary */\n-\twhile (fgets(line, sizeof(line), stdin) != NULL)\n+\twhile (fgets(line, sizeof(line), fin) != NULL)\n \t\tif (is_multipart_boundary(line)) {\n \t\t\tpart_num = 1;\n \t\t\tbreak;\n@@ -739,7 +740,7 @@ static void handle_multipart_body(void)\n \t\treturn;\n \t/* We are on boundary line.  Start slurping the subhead. */\n \twhile (1) {\n-\t\tint hdr = read_one_header_line(line, sizeof(line), stdin);\n+\t\tint hdr = read_one_header_line(line, sizeof(line), fin);\n \t\tif (!hdr) {\n \t\t\tif (handle_multipart_one_part(&seen) < 0)\n \t\t\t\treturn;\n@@ -762,7 +763,7 @@ static void handle_body(void)\n {\n \tint seen = 0;\n \n-\tif (line[0] || fgets(line, sizeof(line), stdin) != NULL) {\n+\tif (line[0] || fgets(line, sizeof(line), fin) != NULL) {\n \t\thandle_commit_msg(&seen);\n \t\thandle_patch();\n \t}\n@@ -773,10 +774,45 @@ static void handle_body(void)\n \t}\n }\n \n+int mailinfo(FILE *in, FILE *out, int ks, char *encoding,\n+\t     const char *msg, const char *patch)\n+{\n+\tkeep_subject = ks;\n+\tmetainfo_charset = encoding;\n+\tfin = in;\n+\tfout = out;\n+\n+\tcmitmsg = fopen(msg, \"w\");\n+\tif (!cmitmsg) {\n+\t\tperror(msg);\n+\t\treturn -1;\n+\t}\n+\tpatchfile = fopen(patch, \"w\");\n+\tif (!patchfile) {\n+\t\tperror(patch);\n+\t\tfclose(cmitmsg);\n+\t\treturn -1;\n+\t}\n+\twhile (1) {\n+\t\tint hdr = read_one_header_line(line, sizeof(line), fin);\n+\t\tif (!hdr) {\n+\t\t\tif (multipart_boundary[0])\n+\t\t\t\thandle_multipart_body();\n+\t\t\telse\n+\t\t\t\thandle_body();\n+\t\t\thandle_info();\n+\t\t\tbreak;\n+\t\t}\n+\t\tcheck_header_line(line);\n+\t}\n+\n+\treturn 0;\n+}\n+\n static const char mailinfo_usage[] =\n \t\"git-mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info\";\n \n-int main(int argc, char **argv)\n+int cmd_mailinfo(int argc, const char **argv, char **envp)\n {\n \t/* NEEDSWORK: might want to do the optional .git/ directory\n \t * discovery\n@@ -797,27 +833,6 @@ int main(int argc, char **argv)\n \n \tif (argc != 3)\n \t\tusage(mailinfo_usage);\n-\tcmitmsg = fopen(argv[1], \"w\");\n-\tif (!cmitmsg) {\n-\t\tperror(argv[1]);\n-\t\texit(1);\n-\t}\n-\tpatchfile = fopen(argv[2], \"w\");\n-\tif (!patchfile) {\n-\t\tperror(argv[2]);\n-\t\texit(1);\n-\t}\n-\twhile (1) {\n-\t\tint hdr = read_one_header_line(line, sizeof(line), stdin);\n-\t\tif (!hdr) {\n-\t\t\tif (multipart_boundary[0])\n-\t\t\t\thandle_multipart_body();\n-\t\t\telse\n-\t\t\t\thandle_body();\n-\t\t\thandle_info();\n-\t\t\tbreak;\n-\t\t}\n-\t\tcheck_header_line(line);\n-\t}\n-\treturn 0;\n+\n+\treturn !!mailinfo(stdin, stdout, keep_subject, metainfo_charset, argv[1], argv[2]);\n }\ndiff --git a/builtin.h b/builtin.h\nindex 92e1e1b..979e0cd 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -1,6 +1,8 @@\n #ifndef BUILTIN_H\n #define BUILTIN_H\n \n+#include <stdio.h>\n+\n #ifndef PATH_MAX\n # define PATH_MAX 4096\n #endif\n@@ -51,4 +53,8 @@ extern int write_tree(unsigned char *sha\n \n extern int cmd_mailsplit(int argc, const char **argv, char **envp);\n extern int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip);\n+\n+extern int cmd_mailinfo(int argc, const char **argv, char **envp);\n+extern int mailinfo(FILE *in, FILE *out, int ks, char *encoding,\n+\t\t    const char *msg, const char *patch);\n #endif\ndiff --git a/git.c b/git.c\nindex 3264c65..1e216de 100644\n--- a/git.c\n+++ b/git.c\n@@ -180,7 +180,8 @@ static void handle_internal_command(int \n \t\t{ \"cat-file\", cmd_cat_file },\n \t\t{ \"rev-parse\", cmd_rev_parse },\n \t\t{ \"write-tree\", cmd_write_tree },\n-\t\t{ \"mailsplit\", cmd_mailsplit }\n+\t\t{ \"mailsplit\", cmd_mailsplit },\n+\t\t{ \"mailinfo\", cmd_mailinfo }\n \t};\n \tint i;\n \n-- \n1.4.0\n"},{"id":"21747","messageId":"448F1E61.9080509@etek.chalmers.se","threadId":"4501","inReplyTo":"448EF791.7070504@etek.chalmers.se","subject":"[PATCH 4/8] Make git-stripspace a builtin","fromName":"Lukas Sandström","fromEmail":"lukass@etek.chalmers.se","sentAt":"2006-06-13T20:21:53Z","receivedAt":"2006-06-13T20:21:53Z","isPatch":true,"sender":{"key":"luksan@gmail.com","avatar":"https://avatars.githubusercontent.com/u/152281?v=4"},"body":"Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n---\n Makefile                             |    6 +++---\n stripspace.c => builtin-stripspace.c |   16 +++++++++++-----\n builtin.h                            |    6 ++++--\n git.c                                |    3 ++-\n 4 files changed, 20 insertions(+), 11 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex e64d943..181255f 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -144,7 +144,7 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)\n \n # The ones that do not have to link with lcrypto, lz nor xdiff.\n SIMPLE_PROGRAMS = \\\n-\tgit-stripspace$X git-daemon$X\n+\tgit-daemon$X\n \n # ... and all the rest that could be moved out of bindir to gitexecdir\n PROGRAMS = \\\n@@ -165,7 +165,7 @@ PROGRAMS = \\\n \n BUILT_INS = git-log$X git-whatchanged$X git-show$X \\\n \tgit-count-objects$X git-diff$X git-push$X git-mailsplit$X \\\n-\tgit-grep$X git-add$X git-rm$X git-rev-list$X \\\n+\tgit-grep$X git-add$X git-rm$X git-rev-list$X git-stripspace$X \\\n \tgit-check-ref-format$X git-rev-parse$X git-mailinfo$X \\\n \tgit-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \\\n \tgit-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \\\n@@ -226,7 +226,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-read-tree.o builtin-commit-tree.o builtin-mailinfo.o \\\n \tbuiltin-apply.o builtin-show-branch.o builtin-diff-files.o \\\n \tbuiltin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \\\n-\tbuiltin-cat-file.o builtin-mailsplit.o\n+\tbuiltin-cat-file.o builtin-mailsplit.o builtin-stripspace.o\n \n GITLIBS = $(LIB_FILE) $(XDIFF_LIB)\n LIBS = $(GITLIBS) -lz\ndiff --git a/stripspace.c b/builtin-stripspace.c\nsimilarity index 76%\nrename from stripspace.c\nrename to builtin-stripspace.c\nindex 65a6346..2ce1264 100644\n--- a/stripspace.c\n+++ b/builtin-stripspace.c\n@@ -1,6 +1,7 @@\n #include <stdio.h>\n #include <string.h>\n #include <ctype.h>\n+#include \"builtin.h\"\n \n /*\n  * Remove empty lines from the beginning and end.\n@@ -28,21 +29,21 @@ static int cleanup(char *line)\n \treturn 1;\n }\n \n-int main(int argc, char **argv)\n+void stripspace(FILE *in, FILE *out)\n {\n \tint empties = -1;\n \tint incomplete = 0;\n \tchar line[1024];\n \n-\twhile (fgets(line, sizeof(line), stdin)) {\n+\twhile (fgets(line, sizeof(line), in)) {\n \t\tincomplete = cleanup(line);\n \n \t\t/* Not just an empty line? */\n \t\tif (line[0] != '\\n') {\n \t\t\tif (empties > 0)\n-\t\t\t\tputchar('\\n');\n+\t\t\t\tfputc('\\n', out);\n \t\t\tempties = 0;\n-\t\t\tfputs(line, stdout);\n+\t\t\tfputs(line, out);\n \t\t\tcontinue;\n \t\t}\n \t\tif (empties < 0)\n@@ -50,6 +51,11 @@ int main(int argc, char **argv)\n \t\tempties++;\n \t}\n \tif (incomplete)\n-\t\tputchar('\\n');\n+\t\tfputc('\\n', out);\n+}\n+\n+int cmd_stripspace(int argc, const char **argv, char **envp)\n+{\n+\tstripspace(stdin, stdout);\n \treturn 0;\n }\ndiff --git a/builtin.h b/builtin.h\nindex 979e0cd..c934d7a 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -55,6 +55,8 @@ extern int cmd_mailsplit(int argc, const\n extern int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip);\n \n extern int cmd_mailinfo(int argc, const char **argv, char **envp);\n-extern int mailinfo(FILE *in, FILE *out, int ks, char *encoding,\n-\t\t    const char *msg, const char *patch);\n+extern int mailinfo(FILE *in, FILE *out, int ks, char *encoding, const char *msg, const char *patch);\n+\n+extern int cmd_stripspace(int argc, const char **argv, char **envp);\n+extern void stripspace(FILE *in, FILE *out);\n #endif\ndiff --git a/git.c b/git.c\nindex 1e216de..31196f5 100644\n--- a/git.c\n+++ b/git.c\n@@ -181,7 +181,8 @@ static void handle_internal_command(int \n \t\t{ \"rev-parse\", cmd_rev_parse },\n \t\t{ \"write-tree\", cmd_write_tree },\n \t\t{ \"mailsplit\", cmd_mailsplit },\n-\t\t{ \"mailinfo\", cmd_mailinfo }\n+\t\t{ \"mailinfo\", cmd_mailinfo },\n+\t\t{ \"stripspace\", cmd_stripspace }\n \t};\n \tint i;\n \n-- \n1.4.0\n"},{"id":"21750","messageId":"448F1E65.7020909@etek.chalmers.se","threadId":"4501","inReplyTo":"448EF791.7070504@etek.chalmers.se","subject":"[PATCH 5/8] Make git-update-index a builtin","fromName":"Lukas Sandström","fromEmail":"lukass@etek.chalmers.se","sentAt":"2006-06-13T20:21:57Z","receivedAt":"2006-06-13T20:21:57Z","isPatch":true,"sender":{"key":"luksan@gmail.com","avatar":"https://avatars.githubusercontent.com/u/152281?v=4"},"body":"Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n---\n Makefile                                 |    6 +++---\n update-index.c => builtin-update-index.c |   19 ++++++++++++-------\n builtin.h                                |    1 +\n git.c                                    |    3 ++-\n 4 files changed, 18 insertions(+), 11 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 181255f..906fc0f 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -157,7 +157,7 @@ PROGRAMS = \\\n \tgit-send-pack$X git-shell$X \\\n \tgit-show-index$X git-ssh-fetch$X \\\n \tgit-ssh-upload$X git-unpack-file$X \\\n-\tgit-unpack-objects$X git-update-index$X git-update-server-info$X \\\n+\tgit-unpack-objects$X git-update-server-info$X \\\n \tgit-upload-pack$X git-verify-pack$X \\\n \tgit-update-ref$X git-symbolic-ref$X \\\n \tgit-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \\\n@@ -170,7 +170,7 @@ BUILT_INS = git-log$X git-whatchanged$X \n \tgit-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \\\n \tgit-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \\\n \tgit-read-tree$X git-commit-tree$X git-write-tree$X \\\n-\tgit-apply$X git-show-branch$X git-diff-files$X \\\n+\tgit-apply$X git-show-branch$X git-diff-files$X git-update-index$X \\\n \tgit-diff-index$X git-diff-stages$X git-diff-tree$X git-cat-file$X\n \n # what 'all' will build and 'install' will install, in gitexecdir\n@@ -221,7 +221,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \\\n \tbuiltin-grep.o builtin-add.o builtin-rev-list.o builtin-check-ref-format.o \\\n \tbuiltin-rm.o builtin-init-db.o builtin-rev-parse.o \\\n-\tbuiltin-tar-tree.o builtin-upload-tar.o \\\n+\tbuiltin-tar-tree.o builtin-upload-tar.o builtin-update-index.o \\\n \tbuiltin-ls-files.o builtin-ls-tree.o builtin-write-tree.o \\\n \tbuiltin-read-tree.o builtin-commit-tree.o builtin-mailinfo.o \\\n \tbuiltin-apply.o builtin-show-branch.o builtin-diff-files.o \\\ndiff --git a/update-index.c b/builtin-update-index.c\nsimilarity index 97%\nrename from update-index.c\nrename to builtin-update-index.c\nindex fbccc4a..325cd09 100644\n--- a/update-index.c\n+++ b/builtin-update-index.c\n@@ -8,6 +8,7 @@ #include \"strbuf.h\"\n #include \"quote.h\"\n #include \"cache-tree.h\"\n #include \"tree-walk.h\"\n+#include \"builtin.h\"\n \n /*\n  * Default to not allowing changes to the list of files. The\n@@ -186,8 +187,6 @@ static void chmod_path(int flip, const c\n \tdie(\"git-update-index: cannot chmod %cx '%s'\", flip, path);\n }\n \n-static struct lock_file lock_file;\n-\n static void update_one(const char *path, const char *prefix, int prefix_length)\n {\n \tconst char *p = prefix_path(prefix, prefix_length, path);\n@@ -238,7 +237,7 @@ static void read_index_info(int line_ter\n \t\t * (2) mode SP type SP sha1          TAB path\n \t\t * The second format is to stuff git-ls-tree output\n \t\t * into the index file.\n-\t\t * \n+\t\t *\n \t\t * (3) mode         SP sha1 SP stage TAB path\n \t\t * This format is to put higher order stages into the\n \t\t * index file and matches git-ls-files --stage output.\n@@ -477,7 +476,7 @@ static int do_reupdate(int ac, const cha\n \treturn 0;\n }\n \n-int main(int argc, const char **argv)\n+int cmd_update_index(int argc, const char **argv, char **envp)\n {\n \tint i, newfd, entries, has_errors = 0, line_termination = '\\n';\n \tint allow_options = 1;\n@@ -486,12 +485,16 @@ int main(int argc, const char **argv)\n \tint prefix_length = prefix ? strlen(prefix) : 0;\n \tchar set_executable_bit = 0;\n \tunsigned int refresh_flags = 0;\n+\tstruct lock_file *lock_file;\n \n \tgit_config(git_default_config);\n \n-\tnewfd = hold_lock_file_for_update(&lock_file, get_index_file());\n+\t/* We can't free this memory, it becomes part of a linked list parsed atexit() */\n+\tlock_file = xmalloc(sizeof(struct lock_file));\n+\n+\tnewfd = hold_lock_file_for_update(lock_file, get_index_file());\n \tif (newfd < 0)\n-\t\tdie(\"unable to create new index file\");\n+\t\tdie(\"unable to create new cachefile\");\n \n \tentries = read_cache();\n \tif (entries < 0)\n@@ -645,9 +648,11 @@ int main(int argc, const char **argv)\n  finish:\n \tif (active_cache_changed) {\n \t\tif (write_cache(newfd, active_cache, active_nr) ||\n-\t\t    commit_lock_file(&lock_file))\n+\t\t    commit_lock_file(lock_file))\n \t\t\tdie(\"Unable to write new index file\");\n \t}\n \n+\trollback_lock_file(lock_file);\n+\n \treturn has_errors ? 1 : 0;\n }\ndiff --git a/builtin.h b/builtin.h\nindex c934d7a..9ee5ea6 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -47,6 +47,7 @@ extern int cmd_diff_stages(int argc, con\n extern int cmd_diff_tree(int argc, const char **argv, char **envp);\n extern int cmd_cat_file(int argc, const char **argv, char **envp);\n extern int cmd_rev_parse(int argc, const char **argv, char **envp);\n+extern int cmd_update_index(int argc, const char **argv, char **envp);\n \n extern int cmd_write_tree(int argc, const char **argv, char **envp);\n extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);\ndiff --git a/git.c b/git.c\nindex 31196f5..4a931fb 100644\n--- a/git.c\n+++ b/git.c\n@@ -182,7 +182,8 @@ static void handle_internal_command(int \n \t\t{ \"write-tree\", cmd_write_tree },\n \t\t{ \"mailsplit\", cmd_mailsplit },\n \t\t{ \"mailinfo\", cmd_mailinfo },\n-\t\t{ \"stripspace\", cmd_stripspace }\n+\t\t{ \"stripspace\", cmd_stripspace },\n+\t\t{ \"update-index\", cmd_update_index }\n \t};\n \tint i;\n \n-- \n1.4.0\n"},{"id":"21749","messageId":"448F1E68.5090504@etek.chalmers.se","threadId":"4501","inReplyTo":"448EF791.7070504@etek.chalmers.se","subject":"[PATCH 6/8] Make git-update-ref a builtin","fromName":"Lukas Sandström","fromEmail":"lukass@etek.chalmers.se","sentAt":"2006-06-13T20:22:00Z","receivedAt":"2006-06-13T20:22:00Z","isPatch":true,"sender":{"key":"luksan@gmail.com","avatar":"https://avatars.githubusercontent.com/u/152281?v=4"},"body":"Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n---\n Makefile                             |    7 ++++---\n update-ref.c => builtin-update-ref.c |    5 ++++-\n builtin.h                            |    1 +\n git.c                                |    3 ++-\n 4 files changed, 11 insertions(+), 5 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 906fc0f..4b30ca0 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -159,11 +159,11 @@ PROGRAMS = \\\n \tgit-ssh-upload$X git-unpack-file$X \\\n \tgit-unpack-objects$X git-update-server-info$X \\\n \tgit-upload-pack$X git-verify-pack$X \\\n-\tgit-update-ref$X git-symbolic-ref$X \\\n+\tgit-symbolic-ref$X \\\n \tgit-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \\\n \tgit-describe$X git-merge-tree$X git-blame$X git-imap-send$X\n \n-BUILT_INS = git-log$X git-whatchanged$X git-show$X \\\n+BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$X \\\n \tgit-count-objects$X git-diff$X git-push$X git-mailsplit$X \\\n \tgit-grep$X git-add$X git-rm$X git-rev-list$X git-stripspace$X \\\n \tgit-check-ref-format$X git-rev-parse$X git-mailinfo$X \\\n@@ -226,7 +226,8 @@ BUILTIN_OBJS = \\\n \tbuiltin-read-tree.o builtin-commit-tree.o builtin-mailinfo.o \\\n \tbuiltin-apply.o builtin-show-branch.o builtin-diff-files.o \\\n \tbuiltin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \\\n-\tbuiltin-cat-file.o builtin-mailsplit.o builtin-stripspace.o\n+\tbuiltin-cat-file.o builtin-mailsplit.o builtin-stripspace.o \\\n+\tbuiltin-update-ref.o\n \n GITLIBS = $(LIB_FILE) $(XDIFF_LIB)\n LIBS = $(GITLIBS) -lz\ndiff --git a/update-ref.c b/builtin-update-ref.c\nsimilarity index 89%\nrename from update-ref.c\nrename to builtin-update-ref.c\nindex a1e6bb9..00333c7 100644\n--- a/update-ref.c\n+++ b/builtin-update-ref.c\n@@ -1,10 +1,11 @@\n #include \"cache.h\"\n #include \"refs.h\"\n+#include \"builtin.h\"\n \n static const char git_update_ref_usage[] =\n \"git-update-ref <refname> <value> [<oldval>] [-m <reason>]\";\n \n-int main(int argc, char **argv)\n+int cmd_update_ref(int argc, const char **argv, char **envp)\n {\n \tconst char *refname=NULL, *value=NULL, *oldval=NULL, *msg=NULL;\n \tstruct ref_lock *lock;\n@@ -52,5 +53,7 @@ int main(int argc, char **argv)\n \t\treturn 1;\n \tif (write_ref_sha1(lock, sha1, msg) < 0)\n \t\treturn 1;\n+\n+\t/* write_ref_sha1 always unlocks the ref, no need to do it explicitly */\n \treturn 0;\n }\ndiff --git a/builtin.h b/builtin.h\nindex 9ee5ea6..c1f3395 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -48,6 +48,7 @@ extern int cmd_diff_tree(int argc, const\n extern int cmd_cat_file(int argc, const char **argv, char **envp);\n extern int cmd_rev_parse(int argc, const char **argv, char **envp);\n extern int cmd_update_index(int argc, const char **argv, char **envp);\n+extern int cmd_update_ref(int argc, const char **argv, char **envp);\n \n extern int cmd_write_tree(int argc, const char **argv, char **envp);\n extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);\ndiff --git a/git.c b/git.c\nindex 4a931fb..652e3c4 100644\n--- a/git.c\n+++ b/git.c\n@@ -183,7 +183,8 @@ static void handle_internal_command(int \n \t\t{ \"mailsplit\", cmd_mailsplit },\n \t\t{ \"mailinfo\", cmd_mailinfo },\n \t\t{ \"stripspace\", cmd_stripspace },\n-\t\t{ \"update-index\", cmd_update_index }\n+\t\t{ \"update-index\", cmd_update_index },\n+\t\t{ \"update-ref\", cmd_update_ref }\n \t};\n \tint i;\n \n-- \n1.4.0\n"},{"id":"21748","messageId":"448F1E6B.6050507@etek.chalmers.se","threadId":"4501","inReplyTo":"448EF791.7070504@etek.chalmers.se","subject":"[PATCH 7/8] Make it possible to call cmd_apply multiple times","fromName":"Lukas Sandström","fromEmail":"lukass@etek.chalmers.se","sentAt":"2006-06-13T20:22:03Z","receivedAt":"2006-06-13T20:22:03Z","isPatch":true,"sender":{"key":"luksan@gmail.com","avatar":"https://avatars.githubusercontent.com/u/152281?v=4"},"body":"* xmalloc a new struct lock_file each invocation.\n* Don't die() if the patch doesn't apply.\n* Initialize the global variables each invocation.\n* Roll back the lock_file.\n\nSigned-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n---\n builtin-apply.c |   94 +++++++++++++++++++++++++++++++++++--------------------\n 1 files changed, 60 insertions(+), 34 deletions(-)\n\ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex e113c74..a76c553 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -22,24 +22,13 @@ #include \"builtin.h\"\n //  --index updates the cache as well.\n //  --cached updates only the cache without ever touching the working tree.\n //\n-static const char *prefix;\n-static int prefix_length = -1;\n-static int newfd = -1;\n-\n-static int p_value = 1;\n-static int allow_binary_replacement = 0;\n-static int check_index = 0;\n-static int write_index = 0;\n-static int cached = 0;\n-static int diffstat = 0;\n-static int numstat = 0;\n-static int summary = 0;\n-static int check = 0;\n-static int apply = 1;\n-static int no_add = 0;\n-static int show_index_info = 0;\n-static int line_termination = '\\n';\n+static const char *prefix, *patch_input_file;\n+static int prefix_length, newfd, p_value, allow_binary_replacement, check_index,\n+\twrite_index, cached, diffstat, numstat, summary, check, apply, no_add,\n+\tshow_index_info, line_termination, whitespace_error, squelch_whitespace_errors,\n+\tapplied_after_stripping;\n static unsigned long p_context = -1;\n+\n static const char apply_usage[] =\n \"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>...\";\n \n@@ -49,10 +38,31 @@ static enum whitespace_eol {\n \terror_on_whitespace,\n \tstrip_whitespace,\n } new_whitespace = warn_on_whitespace;\n-static int whitespace_error = 0;\n-static int squelch_whitespace_errors = 5;\n-static int applied_after_stripping = 0;\n-static const char *patch_input_file = NULL;\n+\n+static void setup_state()\n+{\n+\tprefix = NULL;\n+\tprefix_length = -1;\n+\tnewfd = -1;\n+\tp_value = 1;\n+\tallow_binary_replacement = 0;\n+\tcheck_index = 0;\n+\twrite_index = 0;\n+\tcached = 0;\n+\tdiffstat = 0;\n+\tnumstat = 0;\n+\tsummary = 0;\n+\tcheck = 0;\n+\tapply = 1;\n+\tno_add = 0;\n+\tshow_index_info = 0;\n+\tline_termination = '\\n';\n+\tp_context = -1;\n+\twhitespace_error = 0;\n+\tsquelch_whitespace_errors = 5;\n+\tapplied_after_stripping = 0;\n+\tpatch_input_file = NULL;\n+}\n \n static void parse_whitespace_option(const char *option)\n {\n@@ -2072,7 +2082,7 @@ static void write_out_results(struct pat\n \t}\n }\n \n-static struct lock_file lock_file;\n+static struct lock_file *lock_file;\n \n static struct excludes {\n \tstruct excludes *next;\n@@ -2106,7 +2116,7 @@ static int apply_patch(int fd, const cha\n \n \tpatch_input_file = filename;\n \tif (!buffer)\n-\t\treturn -1;\n+\t\treturn -2;\n \toffset = 0;\n \twhile (size > 0) {\n \t\tstruct patch *patch;\n@@ -2134,7 +2144,7 @@ static int apply_patch(int fd, const cha\n \n \twrite_index = check_index && apply;\n \tif (write_index && newfd < 0) {\n-\t\tnewfd = hold_lock_file_for_update(&lock_file,\n+\t\tnewfd = hold_lock_file_for_update(lock_file,\n \t\t\t\t\t\t  get_index_file());\n \t\tif (newfd < 0)\n \t\t\tdie(\"unable to create new index file\");\n@@ -2145,7 +2155,7 @@ static int apply_patch(int fd, const cha\n \t}\n \n \tif ((check || apply) && check_patch_list(list) < 0)\n-\t\texit(1);\n+\t\treturn -1;\n \n \tif (apply)\n \t\twrite_out_results(list, skipped_patch);\n@@ -2175,20 +2185,27 @@ static int git_apply_config(const char *\n \treturn git_default_config(var, value);\n }\n \n-\n int cmd_apply(int argc, const char **argv, char **envp)\n {\n-\tint i;\n+\tint i, ret = 0;\n \tint read_stdin = 1;\n \tconst char *whitespace_option = NULL;\n \n+\tsetup_state();\n+\n+\t/* This memory can't be free()'d since it's needed atexit() */\n+\tlock_file = xmalloc(sizeof(struct lock_file));\n+\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n \t\tchar *end;\n-\t\tint fd;\n+\t\tint fd, apply_status;\n \n \t\tif (!strcmp(arg, \"-\")) {\n-\t\t\tapply_patch(0, \"<stdin>\");\n+\t\t\tif (apply_patch(0, \"<stdin>\")) {\n+\t\t\t\tret = 1;\n+\t\t\t\tgoto err;\n+\t\t\t}\n \t\t\tread_stdin = 0;\n \t\t\tcontinue;\n \t\t}\n@@ -2281,12 +2298,18 @@ int cmd_apply(int argc, const char **arg\n \t\t\tusage(apply_usage);\n \t\tread_stdin = 0;\n \t\tset_default_whitespace_mode(whitespace_option);\n-\t\tapply_patch(fd, arg);\n+\t\tapply_status = apply_patch(fd, arg);\n \t\tclose(fd);\n+\t\tif (apply_status) {\n+\t\t\tret = 1;\n+\t\t\tgoto err;\n+\t\t}\n \t}\n \tset_default_whitespace_mode(whitespace_option);\n-\tif (read_stdin)\n-\t\tapply_patch(0, \"<stdin>\");\n+\tif (read_stdin && apply_patch(0, \"<stdin>\")) {\n+\t\tret = 1;\n+\t\tgoto err;\n+\t}\n \tif (whitespace_error) {\n \t\tif (squelch_whitespace_errors &&\n \t\t    squelch_whitespace_errors < whitespace_error) {\n@@ -2316,9 +2339,12 @@ int cmd_apply(int argc, const char **arg\n \n \tif (write_index) {\n \t\tif (write_cache(newfd, active_cache, active_nr) ||\n-\t\t    commit_lock_file(&lock_file))\n+\t\t    commit_lock_file(lock_file))\n \t\t\tdie(\"Unable to write new index file\");\n \t}\n \n-\treturn 0;\n+err:\n+\trollback_lock_file(lock_file);\n+\n+\treturn ret;\n }\n-- \n1.4.0\n"},{"id":"21751","messageId":"448F1E6E.8000003@etek.chalmers.se","threadId":"4501","inReplyTo":"448EF791.7070504@etek.chalmers.se","subject":"[PATCH/RFC 8/8] Make git-am a builtin","fromName":"Lukas Sandström","fromEmail":"lukass@etek.chalmers.se","sentAt":"2006-06-13T20:22:06Z","receivedAt":"2006-06-13T20:22:06Z","isPatch":true,"sender":{"key":"luksan@gmail.com","avatar":"https://avatars.githubusercontent.com/u/152281?v=4"},"body":"Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n---\n\nBeing able to switch index-file on the fly would reduce the number of\nsystem() calls.\nA way to check if the index/working dir is dirty would also help.\n\n Makefile     |    6 -\n builtin-am.c |  664 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n builtin.h    |    1 \n git-am.sh    |  427 -------------------------------------\n git.c        |    3 \n 5 files changed, 670 insertions(+), 431 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 4b30ca0..e9b372e 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -122,7 +122,7 @@ SCRIPT_SH = \\\n \tgit-repack.sh git-request-pull.sh git-reset.sh \\\n \tgit-resolve.sh git-revert.sh git-sh-setup.sh \\\n \tgit-tag.sh git-verify-tag.sh \\\n-\tgit-applymbox.sh git-applypatch.sh git-am.sh \\\n+\tgit-applymbox.sh git-applypatch.sh \\\n \tgit-merge.sh git-merge-stupid.sh git-merge-octopus.sh \\\n \tgit-merge-resolve.sh git-merge-ours.sh \\\n \tgit-lost-found.sh git-quiltimport.sh\n@@ -166,7 +166,7 @@ PROGRAMS = \\\n BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$X \\\n \tgit-count-objects$X git-diff$X git-push$X git-mailsplit$X \\\n \tgit-grep$X git-add$X git-rm$X git-rev-list$X git-stripspace$X \\\n-\tgit-check-ref-format$X git-rev-parse$X git-mailinfo$X \\\n+\tgit-check-ref-format$X git-rev-parse$X git-mailinfo$X git-am$X \\\n \tgit-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \\\n \tgit-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \\\n \tgit-read-tree$X git-commit-tree$X git-write-tree$X \\\n@@ -220,7 +220,7 @@ LIB_OBJS = \\\n BUILTIN_OBJS = \\\n \tbuiltin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \\\n \tbuiltin-grep.o builtin-add.o builtin-rev-list.o builtin-check-ref-format.o \\\n-\tbuiltin-rm.o builtin-init-db.o builtin-rev-parse.o \\\n+\tbuiltin-rm.o builtin-init-db.o builtin-rev-parse.o builtin-am.o \\\n \tbuiltin-tar-tree.o builtin-upload-tar.o builtin-update-index.o \\\n \tbuiltin-ls-files.o builtin-ls-tree.o builtin-write-tree.o \\\n \tbuiltin-read-tree.o builtin-commit-tree.o builtin-mailinfo.o \\\ndiff --git a/builtin-am.c b/builtin-am.c\nnew file mode 100644\nindex 0000000..d9e7ac5\n--- /dev/null\n+++ b/builtin-am.c\n@@ -0,0 +1,664 @@\n+/*\n+ * GIT - The information manager from hell\n+ *\n+ * Copyright (C) Lukas Sandström, 2006\n+ */\n+\n+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <unistd.h>\n+#include <errno.h>\n+#include <dirent.h>\n+#include <string.h>\n+#include <stdio.h>\n+#include <stdarg.h>\n+#include <sys/wait.h>\n+\n+#include \"git-compat-util.h\"\n+#include \"cache.h\"\n+#include \"builtin.h\"\n+\n+static char builtin_am_usage[] = \"[--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way] \"\n+\t\t\t\t \"[--interactive] [--whitespace=<option>] <mbox>...\\n\"\n+\t\t\t\t \"or, when resuming [--skip | --resolved]\";\n+\n+static int binary, interactive, threeway, signoff, utf8, keep_subject, resolved, skip, resume;\n+static char whitespace[40] = \"--whitespace=warn\", **env;\n+static const char **mbox, *dotest, *resolvmsg;\n+\n+#define PATCH_PREC 4\n+\n+#define AGAIN 0\n+#define SKIP 1\n+#define YES 2\n+\n+//ugly hack to be able to change the index file\n+extern char *git_index_file;\n+\n+static int rm_rf(const char* path)\n+{\n+\tchar cmd[PATH_MAX + 10];\n+\tsnprintf(cmd, sizeof(cmd), \"rm -rf %s\", path);\n+\treturn system(cmd);\n+}\n+\n+static int mkdir_p(const char *path)\n+{\n+\tchar p[PATH_MAX], n, *l;\n+\n+\tstrcpy(p, path);\n+\twhile ((l = strchr(p, '/'))) {\n+\t\tn = *l;\n+\t\t*l = '\\0';\n+\t\tif (access(p, F_OK) && mkdir(p, 0777))\n+\t\t\treturn -1;\n+\t\t*l = n;\n+\t}\n+\treturn mkdir(p, 0777);\n+}\n+\n+static int fcat(char *file, char *fmt, ...)\n+{\n+\tva_list args;\n+\tint ret;\n+\tFILE *f;\n+\n+\tfile = mkpath(\"%s/%s\", dotest, file);\n+\tif ((f = fopen(file, \"r\")) == NULL) {\n+\t\tperror(file);\n+\t\tdie(\"Couldn't open file %s\", file);\n+\t}\n+\tva_start(args, fmt);\n+\tret = vfscanf(f, fmt, args);\n+\tva_end(args);\n+\tfclose(f);\n+\treturn ret;\n+}\n+\n+static int fecho(char *file, char *fmt, ...)\n+{\n+\tva_list args;\n+\tint ret;\n+\tFILE *f;\n+\n+\tfile = mkpath(\"%s/%s\", dotest, file);\n+\tif ((f = fopen(file, \"w\")) == NULL) {\n+\t\tperror(file);\n+\t\tdie(\"Couldn't open file %s/%s\", dotest, file);\n+\t}\n+\tva_start(args, fmt);\n+\tret = vfprintf(f, fmt, args);\n+\tva_end(args);\n+\tfclose(f);\n+\treturn ret;\n+}\n+\n+static FILE* get_output(char *cmd, int *status)\n+{\n+\tchar c[2000];\n+\tFILE *ret;\n+\tint s;\n+\n+\tsnprintf(c, sizeof(c), \"%s > \\\"%s/outtmp\\\"\", cmd, dotest);\n+\ts = system(c);\n+\tif (status)\n+\t\t*status = s;\n+\tif ((ret = fopen(mkpath(\"%s/outtmp\", dotest), \"r\")) == NULL)\n+\t\tdie(\"cmd: %s\\nOpen \\\"%s\\\" failed.\", c, mkpath(\"%s/outtmp\", dotest));\n+\tunlink(mkpath(\"%s/outtmp\", dotest));\n+\treturn ret;\n+}\n+\n+static int has_zero_output(char *cmd)\n+{\n+\tstruct stat s;\n+\n+\tsystem(mkpath(\"%s > %s/zerotmp\", cmd, dotest));\n+\tstat(mkpath(\"%s/zerotmp\", dotest), &s);\n+\tunlink(mkpath(\"%s/zerotmp\", dotest));\n+\treturn s.st_size == 0;\n+}\n+\n+static int go_next(int this) {\n+\tunlink(mkpath(\"%s/%0*d\", dotest, PATCH_PREC, this));\n+\tunlink(mkpath(\"%s/msg\", dotest));\n+\tunlink(mkpath(\"%s/msg-clean\", dotest));\n+\tunlink(mkpath(\"%s/patch\", dotest));\n+\tunlink(mkpath(\"%s/info\", dotest));\n+\tfecho(\"next\", \"%d\", this + 1);\n+\treturn this + 1;\n+}\n+\n+static void stop_here(int this)\n+{\n+\tfecho(\"next\",\"%d\\n\", this);\n+\texit(1);\n+}\n+\n+static void stop_here_user_resolve(int this)\n+{\n+\tchar cmdline[1000] = \"git am\";\n+\tint pos = 6; /* \"git am\" */\n+\n+\tif (resolvmsg != NULL) {\n+\t\tprintf(\"%s\", resolvmsg);\n+\t\tstop_here(this);\n+\t}\n+\n+\tif (interactive)\n+\t\tpos += sprintf(cmdline + pos, \" -i\");\n+\tif (threeway)\n+\t\tpos += sprintf(cmdline + pos, \" -3\");\n+\tif (strcmp(\".dotest\", dotest))\n+\t\tpos += sprintf(cmdline + pos, \" -d=%s\", dotest);\n+\n+\tprintf(\"When you have resolved this problem run \\\"git am %s --resolved\\\".\\n\", cmdline);\n+\tprintf(\"If you would prefer to skip this patch, instead run \\\"%s --skip\\\".\\n\", cmdline);\n+\n+\tstop_here(this);\n+}\n+\n+static int fall_back_3way()\n+{\n+\tchar cmd[1000];\n+\tchar tmp_index[PATH_MAX], old_index[PATH_MAX] = \"\";\n+\tint ret = -1;\n+\n+\tsnprintf(cmd, sizeof(cmd), \"git-apply -z --index-info \\\"%s/patch\\\"\"\n+\t\t\t\" > %s/patch-merge-index-info 2> /dev/null\", dotest, dotest);\n+\tif (!system(cmd)) {\n+\t\tsnprintf(tmp_index, sizeof(tmp_index),\"%s/patch-merge-tmp-index\", dotest);\n+\t\tif (getenv(INDEX_ENVIRONMENT))\n+\t\t\tstrcpy(old_index, getenv(INDEX_ENVIRONMENT));\n+\t\tsetenv(INDEX_ENVIRONMENT, tmp_index, 1);\n+\n+\t\tsnprintf(cmd, sizeof(cmd), \"git-update-index -z --index-info <\\\"%s/patch-merge-index-info\\\"\", dotest);\n+\t\tif (!system(cmd)) {\n+#if 1\n+\t\t\tsystem(mkpath(\"git-write-tree > \\\"%s/patch-merge-base\\\"\", dotest));\n+\t\t\tsnprintf(cmd, sizeof(cmd), \"git-apply %s --cached < \\\"%s/patch\\\"\", binary ? \"--allow-binary-replacement\":\"\", dotest);\n+\t\t\tif (!system(cmd)) {\n+\t\t\t\tchar his_tree[41], orig_tree[41];\n+\t\t\t\tprintf(\"Using index info to reconstruct a base tree...\\n\");\n+\t\t\t\tsystem(mkpath(\"git-write-tree > \\\"%s/his-tree\\\"\", dotest));\n+\t\t\t\tfcat(\"his-tree\", \"%40s\", his_tree);\n+\t\t\t\tfcat(\"patch-merge-base\", \"%40s\", orig_tree);\n+\n+\t\t\t\tprintf(\"Falling back to patching base and 3-way merge...\\n\");\n+\n+\t\t\t\tif (*old_index)\n+\t\t\t\t\tsetenv(INDEX_ENVIRONMENT, old_index, 1);\n+\t\t\t\telse\n+\t\t\t\t\tunsetenv(INDEX_ENVIRONMENT);\n+\t\t\t\tif (!system(mkpath(\"git-merge-resolve %s -- HEAD %s\", orig_tree, his_tree)))\n+\t\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t}\n+#else\n+\t\t\tunsigned char orig_tree[20], his_tree[20];\n+\n+\t\t\t// We need a way to switch the index file on the fly for this to work\n+\n+\t\t\tchar *opts[] = { \"git-apply\", \"--allow-binary-replacement\", \"--cached\", NULL, NULL };\n+\t\t\tchar **opt = &opts[0];\n+\t\t\tchar patch[PATH_MAX];\n+\t\t\tint optc = ARRAY_SIZE(opts) - 1;\n+\n+\t\t\topts[optc - 1] = strncpy(patch, mkpath(\"%s/patch\", dotest), sizeof(patch));\n+\t\t\tif (!binary) {\n+\t\t\t\topts[1] = \"git-apply\";\n+\t\t\t\topt++; optc--;\n+\t\t\t}\n+\t\t\twrite_tree(orig_tree, 0, NULL);\n+\t\t\tif (!cmd_apply(optc, (const char**)opt, env)) {\n+\t\t\t\tprintf(\"Using index info to reconstruct a base tree...\\n\");\n+\t\t\t\twrite_tree(his_tree, 0, NULL);\n+\n+\t\t\t\tsnprintf(cmd, sizeof(cmd), \"git-merge-resolve %s -- HEAD %s\", sha1_to_hex(orig_tree),\n+\t\t\t\t\t sha1_to_hex(his_tree));\n+\t\t\t\tret = system(cmd);\n+\t\t\t}\n+\t\t}\n+\t\tif (*old_index)\n+\t\t\tsetenv(INDEX_ENVIRONMENT, old_index, 1);\n+\t\telse\n+\t\t\tunsetenv(INDEX_ENVIRONMENT);\n+#endif\n+\t\tif (!ret)\n+\t\t\treturn 0;\n+\t}\n+\tif (!access(mkpath(\"%s/rr-cache/.\", get_git_dir()), F_OK))\n+\t\tsystem(\"git-rerere\");\n+\tdie(\"Failed to merge in the changes.\");\n+}\n+\n+static int go_interactive(void)\n+{\n+\tint action = AGAIN;\n+\n+\tif (!isatty(0))\n+\t\tdie(\"Cannot be interactive without stdin connected to a terminal.\");\n+\n+\twhile (action == AGAIN) {\n+\t\tchar line[1000];\n+\t\tFILE *cmt;\n+\n+\t\tprintf(\"Commit Body is:\\n--------------------------\\n\");\n+\t\tcmt = fopen(mkpath(\"%s/final-commit\", dotest), \"r\");\n+\t\twhile (fgets(line, sizeof(line), cmt))\n+\t\t\tfputs(line, stdout);\n+\t\tfclose(cmt);\n+\t\tprintf(\"--------------------------\\nApply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all \");\n+\n+\t\tfgets(line, sizeof(line), stdin);\n+\t\tswitch (line[0]) {\n+\t\t\tcase 'y':\n+\t\t\tcase 'Y':\n+\t\t\t\taction = YES;\n+\t\t\t\tbreak;\n+\t\t\tcase 'a':\n+\t\t\tcase 'A':\n+\t\t\t\taction = YES;\n+\t\t\t\tinteractive = 0;\n+\t\t\t\tbreak;\n+\t\t\tcase 'n':\n+\t\t\tcase 'N':\n+\t\t\t\taction = SKIP;\n+\t\t\t\tbreak;\n+\t\t\tcase 'e':\n+\t\t\tcase 'E':\n+\t\t\t\tsystem(mkpath(\"\\\"${VISUAL:-${EDITOR:-vi}}\\\" \\\"%s/final-commit\\\"\", dotest));\n+\t\t\t\taction = AGAIN;\n+\t\t\t\tbreak;\n+\t\t\tcase 'v':\n+\t\t\tcase 'V':\n+\t\t\t\tsystem(mkpath(\"LESS=-S ${PAGER:-less} \\\"%s/patch\\\"\", dotest));\n+\t\t\t\taction = AGAIN;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\taction = AGAIN;\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn action;\n+}\n+\n+static int commit(char *subject)\n+{\n+\tunsigned char sha1[20];\n+\tchar commit[41], parent[41], cmd[1000];\n+\tFILE *f;\n+\tint status;\n+\n+\tif (!write_tree(sha1, 0, NULL)) {\n+\t\tprintf(\"Wrote tree %s\\n\", sha1_to_hex(sha1));\n+\t\tf = get_output(\"git-rev-parse --verify HEAD\", &status);\n+\t\tif (!status) {\n+\t\t\tfgets(parent, 41, f);\n+\t\t\tfclose(f);\n+\t\t\tsnprintf(cmd, sizeof(cmd), \"git-commit-tree %s -p %s <\\\"%s/final-commit\\\"\",\n+\t\t\t\t sha1_to_hex(sha1), parent, dotest);\n+\t\t\tf = get_output(cmd, &status);\n+\t\t\tif (!status) {\n+\t\t\t\t//git-update-ref -m \"am: $SUBJECT\" HEAD $commit $parent\n+\t\t\t\tchar *opts[] = { \"git-update-ref\", \"-m\", NULL, \"HEAD\", NULL, NULL, NULL };\n+\t\t\t\tconst char **opt = (const char**)&opts[0];\n+\t\t\t\tfgets(commit, 41, f);\n+\t\t\t\tfclose(f);\n+\t\t\t\tprintf(\"Committed: %s\\n\", commit);\n+\t\t\t\tsnprintf(cmd, sizeof(cmd), \"am: %s\", subject);\n+\t\t\t\topts[2] = cmd;\n+\t\t\t\topts[4] = commit;\n+\t\t\t\topts[5] = parent;\n+\t\t\t\tif (!cmd_update_ref(ARRAY_SIZE(opts) - 1, opt, env))\n+\t\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t}\n+\t}\n+\treturn -1;\n+}\n+\n+int cmd_am(int argc, const char **argv, char **envp)\n+{\n+\tint i, this, last, apply_status, action;\n+\tchar sign[1000] = \"\";\n+\n+\tenv = envp;\n+\n+\tfor (i = 1; i < argc; i++) {\n+\t\tconst char *arg = argv[i];\n+\n+\t\tif (arg[0] != '-')\n+\t\t\tbreak;\n+\t\tif (!strcmp(arg, \"--\")) {\n+\t\t\ti++;\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-i\") || !strcmp(arg, \"--interactive\")) {\n+\t\t\tinteractive = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-b\") || !strcmp(arg, \"--binary\")) {\n+\t\t\tbinary = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-3\") || !strcmp(arg, \"--3way\")) {\n+\t\t\tthreeway = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-s\") || !strcmp(arg, \"--signoff\")) {\n+\t\t\tsignoff = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"--skip\")) {\n+\t\t\tskip = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-u\") || !strcmp(arg, \"--utf8\")) {\n+\t\t\tutf8 = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-k\") || !strcmp(arg, \"--keep\")) {\n+\t\t\tkeep_subject = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-r\") || !strcmp(arg, \"--resolved\")) {\n+\t\t\tresolved = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strncmp(arg, \"--whitespace=\", 13)) {\n+\t\t\tstrncpy(whitespace, arg, sizeof(whitespace));\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strncmp(arg, \"--resolvemsg=\", 13)) {\n+\t\t\tresolvmsg = arg + 13;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strncmp(arg, \"--dotest\", 8)) {\n+\t\t\tif (arg[8] == '=')\n+\t\t\t\tdotest = arg + 9;\n+\t\t\telse {\n+\t\t\t\ti++;\n+\t\t\t\tif (argv[i] == NULL)\n+\t\t\t\t\tdie(builtin_am_usage);\n+\t\t\t\tdotest = argv[i];\n+\t\t\t}\n+\t\t\tcontinue;\n+\t\t}\n+\t\tusage(builtin_am_usage);\n+\t}\n+\tmbox = argv + i;\n+\n+\tif (!dotest)\n+\t\tdotest = \".dotest\";\n+\n+\t/* Cleanup old .dotest */\n+\tif (mbox && !access(dotest, F_OK))\n+\t\tif (fcat(\"next\", \"%d\", &this) && fcat(\"last\", \"%d\",  &last))\n+\t\t\tif (this > last)\n+\t\t\t\trm_rf(dotest);\n+\n+\tif (!access(dotest, F_OK)) {\n+\t\tif (mbox != NULL)\n+\t\t\tdie(\"previous dotest directory \\\"%s\\\" still exists but mbox given.\", dotest);\n+\t\tresume = 1;\n+\t} else {\n+\t\tif (skip || resolved)\n+\t\t\tdie(\"Resolve operation not in progress, we are not resuming.\");\n+\n+\t\tif (mkdir_p(dotest))\n+\t\t\tdie(\"Unable to create directory %s.\", dotest);\n+\n+\t\tif ((last = split_mbox(mbox, dotest, 1 /*allow bare*/, PATCH_PREC, 0 /*skip*/)) == -1) {\n+\t\t\trm_rf(dotest);\n+\t\t\tdie(\"split_mbox failed\");\n+\t\t}\n+\n+\t\t/*\n+\t\t  -b, -s, -u, -k and --whitespace flags are kept for the\n+\t\t  resuming session after a patch failure.\n+\t\t  -3 and -i can and must be given when resuming.\n+\t\t*/\n+\t\tfecho(\"binary\", \"%d\\n\", binary);\n+\t\tfecho(\"whitespace\", \"%s\\n\", whitespace);\n+\t\tfecho(\"sign\", \"%d\\n\", signoff);\n+\t\tfecho(\"utf8\", \"%d\\n\", utf8);\n+\t\tfecho(\"keep\", \"%d\\n\", keep_subject);\n+\t\tfecho(\"next\", \"%d\\n\", 1);\n+\t\tfecho(\"last\", \"%d\\n\", last);\n+\t}\n+\n+\tif (!resolved) {\n+\t\t/* Make sure we have a clean index */\n+\t\tchar buf[PATH_MAX];\n+\t\tint status = 0;\n+\t\tFILE *f;\n+\n+\t\tif ((f = get_output(\"git-diff-index --name-only HEAD\", &status)) == NULL || status)\n+\t\t\tdie(\"Command: \\\"git-diff-index --name-only HEAD\\\" failed\");\n+\n+\t\tif ((status = fgetc(f)) != EOF) {\n+\t\t\tungetc(status, f);\n+\t\t\tfprintf(stderr, \"Dirty index: cannot apply patches. Dirty files:\\n\");\n+\t\t\twhile (fgets(buf, sizeof(buf), f))\n+\t\t\t\tfprintf(stderr, \"%s\", buf);\n+\t\t\treturn 1;\n+\t\t}\n+\t\tfclose(f);\n+\t}\n+\n+\t/* Read back saved state */\n+\tfcat(\"binary\", \"%d\", &binary);\n+\tfcat(\"utf8\", \"%d\", &utf8);\n+\tfcat(\"keep\", \"%d\", &keep_subject);\n+\tfcat(\"whitespace\", \"%40[^\\n]\", whitespace);\n+\tfcat(\"sign\", \"%d\", &signoff);\n+\tfcat(\"last\", \"%d\", &last);\n+\tfcat(\"next\", \"%d\", &this);\n+\n+\tif (this > last) {\n+\t\tprintf(\"Nothing to do.\\n\");\n+\t\trm_rf(dotest);\n+\t\treturn 0;\n+\t}\n+\n+\tif (signoff) {\n+\t\tint off = snprintf(sign, sizeof(sign), \"Signed-off-by: %s <%s>\",\n+\t\t\t\t   getenv(\"GIT_COMMITTER_NAME\"), getenv(\"GIT_COMMITTER_EMAIL\"));\n+\t\tif (off > sizeof(sign))\n+\t\t\tdie (\"Impossibly long committer identifier\");\n+\t}\n+\n+\tif (skip) {\n+\t\tthis++;\n+\t\tresume = 0;\n+\t}\n+\n+\twhile (this <= last) {\n+\t\tchar patch_no[PATCH_PREC + 1];\n+\t\tchar name[1000];\n+\t\tchar email[1000];\n+\t\tchar date[1000];\n+\t\tchar s[1000] = \"[PATCH] \", *subject = &s[0];\n+\n+\t\tsnprintf(patch_no, sizeof(patch_no), \"%0*d\", PATCH_PREC, this);\n+\n+\t\tif (access(mkpath(\"%s/%s\", dotest, patch_no), F_OK)) {\n+\t\t\tresume = 0;\n+\t\t\tthis = go_next(this);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/*\n+\t\t  If we are not resuming, parse and extract the patch information\n+\t\t  into separate files:\n+\t\t  - info records the authorship and title\n+\t\t  - msg is the rest of commit log message\n+\t\t  - patch is the patch body.\n+\n+\t\t When we are resuming, these files are either already prepared\n+\t\t by the user, or the user can tell us to do so by --resolved flag.\n+\t\t*/\n+\t\tif (!resume) {\n+\t\t\tFILE *out, *in;\n+\t\t\tchar msg_path[PATH_MAX];\n+\n+\t\t\tif ((out = fopen(mkpath(\"%s/info\", dotest), \"w\")) == NULL) {\n+\t\t\t\tperror(mkpath(\"%s/info\", dotest));\n+\t\t\t\tdie(\"fopen failed\");\n+\t\t\t}\n+\t\t\tif ((in = fopen(mkpath(\"%s/%s\", dotest, patch_no), \"r\")) == NULL) {\n+\t\t\t\tperror(mkpath(\"%s/%s\", dotest, patch_no));\n+\t\t\t\tdie(\"fopen failed\");\n+\t\t\t}\n+\n+\t\t\tsnprintf(msg_path, sizeof(msg_path), \"%s/msg\", dotest);\n+\t\t\tif (mailinfo(in, out, keep_subject, utf8 ? git_commit_encoding : NULL,\n+\t\t\t    msg_path, mkpath(\"%s/patch\",dotest)))\n+\t\t\t\t    stop_here(this);\n+\t\t\tfclose(in);\n+\t\t\tfclose(out);\n+\n+\t\t\tin = fopen(msg_path, \"r\");\n+\t\t\tout = fopen(mkpath(\"%s/msg-clean\", dotest), \"w\");\n+\t\t\tstripspace(in, out);\n+\t\t\tfclose(in);\n+\t\t\tfclose(out);\n+\t\t}\n+\n+\t\tfcat(\"info\", \"Author: %1000[^\\n]\\nEmail: %1000s\\n\"\n+\t\t     \"Subject: %992[^\\n]\\nDate: %1000[^\\n]\\n\\n\",\n+\t\t     name, email, subject + 8 /*[PATCH] */, date);\n+\n+\t\tif (!keep_subject)\n+\t\t\tsubject = subject + 8; /*[PATCH] */\n+\n+\t\tif (email == NULL || !strcmp(email, \"\")) {\n+\t\t\tprintf(\"Patch does not have a valid e-mail address.\\n\");\n+\t\t\tstop_here(this);\n+\t\t}\n+\n+\t\tif (!resume) { /* Prepare the commit-message and the patch */\n+\t\t\tchar c, *t;\n+\t\t\tchar line[1000];\n+\t\t\tchar last_signoff[1000] = \"\";\n+\t\t\tFILE *cmt, *msg;\n+\n+\t\t\t/* Find the last Signed-off line */\n+\t\t\tmsg = fopen(mkpath(\"%s/msg-clean\", dotest), \"r\");\n+\t\t\twhile ((fgets(line, sizeof(line), msg))) {\n+\t\t\t\tif ((t = strstr(line, \"Signed-off-by: \")))\n+\t\t\t\t\tstrncpy(last_signoff, t, sizeof(last_signoff));\n+\t\t\t}\n+\t\t\tif ((t = strrchr(last_signoff, '>')))\n+\t\t\t\t*++t = '\\0';\n+\n+\t\t\t/* Write the commit-mesage */\n+\t\t\tcmt = fopen(mkpath(\"%s/final-commit\", dotest), \"w\");\n+\t\t\tfprintf(cmt, \"%s\\n\", subject);\n+\n+\t\t\trewind(msg);\n+\t\t\tif ((c = fgetc(msg)) != EOF) {\n+\t\t\t\tfprintf(cmt, \"\\n\");\n+\t\t\t\tungetc(c, msg);\n+\t\t\t}\n+\t\t\twhile (fgets(line, sizeof(line), msg))\n+\t\t\t\tfputs(line, cmt);\n+\n+\t\t\t/* Add a signoff */\n+\t\t\tif (signoff && strcmp(last_signoff, sign)) {\n+\t\t\t\tif (!strcmp(last_signoff, \"\"))\n+\t\t\t\t\tfputc('\\n', cmt);\n+\t\t\t\tfputs(sign, cmt);\n+\t\t\t}\n+\t\t\tfclose(cmt);\n+\t\t\tfclose(msg);\n+\t\t} else\n+\t\t\tif (resolved && interactive)\n+\t\t\t\t/* This is used only for interactive view option. */\n+\t\t\t\tsystem(mkpath(\"git-diff-index -p --cached HEAD >\\\"%s/patch\\\"\", dotest));\n+\n+\t\tresume = 0;\n+\t\tif (interactive)\n+\t\t\taction = go_interactive();\n+\t\telse\n+\t\t\taction = YES;\n+\n+\t\tif (action == SKIP) {\n+\t\t\tthis = go_next(this);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!access(mkpath(\"%s/hooks/applypatch-msg\", get_git_dir()), X_OK))\n+\t\t\tif (system(mkpath(\"%s/hooks/applypatch-msg %s/final-commit\", get_git_dir(), dotest)))\n+\t\t\t\tstop_here(this);\n+\n+\t\tprintf(\"\\nApplying %s\\n\\n\", subject);\n+\n+\t\tif (!resolved) {\n+\t\t\t/*git-apply $binary --index $ws \"$dotest/patch\" */\n+\t\t\tchar patch[PATH_MAX];\n+\t\t\tchar *opts[6] = { \"git-apply\", \"--allow-binary-replacement\", \"--index\", NULL, NULL, NULL };\n+\t\t\tchar **opt = &opts[0];\n+\t\t\tint optc = 5;\n+\n+\t\t\tif (!binary) {\n+\t\t\t\topts[1] = \"git-apply\";\n+\t\t\t\topt++; optc--;\n+\t\t\t}\n+\t\t\topts[3] = whitespace;\n+\t\t\tsnprintf(patch, sizeof(patch), \"%s/patch\", dotest);\n+\t\t\topts[4] = patch;\n+\t\t\tapply_status = cmd_apply(optc, (const char**)opt, envp);\n+\t\t} else {\n+\t\t\t/* Resolved means the user did all the hard work, and\n+\t\t\t   we do not have to do any patch application.  Just\n+\t\t\t   trust what the user has in the index file and the\n+\t\t\t   working tree.*/\n+\t\t\tresolved = 0;\n+\n+\t\t\tif (has_zero_output(\"git-diff-index --cached --name-only HEAD\")) {\n+\t\t\t\tprintf(\"No changes - did you forget update-index?\\n\");\n+\t\t\t\tstop_here_user_resolve(this);\n+\t\t\t}\n+\t\t\tif (!has_zero_output(\"git-ls-files -u\")) {\n+\t\t\t\tprintf(\"You still have unmerged paths in your index,\\n\"\n+\t\t\t\t\t\"did you forget update-index?\");\n+\t\t\t\tstop_here_user_resolve(this);\n+\t\t\t}\n+\t\t\tapply_status = 0;\n+\t\t}\n+\n+\t\tif (apply_status && threeway) {\n+\t\t\tfall_back_3way();\n+\t\t\t/* Applying the patch to an earlier tree and merging the\n+\t\t\t   result may have produced the same tree as ours. */\n+\t\t\tif (has_zero_output(\"git-diff-index --cached --name-only HEAD\")) {\n+\t\t\t\tprintf(\"No changes -- Patch already applied.\\n\");\n+\t\t\t\tthis = go_next(this);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\t/* We have merged successfully */\n+\t\t\tapply_status = 0;\n+\t\t}\n+\n+\t\tif (apply_status) {\n+\t\t\tprintf(\"Patch failed at %s\\n.\", patch_no);\n+\t\t\tstop_here_user_resolve(this);\n+\t\t}\n+\n+\t\tif (!access(mkpath(\"%s/hooks/pre-applypatch\", get_git_dir()), X_OK))\n+\t\t\tif (system(mkpath(\"%s/hooks/pre-applypatch\", get_git_dir())))\n+\t\t\t\tstop_here(this);\n+\n+\t\tif (commit(subject) == -1)\n+\t\t\tstop_here(this);\n+\n+\t\tif (!access(mkpath(\"%s/hooks/post-applypatch\", get_git_dir()), X_OK))\n+\t\t\tsystem(mkpath(\"%s/hooks/post-applypatch\", get_git_dir()));\n+\n+\t\tthis = go_next(this);\n+\t}\n+\trm_rf(dotest);\n+\treturn 0;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex c1f3395..8771e36 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -49,6 +49,7 @@ extern int cmd_cat_file(int argc, const \n extern int cmd_rev_parse(int argc, const char **argv, char **envp);\n extern int cmd_update_index(int argc, const char **argv, char **envp);\n extern int cmd_update_ref(int argc, const char **argv, char **envp);\n+extern int cmd_am(int argc, const char **argv, char **envp);\n \n extern int cmd_write_tree(int argc, const char **argv, char **envp);\n extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);\ndiff --git a/git-am.sh b/git-am.sh\ndeleted file mode 100755\nindex 4232e27..0000000\n--- a/git-am.sh\n+++ /dev/null\n@@ -1,427 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2005, 2006 Junio C Hamano\n-\n-USAGE='[--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way]\n-  [--interactive] [--whitespace=<option>] <mbox>...\n-  or, when resuming [--skip | --resolved]'\n-. git-sh-setup\n-\n-git var GIT_COMMITTER_IDENT >/dev/null || exit\n-\n-stop_here () {\n-    echo \"$1\" >\"$dotest/next\"\n-    exit 1\n-}\n-\n-stop_here_user_resolve () {\n-    if [ -n \"$resolvemsg\" ]; then\n-\t    echo \"$resolvemsg\"\n-\t    stop_here $1\n-    fi\n-    cmdline=$(basename $0)\n-    if test '' != \"$interactive\"\n-    then\n-        cmdline=\"$cmdline -i\"\n-    fi\n-    if test '' != \"$threeway\"\n-    then\n-        cmdline=\"$cmdline -3\"\n-    fi\n-    if test '.dotest' != \"$dotest\"\n-    then\n-        cmdline=\"$cmdline -d=$dotest\"\n-    fi\n-    echo \"When you have resolved this problem run \\\"$cmdline --resolved\\\".\"\n-    echo \"If you would prefer to skip this patch, instead run \\\"$cmdline --skip\\\".\"\n-\n-    stop_here $1\n-}\n-\n-go_next () {\n-\trm -f \"$dotest/$msgnum\" \"$dotest/msg\" \"$dotest/msg-clean\" \\\n-\t\t\"$dotest/patch\" \"$dotest/info\"\n-\techo \"$next\" >\"$dotest/next\"\n-\tthis=$next\n-}\n-\n-fall_back_3way () {\n-    O_OBJECT=`cd \"$GIT_OBJECT_DIRECTORY\" && pwd`\n-\n-    rm -fr \"$dotest\"/patch-merge-*\n-    mkdir \"$dotest/patch-merge-tmp-dir\"\n-\n-    # First see if the patch records the index info that we can use.\n-    if git-apply -z --index-info \"$dotest/patch\" \\\n-\t>\"$dotest/patch-merge-index-info\" 2>/dev/null &&\n-\tGIT_INDEX_FILE=\"$dotest/patch-merge-tmp-index\" \\\n-\tgit-update-index -z --index-info <\"$dotest/patch-merge-index-info\" &&\n-\tGIT_INDEX_FILE=\"$dotest/patch-merge-tmp-index\" \\\n-\tgit-write-tree >\"$dotest/patch-merge-base+\" &&\n-\t# index has the base tree now.\n-\tGIT_INDEX_FILE=\"$dotest/patch-merge-tmp-index\" \\\n-\tgit-apply $binary --cached <\"$dotest/patch\"\n-    then\n-\techo Using index info to reconstruct a base tree...\n-\tmv \"$dotest/patch-merge-base+\" \"$dotest/patch-merge-base\"\n-\tmv \"$dotest/patch-merge-tmp-index\" \"$dotest/patch-merge-index\"\n-    fi\n-\n-    test -f \"$dotest/patch-merge-index\" &&\n-    his_tree=$(GIT_INDEX_FILE=\"$dotest/patch-merge-index\" git-write-tree) &&\n-    orig_tree=$(cat \"$dotest/patch-merge-base\") &&\n-    rm -fr \"$dotest\"/patch-merge-* || exit 1\n-\n-    echo Falling back to patching base and 3-way merge...\n-\n-    # This is not so wrong.  Depending on which base we picked,\n-    # orig_tree may be wildly different from ours, but his_tree\n-    # has the same set of wildly different changes in parts the\n-    # patch did not touch, so resolve ends up cancelling them,\n-    # saying that we reverted all those changes.\n-\n-    git-merge-resolve $orig_tree -- HEAD $his_tree || {\n-\t    if test -d \"$GIT_DIR/rr-cache\"\n-\t    then\n-\t\tgit-rerere\n-\t    fi\n-\t    echo Failed to merge in the changes.\n-\t    exit 1\n-    }\n-}\n-\n-prec=4\n-dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary= ws= resolvemsg=\n-\n-while case \"$#\" in 0) break;; esac\n-do\n-\tcase \"$1\" in\n-\t-d=*|--d=*|--do=*|--dot=*|--dote=*|--dotes=*|--dotest=*)\n-\tdotest=`expr \"$1\" : '-[^=]*=\\(.*\\)'`; shift ;;\n-\t-d|--d|--do|--dot|--dote|--dotes|--dotest)\n-\tcase \"$#\" in 1) usage ;; esac; shift\n-\tdotest=\"$1\"; shift;;\n-\n-\t-i|--i|--in|--int|--inte|--inter|--intera|--interac|--interact|\\\n-\t--interacti|--interactiv|--interactive)\n-\tinteractive=t; shift ;;\n-\n-\t-b|--b|--bi|--bin|--bina|--binar|--binary)\n-\tbinary=t; shift ;;\n-\n-\t-3|--3|--3w|--3wa|--3way)\n-\tthreeway=t; shift ;;\n-\t-s|--s|--si|--sig|--sign|--signo|--signof|--signoff)\n-\tsign=t; shift ;;\n-\t-u|--u|--ut|--utf|--utf8)\n-\tutf8=t; shift ;;\n-\t-k|--k|--ke|--kee|--keep)\n-\tkeep=t; shift ;;\n-\n-\t-r|--r|--re|--res|--reso|--resol|--resolv|--resolve|--resolved)\n-\tresolved=t; shift ;;\n-\n-\t--sk|--ski|--skip)\n-\tskip=t; shift ;;\n-\n-\t--whitespace=*)\n-\tws=$1; shift ;;\n-\n-\t--resolvemsg=*)\n-\tresolvemsg=$(echo \"$1\" | sed -e \"s/^--resolvemsg=//\"); shift ;;\n-\n-\t--)\n-\tshift; break ;;\n-\t-*)\n-\tusage ;;\n-\t*)\n-\tbreak ;;\n-\tesac\n-done\n-\n-# If the dotest directory exists, but we have finished applying all the\n-# patches in them, clear it out.\n-if test -d \"$dotest\" &&\n-   last=$(cat \"$dotest/last\") &&\n-   next=$(cat \"$dotest/next\") &&\n-   test $# != 0 &&\n-   test \"$next\" -gt \"$last\"\n-then\n-   rm -fr \"$dotest\"\n-fi\n-\n-if test -d \"$dotest\"\n-then\n-\ttest \",$#,\" = \",0,\" ||\n-\tdie \"previous dotest directory $dotest still exists but mbox given.\"\n-\tresume=yes\n-else\n-\t# Make sure we are not given --skip nor --resolved\n-\ttest \",$skip,$resolved,\" = ,,, ||\n-\t\tdie \"Resolve operation not in progress, we are not resuming.\"\n-\n-\t# Start afresh.\n-\tmkdir -p \"$dotest\" || exit\n-\n-\tgit-mailsplit -d\"$prec\" -o\"$dotest\" -b -- \"$@\" > \"$dotest/last\" ||  {\n-\t\trm -fr \"$dotest\"\n-\t\texit 1\n-\t}\n-\n-\t# -b, -s, -u, -k and --whitespace flags are kept for the\n-\t# resuming session after a patch failure.\n-\t# -3 and -i can and must be given when resuming.\n-\techo \"$binary\" >\"$dotest/binary\"\n-\techo \" $ws\" >\"$dotest/whitespace\"\n-\techo \"$sign\" >\"$dotest/sign\"\n-\techo \"$utf8\" >\"$dotest/utf8\"\n-\techo \"$keep\" >\"$dotest/keep\"\n-\techo 1 >\"$dotest/next\"\n-fi\n-\n-case \"$resolved\" in\n-'')\n-\tfiles=$(git-diff-index --cached --name-only HEAD) || exit\n-\tif [ \"$files\" ]; then\n-\t   echo \"Dirty index: cannot apply patches (dirty: $files)\" >&2\n-\t   exit 1\n-\tfi\n-esac\n-\n-if test \"$(cat \"$dotest/binary\")\" = t\n-then\n-\tbinary=--allow-binary-replacement\n-fi\n-if test \"$(cat \"$dotest/utf8\")\" = t\n-then\n-\tutf8=-u\n-fi\n-if test \"$(cat \"$dotest/keep\")\" = t\n-then\n-\tkeep=-k\n-fi\n-ws=`cat \"$dotest/whitespace\"`\n-if test \"$(cat \"$dotest/sign\")\" = t\n-then\n-\tSIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e '\n-\t\t\ts/>.*/>/\n-\t\t\ts/^/Signed-off-by: /'\n-\t\t`\n-else\n-\tSIGNOFF=\n-fi\n-\n-last=`cat \"$dotest/last\"`\n-this=`cat \"$dotest/next\"`\n-if test \"$skip\" = t\n-then\n-\tthis=`expr \"$this\" + 1`\n-\tresume=\n-fi\n-\n-if test \"$this\" -gt \"$last\"\n-then\n-\techo Nothing to do.\n-\trm -fr \"$dotest\"\n-\texit\n-fi\n-\n-while test \"$this\" -le \"$last\"\n-do\n-\tmsgnum=`printf \"%0${prec}d\" $this`\n-\tnext=`expr \"$this\" + 1`\n-\ttest -f \"$dotest/$msgnum\" || {\n-\t\tresume=\n-\t\tgo_next\n-\t\tcontinue\n-\t}\n-\n-\t# If we are not resuming, parse and extract the patch information\n-\t# into separate files:\n-\t#  - info records the authorship and title\n-\t#  - msg is the rest of commit log message\n-\t#  - patch is the patch body.\n-\t#\n-\t# When we are resuming, these files are either already prepared\n-\t# by the user, or the user can tell us to do so by --resolved flag.\n-\tcase \"$resume\" in\n-\t'')\n-\t\tgit-mailinfo $keep $utf8 \"$dotest/msg\" \"$dotest/patch\" \\\n-\t\t\t<\"$dotest/$msgnum\" >\"$dotest/info\" ||\n-\t\t\tstop_here $this\n-\t\tgit-stripspace < \"$dotest/msg\" > \"$dotest/msg-clean\"\n-\t\t;;\n-\tesac\n-\n-\tGIT_AUTHOR_NAME=\"$(sed -n '/^Author/ s/Author: //p' \"$dotest/info\")\"\n-\tGIT_AUTHOR_EMAIL=\"$(sed -n '/^Email/ s/Email: //p' \"$dotest/info\")\"\n-\tGIT_AUTHOR_DATE=\"$(sed -n '/^Date/ s/Date: //p' \"$dotest/info\")\"\n-\n-\tif test -z \"$GIT_AUTHOR_EMAIL\"\n-\tthen\n-\t\techo \"Patch does not have a valid e-mail address.\"\n-\t\tstop_here $this\n-\tfi\n-\n-\texport GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE\n-\n-\tSUBJECT=\"$(sed -n '/^Subject/ s/Subject: //p' \"$dotest/info\")\"\n-\tcase \"$keep_subject\" in -k)  SUBJECT=\"[PATCH] $SUBJECT\" ;; esac\n-\n-\tcase \"$resume\" in\n-\t'')\n-\t    if test '' != \"$SIGNOFF\"\n-\t    then\n-\t\tLAST_SIGNED_OFF_BY=`\n-\t\t    sed -ne '/^Signed-off-by: /p' \\\n-\t\t    \"$dotest/msg-clean\" |\n-\t\t    tail -n 1\n-\t\t`\n-\t\tADD_SIGNOFF=`\n-\t\t    test \"$LAST_SIGNED_OFF_BY\" = \"$SIGNOFF\" || {\n-\t\t    test '' = \"$LAST_SIGNED_OFF_BY\" && echo\n-\t\t    echo \"$SIGNOFF\"\n-\t\t}`\n-\t    else\n-\t\tADD_SIGNOFF=\n-\t    fi\n-\t    {\n-\t\techo \"$SUBJECT\"\n-\t\tif test -s \"$dotest/msg-clean\"\n-\t\tthen\n-\t\t\techo\n-\t\t\tcat \"$dotest/msg-clean\"\n-\t\tfi\n-\t\tif test '' != \"$ADD_SIGNOFF\"\n-\t\tthen\n-\t\t\techo \"$ADD_SIGNOFF\"\n-\t\tfi\n-\t    } >\"$dotest/final-commit\"\n-\t    ;;\n-\t*)\n-\t\tcase \"$resolved$interactive\" in\n-\t\ttt)\n-\t\t\t# This is used only for interactive view option.\n-\t\t\tgit-diff-index -p --cached HEAD >\"$dotest/patch\"\n-\t\t\t;;\n-\t\tesac\n-\tesac\n-\n-\tresume=\n-\tif test \"$interactive\" = t\n-\tthen\n-\t    test -t 0 ||\n-\t    die \"cannot be interactive without stdin connected to a terminal.\"\n-\t    action=again\n-\t    while test \"$action\" = again\n-\t    do\n-\t\techo \"Commit Body is:\"\n-\t\techo \"--------------------------\"\n-\t\tcat \"$dotest/final-commit\"\n-\t\techo \"--------------------------\"\n-\t\tprintf \"Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all \"\n-\t\tread reply\n-\t\tcase \"$reply\" in\n-\t\t[yY]*) action=yes ;;\n-\t\t[aA]*) action=yes interactive= ;;\n-\t\t[nN]*) action=skip ;;\n-\t\t[eE]*) \"${VISUAL:-${EDITOR:-vi}}\" \"$dotest/final-commit\"\n-\t\t       action=again ;;\n-\t\t[vV]*) action=again\n-\t\t       LESS=-S ${PAGER:-less} \"$dotest/patch\" ;;\n-\t\t*)     action=again ;;\n-\t\tesac\n-\t    done\n-\telse\n-\t    action=yes\n-\tfi\n-\n-\tif test $action = skip\n-\tthen\n-\t\tgo_next\n-\t\tcontinue\n-\tfi\n-\n-\tif test -x \"$GIT_DIR\"/hooks/applypatch-msg\n-\tthen\n-\t\t\"$GIT_DIR\"/hooks/applypatch-msg \"$dotest/final-commit\" ||\n-\t\tstop_here $this\n-\tfi\n-\n-\techo\n-\techo \"Applying '$SUBJECT'\"\n-\techo\n-\n-\tcase \"$resolved\" in\n-\t'')\n-\t\tgit-apply $binary --index $ws \"$dotest/patch\"\n-\t\tapply_status=$?\n-\t\t;;\n-\tt)\n-\t\t# Resolved means the user did all the hard work, and\n-\t\t# we do not have to do any patch application.  Just\n-\t\t# trust what the user has in the index file and the\n-\t\t# working tree.\n-\t\tresolved=\n-\t\tchanged=\"$(git-diff-index --cached --name-only HEAD)\"\n-\t\tif test '' = \"$changed\"\n-\t\tthen\n-\t\t\techo \"No changes - did you forget update-index?\"\n-\t\t\tstop_here_user_resolve $this\n-\t\tfi\n-\t\tunmerged=$(git-ls-files -u)\n-\t\tif test -n \"$unmerged\"\n-\t\tthen\n-\t\t\techo \"You still have unmerged paths in your index\"\n-\t\t\techo \"did you forget update-index?\"\n-\t\t\tstop_here_user_resolve $this\n-\t\tfi\n-\t\tapply_status=0\n-\t\t;;\n-\tesac\n-\n-\tif test $apply_status = 1 && test \"$threeway\" = t\n-\tthen\n-\t\tif (fall_back_3way)\n-\t\tthen\n-\t\t    # Applying the patch to an earlier tree and merging the\n-\t\t    # result may have produced the same tree as ours.\n-\t\t    changed=\"$(git-diff-index --cached --name-only HEAD)\"\n-\t\t    if test '' = \"$changed\"\n-\t\t    then\n-\t\t\t    echo No changes -- Patch already applied.\n-\t\t\t    go_next\n-\t\t\t    continue\n-\t\t    fi\n-\t\t    # clear apply_status -- we have successfully merged.\n-\t\t    apply_status=0\n-\t\tfi\n-\tfi\n-\tif test $apply_status != 0\n-\tthen\n-\t\techo Patch failed at $msgnum.\n-\t\tstop_here_user_resolve $this\n-\tfi\n-\n-\tif test -x \"$GIT_DIR\"/hooks/pre-applypatch\n-\tthen\n-\t\t\"$GIT_DIR\"/hooks/pre-applypatch || stop_here $this\n-\tfi\n-\n-\ttree=$(git-write-tree) &&\n-\techo Wrote tree $tree &&\n-\tparent=$(git-rev-parse --verify HEAD) &&\n-\tcommit=$(git-commit-tree $tree -p $parent <\"$dotest/final-commit\") &&\n-\techo Committed: $commit &&\n-\tgit-update-ref -m \"am: $SUBJECT\" HEAD $commit $parent ||\n-\tstop_here $this\n-\n-\tif test -x \"$GIT_DIR\"/hooks/post-applypatch\n-\tthen\n-\t\t\"$GIT_DIR\"/hooks/post-applypatch\n-\tfi\n-\n-\tgo_next\n-done\n-\n-rm -fr \"$dotest\"\ndiff --git a/git.c b/git.c\nindex 652e3c4..b9261e4 100644\n--- a/git.c\n+++ b/git.c\n@@ -184,7 +184,8 @@ static void handle_internal_command(int \n \t\t{ \"mailinfo\", cmd_mailinfo },\n \t\t{ \"stripspace\", cmd_stripspace },\n \t\t{ \"update-index\", cmd_update_index },\n-\t\t{ \"update-ref\", cmd_update_ref }\n+\t\t{ \"update-ref\", cmd_update_ref },\n+\t\t{ \"am\", cmd_am }\n \t};\n \tint i;\n \n-- \n1.4.0\n"},{"id":"21761","messageId":"20060614022228.GA13232@spearce.org","threadId":"4501","inReplyTo":"448F1E68.5090504@etek.chalmers.se","subject":"Re: [PATCH 6/8] Make git-update-ref a builtin","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2006-06-14T02:22:28Z","receivedAt":"2006-06-14T02:22:28Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Lukas Sandstr?m <lukass@etek.chalmers.se> wrote:\n> Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>\n> ---\n>  Makefile                             |    7 ++++---\n>  update-ref.c => builtin-update-ref.c |    5 ++++-\n>  builtin.h                            |    1 +\n>  git.c                                |    3 ++-\n>  4 files changed, 11 insertions(+), 5 deletions(-)\n\nThanks for doing this.  I know I had written this change and I was\npretty sure I had sent it to Junio a while ago but I guess it got\nlost in the shuffle and I just failed to follow through with it\nwhen it didn't show up in `next`.\n\n-- \nShawn.\n"}]}