summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--read-cache.c31
-rwxr-xr-xt/t1005-read-tree-reset.sh60
2 files changed, 78 insertions, 13 deletions
diff --git a/read-cache.c b/read-cache.c
index c229fd4..8160022 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1489,25 +1489,30 @@ int write_index(const struct index_state *istate, int newfd)
int read_index_unmerged(struct index_state *istate)
{
int i;
- struct cache_entry **dst;
- struct cache_entry *last = NULL;
+ int unmerged = 0;
read_index(istate);
- dst = istate->cache;
for (i = 0; i < istate->cache_nr; i++) {
struct cache_entry *ce = istate->cache[i];
- if (ce_stage(ce)) {
- remove_name_hash(ce);
- if (last && !strcmp(ce->name, last->name))
- continue;
- cache_tree_invalidate_path(istate->cache_tree, ce->name);
- last = ce;
+ struct cache_entry *new_ce;
+ int size, len;
+
+ if (!ce_stage(ce))
continue;
- }
- *dst++ = ce;
+ unmerged = 1;
+ len = strlen(ce->name);
+ size = cache_entry_size(len);
+ new_ce = xcalloc(1, size);
+ hashcpy(new_ce->sha1, ce->sha1);
+ memcpy(new_ce->name, ce->name, len);
+ new_ce->ce_flags = create_ce_flags(len, 0);
+ new_ce->ce_mode = ce->ce_mode;
+ if (add_index_entry(istate, new_ce, 0))
+ return error("%s: cannot drop to stage #0",
+ ce->name);
+ i = index_name_pos(istate, new_ce->name, len);
}
- istate->cache_nr = dst - istate->cache;
- return !!last;
+ return unmerged;
}
struct update_callback_data
diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh
index b0d31f5..8499116 100755
--- a/t/t1005-read-tree-reset.sh
+++ b/t/t1005-read-tree-reset.sh
@@ -27,4 +27,64 @@ test_expect_success 'reset should work' '
test_cmp expect actual
'
+test_expect_success 'reset should remove remnants from a failed merge' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
+test_expect_success 'Porcelain reset should remove remnants too' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git reset --hard &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
+test_expect_success 'Porcelain checkout -f should remove remnants too' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git checkout -f &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
+test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git checkout -f HEAD &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
test_done