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