git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/8] Make git-write-tree a builtin
       [not found] <448EF791.7070504@etek.chalmers.se>
@ 2006-06-13 20:21 ` Lukas Sandström
  2006-06-13 20:21 ` [PATCH 2/8] Make git-mailsplit " Lukas Sandström
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Lukas Sandström @ 2006-06-13 20:21 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List; +Cc: Lukas Sandström

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
 Makefile                             |    6 ++-
 write-tree.c => builtin-write-tree.c |   68 +++++++++++++++++++++-------------
 builtin.h                            |    3 ++
 git.c                                |    3 +-
 4 files changed, 50 insertions(+), 30 deletions(-)

diff --git a/Makefile b/Makefile
index 2a1e639..37b5e40 100644
--- a/Makefile
+++ b/Makefile
@@ -159,7 +159,7 @@ PROGRAMS = \
 	git-show-index$X git-ssh-fetch$X \
 	git-ssh-upload$X git-unpack-file$X \
 	git-unpack-objects$X git-update-index$X git-update-server-info$X \
-	git-upload-pack$X git-verify-pack$X git-write-tree$X \
+	git-upload-pack$X git-verify-pack$X \
 	git-update-ref$X git-symbolic-ref$X \
 	git-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \
 	git-describe$X git-merge-tree$X git-blame$X git-imap-send$X
@@ -170,7 +170,7 @@ BUILT_INS = git-log$X git-whatchanged$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 \
 	git-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \
-	git-read-tree$X git-commit-tree$X \
+	git-read-tree$X git-commit-tree$X git-write-tree$X \
 	git-apply$X git-show-branch$X git-diff-files$X \
 	git-diff-index$X git-diff-stages$X git-diff-tree$X git-cat-file$X
 
@@ -223,7 +223,7 @@ BUILTIN_OBJS = \
 	builtin-grep.o builtin-add.o builtin-rev-list.o builtin-check-ref-format.o \
 	builtin-rm.o builtin-init-db.o builtin-rev-parse.o \
 	builtin-tar-tree.o builtin-upload-tar.o \
-	builtin-ls-files.o builtin-ls-tree.o \
+	builtin-ls-files.o builtin-ls-tree.o builtin-write-tree.o \
 	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 \
diff --git a/write-tree.c b/builtin-write-tree.c
similarity index 66%
rename from write-tree.c
rename to builtin-write-tree.c
index bd07da6..c3aac36 100644
--- a/write-tree.c
+++ b/builtin-write-tree.c
@@ -3,41 +3,24 @@
  *
  * Copyright (C) Linus Torvalds, 2005
  */
+#include "builtin.h"
 #include "cache.h"
 #include "tree.h"
 #include "cache-tree.h"
 
-static int missing_ok = 0;
-static char *prefix = NULL;
-
 static const char write_tree_usage[] =
 "git-write-tree [--missing-ok] [--prefix=<prefix>/]";
 
