All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH 3/7] push: beginning of compare-and-swap "force/delete safety"
Date: Tue,  9 Jul 2013 12:53:26 -0700	[thread overview]
Message-ID: <1373399610-8588-4-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1373399610-8588-1-git-send-email-gitster@pobox.com>

This teaches the deepest part of the callchain for "git push" (and
"git send-pack") to optionally allow "the old value of the ref must
be this, otherwise fail this push" we discussed earlier.

Nobody sets the new "expect_old_sha1" and "expect_old_no_trackback"
bitfields yet, so this is still a no-op.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/send-pack.c |  5 +++++
 remote.c            | 21 +++++++++++++++++++--
 remote.h            |  4 ++++
 send-pack.c         |  1 +
 transport-helper.c  |  6 ++++++
 transport.c         |  5 +++++
 6 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index e86d3b5..c86c556 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -55,6 +55,11 @@ static void print_helper_status(struct ref *ref)
 			msg = "needs force";
 			break;
 
+		case REF_STATUS_REJECT_STALE:
+			res = "error";
+			msg = "stale info";
+			break;
+
 		case REF_STATUS_REJECT_ALREADY_EXISTS:
 			res = "error";
 			msg = "already exists";
diff --git a/remote.c b/remote.c
index b1ff7a2..81bc876 100644
--- a/remote.c
+++ b/remote.c
@@ -1416,13 +1416,30 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
 		}
 
 		/*
+		 * If we know what the old value of the remote ref
+		 * should be, reject any push, even forced ones,
+		 * if they do not match.
+		 *
+		 * It also is an error if the user told us to check
+		 * with the remote-tracking branch to find the value
+		 * to expect, but we did not have such a tracking
+		 * branch.
+		 */
+		if (ref->expect_old_sha1 &&
+		    (ref->expect_old_no_trackback ||
+		     hashcmp(ref->old_sha1, ref->old_sha1_expect))) {
+			ref->status = REF_STATUS_REJECT_STALE;
+			continue;
+		}
+
+		/*
 		 * Decide whether an individual refspec A:B can be
 		 * pushed.  The push will succeed if any of the
 		 * following are true:
 		 *
-		 * (1) the remote reference B does not exist
+		 * (1) the remote reference B does not exist (i.e. create)
 		 *
-		 * (2) the remote reference B is being removed (i.e.,
+		 * (2) the remote reference B is being removed (i.e. delete;
 		 *     pushing :B where no source is specified)
 		 *
 		 * (3) the destination is not under refs/tags/, and
diff --git a/remote.h b/remote.h
index a850059..7ad37e6 100644
--- a/remote.h
+++ b/remote.h
@@ -75,10 +75,13 @@ struct ref {
 	struct ref *next;
 	unsigned char old_sha1[20];
 	unsigned char new_sha1[20];
+	unsigned char old_sha1_expect[20]; /* used by expect-old */
 	char *symref;
 	unsigned int
 		force:1,
 		forced_update:1,
+		expect_old_sha1:1,
+		expect_old_no_trackback:1,
 		deletion:1,
 		matched:1;
 
