Merge branch 'ff/c99'
authorJunio C Hamano <junkio@cox.net>
Thu, 22 Jun 2006 09:18:51 +0000 (02:18 -0700)
committerJunio C Hamano <junkio@cox.net>
Thu, 22 Jun 2006 09:18:51 +0000 (02:18 -0700)
* ff/c99:
Remove all void-pointer arithmetic.
Change types used in bitfields to be `int's.
Don't use empty structure initializers.
Cast pointers to `void *' when used in a format.
Don't instantiate structures with FAMs.
Initialize FAMs using `FLEX_ARRAY'.
Remove ranges from switch statements.

37 files changed:
Documentation/git-repo-config.txt
Documentation/git-send-email.txt
Makefile
alloc.c [new file with mode: 0644]
blob.c
builtin-diff-files.c
builtin-diff-index.c
builtin-diff-tree.c
builtin-diff.c
builtin-grep.c
builtin-log.c
builtin-rev-list.c
cache.h
commit.c
config.c
contrib/git-svn/Makefile
contrib/git-svn/git-svn.perl
contrib/git-svn/t/t0002-deep-rmdir.sh [new file with mode: 0644]
daemon.c
diff-lib.c
git-checkout.sh
git-send-email.perl
http-push.c
name-rev.c
object-refs.c
object.c
object.h
repo-config.c
revision.c
revision.h
t/Makefile
t/annotate-tests.sh
t/t1300-repo-config.sh
tag.c
tree.c
xdiff/xutils.c
xdiff/xutils.h
index d5142e0dcd6799b8a94c9cd5a3f2bd17c3cb7289..803c0d5cae6db0a953380adc6ee3980a0afa72e0 100644 (file)
@@ -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
 -------
 
index ad1b9cf2e9b2532c02c0abd3450ecf6272673472..481b3f50e3d690f5cd47ffa2c2d8bb645114e315 100644 (file)
@@ -24,9 +24,16 @@ OPTIONS
 -------
 The options available are:
 
+--bcc::
+       Specify a "Bcc:" value for each email.
+
+       The --bcc option must be repeated for each user you want on the bcc list.
+
 --cc::
        Specify a starting "Cc:" value for each email.
 
+       The --cc option must be repeated for each user you want on the cc list.
+
 --chain-reply-to, --no-chain-reply-to::
        If this is set, each email will be sent as a reply to the previous
        email sent.  If disabled with "--no-chain-reply-to", all emails after
@@ -76,6 +83,8 @@ The options available are:
        Generally, this will be the upstream maintainer of the
        project involved.
 
+       The --to option must be repeated for each user you want on the to list.
+
 
 Author
 ------
index ea8cd283e2407cc0f16b2e7a3fa1421f3193e142..d45f3dcf6214f8a60f3e636d1c5067d273551f0c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -216,7 +216,7 @@ 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 \
@@ -472,7 +472,6 @@ PYTHON_PATH_SQ = $(subst ','\'',$(PYTHON_PATH))
 GIT_PYTHON_DIR_SQ = $(subst ','\'',$(GIT_PYTHON_DIR))
 
 ALL_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' $(COMPAT_CFLAGS)
-ALL_CFLAGS += -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"'
 LIB_OBJS += $(COMPAT_OBJS)
 export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
 ### Build rules
@@ -548,6 +547,8 @@ git$X git.spec \
 
 exec_cmd.o: exec_cmd.c GIT-CFLAGS
        $(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
+builtin-init-db.o: builtin-init-db.c GIT-CFLAGS
+       $(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
 
 http.o: http.c GIT-CFLAGS
        $(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $<
@@ -611,7 +612,7 @@ tags:
        find . -name '*.[hcS]' -print | xargs ctags -a
 
 ### Detect prefix changes
-TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):$(GIT_VERSION):\
+TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):$(GIT_PYTHON_DIR_SQ):\
              $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
 
 GIT-CFLAGS: .FORCE-GIT-CFLAGS
diff --git a/alloc.c b/alloc.c
new file mode 100644 (file)
index 0000000..e3b22f4
--- /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);
+}
diff --git a/blob.c b/blob.c
index 7377008744430cea453010fe93e6c1f51c37fdde..496f270043a617242efa9d27285853feb2597484 100644 (file)
--- a/blob.c
+++ b/blob.c
@@ -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;
index cebda828eec4e90f3d0af050e07a53071b39d5b7..5afc1d7208f8a13b7363be2127cad3b43baa95dd 100644 (file)
@@ -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);
        /*
index 1958580d82e54ab5a5b1e054263eab7264c4bcb2..c42ef9a7a76e7d8f6bc25d593865b9343d4e74b5 100644 (file)
@@ -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);
index 58cf65856d1e9e0ab088dab2c051058cf48cb840..3409a39a9f73f9ed67547f5cc79619c1e402f47b 100644 (file)
@@ -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);
index 6ac3d4b8ca23e7c4d724b22fd3222005d8fe3df8..99a2f766055d6c8c3231e38bd369169d3c742782 100644 (file)
@@ -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);
index 9806499263dcb92c7a6903ead36646baf676b178..2e7986cecefc964f665b10d363569951c1f40293 100644 (file)
@@ -29,10 +29,11 @@ static int pathspec_matches(const char **paths, const char *name)
                int matchlen = strlen(match);
                const char *cp, *meta;
 
-               if ((matchlen <= namelen) &&
-                   !strncmp(name, match, matchlen) &&
-                   (match[matchlen-1] == '/' ||
-                    name[matchlen] == '\0' || name[matchlen] == '/'))
+               if (!matchlen ||
+                   ((matchlen <= namelen) &&
+                    !strncmp(name, match, matchlen) &&
+                    (match[matchlen-1] == '/' ||
+                     name[matchlen] == '\0' || name[matchlen] == '/')))
                        return 1;
                if (!fnmatch(match, name, 0))
                        return 1;
@@ -657,7 +658,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 +678,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 +851,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 +878,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;
index 9187fd337ba767384abab26224b95610aa531807..5a8a50b81dabea4ccd9b0ba0fcb5d925a00560d0 100644 (file)
@@ -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);
        }
 
index 71353eb19db158a60a5ae94f83f53059adc3399b..63bad0e96ade657bef21d9ca0e0de2e0ba8af61c 100644 (file)
@@ -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/cache.h b/cache.h
index 7fcb6d406aa258315f6f2bbba128baee60f59838..eaa5c0c356645df722f05786860b362730e77074 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -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 */
index 5914200a2fba2d618951c3210e2b407c29a62d7b..946615d2ad5c364fe63b201aa9a9574737804c38 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -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 (;;) {
index 984c75f5dd06bd1d53eda206a2b57eea093dfd58..3e077d4c6ca4f7162e3a3254e1b3e90db33270ff 100644 (file)
--- a/config.c
+++ b/config.c
@@ -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) {
index 6aedb10f1261bbcef6a48ef65e1f47d9edc1afda..7c209469438bcef2a5cee0988448a41a56ec30cc 100644 (file)
@@ -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:
index da0ff9ad8a56f41c351946990ee17d1e80f533e8..08c30103f5c247559e15ebd4bb20d7177889ed88 100755 (executable)
@@ -479,17 +479,18 @@ sub commit_lib {
        my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef, 0) : ();
        my $commit_msg = "$GIT_SVN_DIR/.svn-commit.tmp.$$";
 
+       if (defined $LC_ALL) {
+               $ENV{LC_ALL} = $LC_ALL;
+       } else {
+               delete $ENV{LC_ALL};
+       }
        foreach my $c (@revs) {
+               my $log_msg = get_commit_message($c, $commit_msg);
+
                # fork for each commit because there's a memory leak I
                # can't track down... (it's probably in the SVN code)
                defined(my $pid = open my $fh, '-|') or croak $!;
                if (!$pid) {
-                       if (defined $LC_ALL) {
-                               $ENV{LC_ALL} = $LC_ALL;
-                       } else {
-                               delete $ENV{LC_ALL};
-                       }
-                       my $log_msg = get_commit_message($c, $commit_msg);
                        my $ed = SVN::Git::Editor->new(
                                        {       r => $r_last,
                                                ra => $SVN,
@@ -535,6 +536,7 @@ sub commit_lib {
                        ($r_last, $cmt_last) = ($r_new, $cmt_new);
                }
        }
+       $ENV{LC_ALL} = 'C';
        unlink $commit_msg;
 }
 
@@ -2841,13 +2843,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 (file)
index 0000000..d693d18
--- /dev/null
@@ -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
index 2f03f99d2d9f2ed9a23932e5104456f69b721116..bdfe80d2e4f4fc13ad45bd35aeeeb3ec71422a4f 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -264,11 +264,34 @@ static int upload(char *dir)
        return -1;
 }
 
-static int execute(void)
+static int execute(struct sockaddr *addr)
 {
        static char line[1000];
        int pktlen, len;
 
+       if (addr) {
+               char addrbuf[256] = "";
+               int port = -1;
+
+               if (addr->sa_family == AF_INET) {
+                       struct sockaddr_in *sin_addr = (void *) addr;
+                       inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
+                       port = sin_addr->sin_port;
+#ifndef NO_IPV6
+               } else if (addr && addr->sa_family == AF_INET6) {
+                       struct sockaddr_in6 *sin6_addr = (void *) addr;
+
+                       char *buf = addrbuf;
+                       *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
+                       inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
+                       strcat(buf, "]");
+
+                       port = sin6_addr->sin6_port;
+#endif
+               }
+               loginfo("Connection from %s:%d", addrbuf, port);
+       }
+
        alarm(init_timeout ? init_timeout : timeout);
        pktlen = packet_read_line(0, line, sizeof(line));
        alarm(0);
@@ -414,8 +437,6 @@ static void check_max_connections(void)
 static void handle(int incoming, struct sockaddr *addr, int addrlen)
 {
        pid_t pid = fork();
-       char addrbuf[256] = "";
-       int port = -1;
 
        if (pid) {
                unsigned idx;
@@ -436,26 +457,7 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
        dup2(incoming, 1);
        close(incoming);
 
-       if (addr->sa_family == AF_INET) {
-               struct sockaddr_in *sin_addr = (void *) addr;
-               inet_ntop(AF_INET, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
-               port = sin_addr->sin_port;
-
-#ifndef NO_IPV6
-       } else if (addr->sa_family == AF_INET6) {
-               struct sockaddr_in6 *sin6_addr = (void *) addr;
-
-               char *buf = addrbuf;
-               *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
-               inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
-               strcat(buf, "]");
-
-               port = sin6_addr->sin6_port;
-#endif
-       }
-       loginfo("Connection from %s:%d", addrbuf, port);
-
-       exit(execute());
+       exit(execute(addr));
 }
 
 static void child_handler(int signo)
@@ -751,8 +753,16 @@ int main(int argc, char **argv)
        }
 
        if (inetd_mode) {
+               struct sockaddr_storage ss;
+               struct sockaddr *peer = (struct sockaddr *)&ss;
+               socklen_t slen = sizeof(ss);
+
                fclose(stderr); //FIXME: workaround
-               return execute();
+
+               if (getpeername(0, peer, &slen))
+                       peer = NULL;
+
+               return execute(peer);
        }
 
        return serve(port);
index fdc11732dfbe201119182ff701f7fd40d74d1017..116b5a9d6834c9517ccc2202510b37a1e1d863a5 100644 (file)
@@ -332,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);
index 564117f0064aba32e190a49106eaecfdb422b31e..77c25938091b75f51eb3cc5922d67db6333e1e74 100755 (executable)
@@ -137,8 +137,7 @@ fi
 
 if [ "$force" ]
 then
-    git-read-tree --reset $new &&
-       git-checkout-index -q -f -u -a
+    git-read-tree --reset -u $new
 else
     git-update-index --refresh >/dev/null
     merge_error=$(git-read-tree -m -u $old $new 2>&1) || (
index 7b1cca70abcfcbf12c171c91d3f71ad4e43b0474..c5d9e733512ddd4d266c85d4f5cdec4a7d74fa56 100755 (executable)
                    "no-signed-off-cc|no-signed-off-by-cc" => \$no_signed_off_cc,
         );
 
+# Verify the user input
+
+foreach my $entry (@to) {
+       die "Comma in --to entry: $entry'\n" unless $entry !~ m/,/;
+}
+
+foreach my $entry (@initial_cc) {
+       die "Comma in --cc entry: $entry'\n" unless $entry !~ m/,/;
+}
+
+foreach my $entry (@bcclist) {
+       die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/;
+}
+
 # Now, let's fill any that aren't set in with defaults:
 
 sub gitvar {
index 9853619687a25501d1dee052f39ebeedcbd8dc69..8d472f0202827db726ede451be3fd63940c38c96 100644 (file)
@@ -1172,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)
@@ -1700,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,
@@ -1713,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,
@@ -1736,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);
@@ -1757,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) {
@@ -1768,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) {
index c29b93ea7199643885cd74148d03db7d1bbb533b..3a5ac35d163bae5431c9cad8c9e31918c2734241 100644 (file)
@@ -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;
 }
index 8afa2276fbe9e79bba700b99b1ef345bb6d7f5e8..b1b8065851b2723a57e5d6ab0859ca72e52fd55f 100644 (file)
@@ -12,6 +12,18 @@ static unsigned int hash_obj(struct object *obj, unsigned int n)
        return hash % n;
 }
 
+static void insert_ref_hash(struct object_refs *ref, struct object_refs **hash, unsigned int size)
+{
+       int j = hash_obj(ref->base, size);
+
+       while (hash[j]) {
+               j++;
+               if (j >= size)
+                       j = 0;
+       }
+       hash[j] = ref;
+}
+
 static void grow_refs_hash(void)
 {
        int i;
@@ -20,30 +32,16 @@ static void grow_refs_hash(void)
 
        new_hash = calloc(new_hash_size, sizeof(struct object_refs *));
        for (i = 0; i < refs_hash_size; i++) {
-               int j;
                struct object_refs *ref = refs_hash[i];
                if (!ref)
                        continue;
-               j = hash_obj(ref->base, new_hash_size);
-               new_hash[j] = ref;
+               insert_ref_hash(ref, new_hash, new_hash_size);
        }
        free(refs_hash);
        refs_hash = new_hash;
        refs_hash_size = new_hash_size;
 }
 
-static void insert_ref_hash(struct object_refs *ref)
-{
-       int j = hash_obj(ref->base, refs_hash_size);
-
-       while (refs_hash[j]) {
-               j++;
-               if (j >= refs_hash_size)
-                       j = 0;
-       }
-       refs_hash[j] = ref;
-}
-
 static void add_object_refs(struct object *obj, struct object_refs *ref)
 {
        int nr = nr_object_refs + 1;
@@ -51,7 +49,7 @@ static void add_object_refs(struct object *obj, struct object_refs *ref)
        if (nr > refs_hash_size * 2 / 3)
                grow_refs_hash();
        ref->base = obj;
-       insert_ref_hash(ref);
+       insert_ref_hash(ref, refs_hash, refs_hash_size);
        nr_object_refs = nr;
 }
 
@@ -127,6 +125,9 @@ void mark_reachable(struct object *obj, unsigned int mask)
 
        if (!track_object_refs)
                die("cannot do reachability with object refs turned off");
+       /* nothing to lookup */
+       if (!refs_hash_size)
+               return;
        /* If we've been here already, don't bother */
        if (obj->flags & mask)
                return;
index e26e319ccd22e5c9e9125e58f9ed32620afd66b1..37784cee9a90a7e5b44dd660d6b7ea9191b59486 100644 (file)
--- a/object.c
+++ b/object.c
@@ -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;
+}
index c537b4b72acabc8b2425ca9bb50c890e730aa788..6f23a9a18099cbc9fdc827f53843b1157dd10935 100644 (file)
--- a/object.h
+++ b/object.h
@@ -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 */
index 08fc4cc57d064248247c912014e4eba32490f0ff..ab8f1afeea0cbff7707e313af1c18ff56363ae09 100644 (file)
@@ -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)
index 7bff2a10b1044651a776b42d4ee3d91661830aa2..b963f2adfd92050310f7327e1ee10e21d5996a7c 100644 (file)
@@ -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)
index 4020e25c336356868057ee88e84b395f55b87b38..c010a0811604e55f4e46d08d986ae62edfb192ee 100644 (file)
@@ -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
index 549598575b9fdcefe857ddef1b6d980a9773b033..632c55f6d5d66c8e39e213284e163a23b32c2260 100644 (file)
@@ -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
index c04f0e1540794c3d4d950c158beee249ba98b726..1148b0257dafd4e9b63e030052b47b527b5c0d3b 100644 (file)
@@ -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 \
index 8260d57b63d7f988a4c236d99ce2c9931a67c5e3..0de2497746e31f3dce418dbd248ff5d3e7cb939a 100755 (executable)
@@ -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
 
diff --git a/tag.c b/tag.c
index bee8a09cbf5fec119e9b2555beb4cb8b38d8057e..74d0dabe5d8c1f06a3f67475368c34e3b4046456 100644 (file)
--- a/tag.c
+++ b/tag.c
@@ -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;
diff --git a/tree.c b/tree.c
index 64422fd27e3f855b7989bc8cb9a6a0ada7a30472..10236555cc5c127b9b5b2cac8f2514c1b7e87676 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -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;
index 21ab8e7e263983b54c07e44150cedc5c43963a35..f91b4034751df72996afbe6b4b04a9f05638d322 100644 (file)
@@ -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;
index ea38ee903fa142742797feb600b691b5a22b8165..08691a2447126a8a8f96bb8a0369f21524c58c39 100644 (file)
@@ -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);