Skip to content

Commit f38b168

Browse files
jiangxingitster
authored andcommitted
transport-helper: mark failure for atomic push
Commit v2.22.0-1-g3bca1e7f9f (transport-helper: enforce atomic in push_refs_with_push, 2019-07-11) noticed the incomplete report of failure of an atomic push for HTTP protocol. But the implementation has a flaw that mark all remote references as failure. Only mark necessary references as failure in `push_refs_with_push()` of transport-helper. Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 46701bd commit f38b168

3 files changed

Lines changed: 28 additions & 6 deletions

File tree

t/t5541-http-push-smart.sh

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,10 @@ test_expect_success 'push (chunked)' '
177177
test $HEAD = $(git rev-parse --verify HEAD))
178178
'
179179

180-
test_expect_failure 'push --atomic also prevents branch creation, reports collateral' '
180+
## References of remote: atomic1(1) master(2) collateral(2) other(2)
181+
## References of local : atomic2(2) master(1) collateral(3) other(2) collateral1(3) atomic(1)
182+
## Atomic push : master(1) collateral(3) atomic(1)
183+
test_expect_success 'push --atomic also prevents branch creation, reports collateral' '
181184
# Setup upstream repo - empty for now
182185
d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git &&
183186
git init --bare "$d" &&
@@ -189,7 +192,8 @@ test_expect_failure 'push --atomic also prevents branch creation, reports collat
189192
test_commit atomic2 &&
190193
git branch collateral &&
191194
git branch other &&
192-
git push "$up" master collateral other &&
195+
git push "$up" atomic1 master collateral other &&
196+
git tag -d atomic1 &&
193197
194198
# collateral is a valid push, but should be failed by atomic push
195199
git checkout collateral &&
@@ -224,7 +228,11 @@ test_expect_failure 'push --atomic also prevents branch creation, reports collat
224228
225229
# the collateral failure refs should be indicated to the user
226230
grep "^ ! .*rejected.* atomic -> atomic .*atomic push failed" output &&
227-
grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output
231+
grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output &&
232+
233+
# never report what we do not push
234+
! grep "^ ! .*rejected.* atomic1 " output &&
235+
! grep "^ ! .*rejected.* other " output
228236
'
229237

230238
test_expect_success 'push --atomic fails on server-side errors' '

t/t5548-push-porcelain.sh

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ run_git_push_porcelain_output_test() {
136136
# Refs of upstream : master(A) bar(B) baz(A) next(A)
137137
# Refs of workbench: master(B) bar(A) baz(A) next(A)
138138
# git-push : master(B) bar(A) NULL next(A)
139-
test_expect_failure "atomic push failed ($PROTOCOL)" '
139+
test_expect_success "atomic push failed ($PROTOCOL)" '
140140
(
141141
cd workbench &&
142142
git update-ref refs/heads/master $B &&
@@ -150,10 +150,10 @@ run_git_push_porcelain_output_test() {
150150
make_user_friendly_and_stable_output <out >actual &&
151151
cat >expect <<-EOF &&
152152
To <URL/of/upstream.git>
153+
= refs/heads/next:refs/heads/next [up to date]
153154
! refs/heads/bar:refs/heads/bar [rejected] (non-fast-forward)
154155
! (delete):refs/heads/baz [rejected] (atomic push failed)
155156
! refs/heads/master:refs/heads/master [rejected] (atomic push failed)
156-
! refs/heads/next:refs/heads/next [rejected] (atomic push failed)
157157
Done
158158
EOF
159159
test_cmp expect actual &&
@@ -168,7 +168,6 @@ run_git_push_porcelain_output_test() {
168168
EOF
169169
test_cmp expect actual
170170
'
171-
172171
test_expect_success "prepare pre-receive hook ($PROTOCOL)" '
173172
write_script "$upstream/hooks/pre-receive" <<-EOF
174173
exit 1

transport-helper.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,21 @@ static int push_refs_with_push(struct transport *transport,
894894
case REF_STATUS_REJECT_STALE:
895895
case REF_STATUS_REJECT_ALREADY_EXISTS:
896896
if (atomic) {
897+
/* Mark other refs as failed */
898+
for (ref = remote_refs; ref; ref = ref->next) {
899+
if (!ref->peer_ref && !mirror)
900+
continue;
901+
902+
switch (ref->status) {
903+
case REF_STATUS_NONE:
904+
case REF_STATUS_OK:
905+
case REF_STATUS_EXPECTING_REPORT:
906+
ref->status = REF_STATUS_ATOMIC_PUSH_FAILED;
907+
continue;
908+
default:
909+
break; /* do nothing */
910+
}
911+
}
897912
string_list_clear(&cas_options, 0);
898913
return 0;
899914
} else

0 commit comments

Comments
 (0)