-static struct lock_file lock_file;
-
-int main(int argc, char **argv)
+int write_tree(unsigned char *sha1, int missing_ok, const char *prefix)
 {
 	int entries, was_valid, newfd;
 
-	setup_git_directory();
+	/* We can't free this memory, it becomes part of a linked list parsed atexit() */
+	struct lock_file *lock_file = xmalloc(sizeof(struct lock_file));
 
-	newfd = hold_lock_file_for_update(&lock_file, get_index_file());
-	entries = read_cache();
-
-	while (1 < argc) {
-		char *arg = argv[1];
-		if (!strcmp(arg, "--missing-ok"))
-			missing_ok = 1;
-		else if (!strncmp(arg, "--prefix=", 9))
-			prefix = arg + 9;
-		else
-			die(write_tree_usage);
-		argc--; argv++;
-	}
-
-	if (argc > 2)
-		die("too many options");
+	newfd = hold_lock_file_for_update(lock_file, get_index_file());
 
+	entries = read_cache();
 	if (entries < 0)
 		die("git-write-tree: error reading cache");
 
@@ -45,6 +28,7 @@ int main(int argc, char **argv)
 		active_cache_tree = cache_tree();
 
 	was_valid = cache_tree_fully_valid(active_cache_tree);
+
 	if (!was_valid) {
 		if (cache_tree_update(active_cache_tree,
 				      active_cache, active_nr,
@@ -52,7 +36,7 @@ int main(int argc, char **argv)
 			die("git-write-tree: error building trees");
 		if (0 <= newfd) {
 			if (!write_cache(newfd, active_cache, active_nr))
-				commit_lock_file(&lock_file);
+				commit_lock_file(lock_file);
 		}
 		/* Not being able to write is fine -- we are only interested
 		 * in updating the cache-tree part, and if the next caller
@@ -61,12 +45,44 @@ int main(int argc, char **argv)
 		 * performance penalty and not a big deal.
 		 */
 	}
+
 	if (prefix) {
 		struct cache_tree *subtree =
 			cache_tree_find(active_cache_tree, prefix);
-		printf("%s\n", sha1_to_hex(subtree->sha1));
+		memcpy(sha1, subtree->sha1, 20);
 	}
 	else
-		printf("%s\n", sha1_to_hex(active_cache_tree->sha1));
+		memcpy(sha1, active_cache_tree->sha1, 20);
+
+	rollback_lock_file(lock_file);
+
 	return 0;
 }
+
+int cmd_write_tree(int argc, const char **argv, char **envp)
+{
+	int missing_ok = 0, ret;
+	const char *prefix = NULL;
+	unsigned char sha1[20];
+
+	setup_git_directory();
+
+	while (1 < argc) {
+		const char *arg = argv[1];
+		if (!strcmp(arg, "--missing-ok"))
+			missing_ok = 1;
+		else if (!strncmp(arg, "--prefix=", 9))
+			prefix = arg + 9;
+		else
+			die(write_tree_usage);
+		argc--; argv++;
+	}
+
+	if (argc > 2)
+		die("too many options");
+
+	ret = write_tree(sha1, missing_ok, prefix);
+	printf("%s\n", sha1_to_hex(sha1));
+
+	return ret;
+}
diff --git a/builtin.h b/builtin.h
index b9f36be..885422e 100644
--- a/builtin.h
+++ b/builtin.h
@@ -46,4 +46,7 @@ extern int cmd_diff_tree(int argc, const
 extern int cmd_cat_file(int argc, const char **argv, char **envp);
 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);
+
 #endif
diff --git a/git.c b/git.c
index 9469d44..5868fb9 100644
--- a/git.c
+++ b/git.c
@@ -178,7 +178,8 @@ static void handle_internal_command(int 
 		{ "diff-stages", cmd_diff_stages },
 		{ "diff-tree", cmd_diff_tree },
 		{ "cat-file", cmd_cat_file },
-		{ "rev-parse", cmd_rev_parse }
+		{ "rev-parse", cmd_rev_parse },
+		{ "write-tree", cmd_write_tree }
 	};
 	int i;
 
-- 
1.4.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/8] Make git-mailsplit a builtin
       [not found] <448EF791.7070504@etek.chalmers.se>
  2006-06-13 20:21 ` [PATCH 1/8] Make git-write-tree a builtin Lukas Sandström
@ 2006-06-13 20:21 ` Lukas Sandström
  2006-06-13 20:21 ` [PATCH 3/8] Make git-mailinfo " Lukas Sandström
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Lukas Sandström @ 2006-06-13 20:21 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List; +Cc: Lukas Sandström

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
 Makefile                           |    5 +--
 mailsplit.c => builtin-mailsplit.c |   71 +++++++++++++++++++++---------------
 builtin.h                          |    2 +
 git.c                              |    3 +-
 4 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/Makefile b/Makefile
index 37b5e40..7bee30d 100644
--- 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/mailsplit.c b/builtin-mailsplit.c
similarity index 85%
rename from mailsplit.c
rename to builtin-mailsplit.c
index 70a569c..e2a0058 100644
--- a/mailsplit.c
+++ b/builtin-mailsplit.c
@@ -12,6 +12,7 @@ #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>...";
@@ -102,14 +103,48 @@ static int split_one(FILE *mbox, const c
 	exit(1);
 }
 
-int main(int argc, const char **argv)
+int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip)
 {
-	int nr = 0, nr_prec = 4;
+	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 };
-	char *name;
 
 	for (argp = argv+1; *argp; argp++) {
 		const char *arg = *argp;
@@ -158,31 +193,9 @@ int main(int argc, const char **argv)
 			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);
-	}
+	ret = split_mbox(argp, dir, allow_bare, nr_prec, nr);
+	if (ret != -1)
+		printf("%d\n", ret);
 
-	printf("%d\n", nr);
-	return 0;
+	return ret == -1;
 }
diff --git a/builtin.h b/builtin.h
index 885422e..92e1e1b 100644
--- a/builtin.h
+++ b/builtin.h
@@ -49,4 +49,6 @@ extern int cmd_rev_parse(int argc, const
 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 5868fb9..3264c65 100644
--- a/git.c
+++ b/git.c
@@ -179,7 +179,8 @@ static void handle_internal_command(int 
 		{ "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;
 
-- 
1.4.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/8] Make git-mailinfo a builtin
       [not found] <448EF791.7070504@etek.chalmers.se>
  2006-06-13 20:21 ` [PATCH 1/8] Make git-write-tree a builtin Lukas Sandström
  2006-06-13 20:21 ` [PATCH 2/8] Make git-mailsplit " Lukas Sandström
@ 2006-06-13 20:21 ` Lukas Sandström
  2006-06-13 20:21 ` [PATCH 4/8] Make git-stripspace " Lukas Sandström
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Lukas Sandström @ 2006-06-13 20:21 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List; +Cc: Lukas Sandström

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
 Makefile                         |   12 ++---
 mailinfo.c => builtin-mailinfo.c |   85 ++++++++++++++++++++++----------------
 builtin.h                        |    6 +++
 git.c                            |    3 +
 4 files changed, 62 insertions(+), 44 deletions(-)

diff --git a/Makefile b/Makefile
index 7bee30d..e64d943 100644
--- a/Makefile
+++ b/Makefile
@@ -151,7 +151,7 @@ PROGRAMS = \
 	git-checkout-index$X git-clone-pack$X \
 	git-convert-objects$X git-fetch-pack$X git-fsck-objects$X \
 	git-hash-object$X git-index-pack$X git-local-fetch$X \
-	git-mailinfo$X git-merge-base$X \
+	git-merge-base$X \
 	git-merge-index$X git-mktag$X git-mktree$X git-pack-objects$X git-patch-id$X \
 	git-peek-remote$X git-prune-packed$X git-receive-pack$X \
 	git-send-pack$X git-shell$X \
@@ -166,7 +166,7 @@ PROGRAMS = \
 BUILT_INS = git-log$X git-whatchanged$X git-show$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-check-ref-format$X git-rev-parse$X git-mailinfo$X \
 	git-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \
 	git-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \
 	git-read-tree$X git-commit-tree$X git-write-tree$X \
@@ -223,7 +223,7 @@ BUILTIN_OBJS = \
 	builtin-rm.o builtin-init-db.o builtin-rev-parse.o \
 	builtin-tar-tree.o builtin-upload-tar.o \
 	builtin-ls-files.o builtin-ls-tree.o builtin-write-tree.o \
-	builtin-read-tree.o builtin-commit-tree.o \
+	builtin-read-tree.o builtin-commit-tree.o builtin-mailinfo.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-mailsplit.o
@@ -486,7 +486,7 @@ strip: $(PROGRAMS) git$X
 git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS)
 	$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
 		$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \
-		$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
+		$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) $(LIB_4_ICONV)
 
 builtin-help.o: common-cmds.h
 
@@ -563,10 +563,6 @@ git-%$X: %.o $(GITLIBS)
 	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 		$(LIB_FILE) $(SIMPLE_LIB)
 
-git-mailinfo$X: mailinfo.o $(LIB_FILE)
-	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
-		$(LIB_FILE) $(SIMPLE_LIB) $(LIB_4_ICONV)
-
 git-local-fetch$X: fetch.o
 git-ssh-fetch$X: rsh.o fetch.o
 git-ssh-upload$X: rsh.o
diff --git a/mailinfo.c b/builtin-mailinfo.c
similarity index 94%
rename from mailinfo.c
rename to builtin-mailinfo.c
index 5b6c215..6e30758 100644
--- a/mailinfo.c
+++ b/builtin-mailinfo.c
@@ -12,8 +12,9 @@ #include <iconv.h>
 #endif
 #include "git-compat-util.h"
 #include "cache.h"
+#include "builtin.h"
 
-static FILE *cmitmsg, *patchfile;
+static FILE *cmitmsg, *patchfile, *fin, *fout;
 
 static int keep_subject = 0;
 static char *metainfo_charset = NULL;
@@ -49,7 +50,7 @@ static int bogus_from(char *line)
 
 	/* This is fallback, so do not bother if we already have an
 	 * e-mail address.
-	 */ 
+	 */
 	if (*email)
 		return 0;
 
@@ -311,12 +312,12 @@ static char *cleanup_subject(char *subje
 			if (remove <= len *2) {
 				subject = p+1;
 				continue;
-			}	
+			}
 			break;
 		}
 		return subject;
 	}
-}			
+}
 
 static void cleanup_space(char *buf)
 {
@@ -638,7 +639,7 @@ static void handle_info(void)
 	cleanup_space(email);
 	cleanup_space(sub);
 
-	printf("Author: %s\nEmail: %s\nSubject: %s\nDate: %s\n\n",
+	fprintf(fout, "Author: %s\nEmail: %s\nSubject: %s\nDate: %s\n\n",
 	       name, email, sub, date);
 }
 
@@ -675,7 +676,7 @@ static int handle_commit_msg(int *seen)
 			continue;
 
 		fputs(line, cmitmsg);
-	} while (fgets(line, sizeof(line), stdin) != NULL);
+	} while (fgets(line, sizeof(line), fin) != NULL);
 	fclose(cmitmsg);
 	cmitmsg = NULL;
 	return 0;
@@ -696,7 +697,7 @@ static void handle_patch(void)
 		decode_transfer_encoding(line);
 		fputs(line, patchfile);
 		patch_lines++;
-	} while (fgets(line, sizeof(line), stdin) != NULL);
+	} while (fgets(line, sizeof(line), fin) != NULL);
 }
 
 /* multipart boundary and transfer encoding are set up for us, and we
@@ -709,7 +710,7 @@ static int handle_multipart_one_part(int
 {
 	int n = 0;
 
-	while (fgets(line, sizeof(line), stdin) != NULL) {
+	while (fgets(line, sizeof(line), fin) != NULL) {
 	again:
 		n++;
 		if (is_multipart_boundary(line))
@@ -730,7 +731,7 @@ static void handle_multipart_body(void)
 	int part_num = 0;
 
 	/* Skip up to the first boundary */
-	while (fgets(line, sizeof(line), stdin) != NULL)
+	while (fgets(line, sizeof(line), fin) != NULL)
 		if (is_multipart_boundary(line)) {
 			part_num = 1;
 			break;
@@ -739,7 +740,7 @@ static void handle_multipart_body(void)
 		return;
 	/* We are on boundary line.  Start slurping the subhead. */
 	while (1) {
-		int hdr = read_one_header_line(line, sizeof(line), stdin);
+		int hdr = read_one_header_line(line, sizeof(line), fin);
 		if (!hdr) {
 			if (handle_multipart_one_part(&seen) < 0)
 				return;
@@ -762,7 +763,7 @@ static void handle_body(void)
 {
 	int seen = 0;
 
-	if (line[0] || fgets(line, sizeof(line), stdin) != NULL) {
+	if (line[0] || fgets(line, sizeof(line), fin) != NULL) {
 		handle_commit_msg(&seen);
 		handle_patch();
 	}
@@ -773,10 +774,45 @@ static void handle_body(void)
 	}
 }
 
+int mailinfo(FILE *in, FILE *out, int ks, char *encoding,
+	     const char *msg, const char *patch)
+{
+	keep_subject = ks;
+	metainfo_charset = encoding;
+	fin = in;
+	fout = out;
+
+	cmitmsg = fopen(msg, "w");
+	if (!cmitmsg) {
+		perror(msg);
+		return -1;
+	}
+	patchfile = fopen(patch, "w");
+	if (!patchfile) {
+		perror(patch);
+		fclose(cmitmsg);
+		return -1;
+	}
+	while (1) {
+		int hdr = read_one_header_line(line, sizeof(line), fin);
+		if (!hdr) {
+			if (multipart_boundary[0])
+				handle_multipart_body();
+			else
+				handle_body();
+			handle_info();
+			break;
+		}
+		check_header_line(line);
+	}
+
+	return 0;
+}
+
 static const char mailinfo_usage[] =
 	"git-mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info";
 
-int main(int argc, char **argv)
+int cmd_mailinfo(int argc, const char **argv, char **envp)
 {
 	/* NEEDSWORK: might want to do the optional .git/ directory
 	 * discovery
@@ -797,27 +833,6 @@ int main(int argc, char **argv)
 
 	if (argc != 3)
 		usage(mailinfo_usage);
-	cmitmsg = fopen(argv[1], "w");
-	if (!cmitmsg) {
-		perror(argv[1]);
-		exit(1);
-	}
-	patchfile = fopen(argv[2], "w");
-	if (!patchfile) {
-		perror(argv[2]);
-		exit(1);
-	}
-	while (1) {
-		int hdr = read_one_header_line(line, sizeof(line), stdin);
-		if (!hdr) {
-			if (multipart_boundary[0])
-				handle_multipart_body();
-			else
-				handle_body();
-			handle_info();
-			break;
-		}
-		check_header_line(line);
-	}
-	return 0;
+
+	return !!mailinfo(stdin, stdout, keep_subject, metainfo_charset, argv[1], argv[2]);
 }
diff --git a/builtin.h b/builtin.h
index 92e1e1b..979e0cd 100644
--- a/builtin.h
+++ b/builtin.h
@@ -1,6 +1,8 @@
 #ifndef BUILTIN_H
 #define BUILTIN_H
 
+#include <stdio.h>
+
 #ifndef PATH_MAX
 # define PATH_MAX 4096
 #endif
@@ -51,4 +53,8 @@ extern int write_tree(unsigned char *sha
 
 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);
+
+extern int cmd_mailinfo(int argc, const char **argv, char **envp);
+extern int mailinfo(FILE *in, FILE *out, int ks, char *encoding,
+		    const char *msg, const char *patch);
 #endif
diff --git a/git.c b/git.c
index 3264c65..1e216de 100644
--- a/git.c
+++ b/git.c
@@ -180,7 +180,8 @@ static void handle_internal_command(int 
 		{ "cat-file", cmd_cat_file },
 		{ "rev-parse", cmd_rev_parse },
 		{ "write-tree", cmd_write_tree },
-		{ "mailsplit", cmd_mailsplit }
+		{ "mailsplit", cmd_mailsplit },
+		{ "mailinfo", cmd_mailinfo }
 	};
 	int i;
 
-- 
1.4.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/8] Make git-stripspace a builtin
       [not found] <448EF791.7070504@etek.chalmers.se>
                   ` (2 preceding siblings ...)
  2006-06-13 20:21 ` [PATCH 3/8] Make git-mailinfo " Lukas Sandström
@ 2006-06-13 20:21 ` Lukas Sandström
  2006-06-13 20:21 ` [PATCH 5/8] Make git-update-index " Lukas Sandström
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Lukas Sandström @ 2006-06-13 20:21 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List; +Cc: Lukas Sandström

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
 Makefile                             |    6 +++---
 stripspace.c => builtin-stripspace.c |   16 +++++++++++-----
 builtin.h                            |    6 ++++--
 git.c                                |    3 ++-
 4 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/Makefile b/Makefile
index e64d943..181255f 100644
--- a/Makefile
+++ b/Makefile
@@ -144,7 +144,7 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)
 
 # The ones that do not have to link with lcrypto, lz nor xdiff.
 SIMPLE_PROGRAMS = \
-	git-stripspace$X git-daemon$X
+	git-daemon$X
 
 # ... and all the rest that could be moved out of bindir to gitexecdir
 PROGRAMS = \
@@ -165,7 +165,7 @@ PROGRAMS = \
 
 BUILT_INS = git-log$X git-whatchanged$X git-show$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-grep$X git-add$X git-rm$X git-rev-list$X git-stripspace$X \
 	git-check-ref-format$X git-rev-parse$X git-mailinfo$X \
 	git-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \
 	git-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \
@@ -226,7 +226,7 @@ BUILTIN_OBJS = \
 	builtin-read-tree.o builtin-commit-tree.o builtin-mailinfo.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-mailsplit.o
+	builtin-cat-file.o builtin-mailsplit.o builtin-stripspace.o
 
 GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
 LIBS = $(GITLIBS) -lz
diff --git a/stripspace.c b/builtin-stripspace.c
similarity index 76%
rename from stripspace.c
rename to builtin-stripspace.c
index 65a6346..2ce1264 100644
--- a/stripspace.c
+++ b/builtin-stripspace.c
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include "builtin.h"
 
 /*
  * Remove empty lines from the beginning and end.
@@ -28,21 +29,21 @@ static int cleanup(char *line)
 	return 1;
 }
 
-int main(int argc, char **argv)
+void stripspace(FILE *in, FILE *out)
 {
 	int empties = -1;
 	int incomplete = 0;
 	char line[1024];
 
-	while (fgets(line, sizeof(line), stdin)) {
+	while (fgets(line, sizeof(line), in)) {
 		incomplete = cleanup(line);
 
 		/* Not just an empty line? */
 		if (line[0] != '\n') {
 			if (empties > 0)
-				putchar('\n');
+				fputc('\n', out);
 			empties = 0;
-			fputs(line, stdout);
+			fputs(line, out);
 			continue;
 		}
 		if (empties < 0)
@@ -50,6 +51,11 @@ int main(int argc, char **argv)
 		empties++;
 	}
 	if (incomplete)
-		putchar('\n');
+		fputc('\n', out);
+}
+
+int cmd_stripspace(int argc, const char **argv, char **envp)
+{
+	stripspace(stdin, stdout);
 	return 0;
 }
diff --git a/builtin.h b/builtin.h
index 979e0cd..c934d7a 100644
--- a/builtin.h
+++ b/builtin.h
@@ -55,6 +55,8 @@ extern int cmd_mailsplit(int argc, const
 extern int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip);
 
 extern int cmd_mailinfo(int argc, const char **argv, char **envp);
-extern int mailinfo(FILE *in, FILE *out, int ks, char *encoding,
-		    const char *msg, const char *patch);
+extern int mailinfo(FILE *in, FILE *out, int ks, char *encoding, const char *msg, const char *patch);
+
+extern int cmd_stripspace(int argc, const char **argv, char **envp);
+extern void stripspace(FILE *in, FILE *out);
 #endif
diff --git a/git.c b/git.c
index 1e216de..31196f5 100644
--- a/git.c
+++ b/git.c
@@ -181,7 +181,8 @@ static void handle_internal_command(int 
 		{ "rev-parse", cmd_rev_parse },
 		{ "write-tree", cmd_write_tree },
 		{ "mailsplit", cmd_mailsplit },
-		{ "mailinfo", cmd_mailinfo }
+		{ "mailinfo", cmd_mailinfo },
+		{ "stripspace", cmd_stripspace }
 	};
 	int i;
 
-- 
1.4.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/8] Make git-update-index a builtin
       [not found] <448EF791.7070504@etek.chalmers.se>
                   ` (3 preceding siblings ...)
  2006-06-13 20:21 ` [PATCH 4/8] Make git-stripspace " Lukas Sandström
@ 2006-06-13 20:21 ` Lukas Sandström
  2006-06-13 20:22 ` [PATCH 6/8] Make git-update-ref " Lukas Sandström
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Lukas Sandström @ 2006-06-13 20:21 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List; +Cc: Lukas Sandström

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
 Makefile                                 |    6 +++---
 update-index.c => builtin-update-index.c |   19 ++++++++++++-------
 builtin.h                                |    1 +
 git.c                                    |    3 ++-
 4 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/Makefile b/Makefile
index 181255f..906fc0f 100644
--- a/Makefile
+++ b/Makefile
@@ -157,7 +157,7 @@ PROGRAMS = \
 	git-send-pack$X git-shell$X \
 	git-show-index$X git-ssh-fetch$X \
 	git-ssh-upload$X git-unpack-file$X \
-	git-unpack-objects$X git-update-index$X git-update-server-info$X \
+	git-unpack-objects$X git-update-server-info$X \
 	git-upload-pack$X git-verify-pack$X \
 	git-update-ref$X git-symbolic-ref$X \
 	git-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \
@@ -170,7 +170,7 @@ BUILT_INS = git-log$X git-whatchanged$X 
 	git-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \
 	git-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \
 	git-read-tree$X git-commit-tree$X git-write-tree$X \
-	git-apply$X git-show-branch$X git-diff-files$X \
+	git-apply$X git-show-branch$X git-diff-files$X git-update-index$X \
 	git-diff-index$X git-diff-stages$X git-diff-tree$X git-cat-file$X
 
 # what 'all' will build and 'install' will install, in gitexecdir
@@ -221,7 +221,7 @@ BUILTIN_OBJS = \
 	builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \
 	builtin-grep.o builtin-add.o builtin-rev-list.o builtin-check-ref-format.o \
 	builtin-rm.o builtin-init-db.o builtin-rev-parse.o \
-	builtin-tar-tree.o builtin-upload-tar.o \
+	builtin-tar-tree.o builtin-upload-tar.o builtin-update-index.o \
 	builtin-ls-files.o builtin-ls-tree.o builtin-write-tree.o \
 	builtin-read-tree.o builtin-commit-tree.o builtin-mailinfo.o \
 	builtin-apply.o builtin-show-branch.o builtin-diff-files.o \
diff --git a/update-index.c b/builtin-update-index.c
similarity index 97%
rename from update-index.c
rename to builtin-update-index.c
index fbccc4a..325cd09 100644
--- a/update-index.c
+++ b/builtin-update-index.c
@@ -8,6 +8,7 @@ #include "strbuf.h"
 #include "quote.h"
 #include "cache-tree.h"
 #include "tree-walk.h"
+#include "builtin.h"
 
 /*
  * Default to not allowing changes to the list of files. The
@@ -186,8 +187,6 @@ static void chmod_path(int flip, const c
 	die("git-update-index: cannot chmod %cx '%s'", flip, path);
 }
 
-static struct lock_file lock_file;
-
 static void update_one(const char *path, const char *prefix, int prefix_length)
 {
 	const char *p = prefix_path(prefix, prefix_length, path);
@@ -238,7 +237,7 @@ static void read_index_info(int line_ter
 		 * (2) mode SP type SP sha1          TAB path
 		 * The second format is to stuff git-ls-tree output
 		 * into the index file.
-		 * 
+		 *
 		 * (3) mode         SP sha1 SP stage TAB path
 		 * This format is to put higher order stages into the
 		 * index file and matches git-ls-files --stage output.
@@ -477,7 +476,7 @@ static int do_reupdate(int ac, const cha
 	return 0;
 }
 
-int main(int argc, const char **argv)
+int cmd_update_index(int argc, const char **argv, char **envp)
 {
 	int i, newfd, entries, has_errors = 0, line_termination = '\n';
 	int allow_options = 1;
@@ -486,12 +485,16 @@ int main(int argc, const char **argv)
 	int prefix_length = prefix ? strlen(prefix) : 0;
 	char set_executable_bit = 0;
 	unsigned int refresh_flags = 0;
+	struct lock_file *lock_file;
 
 	git_config(git_default_config);
 
-	newfd = hold_lock_file_for_update(&lock_file, get_index_file());
+	/* We can't free this memory, it becomes part of a linked list parsed atexit() */
+	lock_file = xmalloc(sizeof(struct lock_file));
+
+	newfd = hold_lock_file_for_update(lock_file, get_index_file());
 	if (newfd < 0)
-		die("unable to create new index file");
+		die("unable to create new cachefile");
 
 	entries = read_cache();
 	if (entries < 0)
@@ -645,9 +648,11 @@ int main(int argc, const char **argv)
  finish:
 	if (active_cache_changed) {
 		if (write_cache(newfd, active_cache, active_nr) ||
-		    commit_lock_file(&lock_file))
+		    commit_lock_file(lock_file))
 			die("Unable to write new index file");
 	}
 
+	rollback_lock_file(lock_file);
+
 	return has_errors ? 1 : 0;
 }
diff --git a/builtin.h b/builtin.h
index c934d7a..9ee5ea6 100644
--- a/builtin.h
+++ b/builtin.h
@@ -47,6 +47,7 @@ extern int cmd_diff_stages(int argc, con
 extern int cmd_diff_tree(int argc, const char **argv, char **envp);
 extern int cmd_cat_file(int argc, const char **argv, char **envp);
 extern int cmd_rev_parse(int argc, const char **argv, char **envp);
+extern int cmd_update_index(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);
diff --git a/git.c b/git.c
index 31196f5..4a931fb 100644
--- a/git.c
+++ b/git.c
@@ -182,7 +182,8 @@ static void handle_internal_command(int 
 		{ "write-tree", cmd_write_tree },
 		{ "mailsplit", cmd_mailsplit },
 		{ "mailinfo", cmd_mailinfo },
-		{ "stripspace", cmd_stripspace }
+		{ "stripspace", cmd_stripspace },
+		{ "update-index", cmd_update_index }
 	};
 	int i;
 
-- 
1.4.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/8] Make git-update-ref a builtin
       [not found] <448EF791.7070504@etek.chalmers.se>
                   ` (4 preceding siblings ...)
  2006-06-13 20:21 ` [PATCH 5/8] Make git-update-index " Lukas Sandström
@ 2006-06-13 20:22 ` Lukas Sandström
  2006-06-14  2:22   ` Shawn Pearce
  2006-06-13 20:22 ` [PATCH 7/8] Make it possible to call cmd_apply multiple times Lukas Sandström
  2006-06-13 20:22 ` [PATCH/RFC 8/8] Make git-am a builtin Lukas Sandström
  7 siblings, 1 reply; 9+ messages in thread
From: Lukas Sandström @ 2006-06-13 20:22 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List; +Cc: Lukas Sandström

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
 Makefile                             |    7 ++++---
 update-ref.c => builtin-update-ref.c |    5 ++++-
 builtin.h                            |    1 +
 git.c                                |    3 ++-
 4 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index 906fc0f..4b30ca0 100644
--- a/Makefile
+++ b/Makefile
@@ -159,11 +159,11 @@ PROGRAMS = \
 	git-ssh-upload$X git-unpack-file$X \
 	git-unpack-objects$X git-update-server-info$X \
 	git-upload-pack$X git-verify-pack$X \
-	git-update-ref$X git-symbolic-ref$X \
+	git-symbolic-ref$X \
 	git-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \
 	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 \
+BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$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-stripspace$X \
 	git-check-ref-format$X git-rev-parse$X git-mailinfo$X \
@@ -226,7 +226,8 @@ BUILTIN_OBJS = \
 	builtin-read-tree.o builtin-commit-tree.o builtin-mailinfo.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-mailsplit.o builtin-stripspace.o
+	builtin-cat-file.o builtin-mailsplit.o builtin-stripspace.o \
+	builtin-update-ref.o
 
 GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
 LIBS = $(GITLIBS) -lz
diff --git a/update-ref.c b/builtin-update-ref.c
similarity index 89%
rename from update-ref.c
rename to builtin-update-ref.c
index a1e6bb9..00333c7 100644
--- a/update-ref.c
+++ b/builtin-update-ref.c
@@ -1,10 +1,11 @@
 #include "cache.h"
 #include "refs.h"
+#include "builtin.h"
 
 static const char git_update_ref_usage[] =
 "git-update-ref <refname> <value> [<oldval>] [-m <reason>]";
 
-int main(int argc, char **argv)
+int cmd_update_ref(int argc, const char **argv, char **envp)
 {
 	const char *refname=NULL, *value=NULL, *oldval=NULL, *msg=NULL;
 	struct ref_lock *lock;
@@ -52,5 +53,7 @@ int main(int argc, char **argv)
 		return 1;
 	if (write_ref_sha1(lock, sha1, msg) < 0)
 		return 1;
+
+	/* write_ref_sha1 always unlocks the ref, no need to do it explicitly */
 	return 0;
 }
diff --git a/builtin.h b/builtin.h
index 9ee5ea6..c1f3395 100644
--- a/builtin.h
+++ b/builtin.h
@@ -48,6 +48,7 @@ extern int cmd_diff_tree(int argc, const
 extern int cmd_cat_file(int argc, const char **argv, char **envp);
 extern int cmd_rev_parse(int argc, const char **argv, char **envp);
 extern int cmd_update_index(int argc, const char **argv, char **envp);
+extern int cmd_update_ref(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);
diff --git a/git.c b/git.c
index 4a931fb..652e3c4 100644
--- a/git.c
+++ b/git.c
@@ -183,7 +183,8 @@ static void handle_internal_command(int 
 		{ "mailsplit", cmd_mailsplit },
 		{ "mailinfo", cmd_mailinfo },
 		{ "stripspace", cmd_stripspace },
-		{ "update-index", cmd_update_index }
+		{ "update-index", cmd_update_index },
+		{ "update-ref", cmd_update_ref }
 	};
 	int i;
 
-- 
1.4.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/8] Make it possible to call cmd_apply multiple times
       [not found] <448EF791.7070504@etek.chalmers.se>
                   ` (5 preceding siblings ...)
  2006-06-13 20:22 ` [PATCH 6/8] Make git-update-ref " Lukas Sandström
@ 2006-06-13 20:22 ` Lukas Sandström
  2006-06-13 20:22 ` [PATCH/RFC 8/8] Make git-am a builtin Lukas Sandström
  7 siblings, 0 replies; 9+ messages in thread
From: Lukas Sandström @ 2006-06-13 20:22 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List; +Cc: Lukas Sandström

* xmalloc a new struct lock_file each invocation.
* Don't die() if the patch doesn't apply.
* Initialize the global variables each invocation.
* Roll back the lock_file.

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
 builtin-apply.c |   94 +++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 60 insertions(+), 34 deletions(-)

diff --git a/builtin-apply.c b/builtin-apply.c
index e113c74..a76c553 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -22,24 +22,13 @@ #include "builtin.h"
 //  --index updates the cache as well.
 //  --cached updates only the cache without ever touching the working tree.
 //
-static const char *prefix;
-static int prefix_length = -1;
-static int newfd = -1;
-
-static int p_value = 1;
-static int allow_binary_replacement = 0;
-static int check_index = 0;
-static int write_index = 0;
-static int cached = 0;
-static int diffstat = 0;
-static int numstat = 0;
-static int summary = 0;
-static int check = 0;
-static int apply = 1;
-static int no_add = 0;
-static int show_index_info = 0;
-static int line_termination = '\n';
+static const char *prefix, *patch_input_file;
+static int prefix_length, newfd, p_value, allow_binary_replacement, check_index,
+	write_index, cached, diffstat, numstat, summary, check, apply, no_add,
+	show_index_info, line_termination, whitespace_error, squelch_whitespace_errors,
+	applied_after_stripping;
 static unsigned long p_context = -1;
+
 static const char apply_usage[] =
 "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>...";
 
@@ -49,10 +38,31 @@ static enum whitespace_eol {
 	error_on_whitespace,
 	strip_whitespace,
 } new_whitespace = warn_on_whitespace;
-static int whitespace_error = 0;
-static int squelch_whitespace_errors = 5;
-static int applied_after_stripping = 0;
-static const char *patch_input_file = NULL;
+
+static void setup_state()
+{
+	prefix = NULL;
+	prefix_length = -1;
+	newfd = -1;
+	p_value = 1;
+	allow_binary_replacement = 0;
+	check_index = 0;
+	write_index = 0;
+	cached = 0;
+	diffstat = 0;
+	numstat = 0;
+	summary = 0;
+	check = 0;
+	apply = 1;
+	no_add = 0;
+	show_index_info = 0;
+	line_termination = '\n';
+	p_context = -1;
+	whitespace_error = 0;
+	squelch_whitespace_errors = 5;
+	applied_after_stripping = 0;
+	patch_input_file = NULL;
+}
 
 static void parse_whitespace_option(const char *option)
 {
@@ -2072,7 +2082,7 @@ static void write_out_results(struct pat
 	}
 }
 
-static struct lock_file lock_file;
+static struct lock_file *lock_file;
 
 static struct excludes {
 	struct excludes *next;
@@ -2106,7 +2116,7 @@ static int apply_patch(int fd, const cha
 
 	patch_input_file = filename;
 	if (!buffer)
-		return -1;
+		return -2;
 	offset = 0;
 	while (size > 0) {
 		struct patch *patch;
@@ -2134,7 +2144,7 @@ static int apply_patch(int fd, const cha
 
 	write_index = check_index && apply;
 	if (write_index && newfd < 0) {
-		newfd = hold_lock_file_for_update(&lock_file,
+		newfd = hold_lock_file_for_update(lock_file,
 						  get_index_file());
 		if (newfd < 0)
 			die("unable to create new index file");
@@ -2145,7 +2155,7 @@ static int apply_patch(int fd, const cha
 	}
 
 	if ((check || apply) && check_patch_list(list) < 0)
-		exit(1);
+		return -1;
 
 	if (apply)
 		write_out_results(list, skipped_patch);
@@ -2175,20 +2185,27 @@ static int git_apply_config(const char *
 	return git_default_config(var, value);
 }
 
-
 int cmd_apply(int argc, const char **argv, char **envp)
 {
-	int i;
+	int i, ret = 0;
 	int read_stdin = 1;
 	const char *whitespace_option = NULL;
 
+	setup_state();
+
+	/* This memory can't be free()'d since it's needed atexit() */
+	lock_file = xmalloc(sizeof(struct lock_file));
+
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 		char *end;
-		int fd;
+		int fd, apply_status;
 
 		if (!strcmp(arg, "-")) {
-			apply_patch(0, "<stdin>");
+			if (apply_patch(0, "<stdin>")) {
+				ret = 1;
+				goto err;
+			}
 			read_stdin = 0;
 			continue;
 		}
@@ -2281,12 +2298,18 @@ int cmd_apply(int argc, const char **arg
 			usage(apply_usage);
 		read_stdin = 0;
 		set_default_whitespace_mode(whitespace_option);
-		apply_patch(fd, arg);
+		apply_status = apply_patch(fd, arg);
 		close(fd);
+		if (apply_status) {
+			ret = 1;
+			goto err;
+		}
 	}
 	set_default_whitespace_mode(whitespace_option);
-	if (read_stdin)
-		apply_patch(0, "<stdin>");
+	if (read_stdin && apply_patch(0, "<stdin>")) {
+		ret = 1;
+		goto err;
+	}
 	if (whitespace_error) {
 		if (squelch_whitespace_errors &&
 		    squelch_whitespace_errors < whitespace_error) {
@@ -2316,9 +2339,12 @@ int cmd_apply(int argc, const char **arg
 
 	if (write_index) {
 		if (write_cache(newfd, active_cache, active_nr) ||
-		    commit_lock_file(&lock_file))
+		    commit_lock_file(lock_file))
 			die("Unable to write new index file");
 	}
 
-	return 0;
+err:
+	rollback_lock_file(lock_file);
+
+	return ret;
 }
-- 
1.4.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH/RFC 8/8] Make git-am a builtin
       [not found] <448EF791.7070504@etek.chalmers.se>
                   ` (6 preceding siblings ...)
  2006-06-13 20:22 ` [PATCH 7/8] Make it possible to call cmd_apply multiple times Lukas Sandström
@ 2006-06-13 20:22 ` Lukas Sandström
  7 siblings, 0 replies; 9+ messages in thread
From: Lukas Sandström @ 2006-06-13 20:22 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List; +Cc: Lukas Sandström

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---

Being able to switch index-file on the fly would reduce the number of
system() calls.
A way to check if the index/working dir is dirty would also help.

 Makefile     |    6 -
 builtin-am.c |  664 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 builtin.h    |    1 
 git-am.sh    |  427 -------------------------------------
 git.c        |    3 
 5 files changed, 670 insertions(+), 431 deletions(-)

diff --git a/Makefile b/Makefile
index 4b30ca0..e9b372e 100644
--- a/Makefile
+++ b/Makefile
@@ -122,7 +122,7 @@ SCRIPT_SH = \
 	git-repack.sh git-request-pull.sh git-reset.sh \
 	git-resolve.sh git-revert.sh git-sh-setup.sh \
 	git-tag.sh git-verify-tag.sh \
-	git-applymbox.sh git-applypatch.sh git-am.sh \
+	git-applymbox.sh git-applypatch.sh \
 	git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
 	git-merge-resolve.sh git-merge-ours.sh \
 	git-lost-found.sh git-quiltimport.sh
@@ -166,7 +166,7 @@ PROGRAMS = \
 BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$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-stripspace$X \
-	git-check-ref-format$X git-rev-parse$X git-mailinfo$X \
+	git-check-ref-format$X git-rev-parse$X git-mailinfo$X git-am$X \
 	git-init-db$X git-tar-tree$X git-upload-tar$X git-format-patch$X \
 	git-ls-files$X git-ls-tree$X git-get-tar-commit-id$X \
 	git-read-tree$X git-commit-tree$X git-write-tree$X \
@@ -220,7 +220,7 @@ LIB_OBJS = \
 BUILTIN_OBJS = \
 	builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \
 	builtin-grep.o builtin-add.o builtin-rev-list.o builtin-check-ref-format.o \
-	builtin-rm.o builtin-init-db.o builtin-rev-parse.o \
+	builtin-rm.o builtin-init-db.o builtin-rev-parse.o builtin-am.o \
 	builtin-tar-tree.o builtin-upload-tar.o builtin-update-index.o \
 	builtin-ls-files.o builtin-ls-tree.o builtin-write-tree.o \
 	builtin-read-tree.o builtin-commit-tree.o builtin-mailinfo.o \
diff --git a/builtin-am.c b/builtin-am.c
new file mode 100644
index 0000000..d9e7ac5
--- /dev/null
+++ b/builtin-am.c
@@ -0,0 +1,664 @@
+/*
+ * GIT - The information manager from hell
+ *
+ * Copyright (C) Lukas Sandström, 2006
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/wait.h>
+
+#include "git-compat-util.h"
+#include "cache.h"
+#include "builtin.h"
+
+static char builtin_am_usage[] = "[--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way] "
+				 "[--interactive] [--whitespace=<option>] <mbox>...\n"
+				 "or, when resuming [--skip | --resolved]";
+
+static int binary, interactive, threeway, signoff, utf8, keep_subject, resolved, skip, resume;
+static char whitespace[40] = "--whitespace=warn", **env;
+static const char **mbox, *dotest, *resolvmsg;
+
+#define PATCH_PREC 4
+
+#define AGAIN 0
+#define SKIP 1
+#define YES 2
+
+//ugly hack to be able to change the index file
+extern char *git_index_file;
+
+static int rm_rf(const char* path)
+{
+	char cmd[PATH_MAX + 10];
+	snprintf(cmd, sizeof(cmd), "rm -rf %s", path);
+	return system(cmd);
+}
+
+static int mkdir_p(const char *path)
+{
+	char p[PATH_MAX], n, *l;
+
+	strcpy(p, path);
+	while ((l = strchr(p, '/'))) {
+		n = *l;
+		*l = '\0';
+		if (access(p, F_OK) && mkdir(p, 0777))
+			return -1;
+		*l = n;
+	}
+	return mkdir(p, 0777);
+}
+
+static int fcat(char *file, char *fmt, ...)
+{
+	va_list args;
+	int ret;
+	FILE *f;
+
+	file = mkpath("%s/%s", dotest, file);
+	if ((f = fopen(file, "r")) == NULL) {
+		perror(file);
+		die("Couldn't open file %s", file);
+	}
+	va_start(args, fmt);
+	ret = vfscanf(f, fmt, args);
+	va_end(args);
+	fclose(f);
+	return ret;
+}
+
+static int fecho(char *file, char *fmt, ...)
+{
+	va_list args;
+	int ret;
+	FILE *f;
+
+	file = mkpath("%s/%s", dotest, file);
+	if ((f = fopen(file, "w")) == NULL) {
+		perror(file);
+		die("Couldn't open file %s/%s", dotest, file);
+	}
+	va_start(args, fmt);
+	ret = vfprintf(f, fmt, args);
+	va_end(args);
+	fclose(f);
+	return ret;
+}
+
+static FILE* get_output(char *cmd, int *status)
+{
+	char c[2000];
+	FILE *ret;
+	int s;
+
+	snprintf(c, sizeof(c), "%s > \"%s/outtmp\"", cmd, dotest);
+	s = system(c);
+	if (status)
+		*status = s;
+	if ((ret = fopen(mkpath("%s/outtmp", dotest), "r")) == NULL)
+		die("cmd: %s\nOpen \"%s\" failed.", c, mkpath("%s/outtmp", dotest));
+	unlink(mkpath("%s/outtmp", dotest));
+	return ret;
+}
+
+static int has_zero_output(char *cmd)
+{
+	struct stat s;
+
+	system(mkpath("%s > %s/zerotmp", cmd, dotest));
+	stat(mkpath("%s/zerotmp", dotest), &s);
+	unlink(mkpath("%s/zerotmp", dotest));
+	return s.st_size == 0;
+}
+
+static int go_next(int this) {
+	unlink(mkpath("%s/%0*d", dotest, PATCH_PREC, this));
+	unlink(mkpath("%s/msg", dotest));
+	unlink(mkpath("%s/msg-clean", dotest));
+	unlink(mkpath("%s/patch", dotest));
+	unlink(mkpath("%s/info", dotest));
+	fecho("next", "%d", this + 1);
+	return this + 1;
+}
+
+static void stop_here(int this)
+{
+	fecho("next","%d\n", this);
+	exit(1);
+}
+
+static void stop_here_user_resolve(int this)
+{
+	char cmdline[1000] = "git am";
+	int pos = 6; /* "git am" */
+
+	if (resolvmsg != NULL) {
+		printf("%s", resolvmsg);
+		stop_here(this);
+	}
+
+	if (interactive)
+		pos += sprintf(cmdline + pos, " -i");
+	if (threeway)
+		pos += sprintf(cmdline + pos, " -3");
+	if (strcmp(".dotest", dotest))
+		pos += sprintf(cmdline + pos, " -d=%s", dotest);
+
+	printf("When you have resolved this problem run \"git am %s --resolved\".\n", cmdline);
+	printf("If you would prefer to skip this patch, instead run \"%s --skip\".\n", cmdline);
+
+	stop_here(this);
+}
+
+static int fall_back_3way()
+{
+	char cmd[1000];
+	char tmp_index[PATH_MAX], old_index[PATH_MAX] = "";
+	int ret = -1;
+
+	snprintf(cmd, sizeof(cmd), "git-apply -z --index-info \"%s/patch\""
+			" > %s/patch-merge-index-info 2> /dev/null", dotest, dotest);
+	if (!system(cmd)) {
+		snprintf(tmp_index, sizeof(tmp_index),"%s/patch-merge-tmp-index", dotest);
+		if (getenv(INDEX_ENVIRONMENT))
+			strcpy(old_index, getenv(INDEX_ENVIRONMENT));
+		setenv(INDEX_ENVIRONMENT, tmp_index, 1);
+
+		snprintf(cmd, sizeof(cmd), "git-update-index -z --index-info <\"%s/patch-merge-index-info\"", dotest);
+		if (!system(cmd)) {
+#if 1
+			system(mkpath("git-write-tree > \"%s/patch-merge-base\"", dotest));
+			snprintf(cmd, sizeof(cmd), "git-apply %s --cached < \"%s/patch\"", binary ? "--allow-binary-replacement":"", dotest);
+			if (!system(cmd)) {
+				char his_tree[41], orig_tree[41];
+				printf("Using index info to reconstruct a base tree...\n");
+				system(mkpath("git-write-tree > \"%s/his-tree\"", dotest));
+				fcat("his-tree", "%40s", his_tree);
+				fcat("patch-merge-base", "%40s", orig_tree);
+
+				printf("Falling back to patching base and 3-way merge...\n");
+
+				if (*old_index)
+					setenv(INDEX_ENVIRONMENT, old_index, 1);
+				else
+					unsetenv(INDEX_ENVIRONMENT);
+				if (!system(mkpath("git-merge-resolve %s -- HEAD %s", orig_tree, his_tree)))
+					return 0;
+			}
+		}
+#else
+			unsigned char orig_tree[20], his_tree[20];
+
+			// We need a way to switch the index file on the fly for this to work
+
+			char *opts[] = { "git-apply", "--allow-binary-replacement", "--cached", NULL, NULL };
+			char **opt = &opts[0];
+			char patch[PATH_MAX];
+			int optc = ARRAY_SIZE(opts) - 1;
+
+			opts[optc - 1] = strncpy(patch, mkpath("%s/patch", dotest), sizeof(patch));
+			if (!binary) {
+				opts[1] = "git-apply";
+				opt++; optc--;
+			}
+			write_tree(orig_tree, 0, NULL);
+			if (!cmd_apply(optc, (const char**)opt, env)) {
+				printf("Using index info to reconstruct a base tree...\n");
+				write_tree(his_tree, 0, NULL);
+
+				snprintf(cmd, sizeof(cmd), "git-merge-resolve %s -- HEAD %s", sha1_to_hex(orig_tree),
+					 sha1_to_hex(his_tree));
+				ret = system(cmd);
+			}
+		}
+		if (*old_index)
+			setenv(INDEX_ENVIRONMENT, old_index, 1);
+		else
+			unsetenv(INDEX_ENVIRONMENT);
+#endif
+		if (!ret)
+			return 0;
+	}
+	if (!access(mkpath("%s/rr-cache/.", get_git_dir()), F_OK))
+		system("git-rerere");
+	die("Failed to merge in the changes.");
+}
+
+static int go_interactive(void)
+{
+	int action = AGAIN;
+
+	if (!isatty(0))
+		die("Cannot be interactive without stdin connected to a terminal.");
+
+	while (action == AGAIN) {
+		char line[1000];
+		FILE *cmt;
+
+		printf("Commit Body is:\n--------------------------\n");
+		cmt = fopen(mkpath("%s/final-commit", dotest), "r");
+		while (fgets(line, sizeof(line), cmt))
+			fputs(line, stdout);
+		fclose(cmt);
+		printf("--------------------------\nApply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all ");
+
+		fgets(line, sizeof(line), stdin);
+		switch (line[0]) {
+			case 'y':
+			case 'Y':
+				action = YES;
+				break;
+			case 'a':
+			case 'A':
+				action = YES;
+				interactive = 0;
+				break;
+			case 'n':
+			case 'N':
+				action = SKIP;
+				break;
+			case 'e':
+			case 'E':
+				system(mkpath("\"${VISUAL:-${EDITOR:-vi}}\" \"%s/final-commit\"", dotest));
+				action = AGAIN;
+				break;
+			case 'v':
+			case 'V':
+				system(mkpath("LESS=-S ${PAGER:-less} \"%s/patch\"", dotest));
+				action = AGAIN;
+				break;
+			default:
+				action = AGAIN;
+				break;
+		}
+	}
+	return action;
+}
+
+static int commit(char *subject)
+{
+	unsigned char sha1[20];
+	char commit[41], parent[41], cmd[1000];
+	FILE *f;
+	int status;
+
+	if (!write_tree(sha1, 0, NULL)) {
+		printf("Wrote tree %s\n", sha1_to_hex(sha1));
+		f = get_output("git-rev-parse --verify HEAD", &status);
+		if (!status) {
+			fgets(parent, 41, f);
+			fclose(f);
+			snprintf(cmd, sizeof(cmd), "git-commit-tree %s -p %s <\"%s/final-commit\"",
+				 sha1_to_hex(sha1), parent, dotest);
+			f = get_output(cmd, &status);
+			if (!status) {
+				//git-update-ref -m "am: $SUBJECT" HEAD $commit $parent
+				char *opts[] = { "git-update-ref", "-m", NULL, "HEAD", NULL, NULL, NULL };
+				const char **opt = (const char**)&opts[0];
+				fgets(commit, 41, f);
+				fclose(f);
+				printf("Committed: %s\n", commit);
+				snprintf(cmd, sizeof(cmd), "am: %s", subject);
+				opts[2] = cmd;
+				opts[4] = commit;
+				opts[5] = parent;
+				if (!cmd_update_ref(ARRAY_SIZE(opts) - 1, opt, env))
+					return 0;
+			}
+		}
+	}
+	return -1;
+}
+
+int cmd_am(int argc, const char **argv, char **envp)
+{
+	int i, this, last, apply_status, action;
+	char sign[1000] = "";
+
+	env = envp;
+
+	for (i = 1; i < argc; i++) {
+		const char *arg = argv[i];
+
+		if (arg[0] != '-')
+			break;
+		if (!strcmp(arg, "--")) {
+			i++;
+			break;
+		}
+		if (!strcmp(arg, "-i") || !strcmp(arg, "--interactive")) {
+			interactive = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-b") || !strcmp(arg, "--binary")) {
+			binary = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-3") || !strcmp(arg, "--3way")) {
+			threeway = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-s") || !strcmp(arg, "--signoff")) {
+			signoff = 1;
+			continue;
+		}
+		if (!strcmp(arg, "--skip")) {
+			skip = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-u") || !strcmp(arg, "--utf8")) {
+			utf8 = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-k") || !strcmp(arg, "--keep")) {
+			keep_subject = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-r") || !strcmp(arg, "--resolved")) {
+			resolved = 1;
+			continue;
+		}
+		if (!strncmp(arg, "--whitespace=", 13)) {
+			strncpy(whitespace, arg, sizeof(whitespace));
+			continue;
+		}
+		if (!strncmp(arg, "--resolvemsg=", 13)) {
+			resolvmsg = arg + 13;
+			continue;
+		}
+		if (!strncmp(arg, "--dotest", 8)) {
+			if (arg[8] == '=')
+				dotest = arg + 9;
+			else {
+				i++;
+				if (argv[i] == NULL)
+					die(builtin_am_usage);
+				dotest = argv[i];
+			}
+			continue;
+		}
+		usage(builtin_am_usage);
+	}
+	mbox = argv + i;
+
+	if (!dotest)
+		dotest = ".dotest";
+
+	/* Cleanup old .dotest */
+	if (mbox && !access(dotest, F_OK))
+		if (fcat("next", "%d", &this) && fcat("last", "%d",  &last))
+			if (this > last)
+				rm_rf(dotest);
+
+	if (!access(dotest, F_OK)) {
+		if (mbox != NULL)
+			die("previous dotest directory \"%s\" still exists but mbox given.", dotest);
+		resume = 1;
+	} else {
+		if (skip || resolved)
+			die("Resolve operation not in progress, we are not resuming.");
+
+		if (mkdir_p(dotest))
+			die("Unable to create directory %s.", dotest);
+
+		if ((last = split_mbox(mbox, dotest, 1 /*allow bare*/, PATCH_PREC, 0 /*skip*/)) == -1) {
+			rm_rf(dotest);
+			die("split_mbox failed");
+		}
+
+		/*
+		  -b, -s, -u, -k and --whitespace flags are kept for the
+		  resuming session after a patch failure.
+		  -3 and -i can and must be given when resuming.
+		*/
+		fecho("binary", "%d\n", binary);
+		fecho("whitespace", "%s\n", whitespace);
+		fecho("sign", "%d\n", signoff);
+		fecho("utf8", "%d\n", utf8);
+		fecho("keep", "%d\n", keep_subject);
+		fecho("next", "%d\n", 1);
+		fecho("last", "%d\n", last);
+	}
+
+	if (!resolved) {
+		/* Make sure we have a clean index */
+		char buf[PATH_MAX];
+		int status = 0;
+		FILE *f;
+
+		if ((f = get_output("git-diff-index --name-only HEAD", &status)) == NULL || status)
+			die("Command: \"git-diff-index --name-only HEAD\" failed");
+
+		if ((status = fgetc(f)) != EOF) {
+			ungetc(status, f);
+			fprintf(stderr, "Dirty index: cannot apply patches. Dirty files:\n");
+			while (fgets(buf, sizeof(buf), f))
+				fprintf(stderr, "%s", buf);
+			return 1;
+		}
+		fclose(f);
+	}
+
+	/* Read back saved state */
+	fcat("binary", "%d", &binary);
+	fcat("utf8", "%d", &utf8);
+	fcat("keep", "%d", &keep_subject);
+	fcat("whitespace", "%40[^\n]", whitespace);
+	fcat("sign", "%d", &signoff);
+	fcat("last", "%d", &last);
+	fcat("next", "%d", &this);
+
+	if (this > last) {
+		printf("Nothing to do.\n");
+		rm_rf(dotest);
+		return 0;
+	}
+
+	if (signoff) {
+		int off = snprintf(sign, sizeof(sign), "Signed-off-by: %s <%s>",
+				   getenv("GIT_COMMITTER_NAME"), getenv("GIT_COMMITTER_EMAIL"));
+		if (off > sizeof(sign))
+			die ("Impossibly long committer identifier");
+	}
+
+	if (skip) {
+		this++;
+		resume = 0;
+	}
+
+	while (this <= last) {
+		char patch_no[PATCH_PREC + 1];
+		char name[1000];
+		char email[1000];
+		char date[1000];
+		char s[1000] = "[PATCH] ", *subject = &s[0];
+
+		snprintf(patch_no, sizeof(patch_no), "%0*d", PATCH_PREC, this);
+
+		if (access(mkpath("%s/%s", dotest, patch_no), F_OK)) {
+			resume = 0;
+			this = go_next(this);
+			continue;
+		}
+
+		/*
+		  If we are not resuming, parse and extract the patch information
+		  into separate files:
+		  - info records the authorship and title
+		  - msg is the rest of commit log message
+		  - patch is the patch body.
+
+		 When we are resuming, these files are either already prepared
+		 by the user, or the user can tell us to do so by --resolved flag.
+		*/
+		if (!resume) {
+			FILE *out, *in;
+			char msg_path[PATH_MAX];
+
+			if ((out = fopen(mkpath("%s/info", dotest), "w")) == NULL) {
+				perror(mkpath("%s/info", dotest));
+				die("fopen failed");
+			}
+			if ((in = fopen(mkpath("%s/%s", dotest, patch_no), "r")) == NULL) {
+				perror(mkpath("%s/%s", dotest, patch_no));
+				die("fopen failed");
+			}
+
+			snprintf(msg_path, sizeof(msg_path), "%s/msg", dotest);
+			if (mailinfo(in, out, keep_subject, utf8 ? git_commit_encoding : NULL,
+			    msg_path, mkpath("%s/patch",dotest)))
+				    stop_here(this);
+			fclose(in);
+			fclose(out);
+
+			in = fopen(msg_path, "r");
+			out = fopen(mkpath("%s/msg-clean", dotest), "w");
+			stripspace(in, out);
+			fclose(in);
+			fclose(out);
+		}
+
+		fcat("info", "Author: %1000[^\n]\nEmail: %1000s\n"
+		     "Subject: %992[^\n]\nDate: %1000[^\n]\n\n",
+		     name, email, subject + 8 /*[PATCH] */, date);
+
+		if (!keep_subject)
+			subject = subject + 8; /*[PATCH] */
+
+		if (email == NULL || !strcmp(email, "")) {
+			printf("Patch does not have a valid e-mail address.\n");
+			stop_here(this);
+		}
+
+		if (!resume) { /* Prepare the commit-message and the patch */
+			char c, *t;
+			char line[1000];
+			char last_signoff[1000] = "";
+			FILE *cmt, *msg;
+
+			/* Find the last Signed-off line */
+			msg = fopen(mkpath("%s/msg-clean", dotest), "r");
+			while ((fgets(line, sizeof(line), msg))) {
+				if ((t = strstr(line, "Signed-off-by: ")))
+					strncpy(last_signoff, t, sizeof(last_signoff));
+			}
+			if ((t = strrchr(last_signoff, '>')))
+				*++t = '\0';
+
+			/* Write the commit-mesage */
+			cmt = fopen(mkpath("%s/final-commit", dotest), "w");
+			fprintf(cmt, "%s\n", subject);
+
+			rewind(msg);
+			if ((c = fgetc(msg)) != EOF) {
+				fprintf(cmt, "\n");
+				ungetc(c, msg);
+			}
+			while (fgets(line, sizeof(line), msg))
+				fputs(line, cmt);
+
+			/* Add a signoff */
+			if (signoff && strcmp(last_signoff, sign)) {
+				if (!strcmp(last_signoff, ""))
+					fputc('\n', cmt);
+				fputs(sign, cmt);
+			}
+			fclose(cmt);
+			fclose(msg);
+		} else
+			if (resolved && interactive)
+				/* This is used only for interactive view option. */
+				system(mkpath("git-diff-index -p --cached HEAD >\"%s/patch\"", dotest));
+
+		resume = 0;
+		if (interactive)
+			action = go_interactive();
+		else
+			action = YES;
+
+		if (action == SKIP) {
+			this = go_next(this);
+			continue;
+		}
+
+		if (!access(mkpath("%s/hooks/applypatch-msg", get_git_dir()), X_OK))
+			if (system(mkpath("%s/hooks/applypatch-msg %s/final-commit", get_git_dir(), dotest)))
+				stop_here(this);
+
+		printf("\nApplying %s\n\n", subject);
+
+		if (!resolved) {
+			/*git-apply $binary --index $ws "$dotest/patch" */
+			char patch[PATH_MAX];
+			char *opts[6] = { "git-apply", "--allow-binary-replacement", "--index", NULL, NULL, NULL };
+			char **opt = &opts[0];
+			int optc = 5;
+
+			if (!binary) {
+				opts[1] = "git-apply";
+				opt++; optc--;
+			}
+			opts[3] = whitespace;
+			snprintf(patch, sizeof(patch), "%s/patch", dotest);
+			opts[4] = patch;
+			apply_status = cmd_apply(optc, (const char**)opt, envp);
+		} else {
+			/* Resolved means the user did all the hard work, and
+			   we do not have to do any patch application.  Just
+			   trust what the user has in the index file and the
+			   working tree.*/
+			resolved = 0;
+
+			if (has_zero_output("git-diff-index --cached --name-only HEAD")) {
+				printf("No changes - did you forget update-index?\n");
+				stop_here_user_resolve(this);
+			}
+			if (!has_zero_output("git-ls-files -u")) {
+				printf("You still have unmerged paths in your index,\n"
+					"did you forget update-index?");
+				stop_here_user_resolve(this);
+			}
+			apply_status = 0;
+		}
+
+		if (apply_status && threeway) {
+			fall_back_3way();
+			/* Applying the patch to an earlier tree and merging the
+			   result may have produced the same tree as ours. */
+			if (has_zero_output("git-diff-index --cached --name-only HEAD")) {
+				printf("No changes -- Patch already applied.\n");
+				this = go_next(this);
+				continue;
+			}
+			/* We have merged successfully */
+			apply_status = 0;
+		}
+
+		if (apply_status) {
+			printf("Patch failed at %s\n.", patch_no);
+			stop_here_user_resolve(this);
+		}
+
+		if (!access(mkpath("%s/hooks/pre-applypatch", get_git_dir()), X_OK))
+			if (system(mkpath("%s/hooks/pre-applypatch", get_git_dir())))
+				stop_here(this);
+
+		if (commit(subject) == -1)
+			stop_here(this);
+
+		if (!access(mkpath("%s/hooks/post-applypatch", get_git_dir()), X_OK))
+			system(mkpath("%s/hooks/post-applypatch", get_git_dir()));
+
+		this = go_next(this);
+	}
+	rm_rf(dotest);
+	return 0;
+}
diff --git a/builtin.h b/builtin.h
index c1f3395..8771e36 100644
--- a/builtin.h
+++ b/builtin.h
@@ -49,6 +49,7 @@ extern int cmd_cat_file(int argc, const 
 extern int cmd_rev_parse(int argc, const char **argv, char **envp);
 extern int cmd_update_index(int argc, const char **argv, char **envp);
 extern int cmd_update_ref(int argc, const char **argv, char **envp);
+extern int cmd_am(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);
diff --git a/git-am.sh b/git-am.sh
deleted file mode 100755
index 4232e27..0000000
--- a/git-am.sh
+++ /dev/null
@@ -1,427 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005, 2006 Junio C Hamano
-
-USAGE='[--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way]
-  [--interactive] [--whitespace=<option>] <mbox>...
-  or, when resuming [--skip | --resolved]'
-. git-sh-setup
-
-git var GIT_COMMITTER_IDENT >/dev/null || exit
-
-stop_here () {
-    echo "$1" >"$dotest/next"
-    exit 1
-}
-
-stop_here_user_resolve () {
-    if [ -n "$resolvemsg" ]; then
-	    echo "$resolvemsg"
-	    stop_here $1
-    fi
-    cmdline=$(basename $0)
-    if test '' != "$interactive"
-    then
-        cmdline="$cmdline -i"
-    fi
-    if test '' != "$threeway"
-    then
-        cmdline="$cmdline -3"
-    fi
-    if test '.dotest' != "$dotest"
-    then
-        cmdline="$cmdline -d=$dotest"
-    fi
-    echo "When you have resolved this problem run \"$cmdline --resolved\"."
-    echo "If you would prefer to skip this patch, instead run \"$cmdline --skip\"."
-
-    stop_here $1
-}
-
-go_next () {
-	rm -f "$dotest/$msgnum" "$dotest/msg" "$dotest/msg-clean" \
-		"$dotest/patch" "$dotest/info"
-	echo "$next" >"$dotest/next"
-	this=$next
-}
-
-fall_back_3way () {
-    O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
-
-    rm -fr "$dotest"/patch-merge-*
-    mkdir "$dotest/patch-merge-tmp-dir"
-
-    # First see if the patch records the index info that we can use.
-    if git-apply -z --index-info "$dotest/patch" \
-	>"$dotest/patch-merge-index-info" 2>/dev/null &&
-	GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
-	git-update-index -z --index-info <"$dotest/patch-merge-index-info" &&
-	GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
-	git-write-tree >"$dotest/patch-merge-base+" &&
-	# index has the base tree now.
-	GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
-	git-apply $binary --cached <"$dotest/patch"
-    then
-	echo Using index info to reconstruct a base tree...
-	mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base"
-	mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index"
-    fi
-
-    test -f "$dotest/patch-merge-index" &&
-    his_tree=$(GIT_INDEX_FILE="$dotest/patch-merge-index" git-write-tree) &&
-    orig_tree=$(cat "$dotest/patch-merge-base") &&
-    rm -fr "$dotest"/patch-merge-* || exit 1
-
-    echo Falling back to patching base and 3-way merge...
-
-    # This is not so wrong.  Depending on which base we picked,
-    # orig_tree may be wildly different from ours, but his_tree
-    # has the same set of wildly different changes in parts the
-    # patch did not touch, so resolve ends up cancelling them,
-    # saying that we reverted all those changes.
-
-    git-merge-resolve $orig_tree -- HEAD $his_tree || {
-	    if test -d "$GIT_DIR/rr-cache"
-	    then
-		git-rerere
-	    fi
-	    echo Failed to merge in the changes.
-	    exit 1
-    }
-}
-
-prec=4
-dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary= ws= resolvemsg=
-
-while case "$#" in 0) break;; esac
-do
-	case "$1" in
-	-d=*|--d=*|--do=*|--dot=*|--dote=*|--dotes=*|--dotest=*)
-	dotest=`expr "$1" : '-[^=]*=\(.*\)'`; shift ;;
-	-d|--d|--do|--dot|--dote|--dotes|--dotest)
-	case "$#" in 1) usage ;; esac; shift
-	dotest="$1"; shift;;
-
-	-i|--i|--in|--int|--inte|--inter|--intera|--interac|--interact|\
-	--interacti|--interactiv|--interactive)
-	interactive=t; shift ;;
-
-	-b|--b|--bi|--bin|--bina|--binar|--binary)
-	binary=t; shift ;;
-
-	-3|--3|--3w|--3wa|--3way)
-	threeway=t; shift ;;
-	-s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
-	sign=t; shift ;;
-	-u|--u|--ut|--utf|--utf8)
-	utf8=t; shift ;;
-	-k|--k|--ke|--kee|--keep)
-	keep=t; shift ;;
-
-	-r|--r|--re|--res|--reso|--resol|--resolv|--resolve|--resolved)
-	resolved=t; shift ;;
-
-	--sk|--ski|--skip)
-	skip=t; shift ;;
-
-	--whitespace=*)
-	ws=$1; shift ;;
-
-	--resolvemsg=*)
-	resolvemsg=$(echo "$1" | sed -e "s/^--resolvemsg=//"); shift ;;
-
-	--)
-	shift; break ;;
-	-*)
-	usage ;;
-	*)
-	break ;;
-	esac
-done
-
-# If the dotest directory exists, but we have finished applying all the
-# patches in them, clear it out.
-if test -d "$dotest" &&
-   last=$(cat "$dotest/last") &&
-   next=$(cat "$dotest/next") &&
-   test $# != 0 &&
-   test "$next" -gt "$last"
-then
-   rm -fr "$dotest"
-fi
-
-if test -d "$dotest"
-then
-	test ",$#," = ",0," ||
-	die "previous dotest directory $dotest still exists but mbox given."
-	resume=yes
-else
-	# Make sure we are not given --skip nor --resolved
-	test ",$skip,$resolved," = ,,, ||
-		die "Resolve operation not in progress, we are not resuming."
-
-	# Start afresh.
-	mkdir -p "$dotest" || exit
-
-	git-mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" ||  {
-		rm -fr "$dotest"
-		exit 1
-	}
-
-	# -b, -s, -u, -k and --whitespace flags are kept for the
-	# resuming session after a patch failure.
-	# -3 and -i can and must be given when resuming.
-	echo "$binary" >"$dotest/binary"
-	echo " $ws" >"$dotest/whitespace"
-	echo "$sign" >"$dotest/sign"
-	echo "$utf8" >"$dotest/utf8"
-	echo "$keep" >"$dotest/keep"
-	echo 1 >"$dotest/next"
-fi
-
-case "$resolved" in
-'')
-	files=$(git-diff-index --cached --name-only HEAD) || exit
-	if [ "$files" ]; then
-	   echo "Dirty index: cannot apply patches (dirty: $files)" >&2
-	   exit 1
-	fi
-esac
-
-if test "$(cat "$dotest/binary")" = t
-then
-	binary=--allow-binary-replacement
-fi
-if test "$(cat "$dotest/utf8")" = t
-then
-	utf8=-u
-fi
-if test "$(cat "$dotest/keep")" = t
-then
-	keep=-k
-fi
-ws=`cat "$dotest/whitespace"`
-if test "$(cat "$dotest/sign")" = t
-then
-	SIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e '
-			s/>.*/>/
-			s/^/Signed-off-by: /'
-		`
-else
-	SIGNOFF=
-fi
-
-last=`cat "$dotest/last"`
-this=`cat "$dotest/next"`
-if test "$skip" = t
-then
-	this=`expr "$this" + 1`
-	resume=
-fi
-
-if test "$this" -gt "$last"
-then
-	echo Nothing to do.
-	rm -fr "$dotest"
-	exit
-fi
-
-while test "$this" -le "$last"
-do
-	msgnum=`printf "%0${prec}d" $this`
-	next=`expr "$this" + 1`
-	test -f "$dotest/$msgnum" || {
-		resume=
-		go_next
-		continue
-	}
-
-	# If we are not resuming, parse and extract the patch information
-	# into separate files:
-	#  - info records the authorship and title
-	#  - msg is the rest of commit log message
-	#  - patch is the patch body.
-	#
-	# When we are resuming, these files are either already prepared
-	# by the user, or the user can tell us to do so by --resolved flag.
-	case "$resume" in
-	'')
-		git-mailinfo $keep $utf8 "$dotest/msg" "$dotest/patch" \
-			<"$dotest/$msgnum" >"$dotest/info" ||
-			stop_here $this
-		git-stripspace < "$dotest/msg" > "$dotest/msg-clean"
-		;;
-	esac
-
-	GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$dotest/info")"
-	GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$dotest/info")"
-	GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$dotest/info")"
-
-	if test -z "$GIT_AUTHOR_EMAIL"
-	then
-		echo "Patch does not have a valid e-mail address."
-		stop_here $this
-	fi
-
-	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
-
-	SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$dotest/info")"
-	case "$keep_subject" in -k)  SUBJECT="[PATCH] $SUBJECT" ;; esac
-
-	case "$resume" in
-	'')
-	    if test '' != "$SIGNOFF"
-	    then
-		LAST_SIGNED_OFF_BY=`
-		    sed -ne '/^Signed-off-by: /p' \
-		    "$dotest/msg-clean" |
-		    tail -n 1
-		`
-		ADD_SIGNOFF=`
-		    test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || {
-		    test '' = "$LAST_SIGNED_OFF_BY" && echo
-		    echo "$SIGNOFF"
-		}`
-	    else
-		ADD_SIGNOFF=
-	    fi
-	    {
-		echo "$SUBJECT"
-		if test -s "$dotest/msg-clean"
-		then
-			echo
-			cat "$dotest/msg-clean"
-		fi
-		if test '' != "$ADD_SIGNOFF"
-		then
-			echo "$ADD_SIGNOFF"
-		fi
-	    } >"$dotest/final-commit"
-	    ;;
-	*)
-		case "$resolved$interactive" in
-		tt)
-			# This is used only for interactive view option.
-			git-diff-index -p --cached HEAD >"$dotest/patch"
-			;;
-		esac
-	esac
-
-	resume=
-	if test "$interactive" = t
-	then
-	    test -t 0 ||
-	    die "cannot be interactive without stdin connected to a terminal."
-	    action=again
-	    while test "$action" = again
-	    do
-		echo "Commit Body is:"
-		echo "--------------------------"
-		cat "$dotest/final-commit"
-		echo "--------------------------"
-		printf "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
-		read reply
-		case "$reply" in
-		[yY]*) action=yes ;;
-		[aA]*) action=yes interactive= ;;
-		[nN]*) action=skip ;;
-		[eE]*) "${VISUAL:-${EDITOR:-vi}}" "$dotest/final-commit"
-		       action=again ;;
-		[vV]*) action=again
-		       LESS=-S ${PAGER:-less} "$dotest/patch" ;;
-		*)     action=again ;;
-		esac
-	    done
-	else
-	    action=yes
-	fi
-
-	if test $action = skip
-	then
-		go_next
-		continue
-	fi
-
-	if test -x "$GIT_DIR"/hooks/applypatch-msg
-	then
-		"$GIT_DIR"/hooks/applypatch-msg "$dotest/final-commit" ||
-		stop_here $this
-	fi
-
-	echo
-	echo "Applying '$SUBJECT'"
-	echo
-
-	case "$resolved" in
-	'')
-		git-apply $binary --index $ws "$dotest/patch"
-		apply_status=$?
-		;;
-	t)
-		# Resolved means the user did all the hard work, and
-		# we do not have to do any patch application.  Just
-		# trust what the user has in the index file and the
-		# working tree.
-		resolved=
-		changed="$(git-diff-index --cached --name-only HEAD)"
-		if test '' = "$changed"
-		then
-			echo "No changes - did you forget update-index?"
-			stop_here_user_resolve $this
-		fi
-		unmerged=$(git-ls-files -u)
-		if test -n "$unmerged"
-		then
-			echo "You still have unmerged paths in your index"
-			echo "did you forget update-index?"
-			stop_here_user_resolve $this
-		fi
-		apply_status=0
-		;;
-	esac
-
-	if test $apply_status = 1 && test "$threeway" = t
-	then
-		if (fall_back_3way)
-		then
-		    # Applying the patch to an earlier tree and merging the
-		    # result may have produced the same tree as ours.
-		    changed="$(git-diff-index --cached --name-only HEAD)"
-		    if test '' = "$changed"
-		    then
-			    echo No changes -- Patch already applied.
-			    go_next
-			    continue
-		    fi
-		    # clear apply_status -- we have successfully merged.
-		    apply_status=0
-		fi
-	fi
-	if test $apply_status != 0
-	then
-		echo Patch failed at $msgnum.
-		stop_here_user_resolve $this
-	fi
-
-	if test -x "$GIT_DIR"/hooks/pre-applypatch
-	then
-		"$GIT_DIR"/hooks/pre-applypatch || stop_here $this
-	fi
-
-	tree=$(git-write-tree) &&
-	echo Wrote tree $tree &&
-	parent=$(git-rev-parse --verify HEAD) &&
-	commit=$(git-commit-tree $tree -p $parent <"$dotest/final-commit") &&
-	echo Committed: $commit &&
-	git-update-ref -m "am: $SUBJECT" HEAD $commit $parent ||
-	stop_here $this
-
-	if test -x "$GIT_DIR"/hooks/post-applypatch
-	then
-		"$GIT_DIR"/hooks/post-applypatch
-	fi
-
-	go_next
-done
-
-rm -fr "$dotest"
diff --git a/git.c b/git.c
index 652e3c4..b9261e4 100644
--- a/git.c
+++ b/git.c
@@ -184,7 +184,8 @@ static void handle_internal_command(int 
 		{ "mailinfo", cmd_mailinfo },
 		{ "stripspace", cmd_stripspace },
 		{ "update-index", cmd_update_index },
-		{ "update-ref", cmd_update_ref }
+		{ "update-ref", cmd_update_ref },
+		{ "am", cmd_am }
 	};
 	int i;
 
-- 
1.4.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 6/8] Make git-update-ref a builtin
  2006-06-13 20:22 ` [PATCH 6/8] Make git-update-ref " Lukas Sandström
