* [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).