diff options
-rw-r--r-- | Documentation/git-tar-tree.txt | 15 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | builtin-init-db.c | 15 | ||||
-rw-r--r-- | builtin-log.c | 7 | ||||
-rw-r--r-- | builtin-tar-tree.c | 47 | ||||
-rw-r--r-- | cache.h | 6 | ||||
-rw-r--r-- | environment.c | 2 | ||||
-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-- | path.c | 14 | ||||
-rw-r--r-- | ppc/sha1.c | 2 | ||||
-rw-r--r-- | setup.c | 17 | ||||
-rw-r--r-- | t/annotate-tests.sh | 4 |
15 files changed, 234 insertions, 120 deletions
diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt index 831537b6f..f2675c419 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 \ @@ -679,7 +679,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-init-db.c b/builtin-init-db.c index 6a24e9bca..7fdd2fa9f 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -263,7 +263,9 @@ int cmd_init_db(int argc, const char **argv, char **envp) if (!strncmp(arg, "--template=", 11)) template_dir = arg+11; else if (!strcmp(arg, "--shared")) - shared_repository = 1; + shared_repository = PERM_GROUP; + else if (!strncmp(arg, "--shared=", 9)) + shared_repository = git_config_perm("arg", arg+9); else die(init_db_usage); } @@ -301,8 +303,15 @@ int cmd_init_db(int argc, const char **argv, char **envp) strcpy(path+len, "/info"); safe_create_dir(path, 1); - if (shared_repository) - git_config_set("core.sharedrepository", "true"); + if (shared_repository) { + char buf[10]; + /* We do not spell "group" and such, so that + * the configuration can be read by older version + * of git. + */ + sprintf(buf, "%d", shared_repository); + git_config_set("core.sharedrepository", buf); + } return 0; } diff --git a/builtin-log.c b/builtin-log.c index 6afa66ce0..9187fd337 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -220,8 +220,11 @@ int cmd_format_patch(int argc, const char **argv, char **envp) } else if (!strcmp(argv[i], "--signoff") || !strcmp(argv[i], "-s")) { - const char *committer = git_committer_info(1); - const char *endpos = strchr(committer, '>'); + const char *committer; + const char *endpos; + setup_ident(); + committer = git_committer_info(1); + endpos = strchr(committer, '>'); if (!endpos) die("bogos committer info %s\n", committer); add_signoff = xmalloc(endpos - committer + 2); diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index f6310b903..39a61b629 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); @@ -208,6 +208,12 @@ extern const unsigned char null_sha1[20]; int git_mkstemp(char *path, size_t n, const char *template); +enum sharedrepo { + PERM_UMASK = 0, + PERM_GROUP, + PERM_EVERYBODY +}; +int git_config_perm(const char *var, const char *value); int adjust_shared_perm(const char *path); int safe_create_leading_directories(char *path); size_t safe_strncpy(char *, const char *, size_t); diff --git a/environment.c b/environment.c index 2e79eab18..3de8eb3b2 100644 --- a/environment.c +++ b/environment.c @@ -18,7 +18,7 @@ int log_all_ref_updates = 0; int warn_ambiguous_refs = 1; int repository_format_version = 0; char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8"; -int shared_repository = 0; +int shared_repository = PERM_UMASK; const char *apply_default_whitespace = NULL; static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir, diff --git a/fsck-objects.c b/fsck-objects.c index 2b1aab488..769bb2a6a 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 000000000..8afa2276f --- /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); @@ -267,11 +267,21 @@ int adjust_shared_perm(const char *path) return -1; mode = st.st_mode; if (mode & S_IRUSR) - mode |= S_IRGRP; + mode |= (shared_repository == PERM_GROUP + ? S_IRGRP + : (shared_repository == PERM_EVERYBODY + ? (S_IRGRP|S_IROTH) + : 0)); + if (mode & S_IWUSR) mode |= S_IWGRP; + if (mode & S_IXUSR) - mode |= S_IXGRP; + mode |= (shared_repository == PERM_GROUP + ? S_IXGRP + : (shared_repository == PERM_EVERYBODY + ? (S_IXGRP|S_IXOTH) + : 0)); if (S_ISDIR(mode)) mode |= S_ISGID; if (chmod(path, mode) < 0) diff --git a/ppc/sha1.c b/ppc/sha1.c index 5ba4fc525..0820398b0 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; @@ -219,12 +219,27 @@ const char *setup_git_directory_gently(int *nongit_ok) return cwd + offset; } +int git_config_perm(const char *var, const char *value) +{ + if (value) { + if (!strcmp(value, "umask")) + return PERM_UMASK; + if (!strcmp(value, "group")) + return PERM_GROUP; + if (!strcmp(value, "all") || + !strcmp(value, "world") || + !strcmp(value, "everybody")) + return PERM_EVERYBODY; + } + return git_config_bool(var, value); +} + int check_repository_format_version(const char *var, const char *value) { if (strcmp(var, "core.repositoryformatversion") == 0) repository_format_version = git_config_int(var, value); else if (strcmp(var, "core.sharedrepository") == 0) - shared_repository = git_config_bool(var, value); + shared_repository = git_config_perm(var, value); return 0; } diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index 114938c3f..c04f0e154 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 \ |