From 7dcbeaa0df01661f31a0d93e5d5787a5d3767358 Mon Sep 17 00:00:00 2001 From: Jiang Xin Date: Fri, 17 Apr 2020 05:45:32 -0400 Subject: send-pack: fix inconsistent porcelain output The porcelain output of a failed `git-push` command is inconsistent for different protocols. For example, the following `git-push` command may fail due to the failure of the `pre-receive` hook. git push --porcelain origin HEAD:refs/heads/master For SSH protocol, the porcelain output does not end with a "Done" message: To ! HEAD:refs/heads/master [remote rejected] (pre-receive hook declined) While for HTTP protocol, the porcelain output does end with a "Done" message: To ! HEAD:refs/heads/master [remote rejected] (pre-receive hook declined) Done The following code at the end of function `send_pack()` indicates that `send_pack()` should not return an error if some references are rejected in porcelain mode. int send_pack(...) ... ... if (args->porcelain) return 0; for (ref = remote_refs; ref; ref = ref->next) { switch (ref->status) { case REF_STATUS_NONE: case REF_STATUS_UPTODATE: case REF_STATUS_OK: break; default: return -1; } } return 0; } So if atomic push failed, must check the porcelain mode before return an error. And `receive_status()` should not return an error for a failed updated reference, because `send_pack()` will check them instead. Signed-off-by: Jiang Xin Signed-off-by: Junio C Hamano --- send-pack.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'send-pack.c') diff --git a/send-pack.c b/send-pack.c index 0407841ae8..1835cd5582 100644 --- a/send-pack.c +++ b/send-pack.c @@ -190,10 +190,8 @@ static int receive_status(struct packet_reader *reader, struct ref *refs) if (reader->line[0] == 'o' && reader->line[1] == 'k') hint->status = REF_STATUS_OK; - else { + else hint->status = REF_STATUS_REMOTE_REJECT; - ret = -1; - } hint->remote_status = xstrdup_or_null(msg); /* start our next search from the next ref */ hint = hint->next; @@ -489,7 +487,8 @@ int send_pack(struct send_pack_args *args, if (use_atomic) { strbuf_release(&req_buf); strbuf_release(&cap_buf); - return atomic_push_failure(args, remote_refs, ref); + atomic_push_failure(args, remote_refs, ref); + return args->porcelain ? 0 : -1; } /* else fallthrough */ default: -- cgit v1.2.3 From 46701bde690f94fb1532bce110eae93d5f6b68a1 Mon Sep 17 00:00:00 2001 From: Jiang Xin Date: Fri, 17 Apr 2020 05:45:34 -0400 Subject: send-pack: mark failure of atomic push properly When pushing with SSH or other smart protocol, references are validated by function `check_to_send_update()` before they are sent in commands to `send_pack()` of "receve-pack". For atomic push, if a reference is rejected after the validation, only references pushed by user should be marked as failure, instead of report failure on all remote references. Commit v2.22.0-1-g3bca1e7f9f (transport-helper: enforce atomic in push_refs_with_push, 2019-07-11) wanted to fix report issue of HTTP protocol, but marked all remote references failure for atomic push. In order to fix the issue of status report for SSH or other built-in smart protocol, revert part of that commit and add additional status for function `atomic_push_failure()`. The additional status for it except the "REF_STATUS_EXPECTING_REPORT" status are: - REF_STATUS_NONE : Not marked as "REF_STATUS_EXPECTING_REPORT" yet. - REF_STATUS_OK : Assume OK for dryrun or status_report is disabled. This fix won't resolve the issue of status report in transport-helper for HTTP or other protocols, and breaks test case in t5541. Will fix it in additional commit. Signed-off-by: Jiang Xin Signed-off-by: Junio C Hamano --- send-pack.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'send-pack.c') diff --git a/send-pack.c b/send-pack.c index 1835cd5582..efefb687b2 100644 --- a/send-pack.c +++ b/send-pack.c @@ -332,6 +332,8 @@ static int atomic_push_failure(struct send_pack_args *args, continue; switch (ref->status) { + case REF_STATUS_NONE: + case REF_STATUS_OK: case REF_STATUS_EXPECTING_REPORT: ref->status = REF_STATUS_ATOMIC_PUSH_FAILED; continue; -- cgit v1.2.3 From dfe1b7f19c04fd10e9bafce91bc1da0c18bbb194 Mon Sep 17 00:00:00 2001 From: Jiang Xin Date: Fri, 17 Apr 2020 05:45:36 -0400 Subject: transport-helper: new method reject_atomic_push() Add new method in transport-helper to reject all references if any reference is failed for atomic push. This method is reused in "send-pack.c" and "transport-helper.c", one for SSH, git and file protocols, and the other for HTTP protocol. Signed-off-by: Jiang Xin Signed-off-by: Junio C Hamano --- send-pack.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) (limited to 'send-pack.c') diff --git a/send-pack.c b/send-pack.c index efefb687b2..a7c53193c9 100644 --- a/send-pack.c +++ b/send-pack.c @@ -320,31 +320,6 @@ free_return: return update_seen; } - -static int atomic_push_failure(struct send_pack_args *args, - struct ref *remote_refs, - struct ref *failing_ref) -{ - struct ref *ref; - /* Mark other refs as failed */ - for (ref = remote_refs; ref; ref = ref->next) { - if (!ref->peer_ref && !args->send_mirror) - continue; - - switch (ref->status) { - case REF_STATUS_NONE: - case REF_STATUS_OK: - case REF_STATUS_EXPECTING_REPORT: - ref->status = REF_STATUS_ATOMIC_PUSH_FAILED; - continue; - default: - break; /* do nothing */ - } - } - return error("atomic push failed for ref %s. status: %d\n", - failing_ref->name, failing_ref->status); -} - #define NONCE_LEN_LIMIT 256 static void reject_invalid_nonce(const char *nonce, int len) @@ -489,7 +464,9 @@ int send_pack(struct send_pack_args *args, if (use_atomic) { strbuf_release(&req_buf); strbuf_release(&cap_buf); - atomic_push_failure(args, remote_refs, ref); + reject_atomic_push(remote_refs, args->send_mirror); + error("atomic push failed for ref %s. status: %d\n", + ref->name, ref->status); return args->porcelain ? 0 : -1; } /* else fallthrough */ -- cgit v1.2.3