diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index cc53b81ac4..58cf65856d 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -138,11 +138,15 @@ int cmd_diff_tree(int argc, const char **argv, char **envp) if (opt->diffopt.detect_rename) opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE | DIFF_SETUP_USE_CACHE); - while (fgets(line, sizeof(line), stdin)) - if (line[0] == '\n') + while (fgets(line, sizeof(line), stdin)) { + unsigned char sha1[20]; + + if (get_sha1_hex(line, sha1)) { + fputs(line, stdout); fflush(stdout); + } else diff_tree_stdin(line); - + } return 0; } diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 6a2ceba9ce..d70411f2af 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -9,8 +9,8 @@ #include "object.h" #include "tree.h" -#include "cache-tree.h" #include "tree-walk.h" +#include "cache-tree.h" #include #include #include "builtin.h" @@ -31,7 +31,17 @@ static int merge_size = 0; static struct object_list *trees = NULL; -static struct cache_entry df_conflict_entry = { +static struct cache_entry df_conflict_entry = { +}; + +struct tree_entry_list { + struct tree_entry_list *next; + unsigned directory : 1; + unsigned executable : 1; + unsigned symlink : 1; + unsigned int mode; + const char *name; + const unsigned char *sha1; }; static struct tree_entry_list df_conflict_list = { @@ -41,6 +51,39 @@ static struct tree_entry_list df_conflict_list = { typedef int (*merge_fn_t)(struct cache_entry **src); +static struct tree_entry_list *create_tree_entry_list(struct tree *tree) +{ + struct tree_desc desc; + struct tree_entry_list *ret = NULL; + struct tree_entry_list **list_p = &ret; + + desc.buf = tree->buffer; + desc.size = tree->size; + + while (desc.size) { + unsigned mode; + const char *path; + const unsigned char *sha1; + struct tree_entry_list *entry; + + sha1 = tree_entry_extract(&desc, &path, &mode); + update_tree_entry(&desc); + + entry = xmalloc(sizeof(struct tree_entry_list)); + entry->name = path; + entry->sha1 = sha1; + entry->mode = mode; + entry->directory = S_ISDIR(mode) != 0; + entry->executable = (mode & S_IXUSR) != 0; + entry->symlink = S_ISLNK(mode) != 0; + entry->next = NULL; + + *list_p = entry; + list_p = &entry->next; + } + return ret; +} + static int entcmp(const char *name1, int dir1, const char *name2, int dir2) { int len1 = strlen(name1); @@ -803,12 +846,12 @@ static int read_cache_unmerged(void) static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree) { struct tree_desc desc; - int cnt = 0; + int cnt; memcpy(it->sha1, tree->object.sha1, 20); desc.buf = tree->buffer; desc.size = tree->size; - + cnt = 0; while (desc.size) { unsigned mode; const char *name; @@ -816,14 +859,11 @@ static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree) sha1 = tree_entry_extract(&desc, &name, &mode); update_tree_entry(&desc); - if (!S_ISDIR(mode)) cnt++; else { struct cache_tree_sub *sub; - struct tree *subtree; - - subtree = lookup_tree(sha1); + struct tree *subtree = lookup_tree(sha1); if (!subtree->object.parsed) parse_tree(subtree); sub = cache_tree_sub(it, name); diff --git a/fetch.c b/fetch.c index ae65b42056..b03c2012ef 100644 --- a/fetch.c +++ b/fetch.c @@ -3,6 +3,7 @@ #include "cache.h" #include "commit.h" #include "tree.h" +#include "tree-walk.h" #include "tag.h" #include "blob.h" #include "refs.h" @@ -37,27 +38,32 @@ static int process(struct object *obj); static int process_tree(struct tree *tree) { - struct tree_entry_list *entry; + struct tree_desc desc; if (parse_tree(tree)) return -1; - entry = create_tree_entry_list(tree); - while (entry) { - struct tree_entry_list *next = entry->next; + desc.buf = tree->buffer; + desc.size = tree->size; + while (desc.size) { + unsigned mode; + const char *name; + const unsigned char *sha1; - if (entry->directory) { - struct tree *tree = lookup_tree(entry->sha1); + sha1 = tree_entry_extract(&desc, &name, &mode); + update_tree_entry(&desc); + + if (S_ISDIR(mode)) { + struct tree *tree = lookup_tree(sha1); process_tree(tree); } else { - struct blob *blob = lookup_blob(entry->sha1); + struct blob *blob = lookup_blob(sha1); process(&blob->object); } - free(entry); - entry = next; } free(tree->buffer); tree->buffer = NULL; + tree->size = 0; return 0; } diff --git a/fsck-objects.c b/fsck-objects.c index 42778e87d0..33ce366e99 100644 --- a/fsck-objects.c +++ b/fsck-objects.c @@ -9,6 +9,7 @@ #include "refs.h" #include "pack.h" #include "cache-tree.h" +#include "tree-walk.h" #define REACHABLE 0x0001 #define SEEN 0x0002 @@ -116,15 +117,15 @@ static void check_connectivity(void) #define TREE_UNORDERED (-1) #define TREE_HAS_DUPS (-2) -static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) +static int verify_ordered(unsigned mode1, const char *name1, unsigned mode2, const char *name2) { - int len1 = strlen(a->name); - int len2 = strlen(b->name); + int len1 = strlen(name1); + int len2 = strlen(name2); int len = len1 < len2 ? len1 : len2; unsigned char c1, c2; int cmp; - cmp = memcmp(a->name, b->name, len); + cmp = memcmp(name1, name2, len); if (cmp < 0) return 0; if (cmp > 0) @@ -135,8 +136,8 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) * Now we need to order the next one, but turn * a '\0' into a '/' for a directory entry. */ - c1 = a->name[len]; - c2 = b->name[len]; + c1 = name1[len]; + c2 = name2[len]; if (!c1 && !c2) /* * git-write-tree used to write out a nonsense tree that has @@ -144,9 +145,9 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) * sure we do not have duplicate entries. */ return TREE_HAS_DUPS; - if (!c1 && a->directory) + if (!c1 && S_ISDIR(mode1)) c1 = '/'; - if (!c2 && b->directory) + if (!c2 && S_ISDIR(mode2)) c2 = '/'; return c1 < c2 ? 0 : TREE_UNORDERED; } @@ -159,17 +160,32 @@ static int fsck_tree(struct tree *item) int has_bad_modes = 0; int has_dup_entries = 0; int not_properly_sorted = 0; - struct tree_entry_list *entry, *last; + struct tree_desc desc; + unsigned o_mode; + const char *o_name; + const unsigned char *o_sha1; - last = NULL; - for (entry = create_tree_entry_list(item); entry; entry = entry->next) { - if (strchr(entry->name, '/')) + desc.buf = item->buffer; + desc.size = item->size; + + o_mode = 0; + o_name = NULL; + o_sha1 = NULL; + while (desc.size) { + unsigned mode; + const char *name; + const unsigned char *sha1; + + sha1 = tree_entry_extract(&desc, &name, &mode); + + if (strchr(name, '/')) has_full_path = 1; - has_zero_pad |= entry->zeropad; + has_zero_pad |= *(char *)desc.buf == '0'; + update_tree_entry(&desc); - switch (entry->mode) { + switch (mode) { /* - * Standard modes.. + * Standard modes.. */ case S_IFREG | 0755: case S_IFREG | 0644: @@ -188,8 +204,8 @@ static int fsck_tree(struct tree *item) has_bad_modes = 1; } - if (last) { - switch (verify_ordered(last, entry)) { + if (o_name) { + switch (verify_ordered(o_mode, o_name, mode, name)) { case TREE_UNORDERED: not_properly_sorted = 1; break; @@ -199,13 +215,12 @@ static int fsck_tree(struct tree *item) default: break; } - free(last); } - last = entry; + o_mode = mode; + o_name = name; + o_sha1 = sha1; } - if (last) - free(last); free(item->buffer); item->buffer = NULL; diff --git a/revision.c b/revision.c index c51ea833f9..8e93e40bb3 100644 --- a/revision.c +++ b/revision.c @@ -53,8 +53,8 @@ static void mark_blob_uninteresting(struct blob *blob) void mark_tree_uninteresting(struct tree *tree) { + struct tree_desc desc; struct object *obj = &tree->object; - struct tree_entry_list *entry; if (obj->flags & UNINTERESTING) return; @@ -63,16 +63,29 @@ void mark_tree_uninteresting(struct tree *tree) return; if (parse_tree(tree) < 0) die("bad tree %s", sha1_to_hex(obj->sha1)); - entry = create_tree_entry_list(tree); - while (entry) { - struct tree_entry_list *next = entry->next; - if (entry->directory) - mark_tree_uninteresting(lookup_tree(entry->sha1)); + + desc.buf = tree->buffer; + desc.size = tree->size; + while (desc.size) { + unsigned mode; + const char *name; + const unsigned char *sha1; + + sha1 = tree_entry_extract(&desc, &name, &mode); + update_tree_entry(&desc); + + if (S_ISDIR(mode)) + mark_tree_uninteresting(lookup_tree(sha1)); else - mark_blob_uninteresting(lookup_blob(entry->sha1)); - free(entry); - entry = next; + mark_blob_uninteresting(lookup_blob(sha1)); } + + /* + * We don't care about the tree any more + * after it has been marked uninteresting. + */ + free(tree->buffer); + tree->buffer = NULL; } void mark_parents_uninteresting(struct commit *commit) diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index acaa4d6bdc..201d1642da 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -8,30 +8,34 @@ test_description='Test of the various options to git-rm.' . ./test-lib.sh # Setup some files to be removed, some with funny characters -touch -- foo bar baz 'space embedded' -q -git-add -- foo bar baz 'space embedded' -q -git-commit -m "add normal files" -test_tabs=y -if touch -- 'tab embedded' 'newline +test_expect_success \ + 'Initialize test directory' \ + "touch -- foo bar baz 'space embedded' -q && + git-add -- foo bar baz 'space embedded' -q && + git-commit -m 'add normal files' && + test_tabs=y && + if touch -- 'tab embedded' 'newline embedded' -then -git-add -- 'tab embedded' 'newline -embedded' -git-commit -m "add files with tabs and newlines" -else - say 'Your filesystem does not allow tabs in filenames.' - test_tabs=n -fi + then + git-add -- 'tab embedded' 'newline +embedded' && + git-commit -m 'add files with tabs and newlines' + else + say 'Your filesystem does not allow tabs in filenames.' + test_tabs=n + fi" # Later we will try removing an unremovable path to make sure # git-rm barfs, but if the test is run as root that cannot be # arranged. -: >test-file -chmod a-w . -rm -f test-file -test -f test-file && test_failed_remove=y -chmod 775 . -rm -f test-file +test_expect_success \ + 'Determine rm behavior' \ + ': >test-file + chmod a-w . + rm -f test-file + test -f test-file && test_failed_remove=y + chmod 775 . + rm -f test-file' test_expect_success \ 'Pre-check that foo exists and is in index before git-rm foo' \ diff --git a/tree.c b/tree.c index db6e59f20e..fb18724259 100644 --- a/tree.c +++ b/tree.c @@ -201,49 +201,6 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size) return 0; } -struct tree_entry_list *create_tree_entry_list(struct tree *tree) -{ - struct tree_desc desc; - struct tree_entry_list *ret = NULL; - struct tree_entry_list **list_p = &ret; - - desc.buf = tree->buffer; - desc.size = tree->size; - - while (desc.size) { - unsigned mode; - const char *path; - const unsigned char *sha1; - struct tree_entry_list *entry; - - sha1 = tree_entry_extract(&desc, &path, &mode); - - entry = xmalloc(sizeof(struct tree_entry_list)); - entry->name = path; - entry->sha1 = sha1; - entry->mode = mode; - entry->directory = S_ISDIR(mode) != 0; - entry->executable = (mode & S_IXUSR) != 0; - entry->symlink = S_ISLNK(mode) != 0; - entry->zeropad = *(const char *)(desc.buf) == '0'; - entry->next = NULL; - - update_tree_entry(&desc); - *list_p = entry; - list_p = &entry->next; - } - return ret; -} - -void free_tree_entry_list(struct tree_entry_list *list) -{ - while (list) { - struct tree_entry_list *next = list->next; - free(list); - list = next; - } -} - int parse_tree(struct tree *item) { char type[20]; diff --git a/tree.h b/tree.h index c7b524861b..dd25c539ef 100644 --- a/tree.h +++ b/tree.h @@ -5,26 +5,12 @@ extern const char *tree_type; -struct tree_entry_list { - struct tree_entry_list *next; - unsigned directory : 1; - unsigned executable : 1; - unsigned symlink : 1; - unsigned zeropad : 1; - unsigned int mode; - const char *name; - const unsigned char *sha1; -}; - struct tree { struct object object; void *buffer; unsigned long size; }; -struct tree_entry_list *create_tree_entry_list(struct tree *); -void free_tree_entry_list(struct tree_entry_list *); - struct tree *lookup_tree(const unsigned char *sha1); int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size);