git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH] transport-helper: enforce atomic in push_refs_with_push
@ 2019-07-02  0:53 Emily Shaffer
  2019-07-02 13:51 ` Johannes Schindelin
                   ` (4 more replies)
  0 siblings, 5 replies; 45+ messages in thread
From: Emily Shaffer @ 2019-07-02  0:53 UTC (permalink / raw)
  To: git; +Cc: Emily Shaffer, Junio C Hamano

Teach transport-helper how to notice if skipping a ref during push would
violate atomicity on the client side. We notice that a ref would be
rejected, and choose not to send it, but don't notice that if the client
has asked for --atomic we are violating atomicity if all the other
pushes we are sending would succeed. Asking the server end to uphold
atomicity wouldn't work here as the server doesn't have any idea that we
tried to update a ref that's broken.

The added test-case is a succinct way to reproduce this issue that fails
today. The same steps work fine when we aren't using a transport-helper
to get to the upstream, i.e. when we've added a local repository as a
remote:

  git remote add ~/upstream upstream

Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
---
 t/t5541-http-push-smart.sh | 58 ++++++++++++++++++++++++++++++++++++++
 transport-helper.c         |  6 ++++
 transport.c                | 15 +++++++++-
 3 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
index 8ef8763e06..b57f6d480f 100755
--- a/t/t5541-http-push-smart.sh
+++ b/t/t5541-http-push-smart.sh
@@ -177,6 +177,64 @@ test_expect_success 'push (chunked)' '
 	 test $HEAD = $(git rev-parse --verify HEAD))
 '
 
+test_expect_success 'push --atomic also prevents branch creation' '
+	# Make up/master
+	d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git &&
+	git init --bare "$d" &&
+	git --git-dir="$d" config http.receivepack true &&
+	up="$HTTPD_URL"/smart/atomic-branches.git &&
+	test_commit atomic1 &&
+	test_commit atomic2 &&
+	git push "$up" master &&
+	# Make master incompatible with up/master
+	git reset --hard HEAD^ &&
+	# Add a new branch
+	git branch atomic &&
+	# --atomic should roll back creation of up/atomic
+	test_must_fail git push --atomic "$up" master atomic &&
+	git ls-remote "$up" >up-remotes &&
+	test_must_fail grep atomic up-remotes
+'
+
+test_expect_success 'push --atomic shows all failed refs' '
+	# Make up/master, up/allrefs
+	d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-failed-refs.git &&
+	git init --bare "$d" &&
+	git --git-dir="$d" config http.receivepack true &&
+	up="$HTTPD_URL"/smart/atomic-failed-refs.git &&
+	test_commit allrefs1 &&
+	test_commit allrefs2 &&
+	git branch allrefs &&
+	git push "$up" master allrefs &&
+	# Make master and allrefs incompatible with up/master, up/allrefs
+	git checkout allrefs &&
+	git reset --hard HEAD^ &&
+	git checkout master &&
+	git reset --hard HEAD^ &&
+	# --atomic should complain about both master and allrefs
+	test_must_fail git push --atomic "$up" master allrefs >&output &&
+	grep master output &&
+	grep allrefs output
+'
+
+test_expect_success 'push --atomic indicates collateral failures' '
+	# Make up/master, up/collateral
+	d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-collateral.git &&
+	git init --bare "$d" &&
+	git --git-dir="$d" config http.receivepack true &&
+	up="$HTTPD_URL"/smart/atomic-collateral.git &&
+	test_commit collateral1 &&
+	test_commit collateral2 &&
+	git branch collateral &&
+	git push "$up" master collateral &&
+	# Make master incompatible with up/master
+	git reset --hard HEAD^ &&
+	# --atomic should mention collateral was OK but failed anyway
+	test_must_fail git push --atomic "$up" master collateral >&output &&
+	grep "master -> master" output &&
+	grep "collateral -> collateral" output
+'
+
 test_expect_success 'push --all can push to empty repo' '
 	d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
 	git init --bare "$d" &&
