t: add tests for restore

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Apr 25, 2019 at 16:45 UTC 4df3ec6324ba78b9b28ce1ecb872594dd1bffa1c
3 files changed +221
t/lib-patch-mode.sh
+12
@@ -2,28 +2,40 @@
2
3 . ./test-lib.sh
4
5 +# set_state <path> <worktree-content> <index-content>
6 +#
7 +# Prepare the content for path in worktree and the index as specified.
8 set_state () {
9 echo "$3" > "$1" &&
10 git add "$1" &&
11 echo "$2" > "$1"
12 }
13
14 +# save_state <path>
15 +#
16 +# Save index/worktree content of <path> in the files _worktree_<path>
17 +# and _index_<path>
18 save_state () {
19 noslash="$(echo "$1" | tr / _)" &&
20 cat "$1" > _worktree_"$noslash" &&
21 git show :"$1" > _index_"$noslash"
22 }
23
24 +# set_and_save_state <path> <worktree-content> <index-content>
25 set_and_save_state () {
26 set_state "$@" &&
27 save_state "$1"
28 }
29
30 +# verify_state <path> <expected-worktree-content> <expected-index-content>
31 verify_state () {
32 test "$(cat "$1")" = "$2" &&
33 test "$(git show :"$1")" = "$3"
34 }
35
36 +# verify_saved_state <path>
37 +#
38 +# Call verify_state with expected contents from the last save_state
39 verify_saved_state () {
40 noslash="$(echo "$1" | tr / _)" &&
41 verify_state "$1" "$(cat _worktree_"$noslash")" "$(cat _index_"$noslash")"
t/t2070-restore.sh new
+99
@@ -0,0 +1,99 @@
1 +#!/bin/sh
2 +
3 +test_description='restore basic functionality'
4 +
5 +. ./test-lib.sh
6 +
7 +test_expect_success 'setup' '
8 + test_commit first &&
9 + echo first-and-a-half >>first.t &&
10 + git add first.t &&
11 + test_commit second &&
12 + echo one >one &&
13 + echo two >two &&
14 + echo untracked >untracked &&
15 + echo ignored >ignored &&
16 + echo /ignored >.gitignore &&
17 + git add one two .gitignore &&
18 + git update-ref refs/heads/one master
19 +'
20 +
21 +test_expect_success 'restore without pathspec is not ok' '
22 + test_must_fail git restore &&
23 + test_must_fail git restore --source=first
24 +'
25 +
26 +test_expect_success 'restore a file, ignoring branch of same name' '
27 + cat one >expected &&
28 + echo dirty >>one &&
29 + git restore one &&
30 + test_cmp expected one
31 +'
32 +
33 +test_expect_success 'restore a file on worktree from another ref' '
34 + test_when_finished git reset --hard &&
35 + git cat-file blob first:./first.t >expected &&
36 + git restore --source=first first.t &&
37 + test_cmp expected first.t &&
38 + git cat-file blob HEAD:./first.t >expected &&
39 + git show :first.t >actual &&
40 + test_cmp expected actual
41 +'
42 +
43 +test_expect_success 'restore a file in the index from another ref' '
44 + test_when_finished git reset --hard &&
45 + git cat-file blob first:./first.t >expected &&
46 + git restore --source=first --staged first.t &&
47 + git show :first.t >actual &&
48 + test_cmp expected actual &&
49 + git cat-file blob HEAD:./first.t >expected &&
50 + test_cmp expected first.t
51 +'
52 +
53 +test_expect_success 'restore a file in both the index and worktree from another ref' '
54 + test_when_finished git reset --hard &&
55 + git cat-file blob first:./first.t >expected &&
56 + git restore --source=first --staged --worktree first.t &&
57 + git show :first.t >actual &&
58 + test_cmp expected actual &&
59 + test_cmp expected first.t
60 +'
61 +
62 +test_expect_success 'restore --staged uses HEAD as source' '
63 + test_when_finished git reset --hard &&
64 + git cat-file blob :./first.t >expected &&
65 + echo index-dirty >>first.t &&
66 + git add first.t &&
67 + git restore --staged first.t &&
68 + git cat-file blob :./first.t >actual &&
69 + test_cmp expected actual
70 +'
71 +
72 +test_expect_success 'restore --ignore-unmerged ignores unmerged entries' '
73 + git init unmerged &&
74 + (
75 + cd unmerged &&
76 + echo one >unmerged &&
77 + echo one >common &&
78 + git add unmerged common &&
79 + git commit -m common &&
80 + git switch -c first &&
81 + echo first >unmerged &&
82 + git commit -am first &&
83 + git switch -c second master &&
84 + echo second >unmerged &&
85 + git commit -am second &&
86 + test_must_fail git merge first &&
87 +
88 + echo dirty >>common &&
89 + test_must_fail git restore . &&
90 +
91 + git restore --ignore-unmerged --quiet . >output 2>&1 &&
92 + git diff common >diff-output &&
93 + : >empty &&
94 + test_cmp empty output &&
95 + test_cmp empty diff-output
96 + )
97 +'
98 +
99 +test_done
t/t2071-restore-patch.sh new
+110
@@ -0,0 +1,110 @@
1 +#!/bin/sh
2 +
3 +test_description='git restore --patch'
4 +
5 +. ./lib-patch-mode.sh
6 +
7 +test_expect_success PERL 'setup' '
8 + mkdir dir &&
9 + echo parent >dir/foo &&
10 + echo dummy >bar &&
11 + git add bar dir/foo &&
12 + git commit -m initial &&
13 + test_tick &&
14 + test_commit second dir/foo head &&
15 + set_and_save_state bar bar_work bar_index &&
16 + save_head
17 +'
18 +
19 +test_expect_success PERL 'restore -p without pathspec is fine' '
20 + echo q >cmd &&
21 + git restore -p <cmd
22 +'
23 +
24 +# note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar'
25 +
26 +test_expect_success PERL 'saying "n" does nothing' '
27 + set_and_save_state dir/foo work head &&
28 + test_write_lines n n | git restore -p &&
29 + verify_saved_state bar &&
30 + verify_saved_state dir/foo
31 +'
32 +
33 +test_expect_success PERL 'git restore -p' '
34 + set_and_save_state dir/foo work head &&
35 + test_write_lines n y | git restore -p &&
36 + verify_saved_state bar &&
37 + verify_state dir/foo head head
38 +'
39 +
40 +test_expect_success PERL 'git restore -p with staged changes' '
41 + set_state dir/foo work index &&
42 + test_write_lines n y | git restore -p &&
43 + verify_saved_state bar &&
44 + verify_state dir/foo index index
45 +'
46 +
47 +test_expect_success PERL 'git restore -p --source=HEAD' '
48 + set_state dir/foo work index &&
49 + # the third n is to get out in case it mistakenly does not apply
50 + test_write_lines n y n | git restore -p --source=HEAD &&
51 + verify_saved_state bar &&
52 + verify_state dir/foo head index
53 +'
54 +
55 +test_expect_success PERL 'git restore -p --source=HEAD^' '
56 + set_state dir/foo work index &&
57 + # the third n is to get out in case it mistakenly does not apply
58 + test_write_lines n y n | git restore -p --source=HEAD^ &&
59 + verify_saved_state bar &&
60 + verify_state dir/foo parent index
61 +'
62 +
63 +test_expect_success PERL 'git restore -p handles deletion' '
64 + set_state dir/foo work index &&
65 + rm dir/foo &&
66 + test_write_lines n y | git restore -p &&
67 + verify_saved_state bar &&
68 + verify_state dir/foo index index
69 +'
70 +
71 +# The idea in the rest is that bar sorts first, so we always say 'y'
72 +# first and if the path limiter fails it'll apply to bar instead of
73 +# dir/foo. There's always an extra 'n' to reject edits to dir/foo in
74 +# the failure case (and thus get out of the loop).
75 +
76 +test_expect_success PERL 'path limiting works: dir' '
77 + set_state dir/foo work head &&
78 + test_write_lines y n | git restore -p dir &&
79 + verify_saved_state bar &&
80 + verify_state dir/foo head head
81 +'
82 +
83 +test_expect_success PERL 'path limiting works: -- dir' '
84 + set_state dir/foo work head &&
85 + test_write_lines y n | git restore -p -- dir &&
86 + verify_saved_state bar &&
87 + verify_state dir/foo head head
88 +'
89 +
90 +test_expect_success PERL 'path limiting works: HEAD^ -- dir' '
91 + set_state dir/foo work head &&
92 + # the third n is to get out in case it mistakenly does not apply
93 + test_write_lines y n n | git restore -p --source=HEAD^ -- dir &&
94 + verify_saved_state bar &&
95 + verify_state dir/foo parent head
96 +'
97 +
98 +test_expect_success PERL 'path limiting works: foo inside dir' '
99 + set_state dir/foo work head &&
100 + # the third n is to get out in case it mistakenly does not apply
101 + test_write_lines y n n | (cd dir && git restore -p foo) &&
102 + verify_saved_state bar &&
103 + verify_state dir/foo head head
104 +'
105 +
106 +test_expect_success PERL 'none of this moved HEAD' '
107 + verify_saved_head
108 +'
109 +
110 +test_done