From: Jonathan Tan <jonathantanmy@google.com>
To: git@vger.kernel.org
Cc: Jonathan Tan <jonathantanmy@google.com>
Subject: [PATCH 3/4] remote-curl: teach --base for http(s)://
Date: Mon, 2 Nov 2020 16:26:12 -0800 [thread overview]
Message-ID: <d0a996f77689a12a52b192599fd5e6d27192a648.1604362701.git.jonathantanmy@google.com> (raw)
In-Reply-To: <cover.1604362701.git.jonathantanmy@google.com>
For the http(s):// transports, teach push the "--base" parameter, which
indicates an ancestor of the commits to be pushed that is believed to be
known by the server.
This is done through a new remote helper capability and option
"push-base". If a remote helper advertises this capability, then it also
supports the option of the same name. Git can then use this option to
inform the remote helper of a base that the user has specified.
See the commit message of this commit's parent for more information.
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
Documentation/gitremote-helpers.txt | 8 ++++++++
remote-curl.c | 25 +++++++++++++++++-------
t/t5700-protocol-v1.sh | 30 +++++++++++++++++++++++++++++
transport-helper.c | 15 +++++++++++++++
4 files changed, 71 insertions(+), 7 deletions(-)
diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt
index 6f1e269ae4..b4eff16a59 100644
--- a/Documentation/gitremote-helpers.txt
+++ b/Documentation/gitremote-helpers.txt
@@ -116,6 +116,9 @@ Supported commands: 'stateless-connect'.
+
Supported commands: 'list for-push', 'push'.
+'push-base'::
+ Indicates that this remote helper supports the 'push-base' option.
+
'export'::
Can discover remote refs and push specified objects from a
fast-import stream to remote refs.
@@ -541,6 +544,11 @@ set by Git if the remote helper has the 'option' capability.
If set to an algorithm, indicate that the caller wants to interact with
the remote side using that algorithm.
+'option push-base' <ref>::
+ Only supported if this remote helper advertises the 'push-base'
+ capability. Indicate that <ref> is an ancestor of the commits to be
+ pushed, and it is believed to be known by the server.
+
SEE ALSO
--------
linkgit:git-remote[1]
diff --git a/remote-curl.c b/remote-curl.c
index 32cc4a0c55..7919e4ebcf 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -29,6 +29,7 @@ struct options {
struct string_list deepen_not;
struct string_list push_options;
char *filter;
+ struct object_id push_base;
unsigned progress : 1,
check_self_contained_and_connected : 1,
cloning : 1,
@@ -205,6 +206,10 @@ static int set_option(const char *name, const char *value)
options.hash_algo = &hash_algos[algo];
}
return 0;
+ } else if (!strcmp(name, "push-base")) {
+ if (get_oid(value, &options.push_base))
+ die(_("%s is not a valid object"), value);
+ return 0;
} else {
return 1 /* unsupported */;
}
@@ -364,16 +369,21 @@ static int show_http_message(struct strbuf *type, struct strbuf *charset,
}
static int get_protocol_http_header(enum protocol_version version,
+ const struct object_id *base,
struct strbuf *header)
{
- if (version > 0) {
+ if (version > 0)
strbuf_addf(header, GIT_PROTOCOL_HEADER ": version=%d",
version);
-
- return 1;
+ if (!is_null_oid(base)) {
+ if (version > 0)
+ strbuf_addch(header, ':');
+ else
+ strbuf_addstr(header, GIT_PROTOCOL_HEADER ": ");
+ strbuf_addf(header, "base=%s", oid_to_hex(base));
}
- return 0;
+ return !!(version > 0 || !(is_null_oid(base)));
}
static void check_smart_http(struct discovery *d, const char *service,
@@ -469,7 +479,7 @@ static struct discovery *discover_refs(const char *service, int for_push)
version = protocol_v0;
/* Add the extra Git-Protocol header */
- if (get_protocol_http_header(version, &protocol_header))
+ if (get_protocol_http_header(version, &options.push_base, &protocol_header))
string_list_append(&extra_headers, protocol_header.buf);
memset(&http_options, 0, sizeof(http_options));
@@ -1074,7 +1084,7 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads,
strbuf_addf(&buf, "Accept: application/x-%s-result", svc);
rpc->hdr_accept = strbuf_detach(&buf, NULL);
- if (get_protocol_http_header(heads->version, &buf))
+ if (get_protocol_http_header(heads->version, &options.push_base, &buf))
rpc->protocol_header = strbuf_detach(&buf, NULL);
else
rpc->protocol_header = NULL;
@@ -1406,7 +1416,7 @@ static int stateless_connect(const char *service_name)
rpc.service_url = xstrfmt("%s%s", url.buf, rpc.service_name);
rpc.hdr_content_type = xstrfmt("Content-Type: application/x-%s-request", rpc.service_name);
rpc.hdr_accept = xstrfmt("Accept: application/x-%s-result", rpc.service_name);
- if (get_protocol_http_header(discover->version, &buf)) {
+ if (get_protocol_http_header(discover->version, &options.push_base, &buf)) {
rpc.protocol_header = strbuf_detach(&buf, NULL);
} else {
rpc.protocol_header = NULL;
@@ -1538,6 +1548,7 @@ int cmd_main(int argc, const char **argv)
printf("push\n");
printf("check-connectivity\n");
printf("object-format\n");
+ printf("push-base\n");
printf("\n");
fflush(stdout);
} else if (skip_prefix(buf.buf, "stateless-connect ", &arg)) {
diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh
index 22459d37f5..4ee29c1be0 100755
--- a/t/t5700-protocol-v1.sh
+++ b/t/t5700-protocol-v1.sh
@@ -373,6 +373,36 @@ test_expect_success 'push with http:// using protocol v1' '
grep "git< version 1" log
'
+test_expect_success 'push with http:// using protocol v1 and --base' '
+ test_commit -C http_child four &&
+ COMMON_HASH=$(git -C http_child rev-parse three) &&
+
+ # Push to another branch, as the target repository has the
+ # master branch checked out and we cannot push into it.
+ GIT_TRACE_PACKET=1 test_might_fail git -C http_child -c protocol.version=1 \
+ push --base=three origin HEAD:client_branch_four 2>log &&
+
+ # Server responded using protocol v1
+ grep "git< version 1" log &&
+ # Server advertised only the expected object
+ grep "$COMMON_HASH .have" log
+'
+
+test_expect_success 'push with http:// using protocol v0 and --base' '
+ test_commit -C http_child five &&
+ COMMON_HASH=$(git -C http_child rev-parse four) &&
+
+ # Push to another branch, as the target repository has the
+ # master branch checked out and we cannot push into it.
+ GIT_TRACE_PACKET=1 git -C http_child -c protocol.version=0 \
+ push --base=four origin HEAD:client_branch_five 2>log &&
+
+ # Server did not respond with any version
+ ! grep "git< version" log &&
+ # Server advertised only the expected object
+ grep "$COMMON_HASH .have" log
+'
+
# DO NOT add non-httpd-specific tests here, because the last part of this
# test script is only executed when httpd is available and enabled.
diff --git a/transport-helper.c b/transport-helper.c
index b573b6c730..15d9527419 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -27,6 +27,7 @@ struct helper_data {
export : 1,
option : 1,
push : 1,
+ push_base : 1,
connect : 1,
stateless_connect : 1,
signed_tags : 1,
@@ -186,6 +187,8 @@ static struct child_process *get_helper(struct transport *transport)
data->option = 1;
else if (!strcmp(capname, "push"))
data->push = 1;
+ else if (!strcmp(capname, "push-base"))
+ data->push_base = 1;
else if (!strcmp(capname, "import"))
data->import = 1;
else if (!strcmp(capname, "bidi-import"))
@@ -1183,6 +1186,18 @@ static struct ref *get_refs_list_using_list(struct transport *transport,
exit(128);
}
+ if (!is_null_oid(&data->transport_options.push_base)) {
+ if (data->push_base) {
+ write_str_in_full(helper->in, "option push-base ");
+ write_str_in_full(helper->in, oid_to_hex(&data->transport_options.push_base));
+ write_str_in_full(helper->in, "\n");
+ if (recvline(data, &buf) || strcmp(buf.buf, "ok"))
+ exit(128);
+ } else {
+ warning(_("transport does not support --base"));
+ }
+ }
+
if (data->push && for_push)
write_str_in_full(helper->in, "list for-push\n");
else
--
2.29.1.341.ge80a0c044ae-goog
next prev parent reply other threads:[~2020-11-03 0:27 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-03 0:26 [PATCH 0/4] "Push" protocol change proposal: user-specified base Jonathan Tan
2020-11-03 0:26 ` [PATCH 1/4] connect: refactor building of Extra Parameters Jonathan Tan
2020-11-03 0:26 ` [PATCH 2/4] push: teach --base for ssh:// and file:// Jonathan Tan
2020-11-03 10:23 ` SZEDER Gábor
2020-11-08 19:31 ` Junio C Hamano
2020-11-03 13:57 ` Derrick Stolee
2020-11-08 19:30 ` Junio C Hamano
2020-11-03 0:26 ` Jonathan Tan [this message]
2020-11-03 1:13 ` [PATCH 3/4] remote-curl: teach --base for http(s):// Junio C Hamano
2020-11-03 0:26 ` [PATCH 4/4] Doc: push with --base Jonathan Tan
2020-11-03 5:35 ` Jonathan Nieder
2020-11-03 15:18 ` Jeff King
2020-11-03 17:35 ` Junio C Hamano
2020-11-09 19:56 ` Jonathan Tan
2020-11-09 21:00 ` Derrick Stolee
2020-11-09 22:22 ` Jonathan Tan
2020-11-09 21:20 ` Junio C Hamano
2020-11-09 21:40 ` Jeff King
2020-11-09 22:47 ` Jonathan Tan
2020-11-03 13:53 ` Derrick Stolee
2020-11-03 0:46 ` [PATCH 0/4] "Push" protocol change proposal: user-specified base 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=d0a996f77689a12a52b192599fd5e6d27192a648.1604362701.git.jonathantanmy@google.com \
--to=jonathantanmy@google.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 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 NNTP newsgroup(s).