diff mbox series

[v3,8/8] send-pack: gracefully close the connection for atomic push

Message ID 9f49278ef108f08d512ee13128ed8277e12c002d.1733830410.git.zhiyou.jx@alibaba-inc.com (mailing list archive)
State New
Headers show
Series fix behaviors of git-push --porcelain | expand

Commit Message

Jiang Xin Dec. 10, 2024, 11:36 a.m. UTC
From: Jiang Xin <zhiyou.jx@alibaba-inc.com>

Patrick reported an issue that the exit code of git-receive-pack(1) is
ignored during atomic push with "--porcelain" flag, and added new test
cases in t5543.

This issue originated from commit 7dcbeaa0df (send-pack: fix
inconsistent porcelain output, 2020-04-17). At that time, I chose to
ignore the exit code of "finish_connect()" without investigating the
root cause of the abnormal termination of git-receive-pack. That was an
incorrect solution.

The root cause is that an atomic push operation terminates early without
sending a flush packet to git-receive-pack. As a result,
git-receive-pack continues waiting for commands without exiting. By
sending a flush packet at the appropriate location in "send_pack()", we
ensure that the git-receive-pack process closes properly, avoiding an
erroneous exit code for git-push. At the same time, revert the changes
to the "transport.c" file made in commit 7dcbeaa0df.

Reported-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
---
 send-pack.c            |  1 +
 t/t5543-atomic-push.sh |  4 ++--
 transport.c            | 10 +---------
 3 files changed, 4 insertions(+), 11 deletions(-)

Comments

Patrick Steinhardt Dec. 16, 2024, 8:36 a.m. UTC | #1
On Tue, Dec 10, 2024 at 07:36:28PM +0800, Jiang Xin wrote:
> diff --git a/send-pack.c b/send-pack.c
> index f1556dd53c..439b249c79 100644
> --- a/send-pack.c
> +++ b/send-pack.c
> @@ -631,6 +631,7 @@ int send_pack(struct send_pack_args *args,
>  				error("atomic push failed for ref %s. status: %d",
>  				      ref->name, ref->status);
>  				ret = ERROR_SEND_PACK_BAD_REF_STATUS;
> +				packet_flush(out);
>  				goto out;
>  			}
>  			/* else fallthrough */

Nice and easy fix.

Patrick
diff mbox series

Patch

diff --git a/send-pack.c b/send-pack.c
index f1556dd53c..439b249c79 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -631,6 +631,7 @@  int send_pack(struct send_pack_args *args,
 				error("atomic push failed for ref %s. status: %d",
 				      ref->name, ref->status);
 				ret = ERROR_SEND_PACK_BAD_REF_STATUS;
+				packet_flush(out);
 				goto out;
 			}
 			/* else fallthrough */
diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh
index 32181b9afb..3a700b0676 100755
--- a/t/t5543-atomic-push.sh
+++ b/t/t5543-atomic-push.sh
@@ -280,7 +280,7 @@  test_expect_success 'atomic push reports (reject by non-ff)' '
 	test_cmp expect actual
 '
 
-test_expect_failure 'atomic push reports exit code failure' '
+test_expect_success 'atomic push reports exit code failure' '
 	write_script receive-pack-wrapper <<-\EOF &&
 	git-receive-pack "$@"
 	exit 1
@@ -296,7 +296,7 @@  test_expect_failure 'atomic push reports exit code failure' '
 	test_cmp expect err
 '
 
-test_expect_failure 'atomic push reports exit code failure with porcelain' '
+test_expect_success 'atomic push reports exit code failure with porcelain' '
 	write_script receive-pack-wrapper <<-\EOF &&
 	git-receive-pack "$@"
 	exit 1
diff --git a/transport.c b/transport.c
index 454d7f21a9..afcbca293b 100644
--- a/transport.c
+++ b/transport.c
@@ -928,15 +928,7 @@  static int git_transport_push(struct transport *transport, struct ref *remote_re
 
 	close(data->fd[1]);
 	close(data->fd[0]);
-	/*
-	 * Atomic push may abort the connection early and close the pipe,
-	 * which may cause an error for `finish_connect()`. Ignore this error
-	 * for atomic git-push.
-	 */
-	if (ret || args.atomic)
-		finish_connect(data->conn);
-	else
-		ret = finish_connect(data->conn);
+	ret |= finish_connect(data->conn);
 	data->conn = NULL;
 	data->finished_handshake = 0;