2011-09-30 21:33:15 +04:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='checkout $tree -- $paths'
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
test_expect_success setup '
|
|
|
|
mkdir dir &&
|
|
|
|
>dir/master &&
|
|
|
|
echo common >dir/common &&
|
|
|
|
git add dir/master dir/common &&
|
|
|
|
test_tick && git commit -m "master has dir/master" &&
|
|
|
|
git checkout -b next &&
|
|
|
|
git mv dir/master dir/next0 &&
|
|
|
|
echo next >dir/next1 &&
|
|
|
|
git add dir &&
|
|
|
|
test_tick && git commit -m "next has dir/next but not dir/master"
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'checking out paths out of a tree does not clobber unrelated paths' '
|
|
|
|
git checkout next &&
|
|
|
|
git reset --hard &&
|
|
|
|
rm dir/next0 &&
|
|
|
|
cat dir/common >expect.common &&
|
|
|
|
echo modified >expect.next1 &&
|
|
|
|
cat expect.next1 >dir/next1 &&
|
|
|
|
echo untracked >expect.next2 &&
|
|
|
|
cat expect.next2 >dir/next2 &&
|
|
|
|
|
|
|
|
git checkout master dir &&
|
|
|
|
|
|
|
|
test_cmp expect.common dir/common &&
|
|
|
|
test_path_is_file dir/master &&
|
|
|
|
git diff --exit-code master dir/master &&
|
|
|
|
|
|
|
|
test_path_is_missing dir/next0 &&
|
|
|
|
test_cmp expect.next1 dir/next1 &&
|
|
|
|
test_path_is_file dir/next2 &&
|
|
|
|
test_must_fail git ls-files --error-unmatch dir/next2 &&
|
|
|
|
test_cmp expect.next2 dir/next2
|
|
|
|
'
|
|
|
|
|
checkout: avoid unnecessary match_pathspec calls
In checkout_paths() we do this
- for all updated items, call match_pathspec
- for all items, call match_pathspec (inside unmerge_cache)
- for all items, call match_pathspec (for showing "path .. is unmerged)
- for updated items, call match_pathspec and update paths
That's a lot of duplicate match_pathspec(s) and the function is not
exactly cheap to be called so many times, especially on large indexes.
This patch makes it call match_pathspec once per updated index entry,
save the result in ce_flags and reuse the results in the following
loops.
The changes in 0a1283b (checkout $tree $path: do not clobber local
changes in $path not in $tree - 2011-09-30) limit the affected paths
to ones we read from $tree. We do not do anything to other modified
entries in this case, so the "for all items" above could be modified
to "for all updated items". But..
The command's behavior now is modified slightly: unmerged entries that
match $path, but not updated by $tree, are now NOT touched. Although
this should be considered a bug fix, not a regression. A new test is
added for this change.
And while at there, free ps_matched after use.
The following command is tested on webkit, 215k entries. The pattern
is chosen mainly to make match_pathspec sweat:
git checkout -- "*[a-zA-Z]*[a-zA-Z]*[a-zA-Z]*"
before after
real 0m3.493s 0m2.737s
user 0m2.239s 0m1.586s
sys 0m1.252s 0m1.151s
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-03-27 09:58:21 +04:00
|
|
|
test_expect_success 'do not touch unmerged entries matching $path but not in $tree' '
|
|
|
|
git checkout next &&
|
|
|
|
git reset --hard &&
|
|
|
|
|
|
|
|
cat dir/common >expect.common &&
|
|
|
|
EMPTY_SHA1=$(git hash-object -w --stdin </dev/null) &&
|
|
|
|
git rm dir/next0 &&
|
|
|
|
cat >expect.next0 <<-EOF &&
|
|
|
|
100644 $EMPTY_SHA1 1 dir/next0
|
|
|
|
100644 $EMPTY_SHA1 2 dir/next0
|
|
|
|
EOF
|
|
|
|
git update-index --index-info <expect.next0 &&
|
|
|
|
|
|
|
|
git checkout master dir &&
|
|
|
|
|
|
|
|
test_cmp expect.common dir/common &&
|
|
|
|
test_path_is_file dir/master &&
|
|
|
|
git diff --exit-code master dir/master &&
|
|
|
|
git ls-files -s dir/next0 >actual.next0 &&
|
|
|
|
test_cmp expect.next0 actual.next0
|
|
|
|
'
|
|
|
|
|
2014-11-13 21:30:34 +03:00
|
|
|
test_expect_success 'do not touch files that are already up-to-date' '
|
|
|
|
git reset --hard &&
|
|
|
|
echo one >file1 &&
|
|
|
|
echo two >file2 &&
|
|
|
|
git add file1 file2 &&
|
|
|
|
git commit -m base &&
|
|
|
|
echo modified >file1 &&
|
2018-03-24 10:44:31 +03:00
|
|
|
test-tool chmtime =1000000000 file2 &&
|
2014-11-13 21:30:34 +03:00
|
|
|
git update-index -q --refresh &&
|
|
|
|
git checkout HEAD -- file1 file2 &&
|
|
|
|
echo one >expect &&
|
|
|
|
test_cmp expect file1 &&
|
2018-04-07 01:19:47 +03:00
|
|
|
echo "1000000000" >expect &&
|
2018-04-25 07:29:00 +03:00
|
|
|
test-tool chmtime --get file2 >actual &&
|
2014-11-13 21:30:34 +03:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
checkout.c: unstage empty deleted ita files
It is possible to delete a committed file from the index and then add it
as intent-to-add. After `git checkout HEAD <pathspec>`, the file should
be identical in the index and HEAD. The command already works correctly
if the file has contents in HEAD. This patch provides the desired
behavior even when the file is empty in HEAD.
`git checkout HEAD <pathspec>` calls tree.c:read_tree_1(), with fn
pointing to checkout.c:update_some(). update_some() creates a new cache
entry but discards it when its mode and oid match those of the old
entry. A cache entry for an ita file and a cache entry for an empty file
have the same oid. Therefore, an empty deleted ita file previously
passed both of these checks, and the new entry was discarded, so the
file remained unchanged in the index. After this fix, if the file is
marked as ita in the cache, then we avoid discarding the new entry and
add the new entry to the cache instead.
This change should not affect newly added ita files. For those, inside
tree.c:read_tree_1(), tree_entry_interesting() returns
entry_not_interesting, so fn is never called.
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Varun Naik <vcnaik94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-02 19:28:52 +03:00
|
|
|
test_expect_success 'checkout HEAD adds deleted intent-to-add file back to index' '
|
|
|
|
echo "nonempty" >nonempty &&
|
|
|
|
>empty &&
|
|
|
|
git add nonempty empty &&
|
|
|
|
git commit -m "create files to be deleted" &&
|
|
|
|
git rm --cached nonempty empty &&
|
|
|
|
git add -N nonempty empty &&
|
|
|
|
git checkout HEAD nonempty empty &&
|
|
|
|
git diff --cached --exit-code
|
|
|
|
'
|
|
|
|
|
2011-09-30 21:33:15 +04:00
|
|
|
test_done
|