diff options
-rw-r--r-- | Documentation/git-tar-tree.txt | 15 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | builtin-tar-tree.c | 47 | ||||
-rw-r--r-- | fsck-objects.c | 5 | ||||
-rw-r--r-- | object-refs.c | 142 | ||||
-rw-r--r-- | object.c | 70 | ||||
-rw-r--r-- | object.h | 4 | ||||
-rw-r--r-- | ppc/sha1.c | 2 | ||||
-rw-r--r-- | t/annotate-tests.sh | 4 |
9 files changed, 182 insertions, 111 deletions
diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt index 831537b6ff..f2675c4193 100644 --- a/Documentation/git-tar-tree.txt +++ b/Documentation/git-tar-tree.txt @@ -39,19 +39,24 @@ OPTIONS Examples -------- -git tar-tree HEAD | (cd /var/tmp/ && mkdir junk && tar Cxf junk -):: +git tar-tree HEAD junk | (cd /var/tmp/ && tar xf -):: Create a tar archive that contains the contents of the latest commit on the current branch, and extracts it in `/var/tmp/junk` directory. -git tar-tree v2.6.17 linux-2.6.17 | gzip >linux-2.6.17.tar.gz +git tar-tree v1.4.0 git-1.4.0 | gzip >git-1.4.0.tar.gz:: - Create a tarball for v2.6.17 release. + Create a tarball for v1.4.0 release. -git tar-tree --remote=example.com:git.git v0.99 >git-0.99.tar +git tar-tree v1.4.0{caret}\{tree\} git-1.4.0 | gzip >git-1.4.0.tar.gz:: - Get a tarball v0.99 from example.com. + Create a tarball for v1.4.0 release, but without a + global extended pax header. + +git tar-tree --remote=example.com:git.git v1.4.0 >git-1.4.0.tar:: + + Get a tarball v1.4.0 from example.com. Author ------ @@ -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 \ @@ -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 diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index f6310b9032..39a61b6293 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -22,8 +22,10 @@ static unsigned long offset; static time_t archive_time; /* tries hard to write, either succeeds or dies in the attempt */ -static void reliable_write(void *buf, unsigned long size) +static void reliable_write(const void *data, unsigned long size) { + const char *buf = data; + while (size > 0) { long ret = xwrite(1, buf, size); if (ret < 0) { @@ -47,37 +49,13 @@ static void write_if_needed(void) } } -/* acquire the next record from the buffer; user must call write_if_needed() */ -static char *get_record(void) -{ - char *p = block + offset; - memset(p, 0, RECORDSIZE); - offset += RECORDSIZE; - return p; -} - -/* - * The end of tar archives is marked by 1024 nul bytes and after that - * follows the rest of the block (if any). - */ -static void write_trailer(void) -{ - get_record(); - write_if_needed(); - get_record(); - write_if_needed(); - while (offset) { - get_record(); - write_if_needed(); - } -} - /* * queues up writes, so that all our write(2) calls write exactly one * full block; pads writes to RECORDSIZE */ -static void write_blocked(void *buf, unsigned long size) +static void write_blocked(const void *data, unsigned long size) { + const char *buf = data; unsigned long tail; if (offset) { @@ -107,6 +85,21 @@ static void write_blocked(void *buf, unsigned long size) write_if_needed(); } +/* + * The end of tar archives is marked by 2*512 nul bytes and after that + * follows the rest of the block (if any). + */ +static void write_trailer(void) +{ + int tail = BLOCKSIZE - offset; + memset(block + offset, 0, tail); + reliable_write(block, BLOCKSIZE); + if (tail < 2 * RECORDSIZE) { + memset(block, 0, offset); + reliable_write(block, BLOCKSIZE); + } +} + static void strbuf_append_string(struct strbuf *sb, const char *s) { int slen = strlen(s); 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); + } +} + + @@ -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) { @@ -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); 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; 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 \ |