@ 2006-06-14  2:22   ` Shawn Pearce
  0 siblings, 0 replies; 9+ messages in thread
From: Shawn Pearce @ 2006-06-14  2:22 UTC (permalink / raw)
  To: Lukas Sandström; +Cc: Junio C Hamano, Git Mailing List

Lukas Sandstr?m <lukass@etek.chalmers.se> wrote:
> Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
> ---
>  Makefile                             |    7 ++++---
>  update-ref.c => builtin-update-ref.c |    5 ++++-
>  builtin.h                            |    1 +
>  git.c                                |    3 ++-
>  4 files changed, 11 insertions(+), 5 deletions(-)

Thanks for doing this.  I know I had written this change and I was
pretty sure I had sent it to Junio a while ago but I guess it got
lost in the shuffle and I just failed to follow through with it
when it didn't show up in `next`.

-- 
Shawn.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2006-06-14  2:23 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <448EF791.7070504@etek.chalmers.se>
2006-06-13 20:21 ` [PATCH 1/8] Make git-write-tree a builtin Lukas Sandström
2006-06-13 20:21 ` [PATCH 2/8] Make git-mailsplit " Lukas Sandström
2006-06-13 20:21 ` [PATCH 3/8] Make git-mailinfo " Lukas Sandström
2006-06-13 20:21 ` [PATCH 4/8] Make git-stripspace " Lukas Sandström
2006-06-13 20:21 ` [PATCH 5/8] Make git-update-index " Lukas Sandström
2006-06-13 20:22 ` [PATCH 6/8] Make git-update-ref " Lukas Sandström
2006-06-14  2:22   ` Shawn Pearce
2006-06-13 20:22 ` [PATCH 7/8] Make it possible to call cmd_apply multiple times Lukas Sandström
2006-06-13 20:22 ` [PATCH/RFC 8/8] Make git-am a builtin Lukas Sandström

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).