diff options
-rw-r--r-- | Documentation/git-repo-config.txt | 12 | ||||
-rw-r--r-- | Makefile | 42 | ||||
-rw-r--r-- | alloc.c | 51 | ||||
-rw-r--r-- | blame.c | 4 | ||||
-rw-r--r-- | blob.c | 2 | ||||
-rw-r--r-- | builtin-diff-files.c | 2 | ||||
-rw-r--r-- | builtin-diff-index.c | 2 | ||||
-rw-r--r-- | builtin-diff-tree.c | 42 | ||||
-rw-r--r-- | builtin-diff.c | 26 | ||||
-rw-r--r-- | builtin-grep.c | 16 | ||||
-rw-r--r-- | builtin-log.c | 4 | ||||
-rw-r--r-- | builtin-mailinfo.c (renamed from mailinfo.c) | 85 | ||||
-rw-r--r-- | builtin-mailsplit.c (renamed from mailsplit.c) | 71 | ||||
-rw-r--r-- | builtin-read-tree.c | 3 | ||||
-rw-r--r-- | builtin-rev-list.c | 64 | ||||
-rw-r--r-- | builtin-stripspace.c (renamed from stripspace.c) | 16 | ||||
-rw-r--r-- | builtin-update-index.c (renamed from update-index.c) | 19 | ||||
-rw-r--r-- | builtin-update-ref.c (renamed from update-ref.c) | 5 | ||||
-rw-r--r-- | builtin-write-tree.c (renamed from write-tree.c) | 68 | ||||
-rw-r--r-- | builtin.h | 15 | ||||
-rw-r--r-- | cache.h | 11 | ||||
-rw-r--r-- | commit.c | 23 | ||||
-rw-r--r-- | config.c | 43 | ||||
-rw-r--r-- | connect.c | 5 | ||||
-rw-r--r-- | contrib/git-svn/Makefile | 3 | ||||
-rwxr-xr-x | contrib/git-svn/git-svn.perl | 15 | ||||
-rw-r--r-- | contrib/git-svn/t/t0002-deep-rmdir.sh | 29 | ||||
-rw-r--r-- | daemon.c | 5 | ||||
-rw-r--r-- | diff-delta.c | 3 | ||||
-rw-r--r-- | diff-lib.c | 45 | ||||
-rw-r--r-- | diff.c | 79 | ||||
-rw-r--r-- | diff.h | 3 | ||||
-rw-r--r-- | git.c | 8 | ||||
-rw-r--r-- | http-fetch.c | 13 | ||||
-rw-r--r-- | http-push.c | 41 | ||||
-rw-r--r-- | imap-send.c | 2 | ||||
-rw-r--r-- | merge-index.c | 5 | ||||
-rw-r--r-- | name-rev.c | 19 | ||||
-rw-r--r-- | object.c | 17 | ||||
-rw-r--r-- | object.h | 13 | ||||
-rw-r--r-- | pager.c | 2 | ||||
-rw-r--r-- | quote.c | 9 | ||||
-rw-r--r-- | repo-config.c | 37 | ||||
-rw-r--r-- | revision.c | 33 | ||||
-rw-r--r-- | revision.h | 12 | ||||
-rw-r--r-- | t/Makefile | 2 | ||||
-rw-r--r-- | t/annotate-tests.sh | 2 | ||||
-rwxr-xr-x | t/t1300-repo-config.sh | 24 | ||||
-rw-r--r-- | tag.c | 2 | ||||
-rw-r--r-- | tree.c | 2 | ||||
-rw-r--r-- | xdiff/xutils.c | 11 | ||||
-rw-r--r-- | xdiff/xutils.h | 1 |
52 files changed, 727 insertions, 341 deletions
diff --git a/Documentation/git-repo-config.txt b/Documentation/git-repo-config.txt index d5142e0dcd..803c0d5cae 100644 --- a/Documentation/git-repo-config.txt +++ b/Documentation/git-repo-config.txt @@ -73,6 +73,18 @@ OPTIONS List all variables set in .git/config. +ENVIRONMENT +----------- + +GIT_CONFIG:: + Take the configuration from the given file instead of .git/config. + +GIT_CONFIG_LOCAL:: + Currently the same as $GIT_CONFIG; when Git will support global + configuration files, this will cause it to take the configuration + from the global configuration file in addition to the given file. + + EXAMPLE ------- @@ -144,34 +144,33 @@ 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 + git-daemon$X # ... and all the rest that could be moved out of bindir to gitexecdir 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 \ 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-update-ref$X git-symbolic-ref$X \ + git-unpack-objects$X git-update-server-info$X \ + git-upload-pack$X git-verify-pack$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 \ - git-count-objects$X git-diff$X git-push$X \ - git-grep$X git-add$X git-rm$X git-rev-list$X \ - git-check-ref-format$X git-rev-parse$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 \ 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-apply$X git-show-branch$X git-diff-files$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-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 @@ -216,18 +215,19 @@ LIB_OBJS = \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \ - $(DIFF_OBJS) + alloc.o $(DIFF_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-tar-tree.o builtin-upload-tar.o \ - builtin-ls-files.o builtin-ls-tree.o \ - builtin-read-tree.o builtin-commit-tree.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 \ builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \ - builtin-cat-file.o + builtin-cat-file.o builtin-mailsplit.o builtin-stripspace.o \ + builtin-update-ref.o GITLIBS = $(LIB_FILE) $(XDIFF_LIB) LIBS = $(GITLIBS) -lz @@ -380,9 +380,7 @@ ifdef NEEDS_LIBICONV else ICONV_LINK = endif - LIB_4_ICONV = $(ICONV_LINK) -liconv -else - LIB_4_ICONV = + LIBS += $(ICONV_LINK) -liconv endif ifdef NEEDS_SOCKET LIBS += -lsocket @@ -565,10 +563,6 @@ $(SIMPLE_PROGRAMS) : git-%$X : %.o $(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/alloc.c b/alloc.c new file mode 100644 index 0000000000..e3b22f4322 --- /dev/null +++ b/alloc.c @@ -0,0 +1,51 @@ +/* + * alloc.c - specialized allocator for internal objects + * + * Copyright (C) 2006 Linus Torvalds + * + * The standard malloc/free wastes too much space for objects, partly because + * it maintains all the allocation infrastructure (which isn't needed, since + * we never free an object descriptor anyway), but even more because it ends + * up with maximal alignment because it doesn't know what the object alignment + * for the new allocation is. + */ +#include "cache.h" +#include "object.h" +#include "blob.h" +#include "tree.h" +#include "commit.h" +#include "tag.h" + +#define BLOCKING 1024 + +#define DEFINE_ALLOCATOR(name) \ +static unsigned int name##_allocs; \ +struct name *alloc_##name##_node(void) \ +{ \ + static int nr; \ + static struct name *block; \ + \ + if (!nr) { \ + nr = BLOCKING; \ + block = xcalloc(BLOCKING, sizeof(struct name)); \ + } \ + nr--; \ + name##_allocs++; \ + return block++; \ +} + +DEFINE_ALLOCATOR(blob) +DEFINE_ALLOCATOR(tree) +DEFINE_ALLOCATOR(commit) +DEFINE_ALLOCATOR(tag) + +#define REPORT(name) \ + fprintf(stderr, "%10s: %8u (%zu kB)\n", #name, name##_allocs, name##_allocs*sizeof(struct name) >> 10) + +void alloc_report(void) +{ + REPORT(blob); + REPORT(tree); + REPORT(commit); + REPORT(tag); +} @@ -301,9 +301,9 @@ static void fill_line_map(struct commit *commit, struct commit *other, if (DEBUG) printf("map: i1: %d %d %p i2: %d %d %p\n", i1, map[i1], - i1 != -1 ? blame_lines[map[i1]] : NULL, + (void *) (i1 != -1 ? blame_lines[map[i1]] : NULL), i2, map2[i2], - i2 != -1 ? blame_lines[map2[i2]] : NULL); + (void *) (i2 != -1 ? blame_lines[map2[i2]] : NULL)); if (map2[i2] != -1 && blame_lines[map[i1]] && !blame_lines[map2[i2]]) @@ -8,7 +8,7 @@ struct blob *lookup_blob(const unsigned char *sha1) { struct object *obj = lookup_object(sha1); if (!obj) { - struct blob *ret = xcalloc(1, sizeof(struct blob)); + struct blob *ret = alloc_blob_node(); created_object(sha1, &ret->object); ret->object.type = TYPE_BLOB; return ret; diff --git a/builtin-diff-files.c b/builtin-diff-files.c index cebda828ee..5afc1d7208 100644 --- a/builtin-diff-files.c +++ b/builtin-diff-files.c @@ -41,7 +41,7 @@ int cmd_diff_files(int argc, const char **argv, char **envp) * rev.max_count is reasonable (0 <= n <= 3), * there is no other revision filtering parameters. */ - if (rev.pending_objects || + if (rev.pending.nr || rev.min_age != -1 || rev.max_age != -1) usage(diff_files_usage); /* diff --git a/builtin-diff-index.c b/builtin-diff-index.c index 1958580d82..c42ef9a7a7 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -32,7 +32,7 @@ int cmd_diff_index(int argc, const char **argv, char **envp) * Make sure there is one revision (i.e. pending object), * and there is no revision filtering parameters. */ - if (!rev.pending_objects || rev.pending_objects->next || + if (rev.pending.nr != 1 || rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1) usage(diff_cache_usage); return run_diff_index(&rev, cached); diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index 58cf65856d..3409a39a9f 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -65,7 +65,6 @@ int cmd_diff_tree(int argc, const char **argv, char **envp) char line[1000]; struct object *tree1, *tree2; static struct rev_info *opt = &log_tree_opt; - struct object_list *list; int read_stdin = 0; git_config(git_diff_config); @@ -86,45 +85,28 @@ int cmd_diff_tree(int argc, const char **argv, char **envp) } /* - * NOTE! "setup_revisions()" will have inserted the revisions - * it parsed in reverse order. So if you do - * - * git-diff-tree a b - * - * the commit list will be "b" -> "a" -> NULL, so we reverse - * the order of the objects if the first one is not marked - * UNINTERESTING. + * NOTE! We expect "a ^b" to be equal to "a..b", so we + * reverse the order of the objects if the second one + * is marked UNINTERESTING. */ - nr_sha1 = 0; - list = opt->pending_objects; - if (list) { - nr_sha1++; - tree1 = list->item; - list = list->next; - if (list) { - nr_sha1++; - tree2 = tree1; - tree1 = list->item; - if (list->next) - usage(diff_tree_usage); - /* Switch them around if the second one was uninteresting.. */ - if (tree2->flags & UNINTERESTING) { - struct object *tmp = tree2; - tree2 = tree1; - tree1 = tmp; - } - } - } - + nr_sha1 = opt->pending.nr; switch (nr_sha1) { case 0: if (!read_stdin) usage(diff_tree_usage); break; case 1: + tree1 = opt->pending.objects[0].item; diff_tree_commit_sha1(tree1->sha1); break; case 2: + tree1 = opt->pending.objects[0].item; + tree2 = opt->pending.objects[1].item; + if (tree2->flags & UNINTERESTING) { + struct object *tmp = tree2; + tree2 = tree1; + tree1 = tmp; + } diff_tree_sha1(tree1->sha1, tree2->sha1, "", &opt->diffopt); diff --git a/builtin-diff.c b/builtin-diff.c index 6ac3d4b8ca..99a2f76605 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -50,7 +50,7 @@ static int builtin_diff_files(struct rev_info *revs, * specified rev.max_count is reasonable (0 <= n <= 3), and * there is no other revision filtering parameter. */ - if (revs->pending_objects || + if (revs->pending.nr || revs->min_age != -1 || revs->max_age != -1 || 3 < revs->max_count) @@ -172,7 +172,7 @@ static int builtin_diff_index(struct rev_info *revs, * Make sure there is one revision (i.e. pending object), * and there is no revision filtering parameters. */ - if (!revs->pending_objects || revs->pending_objects->next || + if (revs->pending.nr != 1 || revs->max_count != -1 || revs->min_age != -1 || revs->max_age != -1) usage(builtin_diff_usage); @@ -181,10 +181,10 @@ static int builtin_diff_index(struct rev_info *revs, static int builtin_diff_tree(struct rev_info *revs, int argc, const char **argv, - struct object_list *ent) + struct object_array_entry *ent) { const unsigned char *(sha1[2]); - int swap = 1; + int swap = 0; while (1 < argc) { const char *arg = argv[1]; if (!strcmp(arg, "--raw")) @@ -195,10 +195,10 @@ static int builtin_diff_tree(struct rev_info *revs, } /* We saw two trees, ent[0] and ent[1]. - * unless ent[0] is unintesting, they are swapped + * if ent[1] is unintesting, they are swapped */ - if (ent[0].item->flags & UNINTERESTING) - swap = 0; + if (ent[1].item->flags & UNINTERESTING) + swap = 1; sha1[swap] = ent[0].item->sha1; sha1[1-swap] = ent[1].item->sha1; diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt); @@ -208,7 +208,7 @@ static int builtin_diff_tree(struct rev_info *revs, static int builtin_diff_combined(struct rev_info *revs, int argc, const char **argv, - struct object_list *ent, + struct object_array_entry *ent, int ents) { const unsigned char (*parent)[20]; @@ -242,13 +242,14 @@ void add_head(struct rev_info *revs) obj = parse_object(sha1); if (!obj) return; - add_object(obj, &revs->pending_objects, NULL, "HEAD"); + add_pending_object(revs, obj, "HEAD"); } int cmd_diff(int argc, const char **argv, char **envp) { + int i; struct rev_info rev; - struct object_list *list, ent[100]; + struct object_array_entry ent[100]; int ents = 0, blobs = 0, paths = 0; const char *path = NULL; struct blobinfo blob[2]; @@ -281,7 +282,7 @@ int cmd_diff(int argc, const char **argv, char **envp) /* Do we have --cached and not have a pending object, then * default to HEAD by hand. Eek. */ - if (!rev.pending_objects) { + if (!rev.pending.nr) { int i; for (i = 1; i < argc; i++) { const char *arg = argv[i]; @@ -294,7 +295,8 @@ int cmd_diff(int argc, const char **argv, char **envp) } } - for (list = rev.pending_objects; list; list = list->next) { + for (i = 0; i < rev.pending.nr; i++) { + struct object_array_entry *list = rev.pending.objects+i; struct object *obj = list->item; const char *name = list->name; int flags = (obj->flags & UNINTERESTING); diff --git a/builtin-grep.c b/builtin-grep.c index 9806499263..6a240fb6e9 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -657,7 +657,7 @@ int cmd_grep(int argc, const char **argv, char **envp) int cached = 0; int seen_dashdash = 0; struct grep_opt opt; - struct object_list *list, **tail, *object_list = NULL; + struct object_array list = { 0, 0, NULL }; const char *prefix = setup_git_directory(); const char **paths = NULL; int i; @@ -677,7 +677,6 @@ int cmd_grep(int argc, const char **argv, char **envp) * that continues up to the -- (if exists), and then paths. */ - tail = &object_list; while (1 < argc) { const char *arg = argv[1]; argc--; argv++; @@ -851,12 +850,9 @@ int cmd_grep(int argc, const char **argv, char **envp) /* Is it a rev? */ if (!get_sha1(arg, sha1)) { struct object *object = parse_object(sha1); - struct object_list *elem; if (!object) die("bad object %s", arg); - elem = object_list_insert(object, tail); - elem->name = arg; - tail = &elem->next; + add_object_array(object, arg, &list); continue; } if (!strcmp(arg, "--")) { @@ -881,16 +877,16 @@ int cmd_grep(int argc, const char **argv, char **envp) paths[1] = NULL; } - if (!object_list) + if (!list.nr) return !grep_cache(&opt, paths, cached); if (cached) die("both --cached and trees are given."); - for (list = object_list; list; list = list->next) { + for (i = 0; i < list.nr; i++) { struct object *real_obj; - real_obj = deref_tag(list->item, NULL, 0); - if (grep_object(&opt, paths, real_obj, list->name)) + real_obj = deref_tag(list.objects[i].item, NULL, 0); + if (grep_object(&opt, paths, real_obj, list.objects[i].name)) hit = 1; } return !hit; diff --git a/builtin-log.c b/builtin-log.c index 9187fd337b..5a8a50b81d 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -257,8 +257,8 @@ int cmd_format_patch(int argc, const char **argv, char **envp) output_directory); } - if (rev.pending_objects && rev.pending_objects->next == NULL) { - rev.pending_objects->item->flags |= UNINTERESTING; + if (rev.pending.nr == 1) { + rev.pending.objects[0].item->flags |= UNINTERESTING; add_head(&rev); } diff --git a/mailinfo.c b/builtin-mailinfo.c index d9b74f30de..821642a7af 100644 --- a/mailinfo.c +++ b/builtin-mailinfo.c @@ -12,11 +12,12 @@ #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; +static const char *metainfo_charset = NULL; static char line[1000]; static char date[1000]; static char name[1000]; @@ -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; @@ -322,13 +323,13 @@ static char *cleanup_subject(char *subject) if (remove <= len *2) { subject = p+1; continue; - } + } break; } eatspace(subject); return subject; } -} +} static void cleanup_space(char *buf) { @@ -648,7 +649,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); } @@ -685,7 +686,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; @@ -706,7 +707,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 @@ -719,7 +720,7 @@ static int handle_multipart_one_part(int *seen) { int n = 0; - while (fgets(line, sizeof(line), stdin) != NULL) { + while (fgets(line, sizeof(line), fin) != NULL) { again: n++; if (is_multipart_boundary(line)) @@ -740,7 +741,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; @@ -749,7 +750,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; @@ -781,10 +782,45 @@ static void handle_body(void) } } +int mailinfo(FILE *in, FILE *out, int ks, const 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 @@ -805,27 +841,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/mailsplit.c b/builtin-mailsplit.c index 70a569c12a..e2a0058435 100644 --- a/mailsplit.c +++ b/builtin-mailsplit.c @@ -12,6 +12,7 @@ #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 char *name, int allow_bare) 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-read-tree.c b/builtin-read-tree.c index 04506da892..9a2099d730 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -31,8 +31,7 @@ static int merge_size = 0; static struct object_list *trees = NULL; -static struct cache_entry df_conflict_entry = { -}; +static struct cache_entry df_conflict_entry; struct tree_entry_list { struct tree_entry_list *next; diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 71353eb19d..63bad0e96a 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -99,26 +99,26 @@ static void show_commit(struct commit *commit) } } -static struct object_list **process_blob(struct blob *blob, - struct object_list **p, - struct name_path *path, - const char *name) +static void process_blob(struct blob *blob, + struct object_array *p, + struct name_path *path, + const char *name) { struct object *obj = &blob->object; if (!revs.blob_objects) - return p; + return; if (obj->flags & (UNINTERESTING | SEEN)) - return p; + return; obj->flags |= SEEN; name = strdup(name); - return add_object(obj, p, path, name); + add_object(obj, p, path, name); } -static struct object_list **process_tree(struct tree *tree, - struct object_list **p, - struct name_path *path, - const char *name) +static void process_tree(struct tree *tree, + struct object_array *p, + struct name_path *path, + const char *name) { struct object *obj = &tree->object; struct tree_desc desc; @@ -126,14 +126,14 @@ static struct object_list **process_tree(struct tree *tree, struct name_path me; if (!revs.tree_objects) - return p; + return; if (obj->flags & (UNINTERESTING | SEEN)) - return p; + return; if (parse_tree(tree) < 0) die("bad tree object %s", sha1_to_hex(obj->sha1)); obj->flags |= SEEN; name = strdup(name); - p = add_object(obj, p, path, name); + add_object(obj, p, path, name); me.up = path; me.elem = name; me.elem_len = strlen(name); @@ -143,57 +143,59 @@ static struct object_list **process_tree(struct tree *tree, while (tree_entry(&desc, &entry)) { if (S_ISDIR(entry.mode)) - p = process_tree(lookup_tree(entry.sha1), p, &me, entry.path); + process_tree(lookup_tree(entry.sha1), p, &me, entry.path); else - p = process_blob(lookup_blob(entry.sha1), p, &me, entry.path); + process_blob(lookup_blob(entry.sha1), p, &me, entry.path); } free(tree->buffer); tree->buffer = NULL; - return p; } static void show_commit_list(struct rev_info *revs) { + int i; struct commit *commit; - struct object_list *objects = NULL, **p = &objects, *pending; + struct object_array objects = { 0, 0, NULL }; while ((commit = get_revision(revs)) != NULL) { - p = process_tree(commit->tree, p, NULL, ""); + process_tree(commit->tree, &objects, NULL, ""); show_commit(commit); } - for (pending = revs->pending_objects; pending; pending = pending->next) { + for (i = 0; i < revs->pending.nr; i++) { + struct object_array_entry *pending = revs->pending.objects + i; struct object *obj = pending->item; const char *name = pending->name; if (obj->flags & (UNINTERESTING | SEEN)) continue; if (obj->type == TYPE_TAG) { obj->flags |= SEEN; - p = add_object(obj, p, NULL, name); + add_object_array(obj, name, &objects); continue; } if (obj->type == TYPE_TREE) { - p = process_tree((struct tree *)obj, p, NULL, name); + process_tree((struct tree *)obj, &objects, NULL, name); continue; } if (obj->type == TYPE_BLOB) { - p = process_blob((struct blob *)obj, p, NULL, name); + process_blob((struct blob *)obj, &objects, NULL, name); continue; } die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name); } - while (objects) { + for (i = 0; i < objects.nr; i++) { + struct object_array_entry *p = objects.objects + i; + /* An object with name "foo\n0000000..." can be used to * confuse downstream git-pack-objects very badly. */ - const char *ep = strchr(objects->name, '\n'); + const char *ep = strchr(p->name, '\n'); if (ep) { - printf("%s %.*s\n", sha1_to_hex(objects->item->sha1), - (int) (ep - objects->name), - objects->name); + printf("%s %.*s\n", sha1_to_hex(p->item->sha1), + (int) (ep - p->name), + p->name); } else - printf("%s %s\n", sha1_to_hex(objects->item->sha1), objects->name); - objects = objects->next; + printf("%s %s\n", sha1_to_hex(p->item->sha1), p->name); } } @@ -348,7 +350,7 @@ int cmd_rev_list(int argc, const char **argv, char **envp) if ((!list && (!(revs.tag_objects||revs.tree_objects||revs.blob_objects) && - !revs.pending_objects)) || + !revs.pending.nr)) || revs.diff) usage(rev_list_usage); diff --git a/stripspace.c b/builtin-stripspace.c index 65a6346452..2ce1264f7b 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/update-index.c b/builtin-update-index.c index fbccc4a67b..ef50243452 100644 --- a/update-index.c +++ b/builtin-update-index.c @@ -8,6 +8,7 @@ #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 char *path) 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_termination) * (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 char **av, 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 = xcalloc(1, 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/update-ref.c b/builtin-update-ref.c index a1e6bb90fe..00333c7e7c 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/write-tree.c b/builtin-write-tree.c index bd07da6183..70e9b6fcc6 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 = xcalloc(1, 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; +} @@ -1,6 +1,8 @@ #ifndef BUILTIN_H #define BUILTIN_H +#include <stdio.h> + #ifndef PATH_MAX # define PATH_MAX 4096 #endif @@ -45,5 +47,18 @@ extern int cmd_diff_stages(int argc, const char **argv, char **envp); 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_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); + +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, const 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 @@ -384,4 +384,15 @@ extern void setup_pager(void); int decode_85(char *dst, char *line, int linelen); void encode_85(char *buf, unsigned char *data, int bytes); +/* alloc.c */ +struct blob; +struct tree; +struct commit; +struct tag; +extern struct blob *alloc_blob_node(void); +extern struct tree *alloc_tree_node(void); +extern struct commit *alloc_commit_node(void); +extern struct tag *alloc_tag_node(void); +extern void alloc_report(void); + #endif /* CACHE_H */ @@ -84,7 +84,7 @@ struct commit *lookup_commit(const unsigned char *sha1) { struct object *obj = lookup_object(sha1); if (!obj) { - struct commit *ret = xcalloc(1, sizeof(struct commit)); + struct commit *ret = alloc_commit_node(); created_object(sha1, &ret->object); ret->object.type = TYPE_COMMIT; return ret; @@ -447,7 +447,7 @@ static int add_rfc2047(char *buf, const char *line, int len) memcpy(bp, q_utf8, sizeof(q_utf8)-1); bp += sizeof(q_utf8)-1; for (i = 0; i < len; i++) { - unsigned ch = line[i]; + unsigned ch = line[i] & 0xFF; if (is_rfc2047_special(ch)) { sprintf(bp, "=%02X", ch); bp += 3; @@ -571,10 +571,23 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit * to say this is not a 7-bit ASCII. */ if (fmt == CMIT_FMT_EMAIL && !after_subject) { - int i; - for (i = 0; !plain_non_ascii && msg[i] && i < len; i++) - if (msg[i] & 0x80) + int i, ch, in_body; + + for (in_body = i = 0; (ch = msg[i]) && i < len; i++) { + if (!in_body) { + /* author could be non 7-bit ASCII but + * the log may so; skip over the + * header part first. + */ + if (ch == '\n' && + i + 1 < len && msg[i+1] == '\n') + in_body = 1; + } + else if (ch & 0x80) { plain_non_ascii = 1; + break; + } + } } for (;;) { @@ -317,7 +317,33 @@ int git_config_from_file(config_fn_t fn, const char *filename) int git_config(config_fn_t fn) { - return git_config_from_file(fn, git_path("config")); + int ret = 0; + char *repo_config = NULL; + const char *home = NULL, *filename; + + /* $GIT_CONFIG makes git read _only_ the given config file, + * $GIT_CONFIG_LOCAL will make it process it in addition to the + * global config file, the same way it would the per-repository + * config file otherwise. */ + filename = getenv("GIT_CONFIG"); + if (!filename) { + home = getenv("HOME"); + filename = getenv("GIT_CONFIG_LOCAL"); + if (!filename) + filename = repo_config = strdup(git_path("config")); + } + + if (home) { + char *user_config = strdup(mkpath("%s/.gitconfig", home)); + if (!access(user_config, R_OK)) + ret = git_config_from_file(fn, user_config); + free(user_config); + } + + ret += git_config_from_file(fn, filename); + if (repo_config) + free(repo_config); + return ret; } /* @@ -490,10 +516,19 @@ int git_config_set_multivar(const char* key, const char* value, int i, dot; int fd = -1, in_fd; int ret; - char* config_filename = strdup(git_path("config")); - char* lock_file = strdup(git_path("config.lock")); + char* config_filename; + char* lock_file; const char* last_dot = strrchr(key, '.'); + config_filename = getenv("GIT_CONFIG"); + if (!config_filename) { + config_filename = getenv("GIT_CONFIG_LOCAL"); + if (!config_filename) + config_filename = git_path("config"); + } + config_filename = strdup(config_filename); + lock_file = strdup(mkpath("%s.lock", config_filename)); + /* * Since "key" actually contains the section name and the real * key name separated by a dot, we have to know where the dot is. @@ -600,7 +635,7 @@ int git_config_set_multivar(const char* key, const char* value, * As a side effect, we make sure to transform only a valid * existing config file. */ - if (git_config(store_aux)) { + if (git_config_from_file(store_aux, config_filename)) { fprintf(stderr, "invalid config file\n"); free(store.key); if (store.value_regex != NULL) { @@ -581,6 +581,11 @@ int git_connect(int fd[2], char *url, const char *prog) enum protocol protocol = PROTO_LOCAL; int free_path = 0; + /* Without this we cannot rely on waitpid() to tell + * what happened to our children. + */ + signal(SIGCHLD, SIG_DFL); + host = strstr(url, "://"); if(host) { *host = '\0'; diff --git a/contrib/git-svn/Makefile b/contrib/git-svn/Makefile index 6aedb10f12..7c20946943 100644 --- a/contrib/git-svn/Makefile +++ b/contrib/git-svn/Makefile @@ -29,8 +29,7 @@ git-svn.html : git-svn.txt asciidoc -b xhtml11 -d manpage \ -f ../../Documentation/asciidoc.conf $< test: git-svn - cd t && $(SHELL) ./t0000-contrib-git-svn.sh $(TEST_FLAGS) - cd t && $(SHELL) ./t0001-contrib-git-svn-props.sh $(TEST_FLAGS) + cd t && for i in t????-*.sh; do $(SHELL) ./$$i $(TEST_FLAGS); done # we can test NO_OPTIMIZE_COMMITS independently of LC_ALL full-test: diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl index da0ff9ad8a..7e7f2f0cd9 100755 --- a/contrib/git-svn/git-svn.perl +++ b/contrib/git-svn/git-svn.perl @@ -2841,13 +2841,20 @@ sub rmdirs { exec qw/git-ls-tree --name-only -r -z/, $self->{c} or croak $!; } local $/ = "\0"; + my @svn_path = split m#/#, $self->{svn_path}; while (<$fh>) { chomp; - $_ = $self->{svn_path} . '/' . $_; - my ($dn) = ($_ =~ m#^(.*?)/?(?:[^/]+)$#); - delete $rm->{$dn}; - last unless %$rm; + my @dn = (@svn_path, (split m#/#, $_)); + while (pop @dn) { + delete $rm->{join '/', @dn}; + } + unless (%$rm) { + close $fh; + return; + } } + close $fh; + my ($r, $p, $bat) = ($self->{r}, $self->{pool}, $self->{bat}); foreach my $d (sort { $b =~ tr#/#/# <=> $a =~ tr#/#/# } keys %$rm) { $self->close_directory($bat->{$d}, $p); diff --git a/contrib/git-svn/t/t0002-deep-rmdir.sh b/contrib/git-svn/t/t0002-deep-rmdir.sh new file mode 100644 index 0000000000..d693d183c8 --- /dev/null +++ b/contrib/git-svn/t/t0002-deep-rmdir.sh @@ -0,0 +1,29 @@ +test_description='git-svn rmdir' +. ./lib-git-svn.sh + +test_expect_success 'initialize repo' " + mkdir import && + cd import && + mkdir -p deeply/nested/directory/number/1 && + mkdir -p deeply/nested/directory/number/2 && + echo foo > deeply/nested/directory/number/1/file && + echo foo > deeply/nested/directory/number/2/another && + svn import -m 'import for git-svn' . $svnrepo && + cd .. + " + +test_expect_success 'mirror via git-svn' " + git-svn init $svnrepo && + git-svn fetch && + git checkout -f -b test-rmdir remotes/git-svn + " + +test_expect_success 'Try a commit on rmdir' " + git rm -f deeply/nested/directory/number/2/another && + git commit -a -m 'remove another' && + git-svn commit --rmdir HEAD && + svn ls -R $svnrepo | grep ^deeply/nested/directory/number/1 + " + + +test_done @@ -671,6 +671,11 @@ int main(int argc, char **argv) int inetd_mode = 0; int i; + /* Without this we cannot rely on waitpid() to tell + * what happened to our children. + */ + signal(SIGCHLD, SIG_DFL); + for (i = 1; i < argc; i++) { char *arg = argv[i]; diff --git a/diff-delta.c b/diff-delta.c index 25a798d050..74486b1b81 100644 --- a/diff-delta.c +++ b/diff-delta.c @@ -22,6 +22,7 @@ #include <string.h> #include "delta.h" +#include "git-compat-util.h" /* maximum hash entry list for the same hash bucket */ #define HASH_LIMIT 64 @@ -131,7 +132,7 @@ struct delta_index { const void *src_buf; unsigned long src_size; unsigned int hash_mask; - struct index_entry *hash[0]; + struct index_entry *hash[FLEX_ARRAY]; }; struct delta_index * create_delta_index(const void *buf, unsigned long bufsize) diff --git a/diff-lib.c b/diff-lib.c index 2183b41b03..116b5a9d68 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -34,21 +34,23 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed) continue; if (ce_stage(ce)) { - struct { - struct combine_diff_path p; - struct combine_diff_parent filler[5]; - } combine; + struct combine_diff_path *dpath; int num_compare_stages = 0; + size_t path_len; - combine.p.next = NULL; - combine.p.len = ce_namelen(ce); - combine.p.path = xmalloc(combine.p.len + 1); - memcpy(combine.p.path, ce->name, combine.p.len); - combine.p.path[combine.p.len] = 0; - combine.p.mode = 0; - memset(combine.p.sha1, 0, 20); - memset(&combine.p.parent[0], 0, - sizeof(combine.filler)); + path_len = ce_namelen(ce); + + dpath = xmalloc (combine_diff_path_size (5, path_len)); + dpath->path = (char *) &(dpath->parent[5]); + + dpath->next = NULL; + dpath->len = path_len; + memcpy(dpath->path, ce->name, path_len); + dpath->path[path_len] = '\0'; + dpath->mode = 0; + memset(dpath->sha1, 0, 20); + memset(&(dpath->parent[0]), 0, + sizeof(struct combine_diff_parent)*5); while (i < entries) { struct cache_entry *nce = active_cache[i]; @@ -64,11 +66,11 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed) if (2 <= stage) { int mode = ntohl(nce->ce_mode); num_compare_stages++; - memcpy(combine.p.parent[stage-2].sha1, + memcpy(dpath->parent[stage-2].sha1, nce->sha1, 20); - combine.p.parent[stage-2].mode = + dpath->parent[stage-2].mode = canon_mode(mode); - combine.p.parent[stage-2].status = + dpath->parent[stage-2].status = DIFF_STATUS_MODIFIED; } @@ -83,13 +85,14 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed) i--; if (revs->combine_merges && num_compare_stages == 2) { - show_combined_diff(&combine.p, 2, + show_combined_diff(dpath, 2, revs->dense_combined_merges, revs); - free(combine.p.path); + free(dpath); continue; } - free(combine.p.path); + free(dpath); + dpath = NULL; /* * Show the diff for the 'ce' if we found the one @@ -329,8 +332,8 @@ int run_diff_index(struct rev_info *revs, int cached) } mark_merge_entries(); - ent = revs->pending_objects->item; - tree_name = revs->pending_objects->name; + ent = revs->pending.objects[0].item; + tree_name = revs->pending.objects[0].name; tree = parse_tree_indirect(ent->sha1); if (!tree) return error("bad tree object %s", tree_name); @@ -25,6 +25,20 @@ int git_diff_config(const char *var, const char *value) return git_default_config(var, value); } +enum color_diff { + DIFF_PLAIN = 0, + DIFF_METAINFO = 1, + DIFF_FILE_OLD = 2, + DIFF_FILE_NEW = 3, +}; + +static const char *diff_colors[] = { + "\033[0;0m", + "\033[1;35m", + "\033[1;31m", + "\033[1;34m", +}; + static char *quote_one(const char *str) { int needlen; @@ -177,23 +191,54 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one) } struct emit_callback { + struct xdiff_emit_state xm; + int nparents, color_diff; const char **label_path; }; -static int fn_out(void *priv, mmbuffer_t *mb, int nbuf) +static inline void color_diff(int diff_use_color, enum color_diff ix) +{ + if (diff_use_color) + fputs(diff_colors[ix], stdout); +} + +static void fn_out_consume(void *priv, char *line, unsigned long len) { int i; struct emit_callback *ecbdata = priv; if (ecbdata->label_path[0]) { + color_diff(ecbdata->color_diff, DIFF_METAINFO); printf("--- %s\n", ecbdata->label_path[0]); + color_diff(ecbdata->color_diff, DIFF_METAINFO); printf("+++ %s\n", ecbdata->label_path[1]); ecbdata->label_path[0] = ecbdata->label_path[1] = NULL; } - for (i = 0; i < nbuf; i++) - if (!fwrite(mb[i].ptr, mb[i].size, 1, stdout)) - return -1; - return 0; + + /* This is not really necessary for now because + * this codepath only deals with two-way diffs. + */ + for (i = 0; i < len && line[i] == '@'; i++) + ; + if (2 <= i && i < len && line[i] == ' ') { + ecbdata->nparents = i - 1; + color_diff(ecbdata->color_diff, DIFF_METAINFO); + } + else if (len < ecbdata->nparents) + color_diff(ecbdata->color_diff, DIFF_PLAIN); + else { + int nparents = ecbdata->nparents; + int color = DIFF_PLAIN; + for (i = 0; i < nparents && len; i++) { + if (line[i] == '-') + color = DIFF_FILE_OLD; + else if (line[i] == '+') + color = DIFF_FILE_NEW; + } + color_diff(ecbdata->color_diff, color); + } + fwrite(line, len, 1, stdout); + color_diff(ecbdata->color_diff, DIFF_PLAIN); } static char *pprint_rename(const char *a, const char *b) @@ -549,25 +594,35 @@ static void builtin_diff(const char *name_a, b_two = quote_two("b/", name_b); lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null"; lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null"; + color_diff(o->color_diff, DIFF_METAINFO); printf("diff --git %s %s\n", a_one, b_two); if (lbl[0][0] == '/') { /* /dev/null */ + color_diff(o->color_diff, DIFF_METAINFO); printf("new file mode %06o\n", two->mode); - if (xfrm_msg && xfrm_msg[0]) + if (xfrm_msg && xfrm_msg[0]) { + color_diff(o->color_diff, DIFF_METAINFO); puts(xfrm_msg); + } } else if (lbl[1][0] == '/') { printf("deleted file mode %06o\n", one->mode); - if (xfrm_msg && xfrm_msg[0]) + if (xfrm_msg && xfrm_msg[0]) { + color_diff(o->color_diff, DIFF_METAINFO); puts(xfrm_msg); + } } else { if (one->mode != two->mode) { + color_diff(o->color_diff, DIFF_METAINFO); printf("old mode %06o\n", one->mode); + color_diff(o->color_diff, DIFF_METAINFO); printf("new mode %06o\n", two->mode); } - if (xfrm_msg && xfrm_msg[0]) + if (xfrm_msg && xfrm_msg[0]) { + color_diff(o->color_diff, DIFF_METAINFO); puts(xfrm_msg); + } /* * we do not run diff between different kind * of objects. @@ -575,6 +630,7 @@ static void builtin_diff(const char *name_a, if ((one->mode ^ two->mode) & S_IFMT) goto free_ab_and_return; if (complete_rewrite) { + color_diff(o->color_diff, DIFF_PLAIN); emit_rewrite_diff(name_a, name_b, one, two); goto free_ab_and_return; } @@ -602,7 +658,9 @@ static void builtin_diff(const char *name_a, xdemitcb_t ecb; struct emit_callback ecbdata; + memset(&ecbdata, 0, sizeof(ecbdata)); ecbdata.label_path = lbl; + ecbdata.color_diff = o->color_diff; xpp.flags = XDF_NEED_MINIMAL; xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; @@ -612,8 +670,9 @@ static void builtin_diff(const char *name_a, xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10); else if (!strncmp(diffopts, "-u", 2)) xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10); - ecb.outf = fn_out; + ecb.outf = xdiff_outf; ecb.priv = &ecbdata; + ecbdata.xm.consume = fn_out_consume; xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); } @@ -1456,6 +1515,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) else if (40 < options->abbrev) options->abbrev = 40; } + else if (!strcmp(arg, "--color")) + options->color_diff = 1; else return 0; return 1; @@ -32,7 +32,8 @@ struct diff_options { full_index:1, silent_on_remove:1, find_copies_harder:1, - summary:1; + summary:1, + color_diff:1; int context; int break_opt; int detect_rename; @@ -178,7 +178,13 @@ static void handle_internal_command(int argc, const char **argv, char **envp) { "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 }, + { "mailsplit", cmd_mailsplit }, + { "mailinfo", cmd_mailinfo }, + { "stripspace", cmd_stripspace }, + { "update-index", cmd_update_index }, + { "update-ref", cmd_update_ref } }; int i; diff --git a/http-fetch.c b/http-fetch.c index da1a7f5416..3a2cb5e1fc 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -1136,13 +1136,14 @@ int fetch(unsigned char *sha1) static inline int needs_quote(int ch) { - switch (ch) { - case '/': case '-': case '.': - case 'A'...'Z': case 'a'...'z': case '0'...'9': + if (((ch >= 'A') && (ch <= 'Z')) + || ((ch >= 'a') && (ch <= 'z')) + || ((ch >= '0') && (ch <= '9')) + || (ch == '/') + || (ch == '-') + || (ch == '.')) return 0; - default: - return 1; - } + return 1; } static inline int hex(int v) diff --git a/http-push.c b/http-push.c index ba64f8fff5..2e7d022819 100644 --- a/http-push.c +++ b/http-push.c @@ -1077,13 +1077,14 @@ static int fetch_indices(void) static inline int needs_quote(int ch) { - switch (ch) { - case '/': case '-': case '.': - case 'A'...'Z': case 'a'...'z': case '0'...'9': + if (((ch >= 'A') && (ch <= 'Z')) + || ((ch >= 'a') && (ch <= 'z')) + || ((ch >= '0') && (ch <= '9')) + || (ch == '/') + || (ch == '-') + || (ch == '.')) return 0; - default: - return 1; - } + return 1; } static inline int hex(int v) @@ -1171,7 +1172,7 @@ static void one_remote_object(const char *hex) obj->flags |= REMOTE; if (!object_list_contains(objects, obj)) - add_object(obj, &objects, NULL, ""); + object_list_insert(obj, &objects); } static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed) @@ -1699,6 +1700,15 @@ static int locking_available(void) return lock_flags; } +struct object_list **add_one_object(struct object *obj, struct object_list **p) +{ + struct object_list *entry = xmalloc(sizeof(struct object_list)); + entry->item = obj; + entry->next = *p; + *p = entry; + return &entry->next; +} + static struct object_list **process_blob(struct blob *blob, struct object_list **p, struct name_path *path, @@ -1712,8 +1722,7 @@ static struct object_list **process_blob(struct blob *blob, return p; obj->flags |= SEEN; - name = strdup(name); - return add_object(obj, p, path, name); + return add_one_object(obj, p); } static struct object_list **process_tree(struct tree *tree, @@ -1735,7 +1744,7 @@ static struct object_list **process_tree(struct tree *tree, obj->flags |= SEEN; name = strdup(name); - p = add_object(obj, p, NULL, name); + p = add_one_object(obj, p); me.up = path; me.elem = name; me.elem_len = strlen(name); @@ -1756,8 +1765,9 @@ static struct object_list **process_tree(struct tree *tree, static int get_delta(struct rev_info *revs, struct remote_lock *lock) { + int i; struct commit *commit; - struct object_list **p = &objects, *pending; + struct object_list **p = &objects; int count = 0; while ((commit = get_revision(revs)) != NULL) { @@ -1767,15 +1777,16 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock) count += add_send_request(&commit->object, lock); } - for (pending = revs->pending_objects; pending; pending = pending->next) { - struct object *obj = pending->item; - const char *name = pending->name; + for (i = 0; i < revs->pending.nr; i++) { + struct object_array_entry *entry = revs->pending.objects + i; + struct object *obj = entry->item; + const char *name = entry->name; if (obj->flags & (UNINTERESTING | SEEN)) continue; if (obj->type == TYPE_TAG) { obj->flags |= SEEN; - p = add_object(obj, p, NULL, name); + p = add_one_object(obj, p); continue; } if (obj->type == TYPE_TREE) { diff --git a/imap-send.c b/imap-send.c index 285ad29afb..94e39cd94c 100644 --- a/imap-send.c +++ b/imap-send.c @@ -93,7 +93,7 @@ typedef struct { char *data; int len; unsigned char flags; - unsigned char crlf:1; + unsigned int crlf:1; } msg_data_t; #define DRV_OK 0 diff --git a/merge-index.c b/merge-index.c index 024196e7ac..190e12fb7c 100644 --- a/merge-index.c +++ b/merge-index.c @@ -99,6 +99,11 @@ int main(int argc, char **argv) { int i, force_file = 0; + /* Without this we cannot rely on waitpid() to tell + * what happened to our children. + */ + signal(SIGCHLD, SIG_DFL); + if (argc < 3) usage("git-merge-index [-o] [-q] <merge-program> (-a | <filename>*)"); diff --git a/name-rev.c b/name-rev.c index c29b93ea71..3a5ac35d16 100644 --- a/name-rev.c +++ b/name-rev.c @@ -125,11 +125,10 @@ static const char* get_rev_name(struct object *o) return buffer; } - + int main(int argc, char **argv) { - struct object_list *revs = NULL; - struct object_list **walker = &revs; + struct object_array revs = { 0, 0, NULL }; int as_is = 0, all = 0, transform_stdin = 0; setup_git_directory(); @@ -184,9 +183,7 @@ int main(int argc, char **argv) if (cutoff > commit->date) cutoff = commit->date; - object_list_append((struct object *)commit, walker); - (*walker)->name = *argv; - walker = &((*walker)->next); + add_object_array((struct object *)commit, *argv, &revs); } for_each_ref(name_ref); @@ -243,9 +240,13 @@ int main(int argc, char **argv) if (objs[i]) printf("%s %s\n", sha1_to_hex(objs[i]->sha1), get_rev_name(objs[i])); - } else - for ( ; revs; revs = revs->next) - printf("%s %s\n", revs->name, get_rev_name(revs->item)); + } else { + int i; + for (i = 0; i < revs.nr; i++) + printf("%s %s\n", + revs.objects[i].name, + get_rev_name(revs.objects[i].item)); + } return 0; } @@ -200,3 +200,20 @@ int object_list_contains(struct object_list *list, struct object *obj) } return 0; } + +void add_object_array(struct object *obj, const char *name, struct object_array *array) +{ + unsigned nr = array->nr; + unsigned alloc = array->alloc; + struct object_array_entry *objects = array->objects; + + if (nr >= alloc) { + alloc = (alloc + 32) * 2; + objects = xrealloc(objects, alloc * sizeof(*objects)); + array->alloc = alloc; + array->objects = objects; + } + objects[nr].item = obj; + objects[nr].name = name; + array->nr = ++nr; +} @@ -4,7 +4,6 @@ struct object_list { struct object *item; struct object_list *next; - const char *name; }; struct object_refs { @@ -13,6 +12,15 @@ struct object_refs { struct object *ref[FLEX_ARRAY]; /* more */ }; +struct object_array { + unsigned int nr; + unsigned int alloc; + struct object_array_entry { + struct object *item; + const char *name; + } *objects; +}; + #define TYPE_BITS 3 #define FLAG_BITS 27 @@ -72,4 +80,7 @@ unsigned object_list_length(struct object_list *list); int object_list_contains(struct object_list *list, struct object *obj); +/* Object array handling .. */ +void add_object_array(struct object *obj, const char *name, struct object_array *array); + #endif /* OBJECT_H */ @@ -46,7 +46,7 @@ void setup_pager(void) close(fd[0]); close(fd[1]); - setenv("LESS", "-S", 0); + setenv("LESS", "-RS", 0); run_pager(pager); die("unable to execute pager '%s'", pager); exit(255); @@ -206,7 +206,14 @@ char *unquote_c_style(const char *quoted, const char **endp) case '\\': case '"': break; /* verbatim */ - case '0'...'7': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': /* octal */ ac = ((ch - '0') << 6); if ((ch = *sp++) < '0' || '7' < ch) diff --git a/repo-config.c b/repo-config.c index 08fc4cc57d..ab8f1afeea 100644 --- a/repo-config.c +++ b/repo-config.c @@ -64,7 +64,20 @@ static int show_config(const char* key_, const char* value_) static int get_value(const char* key_, const char* regex_) { + int ret = -1; char *tl; + char *global = NULL, *repo_config = NULL; + const char *local; + + local = getenv("GIT_CONFIG"); + if (!local) { + const char *home = getenv("HOME"); + local = getenv("GIT_CONFIG_LOCAL"); + if (!local) + local = repo_config = strdup(git_path("config")); + if (home) + global = strdup(mkpath("%s/.gitconfig", home)); + } key = strdup(key_); for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl) @@ -76,7 +89,7 @@ static int get_value(const char* key_, const char* regex_) key_regexp = (regex_t*)malloc(sizeof(regex_t)); if (regcomp(key_regexp, key, REG_EXTENDED)) { fprintf(stderr, "Invalid key pattern: %s\n", key_); - return -1; + goto free_strings; } } @@ -89,11 +102,16 @@ static int get_value(const char* key_, const char* regex_) regexp = (regex_t*)malloc(sizeof(regex_t)); if (regcomp(regexp, regex_, REG_EXTENDED)) { fprintf(stderr, "Invalid pattern: %s\n", regex_); - return -1; + goto free_strings; } } - git_config(show_config); + if (do_all && global) + git_config_from_file(show_config, global); + git_config_from_file(show_config, local); + if (!do_all && !seen && global) + git_config_from_file(show_config, global); + free(key); if (regexp) { regfree(regexp); @@ -101,9 +119,16 @@ static int get_value(const char* key_, const char* regex_) } if (do_all) - return !seen; - - return (seen == 1) ? 0 : 1; + ret = !seen; + else + ret = (seen == 1) ? 0 : 1; + +free_strings: + if (repo_config) + free(repo_config); + if (global) + free(global); + return ret; } int main(int argc, const char **argv) diff --git a/revision.c b/revision.c index 7bff2a10b1..b963f2adfd 100644 --- a/revision.c +++ b/revision.c @@ -31,17 +31,12 @@ static char *path_name(struct name_path *path, const char *name) return n; } -struct object_list **add_object(struct object *obj, - struct object_list **p, - struct name_path *path, - const char *name) +void add_object(struct object *obj, + struct object_array *p, + struct name_path *path, + const char *name) { - struct object_list *entry = xmalloc(sizeof(*entry)); - entry->item = obj; - entry->next = *p; - entry->name = path_name(path, name); - *p = entry; - return &entry->next; + add_object_array(obj, path_name(path, name), p); } static void mark_blob_uninteresting(struct blob *blob) @@ -117,9 +112,9 @@ void mark_parents_uninteresting(struct commit *commit) } } -static void add_pending_object(struct rev_info *revs, struct object *obj, const char *name) +void add_pending_object(struct rev_info *revs, struct object *obj, const char *name) { - add_object(obj, &revs->pending_objects, NULL, name); + add_object_array(obj, name, &revs->pending); } static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags) @@ -836,7 +831,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch object = get_reference(revs, arg, sha1, flags ^ local_flags); add_pending_object(revs, object, arg); } - if (def && !revs->pending_objects) { + if (def && !revs->pending.nr) { unsigned char sha1[20]; struct object *object; if (get_sha1(def, sha1)) @@ -868,11 +863,13 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch void prepare_revision_walk(struct rev_info *revs) { - struct object_list *list; + int nr = revs->pending.nr; + struct object_array_entry *list = revs->pending.objects; - list = revs->pending_objects; - revs->pending_objects = NULL; - while (list) { + revs->pending.nr = 0; + revs->pending.alloc = 0; + revs->pending.objects = NULL; + while (--nr >= 0) { struct commit *commit = handle_commit(revs, list->item, list->name); if (commit) { if (!(commit->object.flags & SEEN)) { @@ -880,7 +877,7 @@ void prepare_revision_walk(struct rev_info *revs) insert_by_date(commit, &revs->commits); } } - list = list->next; + list++; } if (revs->no_walk) diff --git a/revision.h b/revision.h index 4020e25c33..c010a08116 100644 --- a/revision.h +++ b/revision.h @@ -18,7 +18,7 @@ typedef void (prune_fn_t)(struct rev_info *revs, struct commit *commit); struct rev_info { /* Starting list */ struct commit_list *commits; - struct object_list *pending_objects; + struct object_array pending; /* Basic information */ const char *prefix; @@ -99,9 +99,11 @@ struct name_path { const char *elem; }; -extern struct object_list **add_object(struct object *obj, - struct object_list **p, - struct name_path *path, - const char *name); +extern void add_object(struct object *obj, + struct object_array *p, + struct name_path *path, + const char *name); + +extern void add_pending_object(struct rev_info *revs, struct object *obj, const char *name); #endif diff --git a/t/Makefile b/t/Makefile index 549598575b..632c55f6d5 100644 --- a/t/Makefile +++ b/t/Makefile @@ -19,7 +19,7 @@ endif all: $(T) clean $(T): - @echo "*** $@ ***"; '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) + @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) clean: rm -fr trash diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index c04f0e1540..1148b0257d 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -111,7 +111,7 @@ test_expect_success \ test_expect_success \ 'some edit' \ - 'perl -pi -e "s/^1A.*\n$//; s/^3A/99/" file && + 'perl -p -i.orig -e "s/^1A.*\n$//; s/^3A/99/" file && GIT_AUTHOR_NAME="D" git commit -a -m "edit"' test_expect_success \ diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 8260d57b63..0de2497746 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -309,5 +309,29 @@ EOF test_expect_success 'new variable inserts into proper section' 'cmp .git/config expect' +cat > other-config << EOF +[ein] + bahn = strasse +EOF + +cat > expect << EOF +ein.bahn=strasse +EOF + +GIT_CONFIG=other-config git-repo-config -l > output + +test_expect_success 'alternative GIT_CONFIG' 'cmp output expect' + +GIT_CONFIG=other-config git-repo-config anwohner.park ausweis + +cat > expect << EOF +[ein] + bahn = strasse +[anwohner] + park = ausweis +EOF + +test_expect_success '--set in alternative GIT_CONFIG' 'cmp other-config expect' + test_done @@ -19,7 +19,7 @@ struct tag *lookup_tag(const unsigned char *sha1) { struct object *obj = lookup_object(sha1); if (!obj) { - struct tag *ret = xcalloc(1, sizeof(struct tag)); + struct tag *ret = alloc_tag_node(); created_object(sha1, &ret->object); ret->object.type = TYPE_TAG; return ret; @@ -129,7 +129,7 @@ struct tree *lookup_tree(const unsigned char *sha1) { struct object *obj = lookup_object(sha1); if (!obj) { - struct tree *ret = xcalloc(1, sizeof(struct tree)); + struct tree *ret = alloc_tree_node(); created_object(sha1, &ret->object); ret->object.type = TYPE_TREE; return ret; diff --git a/xdiff/xutils.c b/xdiff/xutils.c index 21ab8e7e26..f91b403475 100644 --- a/xdiff/xutils.c +++ b/xdiff/xutils.c @@ -44,21 +44,18 @@ long xdl_bogosqrt(long n) { int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize, xdemitcb_t *ecb) { + int i = 2; mmbuffer_t mb[3]; - int i; mb[0].ptr = (char *) pre; mb[0].size = psize; mb[1].ptr = (char *) rec; mb[1].size = size; - i = 2; - - if (!size || rec[size-1] != '\n') { - mb[2].ptr = "\n\\ No newline at end of file\n"; + if (size > 0 && rec[size - 1] != '\n') { + mb[2].ptr = (char *) "\n\\ No newline at end of file\n"; mb[2].size = strlen(mb[2].ptr); - i = 3; + i++; } - if (ecb->outf(ecb->priv, mb, i) < 0) { return -1; diff --git a/xdiff/xutils.h b/xdiff/xutils.h index ea38ee903f..08691a2447 100644 --- a/xdiff/xutils.h +++ b/xdiff/xutils.h @@ -24,6 +24,7 @@ #define XUTILS_H + long xdl_bogosqrt(long n); int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize, xdemitcb_t *ecb); |