summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin-apply.c17
-rw-r--r--builtin-diff-tree.c10
-rw-r--r--builtin-read-tree.c45
-rw-r--r--fetch.c24
-rw-r--r--fsck-objects.c57
-rw-r--r--revision.c31
-rwxr-xr-xt/t3600-rm.sh42
-rwxr-xr-xt/t4113-apply-ending.sh53
-rw-r--r--tree.c43
-rw-r--r--tree.h14
10 files changed, 217 insertions, 119 deletions
diff --git a/builtin-apply.c b/builtin-apply.c
index f16c753bee..6a4fb9663d 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -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.
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 480e6ed372..00cdb5a6d9 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -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 d9fe41f34f..976a5a459c 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"
@@ -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;
}
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
-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
index 0000000000..7fd0cf62ec
--- /dev/null
+++ b/t/t4113-apply-ending.sh
@@ -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 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);