From 9cd625b79babaf50f50a0e5d96903eaacb1ee600 Mon Sep 17 00:00:00 2001 From: Rene Scharfe Date: Sun, 18 Jun 2006 15:25:33 +0200 Subject: Make release tarballs friendlier to older tar versions git-tar-tree adds an extended pax header to archives if its first parameter points to a commit. It confuses older tars and isn't very useful in the case of git anyway, so stop doing it. Idea: Junio, implementation: Junio. I just wrote it up. :-) Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2a1e6392dd..28517f4c3f 100644 --- a/Makefile +++ b/Makefile @@ -667,7 +667,7 @@ git.spec: git.spec.in GIT_TARNAME=git-$(GIT_VERSION) dist: git.spec git-tar-tree - ./git-tar-tree HEAD $(GIT_TARNAME) > $(GIT_TARNAME).tar + ./git-tar-tree HEAD^{tree} $(GIT_TARNAME) > $(GIT_TARNAME).tar @mkdir -p $(GIT_TARNAME) @cp git.spec $(GIT_TARNAME) @echo $(GIT_VERSION) > $(GIT_TARNAME)/version -- cgit v1.2.3 From 3e4339e6f96e8c4f38a9c6607b98d3e96a2ed783 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 18 Jun 2006 11:45:02 -0700 Subject: Remove "refs" field from "struct object" This shrinks "struct object" to the absolutely minimal size possible. It now contains /only/ the object flags and the SHA1 hash name of the object. The "refs" field, which is really needed only for fsck, is maintained in a separate hashed lookup-table, allowing all normal users to totally ignore it. This helps memory usage, although not as much as I hoped: it looks like the allocation overhead of malloc (and the alignment constraints in particular) means that while the structure size shrinks, the actual allocation overhead mostly does not. [ That said: memory usage is actually down, but not as much as it should be: I suspect just one of the object types actually ended up shrinking its effective allocation size. To get to the next level, we probably need specialized allocators that don't pad the allocation more than necessary. ] The separation makes for some code cleanup, though, and makes the ref tracking that fsck wants a clearly separate thing. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- Makefile | 2 +- fsck-objects.c | 5 +- object-refs.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ object.c | 70 ---------------------------- object.h | 4 +- 5 files changed, 149 insertions(+), 74 deletions(-) create mode 100644 object-refs.c diff --git a/Makefile b/Makefile index 28517f4c3f..5598f48ba3 100644 --- a/Makefile +++ b/Makefile @@ -212,7 +212,7 @@ LIB_OBJS = \ blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \ date.o diff-delta.o entry.o exec_cmd.o ident.o lockfile.o \ object.o pack-check.o patch-delta.o path.o pkt-line.o \ - quote.o read-cache.o refs.o run-command.o dir.o \ + quote.o read-cache.o refs.o run-command.o dir.o object-refs.o \ 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 --git a/fsck-objects.c b/fsck-objects.c index 2b1aab488f..769bb2a6a7 100644 --- a/fsck-objects.c +++ b/fsck-objects.c @@ -64,6 +64,7 @@ static void check_connectivity(void) /* Look up all the requirements, warn about missing objects.. */ for (i = 0; i < obj_allocs; i++) { + const struct object_refs *refs; struct object *obj = objs[i]; if (!obj) @@ -78,8 +79,8 @@ static void check_connectivity(void) continue; } - if (obj->refs) { - const struct object_refs *refs = obj->refs; + refs = lookup_object_refs(obj); + if (refs) { unsigned j; for (j = 0; j < refs->count; j++) { struct object *ref = refs->ref[j]; diff --git a/object-refs.c b/object-refs.c new file mode 100644 index 0000000000..8afa2276fb --- /dev/null +++ b/object-refs.c @@ -0,0 +1,142 @@ +#include "cache.h" +#include "object.h" + +int track_object_refs = 0; + +static unsigned int refs_hash_size, nr_object_refs; +static struct object_refs **refs_hash; + +static unsigned int hash_obj(struct object *obj, unsigned int n) +{ + unsigned int hash = *(unsigned int *)obj->sha1; + return hash % n; +} + +static void grow_refs_hash(void) +{ + int i; + int new_hash_size = (refs_hash_size + 1000) * 3 / 2; + struct object_refs **new_hash; + + 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; + } + 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; + + if (nr > refs_hash_size * 2 / 3) + grow_refs_hash(); + ref->base = obj; + insert_ref_hash(ref); + nr_object_refs = nr; +} + +struct object_refs *lookup_object_refs(struct object *obj) +{ + int j = hash_obj(obj, refs_hash_size); + struct object_refs *ref; + + while ((ref = refs_hash[j]) != NULL) { + if (ref->base == obj) + break; + j++; + if (j >= refs_hash_size) + j = 0; + } + return ref; +} + +struct object_refs *alloc_object_refs(unsigned count) +{ + struct object_refs *refs; + size_t size = sizeof(*refs) + count*sizeof(struct object *); + + refs = xcalloc(1, size); + refs->count = count; + return refs; +} + +static int compare_object_pointers(const void *a, const void *b) +{ + const struct object * const *pa = a; + const struct object * const *pb = b; + if (*pa == *pb) + return 0; + else if (*pa < *pb) + return -1; + else + return 1; +} + +void set_object_refs(struct object *obj, struct object_refs *refs) +{ + unsigned int i, j; + + /* Do not install empty list of references */ + if (refs->count < 1) { + free(refs); + return; + } + + /* Sort the list and filter out duplicates */ + qsort(refs->ref, refs->count, sizeof(refs->ref[0]), + compare_object_pointers); + for (i = j = 1; i < refs->count; i++) { + if (refs->ref[i] != refs->ref[i - 1]) + refs->ref[j++] = refs->ref[i]; + } + if (j < refs->count) { + /* Duplicates were found - reallocate list */ + size_t size = sizeof(*refs) + j*sizeof(struct object *); + refs->count = j; + refs = xrealloc(refs, size); + } + + for (i = 0; i < refs->count; i++) + refs->ref[i]->used = 1; + add_object_refs(obj, refs); +} + +void mark_reachable(struct object *obj, unsigned int mask) +{ + const struct object_refs *refs; + + if (!track_object_refs) + die("cannot do reachability with object refs turned off"); + /* If we've been here already, don't bother */ + if (obj->flags & mask) + return; + obj->flags |= mask; + refs = lookup_object_refs(obj); + if (refs) { + unsigned i; + for (i = 0; i < refs->count; i++) + mark_reachable(refs->ref[i], mask); + } +} + + diff --git a/object.c b/object.c index 0f70890a45..e26e319ccd 100644 --- a/object.c +++ b/object.c @@ -13,8 +13,6 @@ const char *type_names[] = { "none", "blob", "tree", "commit", "bad" }; -int track_object_refs = 0; - static int hashtable_index(const unsigned char *sha1) { unsigned int i; @@ -55,7 +53,6 @@ void created_object(const unsigned char *sha1, struct object *obj) obj->parsed = 0; memcpy(obj->sha1, sha1, 20); obj->type = TYPE_NONE; - obj->refs = NULL; obj->used = 0; if (obj_allocs - 1 <= nr_objs * 2) { @@ -84,73 +81,6 @@ void created_object(const unsigned char *sha1, struct object *obj) nr_objs++; } -struct object_refs *alloc_object_refs(unsigned count) -{ - struct object_refs *refs; - size_t size = sizeof(*refs) + count*sizeof(struct object *); - - refs = xcalloc(1, size); - refs->count = count; - return refs; -} - -static int compare_object_pointers(const void *a, const void *b) -{ - const struct object * const *pa = a; - const struct object * const *pb = b; - if (*pa == *pb) - return 0; - else if (*pa < *pb) - return -1; - else - return 1; -} - -void set_object_refs(struct object *obj, struct object_refs *refs) -{ - unsigned int i, j; - - /* Do not install empty list of references */ - if (refs->count < 1) { - free(refs); - return; - } - - /* Sort the list and filter out duplicates */ - qsort(refs->ref, refs->count, sizeof(refs->ref[0]), - compare_object_pointers); - for (i = j = 1; i < refs->count; i++) { - if (refs->ref[i] != refs->ref[i - 1]) - refs->ref[j++] = refs->ref[i]; - } - if (j < refs->count) { - /* Duplicates were found - reallocate list */ - size_t size = sizeof(*refs) + j*sizeof(struct object *); - refs->count = j; - refs = xrealloc(refs, size); - } - - for (i = 0; i < refs->count; i++) - refs->ref[i]->used = 1; - obj->refs = refs; -} - -void mark_reachable(struct object *obj, unsigned int mask) -{ - if (!track_object_refs) - die("cannot do reachability with object refs turned off"); - /* If we've been here already, don't bother */ - if (obj->flags & mask) - return; - obj->flags |= mask; - if (obj->refs) { - const struct object_refs *refs = obj->refs; - unsigned i; - for (i = 0; i < refs->count; i++) - mark_reachable(refs->ref[i], mask); - } -} - struct object *lookup_object_type(const unsigned char *sha1, const char *type) { if (!type) { diff --git a/object.h b/object.h index f4ee2e55ba..c537b4b72a 100644 --- a/object.h +++ b/object.h @@ -9,6 +9,7 @@ struct object_list { struct object_refs { unsigned count; + struct object *base; struct object *ref[FLEX_ARRAY]; /* more */ }; @@ -28,7 +29,6 @@ struct object { unsigned type : TYPE_BITS; unsigned flags : FLAG_BITS; unsigned char sha1[20]; - struct object_refs *refs; }; extern int track_object_refs; @@ -41,6 +41,8 @@ static inline const char *typename(unsigned int type) return type_names[type > TYPE_TAG ? TYPE_BAD : type]; } +extern struct object_refs *lookup_object_refs(struct object *); + /** Internal only **/ struct object *lookup_object(const unsigned char *sha1); -- cgit v1.2.3 From 476a4dfc05f8d67406af277a00f7079b5d6d51e1 Mon Sep 17 00:00:00 2001 From: Dennis Stosberg Date: Sun, 18 Jun 2006 22:33:21 +0200 Subject: Make t8001-annotate and t8002-blame more portable These two tests assume that "sed" will not modify the final line of a stream if it does not end with a newline character. The assumption is not true at least for FreeBSD and Solaris 9. FreeBSD's "sed" appends a newline character; "sed" in Solaris 9 even removes the incomplete final line. This patch makes the test use perl instead. Signed-off-by: Dennis Stosberg Signed-off-by: Junio C Hamano --- t/annotate-tests.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index 114938c3ff..c04f0e1540 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -111,9 +111,7 @@ test_expect_success \ test_expect_success \ 'some edit' \ - 'mv file file1 && - sed -e 1d -e "5s/3A/99/" file1 >file && - rm -f file1 && + 'perl -pi -e "s/^1A.*\n$//; s/^3A/99/" file && GIT_AUTHOR_NAME="D" git commit -a -m "edit"' test_expect_success \ -- cgit v1.2.3 From b47f509ba59df5bd9a780745ca710272c6dd175b Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 19 Jun 2006 09:25:16 +1000 Subject: Fix PPC SHA1 routine for large input buffers The PPC SHA1 routine had an overflow which meant that it gave incorrect results for input buffers >= 512MB. This fixes it by ensuring that the update of the total length in bits is done using 64-bit arithmetic. Signed-off-by: Paul Mackerras Signed-off-by: Junio C Hamano --- ppc/sha1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppc/sha1.c b/ppc/sha1.c index 5ba4fc5259..0820398b00 100644 --- a/ppc/sha1.c +++ b/ppc/sha1.c @@ -30,7 +30,7 @@ int SHA1_Update(SHA_CTX *c, const void *ptr, unsigned long n) unsigned long nb; const unsigned char *p = ptr; - c->len += n << 3; + c->len += (uint64_t) n << 3; while (n != 0) { if (c->cnt || n < 64) { nb = 64 - c->cnt; -- cgit v1.2.3 From 7f29f7a95c906250c9c99d08242c2c4084c48d24 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Sun, 18 Jun 2006 01:23:58 +0200 Subject: Support for extracting configuration from different files Add $GIT_CONFIG environment variable whose content is used instead of .git/config if set. Also add $GIT_CONFIG_LOCAL as a forward-compatibility cue for whenever we will finally come to support] global configuration files (properly). Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- Documentation/git-repo-config.txt | 12 ++++++++++++ config.c | 12 +++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) 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 ------- diff --git a/config.c b/config.c index 984c75f5dd..d46eb6d829 100644 --- a/config.c +++ b/config.c @@ -317,7 +317,17 @@ 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")); + const char *filename = git_path("config"); + /* Forward-compatibility cue: $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. */ + if (getenv("GIT_CONFIG")) { + filename = getenv("GIT_CONFIG"); + } else if (getenv("GIT_CONFIG_LOCAL")) { + filename = getenv("GIT_CONFIG_LOCAL"); + } + return git_config_from_file(fn, filename); } /* -- cgit v1.2.3