diff --git a/transport-helper.c b/transport-helper.c
index c7e17ec9cb..6b05a88faf 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -853,6 +853,7 @@ static int push_refs_with_push(struct transport *transport,
 {
 	int force_all = flags & TRANSPORT_PUSH_FORCE;
 	int mirror = flags & TRANSPORT_PUSH_MIRROR;
+	int atomic = flags & TRANSPORT_PUSH_ATOMIC;
 	struct helper_data *data = transport->data;
 	struct strbuf buf = STRBUF_INIT;
 	struct ref *ref;
@@ -872,6 +873,11 @@ static int push_refs_with_push(struct transport *transport,
 		case REF_STATUS_REJECT_NONFASTFORWARD:
 		case REF_STATUS_REJECT_STALE:
 		case REF_STATUS_REJECT_ALREADY_EXISTS:
+			if (atomic) {
+				string_list_clear(&cas_options, 0);
+				return 0;
+			} else
+				continue;
 		case REF_STATUS_UPTODATE:
 			continue;
 		default:
diff --git a/transport.c b/transport.c
index f1fcd2c4b0..f4d6b38f9d 100644
--- a/transport.c
+++ b/transport.c
@@ -1226,10 +1226,23 @@ int transport_push(struct repository *r,
 		err = push_had_errors(remote_refs);
 		ret = push_ret | err;
 
-		if (!quiet || err)
+		if ((flags & TRANSPORT_PUSH_ATOMIC) && err) {
+			for (struct ref *it = remote_refs; it; it = it->next)
+				switch (it->status) {
+				case REF_STATUS_NONE:
+				case REF_STATUS_UPTODATE:
+				case REF_STATUS_OK:
+					it->status = REF_STATUS_ATOMIC_PUSH_FAILED;
+				default:
+					continue;
+				}
+		}
+
+		if (!quiet || err) {
 			transport_print_push_status(transport->url, remote_refs,
 					verbose | porcelain, porcelain,
 					reject_reasons);
+		}
 
 		if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
 			set_upstreams(transport, remote_refs, pretend);
-- 
2.22.0.410.gd8fdbe21b5-goog


^ permalink raw reply related	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2019-07-27 16:11 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-02  0:53 [PATCH] transport-helper: enforce atomic in push_refs_with_push Emily Shaffer
2019-07-02 13:51 ` Johannes Schindelin
2019-07-02 18:27   ` Junio C Hamano
2019-07-03 18:56   ` Emily Shaffer
2019-07-03 19:01     ` Emily Shaffer
2019-07-03 19:41     ` Johannes Schindelin
2019-07-03 20:57       ` Emily Shaffer
2019-07-04  8:29         ` Johannes Schindelin
2019-07-09 20:23           ` Emily Shaffer
2019-07-02 19:06 ` Junio C Hamano
2019-07-02 20:16 ` Junio C Hamano
2019-07-03  0:09   ` Emily Shaffer
2019-07-02 21:37 ` Junio C Hamano
2019-07-03  0:08   ` Emily Shaffer
2019-07-03  9:10   ` SZEDER Gábor
2019-07-03 18:13     ` Junio C Hamano
2019-07-03 18:58       ` Emily Shaffer
2019-07-09 21:10 ` [PATCH v2] " Emily Shaffer
2019-07-10 17:44   ` Junio C Hamano
2019-07-10 17:53     ` Junio C Hamano
2019-07-11 21:14       ` Emily Shaffer
2019-07-11 20:57     ` Emily Shaffer
2019-07-11 21:13       ` Junio C Hamano
2019-07-11 21:19   ` [PATCH v3] " Emily Shaffer
2019-07-12 16:25     ` Junio C Hamano
2019-07-16  7:10   ` [PATCH v2] " Carlo Arenas
2019-07-16 16:53     ` Junio C Hamano
2019-07-16 17:21       ` [RFC/PATCH] CodingGuidelines: spell out post-C89 rules Junio C Hamano
2019-07-17  0:55         ` Jonathan Nieder
2019-07-17 16:03           ` Junio C Hamano
2019-07-19  1:15             ` Jonathan Nieder
2019-07-17  1:09         ` Bryan Turner
2019-07-17 16:05           ` Junio C Hamano
2019-07-16 18:00       ` [PATCH v2] transport-helper: enforce atomic in push_refs_with_push Carlo Arenas
2019-07-16 20:28       ` [PATCH] transport-helper: avoid var decl in for () loop control Junio C Hamano
2019-07-17  0:42         ` Jonathan Nieder
2019-07-18 15:22       ` [PATCH v2] transport-helper: enforce atomic in push_refs_with_push SZEDER Gábor
2019-07-18 16:12         ` Junio C Hamano
2019-07-18 23:46           ` SZEDER Gábor
2019-07-18 16:29         ` Eric Sunshine
2019-07-19  1:31         ` Jonathan Nieder
2019-07-19  4:49           ` Carlo Arenas
2019-07-19 19:15             ` Junio C Hamano
2019-07-27  8:43         ` SZEDER Gábor
2019-07-27 16:11           ` Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).