1
+#!/bin/sh
2
+# Copyright (c) 2020, Jacob Keller.
3
+
4
+test_description='"git fetch" with negative refspecs.
5
+
6
+'
7
+
8
+. ./test-lib.sh
9
+
10
+test_expect_success setup '
11
+ echo >file original &&
12
+ git add file &&
13
+ git commit -a -m original
14
+'
15
+
16
+test_expect_success "clone and setup child repos" '
17
+ git clone . one &&
18
+ (
19
+ cd one &&
20
+ echo >file updated by one &&
21
+ git commit -a -m "updated by one" &&
22
+ git switch -c alternate &&
23
+ echo >file updated again by one &&
24
+ git commit -a -m "updated by one again" &&
25
+ git switch master
26
+ ) &&
27
+ git clone . two &&
28
+ (
29
+ cd two &&
30
+ git config branch.master.remote one &&
31
+ git config remote.one.url ../one/.git/ &&
32
+ git config remote.one.fetch +refs/heads/*:refs/remotes/one/* &&
33
+ git config --add remote.one.fetch ^refs/heads/alternate
34
+ ) &&
35
+ git clone . three
36
+'
37
+
38
+test_expect_success "fetch one" '
39
+ echo >file updated by origin &&
40
+ git commit -a -m "updated by origin" &&
41
+ (
42
+ cd two &&
43
+ test_must_fail git rev-parse --verify refs/remotes/one/alternate &&
44
+ git fetch one &&
45
+ test_must_fail git rev-parse --verify refs/remotes/one/alternate &&
46
+ git rev-parse --verify refs/remotes/one/master &&
47
+ mine=$(git rev-parse refs/remotes/one/master) &&
48
+ his=$(cd ../one && git rev-parse refs/heads/master) &&
49
+ test "z$mine" = "z$his"
50
+ )
51
+'
52
+
53
+test_expect_success "fetch with negative refspec on commandline" '
54
+ echo >file updated by origin again &&
55
+ git commit -a -m "updated by origin again" &&
56
+ (
57
+ cd three &&
58
+ alternate_in_one=$(cd ../one && git rev-parse refs/heads/alternate) &&
59
+ echo $alternate_in_one >expect &&
60
+ git fetch ../one/.git refs/heads/*:refs/remotes/one/* ^refs/heads/master &&
61
+ cut -f -1 .git/FETCH_HEAD >actual &&
62
+ test_cmp expect actual
63
+ )
64
+'
65
+
66
+test_expect_success "fetch with negative sha1 refspec fails" '
67
+ echo >file updated by origin yet again &&
68
+ git commit -a -m "updated by origin yet again" &&
69
+ (
70
+ cd three &&
71
+ master_in_one=$(cd ../one && git rev-parse refs/heads/master) &&
72
+ test_must_fail git fetch ../one/.git refs/heads/*:refs/remotes/one/* ^$master_in_one
73
+ )
74
+'
75
+
76
+test_expect_success "fetch with negative pattern refspec" '
77
+ echo >file updated by origin once more &&
78
+ git commit -a -m "updated by origin once more" &&
79
+ (
80
+ cd three &&
81
+ alternate_in_one=$(cd ../one && git rev-parse refs/heads/alternate) &&
82
+ echo $alternate_in_one >expect &&
83
+ git fetch ../one/.git refs/heads/*:refs/remotes/one/* ^refs/heads/m* &&
84
+ cut -f -1 .git/FETCH_HEAD >actual &&
85
+ test_cmp expect actual
86
+ )
87
+'
88
+
89
+test_expect_success "fetch with negative pattern refspec does not expand prefix" '
90
+ echo >file updated by origin another time &&
91
+ git commit -a -m "updated by origin another time" &&
92
+ (
93
+ cd three &&
94
+ alternate_in_one=$(cd ../one && git rev-parse refs/heads/alternate) &&
95
+ master_in_one=$(cd ../one && git rev-parse refs/heads/master) &&
96
+ echo $alternate_in_one >expect &&
97
+ echo $master_in_one >>expect &&
98
+ git fetch ../one/.git refs/heads/*:refs/remotes/one/* ^master &&
99
+ cut -f -1 .git/FETCH_HEAD >actual &&
100
+ test_cmp expect actual
101
+ )
102
+'
103
+
104
+test_expect_success "fetch with negative refspec avoids duplicate conflict" '
105
+ cd "$D" &&
106
+ (
107
+ cd one &&
108
+ git branch dups/a &&
109
+ git branch dups/b &&
110
+ git branch dups/c &&
111
+ git branch other/a &&
112
+ git rev-parse --verify refs/heads/other/a >../expect &&
113
+ git rev-parse --verify refs/heads/dups/b >>../expect &&
114
+ git rev-parse --verify refs/heads/dups/c >>../expect
115
+ ) &&
116
+ (
117
+ cd three &&
118
+ git fetch ../one/.git ^refs/heads/dups/a refs/heads/dups/*:refs/dups/* refs/heads/other/a:refs/dups/a &&
119
+ git rev-parse --verify refs/dups/a >../actual &&
120
+ git rev-parse --verify refs/dups/b >>../actual &&
121
+ git rev-parse --verify refs/dups/c >>../actual
122
+ ) &&
123
+ test_cmp expect actual
124
+'
125
+
126
+test_expect_success "push --prune with negative refspec" '
127
+ (
128
+ cd two &&
129
+ git branch prune/a &&
130
+ git branch prune/b &&
131
+ git branch prune/c &&
132
+ git push ../three refs/heads/prune/* &&
133
+ git branch -d prune/a &&
134
+ git branch -d prune/b &&
135
+ git push --prune ../three refs/heads/prune/* ^refs/heads/prune/b
136
+ ) &&
137
+ (
138
+ cd three &&
139
+ test_write_lines b c >expect &&
140
+ git for-each-ref --format="%(refname:lstrip=3)" refs/heads/prune/ >actual &&
141
+ test_cmp expect actual
142
+ )
143
+'
144
+
145
+test_expect_success "push --prune with negative refspec apply to the destination" '
146
+ (
147
+ cd two &&
148
+ git branch ours/a &&
149
+ git branch ours/b &&
150
+ git branch ours/c &&
151
+ git push ../three refs/heads/ours/*:refs/heads/theirs/* &&
152
+ git branch -d ours/a &&
153
+ git branch -d ours/b &&
154
+ git push --prune ../three refs/heads/ours/*:refs/heads/theirs/* ^refs/heads/theirs/b
155
+ ) &&
156
+ (
157
+ cd three &&
158
+ test_write_lines b c >expect &&
159
+ git for-each-ref --format="%(refname:lstrip=3)" refs/heads/theirs/ >actual &&
160
+ test_cmp expect actual
161
+ )
162
+'
163
+
164
+test_expect_success "fetch --prune with negative refspec" '
165
+ (
166
+ cd two &&
167
+ git branch fetch/a &&
168
+ git branch fetch/b &&
169
+ git branch fetch/c
170
+ ) &&
171
+ (
172
+ cd three &&
173
+ git fetch ../two/.git refs/heads/fetch/*:refs/heads/copied/*
174
+ ) &&
175
+ (
176
+ cd two &&
177
+ git branch -d fetch/a &&
178
+ git branch -d fetch/b
179
+ ) &&
180
+ (
181
+ cd three &&
182
+ test_write_lines b c >expect &&
183
+ git fetch -v ../two/.git --prune refs/heads/fetch/*:refs/heads/copied/* ^refs/heads/fetch/b &&
184
+ git for-each-ref --format="%(refname:lstrip=3)" refs/heads/copied/ >actual &&
185
+ test_cmp expect actual
186
+ )
187
+'
188
+
189
+test_done