Merge branch 'jc/lt-tree-n-cache-tree' into lt/tree-2
authorJunio C Hamano <junkio@cox.net>
Tue, 30 May 2006 05:13:09 +0000 (22:13 -0700)
committerJunio C Hamano <junkio@cox.net>
Tue, 30 May 2006 05:13:09 +0000 (22:13 -0700)
* jc/lt-tree-n-cache-tree:
  adjust to the rebased series by Linus.
  Remove "tree->entries" tree-entry list from tree parser
  Switch "read_tree_recursive()" over to tree-walk functionality
  Make "tree_entry" have a SHA1 instead of a union of object pointers
  Add raw tree buffer info to "struct tree"

This results as if an "ours" merge absorbed the previous "next"
branch change into the 10-patch series, but it really is a result
of an honest merge.

nothing to commit

builtin-apply.c
builtin-diff-tree.c
builtin-read-tree.c
fetch.c
fsck-objects.c
revision.c
t/t3600-rm.sh
t/t4113-apply-ending.sh [new file with mode: 0755]
tree.c
tree.h

index f16c753..6a4fb96 100644 (file)
@@ -1335,6 +1335,7 @@ static int apply_line(char *output, const char *patch, int plen)
 
 static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
 {
+       int match_beginning, match_end;
        char *buf = desc->buffer;
        const char *patch = frag->patch;
        int offset, size = frag->size;
@@ -1397,10 +1398,22 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
        newlines = new;
        leading = frag->leading;
        trailing = frag->trailing;
+
+       /*
+        * If we don't have any leading/trailing data in the patch,
+        * we want it to match at the beginning/end of the file.
+        */
+       match_beginning = !leading && (frag->oldpos == 1);
+       match_end = !trailing;
+
        lines = 0;
        pos = frag->newpos;
        for (;;) {
                offset = find_offset(buf, desc->size, oldlines, oldsize, pos, &lines);
+               if (match_end && offset + oldsize != desc->size)
+                       offset = -1;
+               if (match_beginning && offset)
+                       offset = -1;
                if (offset >= 0) {
                        int diff = newsize - oldsize;
                        unsigned long size = desc->size + diff;
@@ -1430,6 +1443,10 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
                /* Am I at my context limits? */
                if ((leading <= p_context) && (trailing <= p_context))
                        break;
+               if (match_beginning || match_end) {
+                       match_beginning = match_end = 0;
+                       continue;
+               }
                /* Reduce the number of context lines
                 * Reduce both leading and trailing if they are equal
                 * otherwise just reduce the larger context.
index cc53b81..58cf658 100644 (file)
@@ -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;
 }
index 480e6ed..00cdb5a 100644 (file)
@@ -30,7 +30,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 = {
@@ -40,6 +50,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);
diff --git a/fetch.c b/fetch.c
index d9fe41f..976a5a4 100644 (file)
--- 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"
@@ -36,27 +37,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;
 }
 
index 42778e8..33ce366 100644 (file)
@@ -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;
 
index c51ea83..8e93e40 100644 (file)
@@ -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)
index acaa4d6..201d164 100755 (executable)
@@ -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
-embedded'
-then
-git-add -- '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'
-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/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh
new file mode 100755 (executable)
index 0000000..7fd0cf6
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Catalin Marinas
+#
+
+test_description='git-apply trying to add an ending line.
+
+'
+. ./test-lib.sh
+
+# setup
+
+cat >test-patch <<\EOF
+diff --git a/file b/file
+--- a/file
++++ b/file
+@@ -1,2 +1,3 @@
+ a
+ b
++c
+EOF
+
+echo 'a' >file
+echo 'b' >>file
+echo 'c' >>file
+
+test_expect_success setup \
+    'git-update-index --add file'
+
+# test
+
+test_expect_failure 'apply at the end' \
+    'git-apply --index test-patch'
+
+cat >test-patch <<\EOF
+diff a/file b/file
+--- a/file
++++ b/file
+@@ -1,2 +1,3 @@
++a
+ b
+ c
+EOF
+
+echo >file 'a
+b
+c'
+git-update-index file
+
+test_expect_failure 'apply at the beginning' \
+       'git-apply --index test-patch'
+
+test_done
diff --git a/tree.c b/tree.c
index db6e59f..fb18724 100644 (file)
--- 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 c7b5248..dd25c53 100644 (file)
--- 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);