From 6c510bee2013022fbce52f4b0ec0cc593fc0cc48 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 13 Feb 2007 11:07:23 -0800 Subject: Lazy man's auto-CRLF It currently does NOT know about file attributes, so it does its conversion purely based on content. Maybe that is more in the "git philosophy" anyway, since content is king, but I think we should try to do the file attributes to turn it off on demand. Anyway, BY DEFAULT it is off regardless, because it requires a [core] AutoCRLF = true in your config file to be enabled. We could make that the default for Windows, of course, the same way we do some other things (filemode etc). But you can actually enable it on UNIX, and it will cause: - "git update-index" will write blobs without CRLF - "git diff" will diff working tree files without CRLF - "git checkout" will write files to the working tree _with_ CRLF and things work fine. Funnily, it actually shows an odd file in git itself: git clone -n git test-crlf cd test-crlf git config core.autocrlf true git checkout git diff shows a diff for "Documentation/docbook-xsl.css". Why? Because we have actually checked in that file *with* CRLF! So when "core.autocrlf" is true, we'll always generate a *different* hash for it in the index, because the index hash will be for the content _without_ CRLF. Is this complete? I dunno. It seems to work for me. It doesn't use the filename at all right now, and that's probably a deficiency (we could certainly make the "is_binary()" heuristics also take standard filename heuristics into account). I don't pass in the filename at all for the "index_fd()" case (git-update-index), so that would need to be passed around, but this actually works fine. NOTE NOTE NOTE! The "is_binary()" heuristics are totally made-up by yours truly. I will not guarantee that they work at all reasonable. Caveat emptor. But it _is_ simple, and it _is_ safe, since it's all off by default. The patch is pretty simple - the biggest part is the new "convert.c" file, but even that is really just basic stuff that anybody can write in "Teaching C 101" as a final project for their first class in programming. Not to say that it's bug-free, of course - but at least we're not talking about rocket surgery here. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- cache.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'cache.h') diff --git a/cache.h b/cache.h index c62b0b090d..9c019e8bba 100644 --- a/cache.h +++ b/cache.h @@ -201,6 +201,7 @@ extern const char *apply_default_whitespace; extern int zlib_compression_level; extern size_t packed_git_window_size; extern size_t packed_git_limit; +extern int auto_crlf; #define GIT_REPO_VERSION 0 extern int repository_format_version; @@ -468,4 +469,8 @@ extern int nfvasprintf(char **str, const char *fmt, va_list va); extern void trace_printf(const char *format, ...); extern void trace_argv_printf(const char **argv, int count, const char *format, ...); +/* convert.c */ +extern int convert_to_git(const char *path, char **bufp, unsigned long *sizep); +extern int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep); + #endif /* CACHE_H */ -- cgit v1.3-5-g9baa From 185c975faaa790a98a4e00f124461473283500d6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 16 Feb 2007 22:43:48 -0800 Subject: Do not take mode bits from index after type change. When we do not trust executable bit from lstat(2), we copied existing ce_mode bits without checking if the filesystem object is a regular file (which is the only thing we apply the "trust executable bit" business) nor if the blob in the index is a regular file (otherwise, we should do the same as registering a new regular file, which is to default non-executable). Noticed by Johannes Sixt. Signed-off-by: Junio C Hamano --- builtin-apply.c | 2 +- builtin-update-index.c | 13 +++++++------ cache.h | 10 ++++++++++ diff-lib.c | 4 +--- read-cache.c | 13 +++++++------ t/t3700-add.sh | 20 ++++++++++++++++++++ 6 files changed, 46 insertions(+), 16 deletions(-) (limited to 'cache.h') diff --git a/builtin-apply.c b/builtin-apply.c index 3fefdacd94..abe3538715 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1988,7 +1988,7 @@ static int check_patch(struct patch *patch, struct patch *prev_patch) return error("%s: %s", old_name, strerror(errno)); if (!cached) - st_mode = ntohl(create_ce_mode(st.st_mode)); + st_mode = ntohl(ce_mode_from_stat(ce, st.st_mode)); if (patch->is_new < 0) patch->is_new = 0; diff --git a/builtin-update-index.c b/builtin-update-index.c index 1ac613a788..772aaba7bb 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -109,16 +109,17 @@ static int add_file_to_cache(const char *path) ce->ce_flags = htons(namelen); fill_stat_cache_info(ce, &st); - ce->ce_mode = create_ce_mode(st.st_mode); - if (!trust_executable_bit) { + if (trust_executable_bit) + ce->ce_mode = create_ce_mode(st.st_mode); + else { /* If there is an existing entry, pick the mode bits * from it, otherwise assume unexecutable. */ + struct cache_entry *ent; int pos = cache_name_pos(path, namelen); - if (0 <= pos) - ce->ce_mode = active_cache[pos]->ce_mode; - else if (S_ISREG(st.st_mode)) - ce->ce_mode = create_ce_mode(S_IFREG | 0666); + + ent = (0 <= pos) ? active_cache[pos] : NULL; + ce->ce_mode = ce_mode_from_stat(ent, st.st_mode); } if (index_path(ce->sha1, path, &st, !info_only)) diff --git a/cache.h b/cache.h index c62b0b090d..04f8e63baf 100644 --- a/cache.h +++ b/cache.h @@ -106,6 +106,16 @@ static inline unsigned int create_ce_mode(unsigned int mode) return htonl(S_IFLNK); return htonl(S_IFREG | ce_permissions(mode)); } +static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode) +{ + extern int trust_executable_bit; + if (!trust_executable_bit && S_ISREG(mode)) { + if (ce && S_ISREG(ntohl(ce->ce_mode))) + return ce->ce_mode; + return create_ce_mode(0666); + } + return create_ce_mode(mode); +} #define canon_mode(mode) \ (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ S_ISLNK(mode) ? S_IFLNK : S_IFDIR) diff --git a/diff-lib.c b/diff-lib.c index 91cd87742f..556d5345bf 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -170,9 +170,7 @@ static int get_stat_data(struct cache_entry *ce, } changed = ce_match_stat(ce, &st, 0); if (changed) { - mode = create_ce_mode(st.st_mode); - if (!trust_executable_bit && S_ISREG(st.st_mode)) - mode = ce->ce_mode; + mode = ce_mode_from_stat(ce, st.st_mode); sha1 = no_sha1; } } diff --git a/read-cache.c b/read-cache.c index c54a611877..605b352396 100644 --- a/read-cache.c +++ b/read-cache.c @@ -344,16 +344,17 @@ int add_file_to_index(const char *path, int verbose) ce->ce_flags = htons(namelen); fill_stat_cache_info(ce, &st); - ce->ce_mode = create_ce_mode(st.st_mode); - if (!trust_executable_bit) { + if (trust_executable_bit) + ce->ce_mode = create_ce_mode(st.st_mode); + else { /* If there is an existing entry, pick the mode bits * from it, otherwise assume unexecutable. */ + struct cache_entry *ent; int pos = cache_name_pos(path, namelen); - if (pos >= 0) - ce->ce_mode = active_cache[pos]->ce_mode; - else if (S_ISREG(st.st_mode)) - ce->ce_mode = create_ce_mode(S_IFREG | 0666); + + ent = (0 <= pos) ? active_cache[pos] : NULL; + ce->ce_mode = ce_mode_from_stat(ent, st.st_mode); } if (index_path(ce->sha1, path, &st, 1)) diff --git a/t/t3700-add.sh b/t/t3700-add.sh index caaab26c2f..08e035220c 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -30,6 +30,16 @@ test_expect_success \ *) echo fail; git-ls-files --stage xfoo1; (exit 1);; esac' +test_expect_success 'git-add: filemode=0 should not get confused by symlink' ' + rm -f xfoo1 && + ln -s foo xfoo1 && + git-add xfoo1 && + case "`git-ls-files --stage xfoo1`" in + 120000" "*xfoo1) echo ok;; + *) echo fail; git-ls-files --stage xfoo1; (exit 1);; + esac +' + test_expect_success \ 'git-update-index --add: Test that executable bit is not used...' \ 'git config core.filemode 0 && @@ -41,6 +51,16 @@ test_expect_success \ *) echo fail; git-ls-files --stage xfoo2; (exit 1);; esac' +test_expect_success 'git-add: filemode=0 should not get confused by symlink' ' + rm -f xfoo2 && + ln -s foo xfoo2 && + git update-index --add xfoo2 && + case "`git-ls-files --stage xfoo2`" in + 120000" "*xfoo2) echo ok;; + *) echo fail; git-ls-files --stage xfoo2; (exit 1);; + esac +' + test_expect_success \ 'git-update-index --add: Test that executable bit is not used...' \ 'git config core.filemode 0 && -- cgit v1.3-5-g9baa From 21666f1aae4e890d8f50924f9e80763b27e6a45d Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 26 Feb 2007 14:55:59 -0500 Subject: convert object type handling from a string to a number We currently have two parallel notation for dealing with object types in the code: a string and a numerical value. One of them is obviously redundent, and the most used one requires more stack space and a bunch of strcmp() all over the place. This is an initial step for the removal of the version using a char array found in object reading code paths. The patch is unfortunately large but there is no sane way to split it in smaller parts without breaking the system. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- archive-tar.c | 4 +- archive-zip.c | 4 +- blob.c | 6 +- builtin-apply.c | 8 +-- builtin-blame.c | 18 +++-- builtin-cat-file.c | 19 +++--- builtin-commit-tree.c | 7 +- builtin-for-each-ref.c | 4 +- builtin-grep.c | 8 +-- builtin-log.c | 4 +- builtin-pack-objects.c | 32 +++++---- builtin-prune.c | 11 +-- builtin-reflog.c | 4 +- builtin-unpack-objects.c | 39 +++++------ cache.h | 36 +++++----- combine-diff.c | 6 +- commit.c | 6 +- convert-objects.c | 12 ++-- diff.c | 7 +- entry.c | 6 +- fast-import.c | 18 ++--- http-push.c | 6 +- index-pack.c | 10 ++- merge-file.c | 10 +-- merge-recursive.c | 14 ++-- merge-tree.c | 8 +-- mktag.c | 8 +-- mktree.c | 9 +-- object.c | 16 ++--- object.h | 2 +- pack-check.c | 14 ++-- read-cache.c | 4 +- sha1_file.c | 172 ++++++++++++++++++++++------------------------- tag.c | 6 +- tree-diff.c | 6 +- tree.c | 6 +- unpack-file.c | 6 +- 37 files changed, 266 insertions(+), 290 deletions(-) (limited to 'cache.h') diff --git a/archive-tar.c b/archive-tar.c index 7d52a061f4..d9c30d33dc 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -262,7 +262,7 @@ static int write_tar_entry(const unsigned char *sha1, static struct strbuf path; int filenamelen = strlen(filename); void *buffer; - char type[20]; + enum object_type type; unsigned long size; if (!path.alloc) { @@ -283,7 +283,7 @@ static int write_tar_entry(const unsigned char *sha1, buffer = NULL; size = 0; } else { - buffer = read_sha1_file(sha1, type, &size); + buffer = read_sha1_file(sha1, &type, &size); if (!buffer) die("cannot read %s", sha1_to_hex(sha1)); } diff --git a/archive-zip.c b/archive-zip.c index f31b8ed823..7c4984886f 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -167,7 +167,7 @@ static int write_zip_entry(const unsigned char *sha1, int pathlen; unsigned char *out; char *path; - char type[20]; + enum object_type type; void *buffer = NULL; void *deflated = NULL; @@ -195,7 +195,7 @@ static int write_zip_entry(const unsigned char *sha1, if (S_ISREG(mode) && zlib_compression_level != 0) method = 8; result = 0; - buffer = read_sha1_file(sha1, type, &size); + buffer = read_sha1_file(sha1, &type, &size); if (!buffer) die("cannot read %s", sha1_to_hex(sha1)); crc = crc32(crc, buffer, size); diff --git a/blob.c b/blob.c index 9776beac58..0a9ea417b8 100644 --- a/blob.c +++ b/blob.c @@ -30,18 +30,18 @@ int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size) int parse_blob(struct blob *item) { - char type[20]; + enum object_type type; void *buffer; unsigned long size; int ret; if (item->object.parsed) return 0; - buffer = read_sha1_file(item->object.sha1, type, &size); + buffer = read_sha1_file(item->object.sha1, &type, &size); if (!buffer) return error("Could not read %s", sha1_to_hex(item->object.sha1)); - if (strcmp(type, blob_type)) + if (type != OBJ_BLOB) return error("Object %s not a blob", sha1_to_hex(item->object.sha1)); ret = parse_blob_buffer(item, buffer, size); diff --git a/builtin-apply.c b/builtin-apply.c index b84d747e3f..38f647510a 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1912,11 +1912,11 @@ static int apply_binary(struct buffer_desc *desc, struct patch *patch) if (has_sha1_file(sha1)) { /* We already have the postimage */ - char type[10]; + enum object_type type; unsigned long size; free(desc->buffer); - desc->buffer = read_sha1_file(sha1, type, &size); + desc->buffer = read_sha1_file(sha1, &type, &size); if (!desc->buffer) return error("the necessary postimage %s for " "'%s' cannot be read", @@ -1972,8 +1972,8 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry * buf = NULL; if (cached) { if (ce) { - char type[20]; - buf = read_sha1_file(ce->sha1, type, &size); + enum object_type type; + buf = read_sha1_file(ce->sha1, &type, &size); if (!buf) return error("read of %s failed", patch->old_name); diff --git a/builtin-blame.c b/builtin-blame.c index 530b97f97d..9f7dd4e19f 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -87,9 +87,9 @@ struct origin { static char *fill_origin_blob(struct origin *o, mmfile_t *file) { if (!o->file.ptr) { - char type[10]; + enum object_type type; num_read_blob++; - file->ptr = read_sha1_file(o->blob_sha1, type, + file->ptr = read_sha1_file(o->blob_sha1, &type, (unsigned long *)(&(file->size))); o->file = *file; } @@ -263,7 +263,6 @@ static struct origin *get_origin(struct scoreboard *sb, static int fill_blob_sha1(struct origin *origin) { unsigned mode; - char type[10]; if (!is_null_sha1(origin->blob_sha1)) return 0; @@ -271,8 +270,7 @@ static int fill_blob_sha1(struct origin *origin) origin->path, origin->blob_sha1, &mode)) goto error_out; - if (sha1_object_info(origin->blob_sha1, type, NULL) || - strcmp(type, blob_type)) + if (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB) goto error_out; return 0; error_out: @@ -1322,10 +1320,10 @@ static void get_commit_info(struct commit *commit, * we now need to populate them for output. */ if (!commit->buffer) { - char type[20]; + enum object_type type; unsigned long size; commit->buffer = - read_sha1_file(commit->object.sha1, type, &size); + read_sha1_file(commit->object.sha1, &type, &size); } ret->author = author_buf; get_ac_line(commit->buffer, "\nauthor ", @@ -2006,7 +2004,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con buf[fin_size] = 0; origin->file.ptr = buf; origin->file.size = fin_size; - pretend_sha1_file(buf, fin_size, blob_type, origin->blob_sha1); + pretend_sha1_file(buf, fin_size, OBJ_BLOB, origin->blob_sha1); commit->util = origin; /* @@ -2068,7 +2066,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) int show_stats = 0; const char *revs_file = NULL; const char *final_commit_name = NULL; - char type[10]; + enum object_type type; const char *bottomtop = NULL; const char *contents_from = NULL; @@ -2302,7 +2300,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) if (fill_blob_sha1(o)) die("no such path %s in %s", path, final_commit_name); - sb.final_buf = read_sha1_file(o->blob_sha1, type, + sb.final_buf = read_sha1_file(o->blob_sha1, &type, &sb.final_buf_size); } num_read_blob++; diff --git a/builtin-cat-file.c b/builtin-cat-file.c index 6c16bfa1ae..d61d3d5b74 100644 --- a/builtin-cat-file.c +++ b/builtin-cat-file.c @@ -79,7 +79,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long int cmd_cat_file(int argc, const char **argv, const char *prefix) { unsigned char sha1[20]; - char type[20]; + enum object_type type; void *buf; unsigned long size; int opt; @@ -100,14 +100,16 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) buf = NULL; switch (opt) { case 't': - if (!sha1_object_info(sha1, type, NULL)) { - printf("%s\n", type); + type = sha1_object_info(sha1, NULL); + if (type > 0) { + printf("%s\n", typename(type)); return 0; } break; case 's': - if (!sha1_object_info(sha1, type, &size)) { + type = sha1_object_info(sha1, &size); + if (type > 0) { printf("%lu\n", size); return 0; } @@ -117,17 +119,18 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) return !has_sha1_file(sha1); case 'p': - if (sha1_object_info(sha1, type, NULL)) + type = sha1_object_info(sha1, NULL); + if (type < 0) die("Not a valid object name %s", argv[2]); /* custom pretty-print here */ - if (!strcmp(type, tree_type)) + if (type == OBJ_TREE) return cmd_ls_tree(2, argv + 1, NULL); - buf = read_sha1_file(sha1, type, &size); + buf = read_sha1_file(sha1, &type, &size); if (!buf) die("Cannot read object %s", argv[2]); - if (!strcmp(type, tag_type)) { + if (type == OBJ_TAG) { pprint_tag(sha1, buf, size); return 0; } diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c index 2a818a0a2c..04f61d5101 100644 --- a/builtin-commit-tree.c +++ b/builtin-commit-tree.c @@ -47,11 +47,10 @@ static void add_buffer(char **bufp, unsigned int *sizep, const char *fmt, ...) static void check_valid(unsigned char *sha1, const char *expect) { - char type[20]; - - if (sha1_object_info(sha1, type, NULL)) + enum object_type type = sha1_object_info(sha1, NULL); + if (type < 0) die("%s is not a valid object", sha1_to_hex(sha1)); - if (expect && strcmp(type, expect)) + if (expect && type != type_from_string(expect)) die("%s is not a valid '%s' object", sha1_to_hex(sha1), expect); } diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index 14fff2b1c5..b11ca928d6 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -173,8 +173,8 @@ static void verify_format(const char *format) */ static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten) { - char type[20]; - void *buf = read_sha1_file(sha1, type, sz); + enum object_type type; + void *buf = read_sha1_file(sha1, &type, sz); if (buf) *obj = parse_object_buffer(sha1, type, *sz, buf, eaten); diff --git a/builtin-grep.c b/builtin-grep.c index f35f2d023c..96b70227cf 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -84,11 +84,11 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char { unsigned long size; char *data; - char type[20]; + enum object_type type; char *to_free = NULL; int hit; - data = read_sha1_file(sha1, type, &size); + data = read_sha1_file(sha1, &type, &size); if (!data) { error("'%s': unable to read %s", name, sha1_to_hex(sha1)); return 0; @@ -380,10 +380,10 @@ static int grep_tree(struct grep_opt *opt, const char **paths, else if (S_ISREG(entry.mode)) hit |= grep_sha1(opt, entry.sha1, path_buf, tn_len); else if (S_ISDIR(entry.mode)) { - char type[20]; + enum object_type type; struct tree_desc sub; void *data; - data = read_sha1_file(entry.sha1, type, &sub.size); + data = read_sha1_file(entry.sha1, &type, &sub.size); if (!data) die("unable to read tree (%s)", sha1_to_hex(entry.sha1)); diff --git a/builtin-log.c b/builtin-log.c index f43790cbce..1c9f7d02a8 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -89,8 +89,8 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) static int show_object(const unsigned char *sha1, int suppress_header) { unsigned long size; - char type[20]; - char *buf = read_sha1_file(sha1, type, &size); + enum object_type type; + char *buf = read_sha1_file(sha1, &type, &size); int offset = 0; if (!buf) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 1c04618915..8cf24f4079 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -230,8 +230,8 @@ static unsigned char *find_packed_object_name(struct packed_git *p, static void *delta_against(void *buf, unsigned long size, struct object_entry *entry) { unsigned long othersize, delta_size; - char type[10]; - void *otherbuf = read_sha1_file(entry->delta->sha1, type, &othersize); + enum object_type type; + void *otherbuf = read_sha1_file(entry->delta->sha1, &type, &othersize); void *delta_buf; if (!otherbuf) @@ -375,7 +375,7 @@ static unsigned long write_object(struct sha1file *f, struct object_entry *entry) { unsigned long size; - char type[10]; + enum object_type type; void *buf; unsigned char header[10]; unsigned hdrlen, datalen; @@ -416,7 +416,7 @@ static unsigned long write_object(struct sha1file *f, } if (!to_reuse) { - buf = read_sha1_file(entry->sha1, type, &size); + buf = read_sha1_file(entry->sha1, &type, &size); if (!buf) die("unable to read %s", sha1_to_hex(entry->sha1)); if (size != entry->size) @@ -765,7 +765,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1) struct pbase_tree_cache *ent, *nent; void *data; unsigned long size; - char type[20]; + enum object_type type; int neigh; int my_ix = pbase_tree_cache_ix(sha1); int available_ix = -1; @@ -792,10 +792,10 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1) /* Did not find one. Either we got a bogus request or * we need to read and perhaps cache. */ - data = read_sha1_file(sha1, type, &size); + data = read_sha1_file(sha1, &type, &size); if (!data) return NULL; - if (strcmp(type, tree_type)) { + if (type != OBJ_TREE) { free(data); return NULL; } @@ -854,19 +854,19 @@ static void add_pbase_object(struct tree_desc *tree, while (tree_entry(tree,&entry)) { unsigned long size; - char type[20]; + enum object_type type; if (entry.pathlen != cmplen || memcmp(entry.path, name, cmplen) || !has_sha1_file(entry.sha1) || - sha1_object_info(entry.sha1, type, &size)) + (type = sha1_object_info(entry.sha1, &size)) < 0) continue; if (name[cmplen] != '/') { unsigned hash = name_hash(fullname); add_object_entry(entry.sha1, hash, 1); return; } - if (!strcmp(type, tree_type)) { + if (type == OBJ_TREE) { struct tree_desc sub; struct pbase_tree_cache *tree; const char *down = name+cmplen+1; @@ -978,8 +978,6 @@ static void add_preferred_base(unsigned char *sha1) static void check_object(struct object_entry *entry) { - char type[20]; - if (entry->in_pack && !entry->preferred_base) { struct packed_git *p = entry->in_pack; struct pack_window *w_curs = NULL; @@ -1062,10 +1060,10 @@ static void check_object(struct object_entry *entry) /* Otherwise we would do the usual */ } - if (sha1_object_info(entry->sha1, type, &entry->size)) + entry->type = sha1_object_info(entry->sha1, &entry->size); + if (entry->type < 0) die("unable to get type of object %s", sha1_to_hex(entry->sha1)); - entry->type = type_from_string(type); } static unsigned int check_delta_limit(struct object_entry *me, unsigned int n) @@ -1195,7 +1193,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, struct object_entry *trg_entry = trg->entry; struct object_entry *src_entry = src->entry; unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz; - char type[10]; + enum object_type type; void *delta_buf; /* Don't bother doing diffs between different types */ @@ -1246,13 +1244,13 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, /* Load data if not already done */ if (!trg->data) { - trg->data = read_sha1_file(trg_entry->sha1, type, &sz); + trg->data = read_sha1_file(trg_entry->sha1, &type, &sz); if (sz != trg_size) die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(trg_entry->sha1), sz, trg_size); } if (!src->data) { - src->data = read_sha1_file(src_entry->sha1, type, &sz); + src->data = read_sha1_file(src_entry->sha1, &type, &sz); if (sz != src_size) die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(src_entry->sha1), sz, src_size); diff --git a/builtin-prune.c b/builtin-prune.c index 6f0ba0d04d..09864b7a6d 100644 --- a/builtin-prune.c +++ b/builtin-prune.c @@ -10,15 +10,10 @@ static int show_only; static int prune_object(char *path, const char *filename, const unsigned char *sha1) { - char buf[20]; - const char *type; - if (show_only) { - if (sha1_object_info(sha1, buf, NULL)) - type = "unknown"; - else - type = buf; - printf("%s %s\n", sha1_to_hex(sha1), type); + enum object_type type = sha1_object_info(sha1, NULL); + printf("%s %s\n", sha1_to_hex(sha1), + (type > 0) ? typename(type) : "unknown"); return 0; } unlink(mkpath("%s/%s", path, filename)); diff --git a/builtin-reflog.c b/builtin-reflog.c index cefb40da81..186aabce04 100644 --- a/builtin-reflog.c +++ b/builtin-reflog.c @@ -55,8 +55,8 @@ static int tree_is_complete(const unsigned char *sha1) desc.buf = tree->buffer; desc.size = tree->size; if (!desc.buf) { - char type[20]; - void *data = read_sha1_file(sha1, type, &desc.size); + enum object_type type; + void *data = read_sha1_file(sha1, &type, &desc.size); if (!data) { tree->object.flags |= INCOMPLETE; return 0; diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 8f8e898516..3956c56334 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -119,18 +119,18 @@ struct obj_info { static struct obj_info *obj_list; -static void added_object(unsigned nr, const char *type, void *data, - unsigned long size); +static void added_object(unsigned nr, enum object_type type, + void *data, unsigned long size); -static void write_object(unsigned nr, void *buf, unsigned long size, - const char *type) +static void write_object(unsigned nr, enum object_type type, + void *buf, unsigned long size) { - if (write_sha1_file(buf, size, type, obj_list[nr].sha1) < 0) + if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0) die("failed to write object"); added_object(nr, type, buf, size); } -static void resolve_delta(unsigned nr, const char *type, +static void resolve_delta(unsigned nr, enum object_type type, void *base, unsigned long base_size, void *delta, unsigned long delta_size) { @@ -143,12 +143,12 @@ static void resolve_delta(unsigned nr, const char *type, if (!result) die("failed to apply delta"); free(delta); - write_object(nr, result, result_size, type); + write_object(nr, type, result, result_size); free(result); } -static void added_object(unsigned nr, const char *type, void *data, - unsigned long size) +static void added_object(unsigned nr, enum object_type type, + void *data, unsigned long size) { struct delta_info **p = &delta_list; struct delta_info *info; @@ -167,33 +167,24 @@ static void added_object(unsigned nr, const char *type, void *data, } } -static void unpack_non_delta_entry(enum object_type kind, unsigned long size, +static void unpack_non_delta_entry(enum object_type type, unsigned long size, unsigned nr) { void *buf = get_data(size); - const char *type; - - switch (kind) { - case OBJ_COMMIT: type = commit_type; break; - case OBJ_TREE: type = tree_type; break; - case OBJ_BLOB: type = blob_type; break; - case OBJ_TAG: type = tag_type; break; - default: die("bad type %d", kind); - } + if (!dry_run && buf) - write_object(nr, buf, size, type); + write_object(nr, type, buf, size); free(buf); } -static void unpack_delta_entry(enum object_type kind, unsigned long delta_size, +static void unpack_delta_entry(enum object_type type, unsigned long delta_size, unsigned nr) { void *delta_data, *base; unsigned long base_size; - char type[20]; unsigned char base_sha1[20]; - if (kind == OBJ_REF_DELTA) { + if (type == OBJ_REF_DELTA) { hashcpy(base_sha1, fill(20)); use(20); delta_data = get_data(delta_size); @@ -255,7 +246,7 @@ static void unpack_delta_entry(enum object_type kind, unsigned long delta_size, } } - base = read_sha1_file(base_sha1, type, &base_size); + base = read_sha1_file(base_sha1, &type, &base_size); if (!base) { error("failed to read delta-pack base object %s", sha1_to_hex(base_sha1)); diff --git a/cache.h b/cache.h index 8bbc14299d..0117b7eedd 100644 --- a/cache.h +++ b/cache.h @@ -262,13 +262,25 @@ int adjust_shared_perm(const char *path); int safe_create_leading_directories(char *path); char *enter_repo(char *path, int strict); +enum object_type { + OBJ_NONE = 0, + OBJ_COMMIT = 1, + OBJ_TREE = 2, + OBJ_BLOB = 3, + OBJ_TAG = 4, + /* 5 for future expansion */ + OBJ_OFS_DELTA = 6, + OBJ_REF_DELTA = 7, + OBJ_BAD, +}; + /* Read and unpack a sha1 file into memory, write memory to a sha1 file */ -extern int sha1_object_info(const unsigned char *, char *, unsigned long *); -extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size); -extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size); +extern int sha1_object_info(const unsigned char *, unsigned long *); +extern void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size); +extern void * read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size); extern int hash_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1); extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1); -extern int pretend_sha1_file(void *, unsigned long, const char *, unsigned char *); +extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *); extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type); @@ -285,18 +297,6 @@ extern int legacy_loose_object(unsigned char *); extern int has_pack_file(const unsigned char *sha1); extern int has_pack_index(const unsigned char *sha1); -enum object_type { - OBJ_NONE = 0, - OBJ_COMMIT = 1, - OBJ_TREE = 2, - OBJ_BLOB = 3, - OBJ_TAG = 4, - /* 5 for future expansion */ - OBJ_OFS_DELTA = 6, - OBJ_REF_DELTA = 7, - OBJ_BAD, -}; - extern signed char hexval_table[256]; static inline unsigned int hexval(unsigned int c) { @@ -422,9 +422,9 @@ extern struct packed_git *add_packed_git(char *, int, int); extern int num_packed_objects(const struct packed_git *p); extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*); extern unsigned long find_pack_entry_one(const unsigned char *, struct packed_git *); -extern void *unpack_entry(struct packed_git *, unsigned long, char *, unsigned long *); +extern void *unpack_entry(struct packed_git *, unsigned long, enum object_type *, unsigned long *); extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep); -extern void packed_object_info_detail(struct packed_git *, unsigned long, char *, unsigned long *, unsigned long *, unsigned int *, unsigned char *); +extern const char *packed_object_info_detail(struct packed_git *, unsigned long, unsigned long *, unsigned long *, unsigned int *, unsigned char *); /* Dumb servers support */ extern int update_server_info(int); diff --git a/combine-diff.c b/combine-diff.c index 044633d164..9daa0cb9a9 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -92,14 +92,14 @@ struct sline { static char *grab_blob(const unsigned char *sha1, unsigned long *size) { char *blob; - char type[20]; + enum object_type type; if (is_null_sha1(sha1)) { /* deleted blob */ *size = 0; return xcalloc(1, 1); } - blob = read_sha1_file(sha1, type, size); - if (strcmp(type, blob_type)) + blob = read_sha1_file(sha1, &type, size); + if (type != OBJ_BLOB) die("object '%s' is not a blob!", sha1_to_hex(sha1)); return blob; } diff --git a/commit.c b/commit.c index 8d279b0b63..da515a4973 100644 --- a/commit.c +++ b/commit.c @@ -342,18 +342,18 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) int parse_commit(struct commit *item) { - char type[20]; + enum object_type type; void *buffer; unsigned long size; int ret; if (item->object.parsed) return 0; - buffer = read_sha1_file(item->object.sha1, type, &size); + buffer = read_sha1_file(item->object.sha1, &type, &size); if (!buffer) return error("Could not read %s", sha1_to_hex(item->object.sha1)); - if (strcmp(type, commit_type)) { + if (type != OBJ_COMMIT) { free(buffer); return error("Object %s not a commit", sha1_to_hex(item->object.sha1)); diff --git a/convert-objects.c b/convert-objects.c index a630132985..b5f41ae2e3 100644 --- a/convert-objects.c +++ b/convert-objects.c @@ -284,27 +284,27 @@ static void convert_commit(void *buffer, unsigned long size, unsigned char *resu static struct entry * convert_entry(unsigned char *sha1) { struct entry *entry = lookup_entry(sha1); - char type[20]; + enum object_type type; void *buffer, *data; unsigned long size; if (entry->converted) return entry; - data = read_sha1_file(sha1, type, &size); + data = read_sha1_file(sha1, &type, &size); if (!data) die("unable to read object %s", sha1_to_hex(sha1)); buffer = xmalloc(size); memcpy(buffer, data, size); - if (!strcmp(type, blob_type)) { + if (type == OBJ_BLOB) { write_sha1_file(buffer, size, blob_type, entry->new_sha1); - } else if (!strcmp(type, tree_type)) + } else if (type == OBJ_TREE) convert_tree(buffer, size, entry->new_sha1); - else if (!strcmp(type, commit_type)) + else if (type == OBJ_COMMIT) convert_commit(buffer, size, entry->new_sha1); else - die("unknown object type '%s' in %s", type, sha1_to_hex(sha1)); + die("unknown object type %d in %s", type, sha1_to_hex(sha1)); entry->converted = 1; free(buffer); free(data); diff --git a/diff.c b/diff.c index d1eae7214d..f033eb0622 100644 --- a/diff.c +++ b/diff.c @@ -1430,7 +1430,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) } } else { - char type[20]; + enum object_type type; struct sha1_size_cache *e; if (size_only) { @@ -1439,11 +1439,12 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) s->size = e->size; return 0; } - if (!sha1_object_info(s->sha1, type, &s->size)) + type = sha1_object_info(s->sha1, &s->size); + if (type < 0) locate_size_cache(s->sha1, 0, s->size); } else { - s->data = read_sha1_file(s->sha1, type, &s->size); + s->data = read_sha1_file(s->sha1, &type, &s->size); s->should_free = 1; } } diff --git a/entry.c b/entry.c index 472a9ef321..21b5f2e26d 100644 --- a/entry.c +++ b/entry.c @@ -68,10 +68,10 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat void *new; unsigned long size; long wrote; - char type[20]; + enum object_type type; - new = read_sha1_file(ce->sha1, type, &size); - if (!new || strcmp(type, blob_type)) { + new = read_sha1_file(ce->sha1, &type, &size); + if (!new || type != OBJ_BLOB) { if (new) free(new); return error("git-checkout-index: unable to read sha1 file of %s (%s)", diff --git a/fast-import.c b/fast-import.c index aa9eac3925..65e99c2e8b 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1008,11 +1008,11 @@ static void *gfi_unpack_entry( struct object_entry *oe, unsigned long *sizep) { - static char type[20]; + enum object_type type; struct packed_git *p = all_packs[oe->pack_id]; if (p == pack_data) p->pack_size = pack_size + 20; - return unpack_entry(p, oe->offset, type, sizep); + return unpack_entry(p, oe->offset, &type, sizep); } static const char *get_mode(const char *str, uint16_t *modep) @@ -1049,9 +1049,9 @@ static void load_tree(struct tree_entry *root) t->delta_depth = 0; buf = gfi_unpack_entry(myoe, &size); } else { - char type[20]; - buf = read_sha1_file(sha1, type, &size); - if (!buf || strcmp(type, tree_type)) + enum object_type type; + buf = read_sha1_file(sha1, &type, &size); + if (!buf || type != OBJ_TREE) die("Can't load tree %s", sha1_to_hex(sha1)); } @@ -1573,7 +1573,6 @@ static void file_change_m(struct branch *b) struct object_entry *oe = oe; unsigned char sha1[20]; uint16_t mode, inline_data = 0; - char type[20]; p = get_mode(p, &mode); if (!p) @@ -1628,11 +1627,12 @@ static void file_change_m(struct branch *b) die("Not a blob (actually a %s): %s", command_buf.buf, typename(oe->type)); } else { - if (sha1_object_info(sha1, type, NULL)) + enum object_type type = sha1_object_info(sha1, NULL); + if (type < 0) die("Blob not found: %s", command_buf.buf); - if (strcmp(blob_type, type)) + if (type != OBJ_BLOB) die("Not a blob (actually a %s): %s", - command_buf.buf, type); + typename(type), command_buf.buf); } tree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode); diff --git a/http-push.c b/http-push.c index 9ad6fd00b0..0fd73dbf58 100644 --- a/http-push.c +++ b/http-push.c @@ -479,7 +479,7 @@ static void start_put(struct transfer_request *request) char *hex = sha1_to_hex(request->obj->sha1); struct active_request_slot *slot; char *posn; - char type[20]; + enum object_type type; char hdr[50]; void *unpacked; unsigned long len; @@ -487,8 +487,8 @@ static void start_put(struct transfer_request *request) ssize_t size; z_stream stream; - unpacked = read_sha1_file(request->obj->sha1, type, &len); - hdrlen = sprintf(hdr, "%s %lu", type, len) + 1; + unpacked = read_sha1_file(request->obj->sha1, &type, &len); + hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1; /* Set it up */ memset(&stream, 0, sizeof(stream)); diff --git a/index-pack.c b/index-pack.c index 4b527854eb..c56458ebd5 100644 --- a/index-pack.c +++ b/index-pack.c @@ -595,25 +595,23 @@ static void fix_unresolved_deltas(int nr_unresolved) struct delta_entry *d = sorted_by_pos[i]; void *data; unsigned long size; - char type[10]; - enum object_type obj_type; + enum object_type type; int j, first, last; if (objects[d->obj_no].real_type != OBJ_REF_DELTA) continue; - data = read_sha1_file(d->base.sha1, type, &size); + data = read_sha1_file(d->base.sha1, &type, &size); if (!data) continue; - obj_type = type_from_string(type); find_delta_children(&d->base, &first, &last); for (j = first; j <= last; j++) { struct object_entry *child = objects + deltas[j].obj_no; if (child->real_type == OBJ_REF_DELTA) - resolve_delta(child, data, size, obj_type); + resolve_delta(child, data, size, type); } - append_obj_to_pack(data, size, obj_type); + append_obj_to_pack(data, size, type); free(data); if (verbose) percent = display_progress(nr_resolved_deltas, diff --git a/merge-file.c b/merge-file.c index 69dc1ebbf7..748d15c0e0 100644 --- a/merge-file.c +++ b/merge-file.c @@ -7,12 +7,12 @@ static int fill_mmfile_blob(mmfile_t *f, struct blob *obj) { void *buf; unsigned long size; - char type[20]; + enum object_type type; - buf = read_sha1_file(obj->object.sha1, type, &size); + buf = read_sha1_file(obj->object.sha1, &type, &size); if (!buf) return -1; - if (strcmp(type, blob_type)) + if (type != OBJ_BLOB) return -1; f->ptr = buf; f->size = size; @@ -86,12 +86,12 @@ void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsign * modified in the other branch! */ if (!our || !their) { - char type[20]; + enum object_type type; if (base) return NULL; if (!our) our = their; - return read_sha1_file(our->object.sha1, type, size); + return read_sha1_file(our->object.sha1, &type, size); } if (fill_mmfile_blob(&f1, our) < 0) diff --git a/merge-recursive.c b/merge-recursive.c index 397a7ad85b..87cd8709bb 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -560,14 +560,14 @@ static void update_file_flags(const unsigned char *sha, update_wd = 0; if (update_wd) { - char type[20]; + enum object_type type; void *buf; unsigned long size; - buf = read_sha1_file(sha, type, &size); + buf = read_sha1_file(sha, &type, &size); if (!buf) die("cannot read object %s '%s'", sha1_to_hex(sha), path); - if (strcmp(type, blob_type) != 0) + if (type != OBJ_BLOB) die("blob expected for %s '%s'", sha1_to_hex(sha), path); if (S_ISREG(mode)) { @@ -620,7 +620,7 @@ struct merge_file_info static void fill_mm(const unsigned char *sha1, mmfile_t *mm) { unsigned long size; - char type[20]; + enum object_type type; if (!hashcmp(sha1, null_sha1)) { mm->ptr = xstrdup(""); @@ -628,8 +628,8 @@ static void fill_mm(const unsigned char *sha1, mmfile_t *mm) return; } - mm->ptr = read_sha1_file(sha1, type, &size); - if (!mm->ptr || strcmp(type, blob_type)) + mm->ptr = read_sha1_file(sha1, &type, &size); + if (!mm->ptr || type != OBJ_BLOB) die("unable to read blob object %s", sha1_to_hex(sha1)); mm->size = size; } @@ -1213,7 +1213,7 @@ static int merge(struct commit *h1, tree->object.parsed = 1; tree->object.type = OBJ_TREE; - pretend_sha1_file(NULL, 0, tree_type, tree->object.sha1); + pretend_sha1_file(NULL, 0, OBJ_TREE, tree->object.sha1); merged_common_ancestors = make_virtual_commit(tree, "ancestor"); } diff --git a/merge-tree.c b/merge-tree.c index 692ede0e3d..b2867ba722 100644 --- a/merge-tree.c +++ b/merge-tree.c @@ -57,11 +57,11 @@ extern void *merge_file(struct blob *, struct blob *, struct blob *, unsigned lo static void *result(struct merge_list *entry, unsigned long *size) { - char type[20]; + enum object_type type; struct blob *base, *our, *their; if (!entry->stage) - return read_sha1_file(entry->blob->object.sha1, type, size); + return read_sha1_file(entry->blob->object.sha1, &type, size); base = NULL; if (entry->stage == 1) { base = entry->blob; @@ -80,10 +80,10 @@ static void *result(struct merge_list *entry, unsigned long *size) static void *origin(struct merge_list *entry, unsigned long *size) { - char type[20]; + enum object_type type; while (entry) { if (entry->stage == 2) - return read_sha1_file(entry->blob->object.sha1, type, size); + return read_sha1_file(entry->blob->object.sha1, &type, size); entry = entry->link; } return NULL; diff --git a/mktag.c b/mktag.c index 3448a5dde7..931011121e 100644 --- a/mktag.c +++ b/mktag.c @@ -27,13 +27,13 @@ static int verify_object(unsigned char *sha1, const char *expected_type) { int ret = -1; - char type[100]; + enum object_type type; unsigned long size; - void *buffer = read_sha1_file(sha1, type, &size); + void *buffer = read_sha1_file(sha1, &type, &size); if (buffer) { - if (!strcmp(type, expected_type)) - ret = check_sha1_signature(sha1, buffer, size, type); + if (type == type_from_string(expected_type)) + ret = check_sha1_signature(sha1, buffer, size, expected_type); free(buffer); } return ret; diff --git a/mktree.c b/mktree.c index 56205d1e00..d86dde89d6 100644 --- a/mktree.c +++ b/mktree.c @@ -95,7 +95,7 @@ int main(int ac, char **av) int len; char *ptr, *ntr; unsigned mode; - char type[20]; + enum object_type type; char *path; read_line(&sb, stdin, line_termination); @@ -115,11 +115,12 @@ int main(int ac, char **av) ntr[41] != '\t' || get_sha1_hex(ntr + 1, sha1)) die("input format error: %s", sb.buf); - if (sha1_object_info(sha1, type, NULL)) + type = sha1_object_info(sha1, NULL); + if (type < 0) die("object %s unavailable", sha1_to_hex(sha1)); *ntr++ = 0; /* now at the beginning of SHA1 */ - if (strcmp(ptr, type)) - die("object type %s mismatch (%s)", ptr, type); + if (type != type_from_string(ptr)) + die("object type %s mismatch (%s)", ptr, typename(type)); ntr += 41; /* at the beginning of name */ if (line_termination && ntr[0] == '"') path = unquote_c_style(ntr, NULL); diff --git a/object.c b/object.c index 37cedc02e8..0e67af33bf 100644 --- a/object.c +++ b/object.c @@ -158,23 +158,23 @@ struct object *lookup_unknown_object(const unsigned char *sha1) return obj; } -struct object *parse_object_buffer(const unsigned char *sha1, const char *type, unsigned long size, void *buffer, int *eaten_p) +struct object *parse_object_buffer(const unsigned char *sha1, enum object_type type, unsigned long size, void *buffer, int *eaten_p) { struct object *obj; int eaten = 0; - if (!strcmp(type, blob_type)) { + if (type == OBJ_BLOB) { struct blob *blob = lookup_blob(sha1); parse_blob_buffer(blob, buffer, size); obj = &blob->object; - } else if (!strcmp(type, tree_type)) { + } else if (type == OBJ_TREE) { struct tree *tree = lookup_tree(sha1); obj = &tree->object; if (!tree->object.parsed) { parse_tree_buffer(tree, buffer, size); eaten = 1; } - } else if (!strcmp(type, commit_type)) { + } else if (type == OBJ_COMMIT) { struct commit *commit = lookup_commit(sha1); parse_commit_buffer(commit, buffer, size); if (!commit->buffer) { @@ -182,7 +182,7 @@ struct object *parse_object_buffer(const unsigned char *sha1, const char *type, eaten = 1; } obj = &commit->object; - } else if (!strcmp(type, tag_type)) { + } else if (type == OBJ_TAG) { struct tag *tag = lookup_tag(sha1); parse_tag_buffer(tag, buffer, size); obj = &tag->object; @@ -196,13 +196,13 @@ struct object *parse_object_buffer(const unsigned char *sha1, const char *type, struct object *parse_object(const unsigned char *sha1) { unsigned long size; - char type[20]; + enum object_type type; int eaten; - void *buffer = read_sha1_file(sha1, type, &size); + void *buffer = read_sha1_file(sha1, &type, &size); if (buffer) { struct object *obj; - if (check_sha1_signature(sha1, buffer, size, type) < 0) + if (check_sha1_signature(sha1, buffer, size, typename(type)) < 0) printf("sha1 mismatch %s\n", sha1_to_hex(sha1)); obj = parse_object_buffer(sha1, type, size, buffer, &eaten); diff --git a/object.h b/object.h index ade4dae447..749a6f5890 100644 --- a/object.h +++ b/object.h @@ -59,7 +59,7 @@ struct object *parse_object(const unsigned char *sha1); * parsing it. eaten_p indicates if the object has a borrowed copy * of buffer and the caller should not free() it. */ -struct object *parse_object_buffer(const unsigned char *sha1, const char *type, unsigned long size, void *buffer, int *eaten_p); +struct object *parse_object_buffer(const unsigned char *sha1, enum object_type type, unsigned long size, void *buffer, int *eaten_p); /** Returns the object, with potentially excess memory allocated. **/ struct object *lookup_unknown_object(const unsigned char *sha1); diff --git a/pack-check.c b/pack-check.c index 08a9fd8dc0..f248ac8c7a 100644 --- a/pack-check.c +++ b/pack-check.c @@ -43,7 +43,7 @@ static int verify_packfile(struct packed_git *p, for (i = err = 0; i < nr_objects; i++) { unsigned char sha1[20]; void *data; - char type[20]; + enum object_type type; unsigned long size, offset; if (nth_packed_object_sha1(p, i, sha1)) @@ -51,13 +51,13 @@ static int verify_packfile(struct packed_git *p, offset = find_pack_entry_one(sha1, p); if (!offset) die("internal error pack-check find-pack-entry-one"); - data = unpack_entry(p, offset, type, &size); + data = unpack_entry(p, offset, &type, &size); if (!data) { err = error("cannot unpack %s from %s", sha1_to_hex(sha1), p->pack_name); continue; } - if (check_sha1_signature(sha1, data, size, type)) { + if (check_sha1_signature(sha1, data, size, typename(type))) { err = error("packed %s from %s is corrupt", sha1_to_hex(sha1), p->pack_name); free(data); @@ -82,7 +82,7 @@ static void show_pack_info(struct packed_git *p) for (i = 0; i < nr_objects; i++) { unsigned char sha1[20], base_sha1[20]; - char type[20]; + const char *type; unsigned long size; unsigned long store_size; unsigned long offset; @@ -94,9 +94,9 @@ static void show_pack_info(struct packed_git *p) if (!offset) die("internal error pack-check find-pack-entry-one"); - packed_object_info_detail(p, offset, type, &size, &store_size, - &delta_chain_length, - base_sha1); + type = packed_object_info_detail(p, offset, &size, &store_size, + &delta_chain_length, + base_sha1); printf("%s ", sha1_to_hex(sha1)); if (!delta_chain_length) printf("%-6s %lu %lu\n", type, size, offset); diff --git a/read-cache.c b/read-cache.c index 605b352396..d63746476e 100644 --- a/read-cache.c +++ b/read-cache.c @@ -72,7 +72,7 @@ static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size) char *target; void *buffer; unsigned long size; - char type[10]; + enum object_type type; int len; target = xmalloc(expected_size); @@ -81,7 +81,7 @@ static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size) free(target); return -1; } - buffer = read_sha1_file(ce->sha1, type, &size); + buffer = read_sha1_file(ce->sha1, &type, &size); if (!buffer) { free(target); return -1; diff --git a/sha1_file.c b/sha1_file.c index 423ff0acc5..3831614734 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -983,26 +983,27 @@ static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size * too permissive for what we want to check. So do an anal * object header parse by hand. */ -static int parse_sha1_header(char *hdr, char *type, unsigned long *sizep) +static int parse_sha1_header(const char *hdr, unsigned long *sizep) { + char type[10]; int i; unsigned long size; /* * The type can be at most ten bytes (including the * terminating '\0' that we add), and is followed by - * a space. + * a space. */ - i = 10; + i = 0; for (;;) { char c = *hdr++; if (c == ' ') break; - if (!--i) + type[i++] = c; + if (i >= sizeof(type)) return -1; - *type++ = c; } - *type = 0; + type[i] = 0; /* * The length must follow immediately, and be in canonical @@ -1025,17 +1026,17 @@ static int parse_sha1_header(char *hdr, char *type, unsigned long *sizep) /* * The length must be followed by a zero byte */ - return *hdr ? -1 : 0; + return *hdr ? -1 : type_from_string(type); } -void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size) +void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size) { int ret; z_stream stream; char hdr[8192]; ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)); - if (ret < Z_OK || parse_sha1_header(hdr, type, size) < 0) + if (ret < Z_OK || (*type = parse_sha1_header(hdr, size)) < 0) return NULL; return unpack_sha1_rest(&stream, hdr, *size); @@ -1044,7 +1045,7 @@ void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned l static unsigned long get_delta_base(struct packed_git *p, struct pack_window **w_curs, unsigned long *curpos, - enum object_type kind, + enum object_type type, unsigned long delta_obj_offset) { unsigned char *base_info = use_pack(p, w_curs, *curpos, NULL); @@ -1056,7 +1057,7 @@ static unsigned long get_delta_base(struct packed_git *p, * that is assured. An OFS_DELTA longer than the hash size * is stupid, as then a REF_DELTA would be smaller to store. */ - if (kind == OBJ_OFS_DELTA) { + if (type == OBJ_OFS_DELTA) { unsigned used = 0; unsigned char c = base_info[used++]; base_offset = c & 127; @@ -1071,7 +1072,7 @@ static unsigned long get_delta_base(struct packed_git *p, if (base_offset >= delta_obj_offset) die("delta base offset out of bound"); *curpos += used; - } else if (kind == OBJ_REF_DELTA) { + } else if (type == OBJ_REF_DELTA) { /* The base entry _must_ be in the same pack */ base_offset = find_pack_entry_one(base_info, p); if (!base_offset) @@ -1085,28 +1086,25 @@ static unsigned long get_delta_base(struct packed_git *p, /* forward declaration for a mutually recursive function */ static int packed_object_info(struct packed_git *p, unsigned long offset, - char *type, unsigned long *sizep); + unsigned long *sizep); static int packed_delta_info(struct packed_git *p, struct pack_window **w_curs, unsigned long curpos, - enum object_type kind, + enum object_type type, unsigned long obj_offset, - char *type, unsigned long *sizep) { unsigned long base_offset; - base_offset = get_delta_base(p, w_curs, &curpos, kind, obj_offset); + base_offset = get_delta_base(p, w_curs, &curpos, type, obj_offset); + type = packed_object_info(p, base_offset, NULL); /* We choose to only get the type of the base object and * ignore potentially corrupt pack file that expects the delta * based on a base with a wrong size. This saves tons of * inflate() calls. */ - if (packed_object_info(p, base_offset, type, NULL)) - die("cannot get info for delta-pack base"); - if (sizep) { const unsigned char *data; unsigned char delta_head[20], *in; @@ -1141,7 +1139,8 @@ static int packed_delta_info(struct packed_git *p, /* Read the result size */ *sizep = get_delta_hdr_size(&data, delta_head+sizeof(delta_head)); } - return 0; + + return type; } static int unpack_object_header(struct packed_git *p, @@ -1169,38 +1168,36 @@ static int unpack_object_header(struct packed_git *p, return type; } -void packed_object_info_detail(struct packed_git *p, - unsigned long obj_offset, - char *type, - unsigned long *size, - unsigned long *store_size, - unsigned int *delta_chain_length, - unsigned char *base_sha1) +const char *packed_object_info_detail(struct packed_git *p, + unsigned long obj_offset, + unsigned long *size, + unsigned long *store_size, + unsigned int *delta_chain_length, + unsigned char *base_sha1) { struct pack_window *w_curs = NULL; unsigned long curpos, dummy; unsigned char *next_sha1; - enum object_type kind; + enum object_type type; *delta_chain_length = 0; curpos = obj_offset; - kind = unpack_object_header(p, &w_curs, &curpos, size); + type = unpack_object_header(p, &w_curs, &curpos, size); for (;;) { - switch (kind) { + switch (type) { default: die("pack %s contains unknown object type %d", - p->pack_name, kind); + p->pack_name, type); case OBJ_COMMIT: case OBJ_TREE: case OBJ_BLOB: case OBJ_TAG: - strcpy(type, typename(kind)); *store_size = 0; /* notyet */ unuse_pack(&w_curs); - return; + return typename(type); case OBJ_OFS_DELTA: - obj_offset = get_delta_base(p, &w_curs, &curpos, kind, obj_offset); + obj_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset); if (*delta_chain_length == 0) { /* TODO: find base_sha1 as pointed by curpos */ } @@ -1214,39 +1211,38 @@ void packed_object_info_detail(struct packed_git *p, } (*delta_chain_length)++; curpos = obj_offset; - kind = unpack_object_header(p, &w_curs, &curpos, &dummy); + type = unpack_object_header(p, &w_curs, &curpos, &dummy); } } static int packed_object_info(struct packed_git *p, unsigned long obj_offset, - char *type, unsigned long *sizep) + unsigned long *sizep) { struct pack_window *w_curs = NULL; unsigned long size, curpos = obj_offset; - enum object_type kind; + enum object_type type; - kind = unpack_object_header(p, &w_curs, &curpos, &size); + type = unpack_object_header(p, &w_curs, &curpos, &size); - switch (kind) { + switch (type) { case OBJ_OFS_DELTA: case OBJ_REF_DELTA: - packed_delta_info(p, &w_curs, curpos, kind, - obj_offset, type, sizep); + type = packed_delta_info(p, &w_curs, curpos, + type, obj_offset, sizep); break; case OBJ_COMMIT: case OBJ_TREE: case OBJ_BLOB: case OBJ_TAG: - strcpy(type, typename(kind)); if (sizep) *sizep = size; break; default: die("pack %s contains unknown object type %d", - p->pack_name, kind); + p->pack_name, type); } unuse_pack(&w_curs); - return 0; + return type; } static void *unpack_compressed_entry(struct packed_git *p, @@ -1284,15 +1280,14 @@ static void *unpack_delta_entry(struct packed_git *p, struct pack_window **w_curs, unsigned long curpos, unsigned long delta_size, - enum object_type kind, unsigned long obj_offset, - char *type, + enum object_type *type, unsigned long *sizep) { void *delta_data, *result, *base; - unsigned long result_size, base_size, base_offset; + unsigned long base_size, base_offset; - base_offset = get_delta_base(p, w_curs, &curpos, kind, obj_offset); + base_offset = get_delta_base(p, w_curs, &curpos, *type, obj_offset); base = unpack_entry(p, base_offset, type, &base_size); if (!base) die("failed to read delta base object at %lu from %s", @@ -1301,43 +1296,39 @@ static void *unpack_delta_entry(struct packed_git *p, delta_data = unpack_compressed_entry(p, w_curs, curpos, delta_size); result = patch_delta(base, base_size, delta_data, delta_size, - &result_size); + sizep); if (!result) die("failed to apply delta"); free(delta_data); free(base); - *sizep = result_size; return result; } void *unpack_entry(struct packed_git *p, unsigned long obj_offset, - char *type, unsigned long *sizep) + enum object_type *type, unsigned long *sizep) { struct pack_window *w_curs = NULL; - unsigned long size, curpos = obj_offset; - enum object_type kind; - void *retval; + unsigned long curpos = obj_offset; + void *data; - kind = unpack_object_header(p, &w_curs, &curpos, &size); - switch (kind) { + *type = unpack_object_header(p, &w_curs, &curpos, sizep); + switch (*type) { case OBJ_OFS_DELTA: case OBJ_REF_DELTA: - retval = unpack_delta_entry(p, &w_curs, curpos, size, - kind, obj_offset, type, sizep); + data = unpack_delta_entry(p, &w_curs, curpos, *sizep, + obj_offset, type, sizep); break; case OBJ_COMMIT: case OBJ_TREE: case OBJ_BLOB: case OBJ_TAG: - strcpy(type, typename(kind)); - *sizep = size; - retval = unpack_compressed_entry(p, &w_curs, curpos, size); + data = unpack_compressed_entry(p, &w_curs, curpos, *sizep); break; default: - die("unknown object type %i in %s", kind, p->pack_name); + die("unknown object type %i in %s", *type, p->pack_name); } unuse_pack(&w_curs); - return retval; + return data; } int num_packed_objects(const struct packed_git *p) @@ -1444,10 +1435,10 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1, return p; } return NULL; - + } -static int sha1_loose_object_info(const unsigned char *sha1, char *type, unsigned long *sizep) +static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *sizep) { int status; unsigned long mapsize, size; @@ -1461,31 +1452,29 @@ static int sha1_loose_object_info(const unsigned char *sha1, char *type, unsigne if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0) status = error("unable to unpack %s header", sha1_to_hex(sha1)); - else if (parse_sha1_header(hdr, type, &size) < 0) + else if ((status = parse_sha1_header(hdr, &size)) < 0) status = error("unable to parse %s header", sha1_to_hex(sha1)); - else { - status = 0; - if (sizep) - *sizep = size; - } + else if (sizep) + *sizep = size; inflateEnd(&stream); munmap(map, mapsize); return status; } -int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep) +int sha1_object_info(const unsigned char *sha1, unsigned long *sizep) { struct pack_entry e; if (!find_pack_entry(sha1, &e, NULL)) { reprepare_packed_git(); if (!find_pack_entry(sha1, &e, NULL)) - return sha1_loose_object_info(sha1, type, sizep); + return sha1_loose_object_info(sha1, sizep); } - return packed_object_info(e.p, e.offset, type, sizep); + return packed_object_info(e.p, e.offset, sizep); } -static void *read_packed_sha1(const unsigned char *sha1, char *type, unsigned long *size) +static void *read_packed_sha1(const unsigned char *sha1, + enum object_type *type, unsigned long *size) { struct pack_entry e; @@ -1503,7 +1492,7 @@ static void *read_packed_sha1(const unsigned char *sha1, char *type, unsigned lo */ static struct cached_object { unsigned char sha1[20]; - const char *type; + enum object_type type; void *buf; unsigned long size; } *cached_objects; @@ -1521,11 +1510,12 @@ static struct cached_object *find_cached_object(const unsigned char *sha1) return NULL; } -int pretend_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1) +int pretend_sha1_file(void *buf, unsigned long len, enum object_type type, + unsigned char *sha1) { struct cached_object *co; - hash_sha1_file(buf, len, type, sha1); + hash_sha1_file(buf, len, typename(type), sha1); if (has_sha1_file(sha1) || find_cached_object(sha1)) return 0; if (cached_object_alloc <= cached_object_nr) { @@ -1536,14 +1526,15 @@ int pretend_sha1_file(void *buf, unsigned long len, const char *type, unsigned c } co = &cached_objects[cached_object_nr++]; co->size = len; - co->type = strdup(type); + co->type = type; co->buf = xmalloc(len); memcpy(co->buf, buf, len); hashcpy(co->sha1, sha1); return 0; } -void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size) +void *read_sha1_file(const unsigned char *sha1, enum object_type *type, + unsigned long *size) { unsigned long mapsize; void *map, *buf; @@ -1554,7 +1545,7 @@ void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size) buf = xmalloc(co->size + 1); memcpy(buf, co->buf, co->size); ((char*)buf)[co->size] = 0; - strcpy(type, co->type); + *type = co->type; *size = co->size; return buf; } @@ -1573,33 +1564,34 @@ void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size) } void *read_object_with_reference(const unsigned char *sha1, - const char *required_type, + const char *required_type_name, unsigned long *size, unsigned char *actual_sha1_return) { - char type[20]; + enum object_type type, required_type; void *buffer; unsigned long isize; unsigned char actual_sha1[20]; + required_type = type_from_string(required_type_name); hashcpy(actual_sha1, sha1); while (1) { int ref_length = -1; const char *ref_type = NULL; - buffer = read_sha1_file(actual_sha1, type, &isize); + buffer = read_sha1_file(actual_sha1, &type, &isize); if (!buffer) return NULL; - if (!strcmp(type, required_type)) { + if (type == required_type) { *size = isize; if (actual_sha1_return) hashcpy(actual_sha1_return, actual_sha1); return buffer; } /* Handle references */ - else if (!strcmp(type, commit_type)) + else if (type == OBJ_COMMIT) ref_type = "tree "; - else if (!strcmp(type, tag_type)) + else if (type == OBJ_TAG) ref_type = "object "; else { free(buffer); @@ -1841,17 +1833,17 @@ static void *repack_object(const unsigned char *sha1, unsigned long *objsize) z_stream stream; unsigned char *unpacked; unsigned long len; - char type[20]; + enum object_type type; char hdr[32]; int hdrlen; void *buf; /* need to unpack and recompress it by itself */ - unpacked = read_packed_sha1(sha1, type, &len); + unpacked = read_packed_sha1(sha1, &type, &len); if (!unpacked) error("cannot read sha1_file for %s", sha1_to_hex(sha1)); - hdrlen = sprintf(hdr, "%s %lu", type, len) + 1; + hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1; /* Set it up */ memset(&stream, 0, sizeof(stream)); diff --git a/tag.c b/tag.c index 864ac1bb60..30ffc17e41 100644 --- a/tag.c +++ b/tag.c @@ -85,18 +85,18 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size) int parse_tag(struct tag *item) { - char type[20]; + enum object_type type; void *data; unsigned long size; int ret; if (item->object.parsed) return 0; - data = read_sha1_file(item->object.sha1, type, &size); + data = read_sha1_file(item->object.sha1, &type, &size); if (!data) return error("Could not read %s", sha1_to_hex(item->object.sha1)); - if (strcmp(type, tag_type)) { + if (type != OBJ_TAG) { free(data); return error("Object %s not a tag", sha1_to_hex(item->object.sha1)); diff --git a/tree-diff.c b/tree-diff.c index 37d235e06e..c8275823d0 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -139,13 +139,13 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode); if (opt->recursive && S_ISDIR(mode)) { - char type[20]; + enum object_type type; char *newbase = malloc_base(base, path, strlen(path)); struct tree_desc inner; void *tree; - tree = read_sha1_file(sha1, type, &inner.size); - if (!tree || strcmp(type, tree_type)) + tree = read_sha1_file(sha1, &type, &inner.size); + if (!tree || type != OBJ_TREE) die("corrupt tree sha %s", sha1_to_hex(sha1)); inner.buf = tree; diff --git a/tree.c b/tree.c index b6f02fecc4..46923ee61b 100644 --- a/tree.c +++ b/tree.c @@ -190,17 +190,17 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size) int parse_tree(struct tree *item) { - char type[20]; + enum object_type type; void *buffer; unsigned long size; if (item->object.parsed) return 0; - buffer = read_sha1_file(item->object.sha1, type, &size); + buffer = read_sha1_file(item->object.sha1, &type, &size); if (!buffer) return error("Could not read %s", sha1_to_hex(item->object.sha1)); - if (strcmp(type, tree_type)) { + if (type != OBJ_TREE) { free(buffer); return error("Object %s not a tree", sha1_to_hex(item->object.sha1)); diff --git a/unpack-file.c b/unpack-file.c index d24acc2a67..25c56b374a 100644 --- a/unpack-file.c +++ b/unpack-file.c @@ -5,12 +5,12 @@ static char *create_temp_file(unsigned char *sha1) { static char path[50]; void *buf; - char type[100]; + enum object_type type; unsigned long size; int fd; - buf = read_sha1_file(sha1, type, &size); - if (!buf || strcmp(type, blob_type)) + buf = read_sha1_file(sha1, &type, &size); + if (!buf || type != OBJ_BLOB) die("unable to read blob object %s", sha1_to_hex(sha1)); strcpy(path, ".merge_file_XXXXXX"); -- cgit v1.3-5-g9baa