Skip to content

Commit

Permalink
Merge branch 'jc/fix-tree-walk'
Browse files Browse the repository at this point in the history
* jc/fix-tree-walk:
  read-tree --debug-unpack
  unpack-trees.c: look ahead in the index
  unpack-trees.c: prepare for looking ahead in the index
  Aggressive three-way merge: fix D/F case
  traverse_trees(): handle D/F conflict case sanely
  more D/F conflict tests
  tests: move convenience regexp to match object names to test-lib.sh

Conflicts:
	builtin-read-tree.c
	unpack-trees.c
	unpack-trees.h
  • Loading branch information
gitster committed Jan 25, 2010
2 parents eca9388 + ba655da commit 026680f
Show file tree
Hide file tree
Showing 19 changed files with 734 additions and 140 deletions.
36 changes: 36 additions & 0 deletions builtin-read-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,34 @@ static int exclude_per_directory_cb(const struct option *opt, const char *arg,
return 0;
}

static void debug_stage(const char *label, struct cache_entry *ce,
struct unpack_trees_options *o)
{
printf("%s ", label);
if (!ce)
printf("(missing)\n");
else if (ce == o->df_conflict_entry)
printf("(conflict)\n");
else
printf("%06o #%d %s %.8s\n",
ce->ce_mode, ce_stage(ce), ce->name,
sha1_to_hex(ce->sha1));
}

static int debug_merge(struct cache_entry **stages, struct unpack_trees_options *o)
{
int i;

printf("* %d-way merge\n", o->merge_size);
debug_stage("index", stages[0], o);
for (i = 1; i <= o->merge_size; i++) {
char buf[24];
sprintf(buf, "ent#%d", i);
debug_stage(buf, stages[i], o);
}
return 0;
}

static struct lock_file lock_file;

int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
Expand Down Expand Up @@ -101,6 +129,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
"don't check the working tree after merging", 1),
OPT_SET_INT(0, "no-sparse-checkout", &opts.skip_sparse_checkout,
"skip applying sparse checkout filter", 1),
OPT_SET_INT(0, "debug-unpack", &opts.debug_unpack,
"debug unpack-trees", 1),
OPT_END()
};

Expand Down Expand Up @@ -169,6 +199,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
opts.head_idx = 1;
}

if (opts.debug_unpack)
opts.fn = debug_merge;

cache_tree_free(&active_cache_tree);
for (i = 0; i < nr_trees; i++) {
struct tree *tree = trees[i];
Expand All @@ -178,6 +211,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
if (unpack_trees(nr_trees, t, &opts))
return 128;

if (opts.debug_unpack)
return 0; /* do not write the index out */

/*
* When reading only one tree (either the most basic form,
* "-m ent" or "--reset ent" form), we can obtain a fully
Expand Down
2 changes: 2 additions & 0 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ struct cache_entry {
/* Only remove in work directory, not index */
#define CE_WT_REMOVE (0x400000)

#define CE_UNPACKED (0x1000000)

/*
* Extended on-disk flags
*/
Expand Down
19 changes: 1 addition & 18 deletions diff-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,21 +380,6 @@ static void do_oneway_diff(struct unpack_trees_options *o,
show_modified(revs, tree, idx, 1, cached, match_missing);
}

static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_options *o)
{
int len = ce_namelen(ce);
const struct index_state *index = o->src_index;

while (o->pos < index->cache_nr) {
struct cache_entry *next = index->cache[o->pos];
if (len != ce_namelen(next))
break;
if (memcmp(ce->name, next->name, len))
break;
o->pos++;
}
}

