diff options
author | Junio C Hamano <gitster@pobox.com> | 2008-09-10 02:13:41 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-09-10 02:13:41 -0700 |
commit | 94c27881bd98d5bb70e3d4f8a18e384095c876b9 (patch) | |
tree | afb52cefd82080596aa910bb3e84b75e1d10ee9a | |
parent | 9f35e5fd544ab87488b12d9b97be983303e58bd2 (diff) | |
parent | 8fdcf3125465f70c0cad5be5ab192d46e46307c7 (diff) | |
download | git-94c27881bd98d5bb70e3d4f8a18e384095c876b9.tar.gz git-94c27881bd98d5bb70e3d4f8a18e384095c876b9.tar.xz |
Merge branch 'jc/maint-checkout-fix' into maint
* jc/maint-checkout-fix:
checkout: do not check out unmerged higher stages randomly
-rw-r--r-- | builtin-checkout.c | 29 | ||||
-rwxr-xr-x | t/t7201-co.sh | 22 |
2 files changed, 50 insertions, 1 deletions
diff --git a/builtin-checkout.c b/builtin-checkout.c index f6f8f086d..8e77767b4 100644 --- a/builtin-checkout.c +++ b/builtin-checkout.c @@ -76,6 +76,15 @@ static int read_tree_some(struct tree *tree, const char **pathspec) return 0; } +static int skip_same_name(struct cache_entry *ce, int pos) +{ + while (++pos < active_nr && + !strcmp(active_cache[pos]->name, ce->name)) + ; /* skip */ + return pos; +} + + static int checkout_paths(struct tree *source_tree, const char **pathspec) { int pos; @@ -107,6 +116,20 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec) if (report_path_error(ps_matched, pathspec, 0)) return 1; + /* Any unmerged paths? */ + for (pos = 0; pos < active_nr; pos++) { + struct cache_entry *ce = active_cache[pos]; + if (pathspec_match(pathspec, NULL, ce->name, 0)) { + if (!ce_stage(ce)) + continue; + errs = 1; + error("path '%s' is unmerged", ce->name); + pos = skip_same_name(ce, pos) - 1; + } + } + if (errs) + return 1; + /* Now we are committed to check them out */ memset(&state, 0, sizeof(state)); state.force = 1; @@ -114,7 +137,11 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec) for (pos = 0; pos < active_nr; pos++) { struct cache_entry *ce = active_cache[pos]; if (pathspec_match(pathspec, NULL, ce->name, 0)) { - errs |= checkout_entry(ce, &state, NULL); + if (!ce_stage(ce)) { + errs |= checkout_entry(ce, &state, NULL); + continue; + } + pos = skip_same_name(ce, pos) - 1; } } diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 2e2b3bf53..fbec70d3c 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -337,4 +337,26 @@ test_expect_success \ test refs/heads/delete-me = "$(git symbolic-ref HEAD)" && test_must_fail git checkout --track -b track' +test_expect_success 'checkout an unmerged path should fail' ' + rm -f .git/index && + O=$(echo original | git hash-object -w --stdin) && + A=$(echo ourside | git hash-object -w --stdin) && + B=$(echo theirside | git hash-object -w --stdin) && + ( + echo "100644 $A 0 fild" && + echo "100644 $O 1 file" && + echo "100644 $A 2 file" && + echo "100644 $B 3 file" && + echo "100644 $A 0 filf" + ) | git update-index --index-info && + echo "none of the above" >sample && + cat sample >fild && + cat sample >file && + cat sample >filf && + test_must_fail git checkout fild file filf && + test_cmp sample fild && + test_cmp sample filf && + test_cmp sample file +' + test_done |