@@ -102,6 +105,7 @@ struct ref {
 		REF_STATUS_REJECT_NODELETE,
 		REF_STATUS_REJECT_FETCH_FIRST,
 		REF_STATUS_REJECT_NEEDS_FORCE,
+		REF_STATUS_REJECT_STALE,
 		REF_STATUS_UPTODATE,
 		REF_STATUS_REMOTE_REJECT,
 		REF_STATUS_EXPECTING_REPORT
diff --git a/send-pack.c b/send-pack.c
index 9a9908c..b228d65 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -227,6 +227,7 @@ int send_pack(struct send_pack_args *args,
 		case REF_STATUS_REJECT_ALREADY_EXISTS:
 		case REF_STATUS_REJECT_FETCH_FIRST:
 		case REF_STATUS_REJECT_NEEDS_FORCE:
+		case REF_STATUS_REJECT_STALE:
 		case REF_STATUS_UPTODATE:
 			continue;
 		default:
diff --git a/transport-helper.c b/transport-helper.c
index db9bd18..95d22f8 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -683,6 +683,11 @@ static int push_update_ref_status(struct strbuf *buf,
 			free(msg);
 			msg = NULL;
 		}
+		else if (!strcmp(msg, "stale info")) {
+			status = REF_STATUS_REJECT_STALE;
+			free(msg);
+			msg = NULL;
+		}
 	}
 
 	if (*ref)
@@ -756,6 +761,7 @@ static int push_refs_with_push(struct transport *transport,
 		/* Check for statuses set by set_ref_status_for_push() */
 		switch (ref->status) {
 		case REF_STATUS_REJECT_NONFASTFORWARD:
+		case REF_STATUS_REJECT_STALE:
 		case REF_STATUS_REJECT_ALREADY_EXISTS:
 		case REF_STATUS_UPTODATE:
 			continue;
diff --git a/transport.c b/transport.c
index b84dbf0..98f5270 100644
--- a/transport.c
+++ b/transport.c
@@ -709,6 +709,10 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
 		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 						 "needs force", porcelain);
 		break;
+	case REF_STATUS_REJECT_STALE:
+		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
+						 "stale info", porcelain);
+		break;
 	case REF_STATUS_REMOTE_REJECT:
 		print_ref_status('!', "[remote rejected]", ref,
 						 ref->deletion ? NULL : ref->peer_ref,
@@ -1078,6 +1082,7 @@ static int run_pre_push_hook(struct transport *transport,
 	for (r = remote_refs; r; r = r->next) {
 		if (!r->peer_ref) continue;
 		if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue;
+		if (r->status == REF_STATUS_REJECT_STALE) continue;
 		if (r->status == REF_STATUS_UPTODATE) continue;
 
 		strbuf_reset(&buf);
-- 
1.8.3.2-875-g76c723c

  parent reply	other threads:[~2013-07-09 19:53 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-02 20:57 [RFD] Making "git push [--force/--delete]" safer? Junio C Hamano
2013-07-02 22:55 ` Johan Herland
2013-07-03  6:34   ` Johan Herland
2013-07-03  8:49     ` Junio C Hamano
2013-07-03 10:00       ` Johan Herland
2013-07-03 10:06         ` Jonathan del Strother
2013-07-03 10:11           ` Johan Herland
2013-07-03 10:50             ` Michael Haggerty
2013-07-03 12:06               ` Johannes Sixt
2013-07-03 19:53                 ` Junio C Hamano
2013-07-04  5:37                   ` Johannes Sixt
2013-07-04  5:46                     ` Junio C Hamano
2013-07-03 19:50           ` Junio C Hamano
2013-07-03 20:18             ` Junio C Hamano
2013-07-03 19:48         ` Junio C Hamano
2013-07-09 19:53 ` [PATCH 0/7] safer "push --force" with compare-and-swap Junio C Hamano
2013-07-09 19:53   ` [PATCH 1/7] cache.h: move remote/connect API out of it Junio C Hamano
2013-07-09 19:53   ` [PATCH 2/7] builtin/push.c: use OPT_BOOL, not OPT_BOOLEAN Junio C Hamano
2013-07-09 19:53   ` Junio C Hamano [this message]
2013-07-09 19:53   ` [PATCH 4/7] remote.c: add command line option parser for --lockref Junio C Hamano
2013-07-16 22:13     ` John Keeping
2013-07-17 17:06       ` Junio C Hamano
2013-07-17 17:09       ` Junio C Hamano
2013-07-09 19:53   ` [PATCH 5/7] push --lockref: implement logic to populate old_sha1_expect[] Junio C Hamano
2013-07-09 19:53   ` [PATCH 6/7] t5533: test "push --lockref" Junio C Hamano
2013-07-09 19:53   ` [PATCH 7/7] push: document --lockref Junio C Hamano
2013-07-09 20:17     ` Aaron Schrab
2013-07-09 20:39       ` Junio C Hamano
2013-07-09 20:24     ` Johannes Sixt
2013-07-09 20:37       ` Junio C Hamano
2013-07-09 20:55         ` Johannes Sixt
2013-07-09 22:09           ` Junio C Hamano
2013-07-09 23:08             ` Junio C Hamano
2013-07-11 21:10               ` Johannes Sixt
2013-07-11 21:57                 ` Junio C Hamano
2013-07-11 22:14                 ` Junio C Hamano
2013-07-12 17:21                   ` Johannes Sixt
2013-07-12 17:40                     ` Junio C Hamano
2013-07-12 20:00                       ` Johannes Sixt
2013-07-12 21:19                         ` Junio C Hamano
2013-07-13  6:52                           ` Johannes Sixt
2013-07-13 18:14                             ` Junio C Hamano
2013-07-13 20:08                               ` Junio C Hamano
2013-07-13 21:11                                 ` Johannes Sixt
2013-07-14 14:28                                 ` John Keeping
2013-07-13 20:17                               ` Johannes Sixt
2013-07-14 19:17                                 ` Junio C Hamano
2013-07-14 20:21                                   ` Johannes Sixt
2013-07-14 20:34                                     ` Jonathan Nieder
2013-07-14 20:49                                       ` Jonathan Nieder
2013-07-14 20:59                                       ` Johannes Sixt
2013-07-14 21:28                                         ` Jonathan Nieder
2013-07-15  4:10                                           ` Junio C Hamano
2013-07-15  4:44                                             ` Jonathan Nieder
2013-07-15 15:37                                               ` Junio C Hamano
2013-07-15 20:30                                         ` Johannes Sixt
2013-07-15  3:50                                     ` Junio C Hamano
2013-07-15 15:47                                       ` Default expectation of --lockref Junio C Hamano
2013-07-15 20:27                                       ` [PATCH 7/7] push: document --lockref Johannes Sixt
2013-07-09 21:37         ` Marc Branchaud
2013-07-09 20:27     ` Michael Haggerty
2013-07-09 20:42       ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1373399610-8588-4-git-send-email-gitster@pobox.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.