/*
* The unpack_trees() interface is designed for merging, so
* the different source entries are designed primarily for
Expand All @@ -416,9 +401,6 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
struct cache_entry *tree = src[1];
struct rev_info *revs = o->unpack_data;

if (idx && ce_stage(idx))
skip_same_name(idx, o);

/*
* Unpack-trees generates a DF/conflict entry if
* there was a directory in the index and a tree
Expand Down Expand Up @@ -464,6 +446,7 @@ int run_diff_index(struct rev_info *revs, int cached)
exit(128);

diff_set_mnemonic_prefix(&revs->diffopt, "c/", cached ? "i/" : "w/");
diffcore_fix_diff_index(&revs->diffopt);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
return 0;
Expand Down
17 changes: 17 additions & 0 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -3678,6 +3678,23 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
*q = outq;
}

static int diffnamecmp(const void *a_, const void *b_)
{
const struct diff_filepair *a = *((const struct diff_filepair **)a_);
const struct diff_filepair *b = *((const struct diff_filepair **)b_);
const char *name_a, *name_b;

name_a = a->one ? a->one->path : a->two->path;
name_b = b->one ? b->one->path : b->two->path;
return strcmp(name_a, name_b);
}

void diffcore_fix_diff_index(struct diff_options *options)
{
struct diff_queue_struct *q = &diff_queued_diff;
qsort(q->queue, q->nr, sizeof(q->queue[0]), diffnamecmp);
}

void diffcore_std(struct diff_options *options)
{
if (options->skip_stat_unmatch)
Expand Down
1 change: 1 addition & 0 deletions diff.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ extern int diff_setup_done(struct diff_options *);
#define DIFF_PICKAXE_REGEX 2

extern void diffcore_std(struct diff_options *);
extern void diffcore_fix_diff_index(struct diff_options *);

#define COMMON_DIFF_OPTIONS_HELP \
"\ncommon diff options:\n" \
Expand Down
2 changes: 0 additions & 2 deletions t/diff-lib.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
:

_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
sanitize_diff_raw='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]* / X X \1# /'
compare_diff_raw () {
# When heuristics are improved, the score numbers would change.
Expand Down
3 changes: 0 additions & 3 deletions t/t1000-read-tree-m-3way.sh
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,6 @@ cat >expected <<\EOF
100644 X 0 Z/NN
EOF

_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"

check_result () {
git ls-files --stage | sed -e 's/ '"$_x40"' / X /' >current &&
test_cmp expected current
Expand Down
2 changes: 0 additions & 2 deletions t/t1001-read-tree-m-2way.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ read_tree_twoway () {
git read-tree -m "$1" "$2" && git ls-files --stage
}

_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
compare_change () {
sed -n >current \
-e '/^--- /d; /^+++ /d; /^@@ /d;' \
Expand Down
2 changes: 0 additions & 2 deletions t/t1002-read-tree-m-u-2way.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ This is identical to t1001, but uses -u to update the work tree as well.
'
. ./test-lib.sh

_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
compare_change () {
sed >current \
-e '1{/^diff --git /d;}' \
Expand Down
102 changes: 102 additions & 0 deletions t/t1012-read-tree-df.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/bin/sh

test_description='read-tree D/F conflict corner cases'

. ./test-lib.sh

maketree () {
(
rm -f .git/index .git/index.lock &&
git clean -d -f -f -q -x &&
name="$1" &&
shift &&
for it
do
path=$(expr "$it" : '\([^:]*\)') &&
mkdir -p $(dirname "$path") &&
echo "$it" >"$path" &&
git update-index --add "$path" || exit
done &&
git tag "$name" $(git write-tree)
)
}

settree () {
rm -f .git/index .git/index.lock &&
git clean -d -f -f -q -x &&
git read-tree "$1" &&
git checkout-index -f -q -u -a &&
git update-index --refresh
}

checkindex () {
git ls-files -s |
sed "s|^[0-7][0-7]* $_x40 \([0-3]\) |\1 |" >current &&
cat >expect &&
test_cmp expect current
}

test_expect_success setup '
maketree O-000 a/b-2/c/d a/b/c/d a/x &&
maketree A-000 a/b-2/c/d a/b/c/d a/x &&
maketree A-001 a/b-2/c/d a/b/c/d a/b/c/e a/x &&
maketree B-000 a/b-2/c/d a/b a/x &&
maketree O-010 t-0 t/1 t/2 t=3 &&
maketree A-010 t-0 t t=3 &&
maketree B-010 t/1: t=3: &&
maketree O-020 ds/dma/ioat.c ds/dma/ioat_dca.c &&
maketree A-020 ds/dma/ioat/Makefile ds/dma/ioat/registers.h &&
:
'

test_expect_success '3-way (1)' '
settree A-000 &&
git read-tree -m -u O-000 A-000 B-000 &&
checkindex <<-EOF
3 a/b
0 a/b-2/c/d
1 a/b/c/d
2 a/b/c/d
0 a/x
EOF
'

test_expect_success '3-way (2)' '
settree A-001 &&
git read-tree -m -u O-000 A-001 B-000 &&
checkindex <<-EOF
3 a/b
0 a/b-2/c/d
1 a/b/c/d
2 a/b/c/d
2 a/b/c/e
0 a/x
EOF
'

test_expect_success '3-way (3)' '
settree A-010 &&
git read-tree -m -u O-010 A-010 B-010 &&
checkindex <<-EOF
2 t
1 t-0
2 t-0
1 t/1
3 t/1
1 t/2
0 t=3
EOF
'

test_expect_success '2-way (1)' '
settree O-020 &&
git read-tree -m -u O-020 A-020 &&
checkindex <<-EOF
0 ds/dma/ioat/Makefile
0 ds/dma/ioat/registers.h
EOF
'

test_done
2 changes: 0 additions & 2 deletions t/t3100-ls-tree-restrict.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ test_expect_success \
tree=`git write-tree` &&
echo $tree'

_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
test_output () {
sed -e "s/ $_x40 / X /" <current >check
test_cmp expected check
Expand Down
2 changes: 0 additions & 2 deletions t/t3101-ls-tree-dirname.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ test_expect_success \
tree=`git write-tree` &&
echo $tree'

_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05"
test_output () {
sed -e "s/ $_x40 / X /" <current >check
test_cmp expected check
Expand Down
2 changes: 0 additions & 2 deletions t/t4006-diff-mode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ test_expect_success \
'test_chmod +x rezrov &&
git diff-index $tree >current'

_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
sed -e 's/\(:100644 100755\) \('"$_x40"'\) \2 /\1 X X /' <current >check
echo ":100644 100755 X X M rezrov" >expected

Expand Down
3 changes: 0 additions & 3 deletions t/t6012-rev-list-simplify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ note () {
git tag "$1"
}

_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"

unnote () {
git name-rev --tags --stdin | sed -e "s|$_x40 (tags/\([^)]*\)) |\1 |g"
}
Expand Down
4 changes: 2 additions & 2 deletions t/t6035-merge-dir-to-symlink.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ test_expect_success 'setup for merge test' '
git tag baseline
'

test_expect_success 'do not lose a/b-2/c/d in merge (resolve)' '
test_expect_failure 'do not lose a/b-2/c/d in merge (resolve)' '
git reset --hard &&
git checkout baseline^0 &&
git merge -s resolve master &&
Expand All @@ -74,7 +74,7 @@ test_expect_success 'setup a merge where dir a/b-2 changed to symlink' '
git tag test2
'

test_expect_failure 'merge should not have conflicts (resolve)' '
test_expect_success 'merge should not have conflicts (resolve)' '
git reset --hard &&
git checkout baseline^0 &&
git merge -s resolve test2 &&
Expand Down
6 changes: 6 additions & 0 deletions t/test-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
;;
esac

# Convenience
#
# A regexp to match 5 and 40 hexdigits
_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05"

# Each test should start with something like this, after copyright notices:
#
# test_description='Description of this test...
Expand Down
Loading

0 comments on commit 026680f

Please sign in to comment.