git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 0/2] Supporting partial clones in protocol v2
@ 2018-05-01 22:22 Jonathan Tan
  2018-05-01 22:22 ` [PATCH 1/2] upload-pack: fix error message typo Jonathan Tan
                   ` (9 more replies)
  0 siblings, 10 replies; 20+ messages in thread
From: Jonathan Tan @ 2018-05-01 22:22 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan

This patch set is built on "next". (I had to build it on "next" because
bw/protocol-v2 is built on v2.16, which does not have support for
partial clones.)

Partial clones and protocol v2 were built independently, so here is a
patch to support partial clones in protocol v2.

One thing I am a little unhappy about is the fact that the upload-pack
config has to be read in multiple places, but perhaps there is no choice
about that.

Jonathan Tan (2):
  upload-pack: fix error message typo
  {fetch,upload}-pack: support filter in protocol v2

 Documentation/technical/protocol-v2.txt |  9 +++
 fetch-pack.c                            | 23 +++++-
 t/t5701-git-serve.sh                    | 15 ++++
 t/t5702-protocol-v2.sh                  | 97 +++++++++++++++++++++++++
 upload-pack.c                           | 14 +++-
 5 files changed, 151 insertions(+), 7 deletions(-)

-- 
2.17.0.441.gb46fe60e1d-goog


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

* [PATCH 1/2] upload-pack: fix error message typo
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
@ 2018-05-01 22:22 ` Jonathan Tan
  2018-05-01 22:25   ` Jonathan Tan
  2018-05-01 22:22 ` [PATCH 2/2] {fetch,upload}-pack: support filter in protocol v2 Jonathan Tan
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Jonathan Tan @ 2018-05-01 22:22 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan

Fix a typo in an error message.

Also, this line was introduced in 3145ea957d2c ("upload-pack: introduce
fetch server command", 2018-03-15), which did not contain a test for the
case which causes this error to be printed, so introduce a test.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 t/t5701-git-serve.sh | 15 +++++++++++++++
 upload-pack.c        |  2 +-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh
index 72d7bc562..abbe5b19e 100755
--- a/t/t5701-git-serve.sh
+++ b/t/t5701-git-serve.sh
@@ -173,4 +173,19 @@ test_expect_success 'symrefs parameter' '
 	test_cmp actual expect
 '
 
+test_expect_success 'unexpected lines are not allowed in fetch request' '
+	git init server &&
+
+	# Custom request that tries to filter even though it is not advertised.
+	test-pkt-line pack >in <<-EOF &&
+	command=fetch
+	0001
+	this-is-not-a-command
+	0000
+	EOF
+
+	test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err &&
+	grep "unexpected line: .this-is-not-a-command." err
+'
+
 test_done
diff --git a/upload-pack.c b/upload-pack.c
index 87b4d32a6..c4456bb88 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1252,7 +1252,7 @@ static void process_args(struct packet_reader *request,
 		}
 
 		/* ignore unknown lines maybe? */
-		die("unexpect line: '%s'", arg);
+		die("unexpected line: '%s'", arg);
 	}
 }
 
-- 
2.17.0.441.gb46fe60e1d-goog


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

* [PATCH 2/2] {fetch,upload}-pack: support filter in protocol v2
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
  2018-05-01 22:22 ` [PATCH 1/2] upload-pack: fix error message typo Jonathan Tan
@ 2018-05-01 22:22 ` Jonathan Tan
  2018-05-01 22:36   ` Brandon Williams
  2018-05-02  0:31 ` [PATCH v2 0/3] Supporting partial clones " Jonathan Tan
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Jonathan Tan @ 2018-05-01 22:22 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan

The fetch-pack/upload-pack protocol v2 was developed independently of
the filter parameter (used in partial fetches), thus it did not include
support for it. Add support for the filter parameter.

Like in the legacy protocol, the server advertises and supports "filter"
only if uploadpack.allowfilter is configured.

Like in the legacy protocol, the client continues with a warning if
"--filter" is specified, but the server does not advertise it.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 Documentation/technical/protocol-v2.txt |  9 +++
 fetch-pack.c                            | 23 +++++-
 t/t5702-protocol-v2.sh                  | 97 +++++++++++++++++++++++++
 upload-pack.c                           | 12 ++-
 4 files changed, 135 insertions(+), 6 deletions(-)

diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt
index 136179d7d..38d24fd2b 100644
--- a/Documentation/technical/protocol-v2.txt
+++ b/Documentation/technical/protocol-v2.txt
@@ -290,6 +290,15 @@ included in the clients request as well as the potential addition of the
 	Cannot be used with "deepen", but can be used with
 	"deepen-since".
 
+If the 'filter' feature is advertised, the following argument can be
+included in the client's request:
+
+    filter <filter-spec>
+	Request that various objects from the packfile be omitted
+	using one of several filtering techniques. These are intended
+	for use with partial clone and partial fetch operations. See
+	`rev-list` for possible "filter-spec" values.
+
 The response of `fetch` is broken into a number of sections separated by
 delimiter packets (0001), with each section beginning with its section
 header.
diff --git a/fetch-pack.c b/fetch-pack.c
index f93723fec..3ed40aa46 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1191,14 +1191,29 @@ static int send_fetch_request(int fd_out, const struct fetch_pack_args *args,
 	else if (is_repository_shallow() || args->deepen)
 		die(_("Server does not support shallow requests"));
 
+	/* Add filter */
+	if (server_supports_feature("fetch", "filter", 0) &&
+	    args->filter_options.choice) {
+		print_verbose(args, _("Server supports filter"));
+		packet_buf_write(&req_buf, "filter %s",
+				 args->filter_options.filter_spec);
+	} else if (args->filter_options.choice) {
+		warning("filtering not recognized by server, ignoring");
+	}
+
 	/* add wants */
 	add_wants(wants, &req_buf);
 
-	/* Add all of the common commits we've found in previous rounds */
-	add_common(&req_buf, common);
+	if (args->no_dependents) {
+		packet_buf_write(&req_buf, "done");
+		ret = 1;
+	} else {
+		/* Add all of the common commits we've found in previous rounds */
+		add_common(&req_buf, common);
 
-	/* Add initial haves */
-	ret = add_haves(&req_buf, haves_to_send, in_vain);
+		/* Add initial haves */
+		ret = add_haves(&req_buf, haves_to_send, in_vain);
+	}
 
 	/* Send request */
 	packet_buf_flush(&req_buf);
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 56f7c3c32..834ccc6f2 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -201,6 +201,103 @@ test_expect_success 'ref advertisment is filtered during fetch using protocol v2
 	! grep "refs/tags/three" log
 '
 
+test_expect_success 'setup filter tests' '
+	git init server &&
+
+	# 1 commit to create a file, and 1 commit to modify it
+	test_commit -C server message1 a.txt &&
+	test_commit -C server message2 a.txt &&
+	git -C server config protocol.version 2 &&
+	git -C server config uploadpack.allowfilter 1 &&
+	git -C server config uploadpack.allowanysha1inwant 1 &&
+	git -C server config protocol.version 2
+'
+
+test_expect_success 'partial clone' '
+	GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 \
+		clone --filter=blob:none "file://$(pwd)/server" client &&
+	grep "version 2" trace &&
+
+	# Ensure that the old version of the file is missing
+	git -C client rev-list master --quiet --objects --missing=print \
+		>observed.oids &&
+	grep "$(git -C server rev-parse message1:a.txt)" observed.oids &&
+
+	# Ensure that client passes fsck
+	git -C client fsck
+'
+
+test_expect_success 'dynamically fetch missing object' '
+	rm "$(pwd)/trace" &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
+		cat-file -p $(git -C server rev-parse message1:a.txt) &&
+	grep "version 2" trace
+'
+
+test_expect_success 'partial fetch' '
+	rm -rf client "$(pwd)/trace" &&
+	git init client &&
+	SERVER="file://$(pwd)/server" &&
+	test_config -C client extensions.partialClone "$SERVER" &&
+
+	GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
+		fetch --filter=blob:none "$SERVER" master:refs/heads/other &&
+	grep "version 2" trace &&
+
+	# Ensure that the old version of the file is missing
+	git -C client rev-list other --quiet --objects --missing=print \
+		>observed.oids &&
+	grep "$(git -C server rev-parse message1:a.txt)" observed.oids &&
+
+	# Ensure that client passes fsck
+	git -C client fsck
+'
+
+test_expect_success 'do not advertise filter if not configured to do so' '
+	SERVER="file://$(pwd)/server" &&
+
+	rm "$(pwd)/trace" &&
+	git -C server config uploadpack.allowfilter 1 &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 \
+		ls-remote "$SERVER" &&
+	grep "fetch=.*filter" trace &&
+
+	rm "$(pwd)/trace" &&
+	git -C server config uploadpack.allowfilter 0 &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 \
+		ls-remote "$SERVER" &&
+	grep "fetch=" trace >fetch_capabilities &&
+	! grep filter fetch_capabilities
+'
+
+test_expect_success 'partial clone warns if filter is not advertised' '
+	rm -rf client &&
+	git -C server config uploadpack.allowfilter 0 &&
+	git -c protocol.version=2 \
+		clone --filter=blob:none "file://$(pwd)/server" client 2>err &&
+	test_i18ngrep "filtering not recognized by server, ignoring" err
+'
+
+test_expect_success 'even with handcrafted request, filter does not work if not advertised' '
+	git -C server config uploadpack.allowfilter 0 &&
+
+	# Custom request that tries to filter even though it is not advertised.
+	test-pkt-line pack >in <<-EOF &&
+	command=fetch
+	0001
+	want $(git -C server rev-parse master)
+	filter blob:none
+	0000
+	EOF
+
+	test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err &&
+	grep "unexpected line: .filter blob:none." err &&
+
+	# Exercise to ensure that if advertised, filter works
+	git -C server config uploadpack.allowfilter 1 &&
+	git -C server serve --stateless-rpc <in >/dev/null
+'
+
 # Test protocol v2 with 'http://' transport
 #
 . "$TEST_DIRECTORY"/lib-httpd.sh
diff --git a/upload-pack.c b/upload-pack.c
index c4456bb88..3872fa518 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1205,6 +1205,7 @@ static void process_args(struct packet_reader *request,
 {
 	while (packet_reader_read(request) != PACKET_READ_FLUSH) {
 		const char *arg = request->line;
+		const char *p;
 
 		/* process want */
 		if (parse_want(arg))
@@ -1251,6 +1252,11 @@ static void process_args(struct packet_reader *request,
 			continue;
 		}
 
+		if (allow_filter && skip_prefix(arg, "filter ", &p)) {
+			parse_list_objects_filter(&filter_options, p);
+			continue;
+		}
+
 		/* ignore unknown lines maybe? */
 		die("unexpected line: '%s'", arg);
 	}
@@ -1428,7 +1434,9 @@ int upload_pack_v2(struct repository *r, struct argv_array *keys,
 int upload_pack_advertise(struct repository *r,
 			  struct strbuf *value)
 {
-	if (value)
-		strbuf_addstr(value, "shallow");
+	git_config(upload_pack_config, NULL);
+	if (value) {
+		strbuf_addf(value, "%sshallow", allow_filter ? "filter " : "");
+	}
 	return 1;
 }
-- 
2.17.0.441.gb46fe60e1d-goog


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

* Re: [PATCH 1/2] upload-pack: fix error message typo
  2018-05-01 22:22 ` [PATCH 1/2] upload-pack: fix error message typo Jonathan Tan
@ 2018-05-01 22:25   ` Jonathan Tan
  0 siblings, 0 replies; 20+ messages in thread
From: Jonathan Tan @ 2018-05-01 22:25 UTC (permalink / raw)
  To: Jonathan Tan; +Cc: git

On Tue,  1 May 2018 15:22:20 -0700
Jonathan Tan <jonathantanmy@google.com> wrote:

> +test_expect_success 'unexpected lines are not allowed in fetch request' '
> +	git init server &&
> +
> +	# Custom request that tries to filter even though it is not advertised.

Oops...I saw this copy-and-paste error right after I sent the e-mails.
I'll remove this in the next reroll (if there is one).

> +	test-pkt-line pack >in <<-EOF &&
> +	command=fetch
> +	0001
> +	this-is-not-a-command
> +	0000
> +	EOF
> +
> +	test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err &&
> +	grep "unexpected line: .this-is-not-a-command." err
> +'

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

* Re: [PATCH 2/2] {fetch,upload}-pack: support filter in protocol v2
  2018-05-01 22:22 ` [PATCH 2/2] {fetch,upload}-pack: support filter in protocol v2 Jonathan Tan
@ 2018-05-01 22:36   ` Brandon Williams
  0 siblings, 0 replies; 20+ messages in thread
From: Brandon Williams @ 2018-05-01 22:36 UTC (permalink / raw)
  To: Jonathan Tan; +Cc: git

On 05/01, Jonathan Tan wrote:
> The fetch-pack/upload-pack protocol v2 was developed independently of
> the filter parameter (used in partial fetches), thus it did not include
> support for it. Add support for the filter parameter.
> 
> Like in the legacy protocol, the server advertises and supports "filter"
> only if uploadpack.allowfilter is configured.
> 
> Like in the legacy protocol, the client continues with a warning if
> "--filter" is specified, but the server does not advertise it.
> 
> Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
> ---
>  Documentation/technical/protocol-v2.txt |  9 +++
>  fetch-pack.c                            | 23 +++++-
>  t/t5702-protocol-v2.sh                  | 97 +++++++++++++++++++++++++
>  upload-pack.c                           | 12 ++-
>  4 files changed, 135 insertions(+), 6 deletions(-)
> 

> @@ -1428,7 +1434,9 @@ int upload_pack_v2(struct repository *r, struct argv_array *keys,
>  int upload_pack_advertise(struct repository *r,
>  			  struct strbuf *value)
>  {
> -	if (value)
> -		strbuf_addstr(value, "shallow");
> +	git_config(upload_pack_config, NULL);
> +	if (value) {
> +		strbuf_addf(value, "%sshallow", allow_filter ? "filter " : "");
> +	}

This is a bit difficult to read and there is no reason why we would need
to read the entire upload_pack_config to determine if we need to filter
things (we will need to read the config if cmd "fetch" is requested
though).  Instead it may be better to do the following:

  if (value) {
    strbuf_addstr(value, "shallow");
    if (repo_config_get(r, "uplaodpack.filter"))
      strbuf_addstr(value, " filter");
  }

This way its easier to read and you only are reading the required value
from the config.

>  	return 1;
>  }
> -- 
> 2.17.0.441.gb46fe60e1d-goog
> 

-- 
Brandon Williams

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

* [PATCH v2 0/3] Supporting partial clones in protocol v2
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
  2018-05-01 22:22 ` [PATCH 1/2] upload-pack: fix error message typo Jonathan Tan
  2018-05-01 22:22 ` [PATCH 2/2] {fetch,upload}-pack: support filter in protocol v2 Jonathan Tan
@ 2018-05-02  0:31 ` Jonathan Tan
  2018-05-02  0:31 ` [PATCH v2 1/3] upload-pack: fix error message typo Jonathan Tan
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Jonathan Tan @ 2018-05-02  0:31 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan, bmwill

> This is a bit difficult to read and there is no reason why we would need
> to read the entire upload_pack_config to determine if we need to filter
> things (we will need to read the config if cmd "fetch" is requested
> though).  Instead it may be better to do the following:
> 
>   if (value) {
>     strbuf_addstr(value, "shallow");
>     if (repo_config_get(r, "uplaodpack.filter"))
>       strbuf_addstr(value, " filter");
>   }
> 
> This way its easier to read and you only are reading the required value
> from the config.

Thanks, Brandon. I went ahead and used repo_config_get_bool(), and
indeed it works.

Removing the call to git_config() from there exposed another issue in
that configs were not read if upload-pack was used with protocol v2, so
I inserted a patch in the middle addressing that. While writing that
patch, I noticed that uploadpack.packobjectshook couldn't take filenames
with spaces, which I think is due to prepare_shell_cmd() in
run-command.c not quoting properly. Adding single quotes around "%s"
worked, but made other tests fail. Instead of continuing down that
rabbit hole, I just made the uploadpack.packobjectshook not have any
spaces, just like in t5544.

Jonathan Tan (3):
  upload-pack: fix error message typo
  upload-pack: read config when serving protocol v2
  {fetch,upload}-pack: support filter in protocol v2

 Documentation/technical/protocol-v2.txt |   9 ++
 fetch-pack.c                            |  23 ++++-
 t/t5701-git-serve.sh                    |  14 +++
 t/t5702-protocol-v2.sh                  | 112 ++++++++++++++++++++++++
 upload-pack.c                           |  19 +++-
 5 files changed, 171 insertions(+), 6 deletions(-)

-- 
2.17.0.441.gb46fe60e1d-goog


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

* [PATCH v2 1/3] upload-pack: fix error message typo
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
                   ` (2 preceding siblings ...)
  2018-05-02  0:31 ` [PATCH v2 0/3] Supporting partial clones " Jonathan Tan
@ 2018-05-02  0:31 ` Jonathan Tan
  2018-05-03 18:58   ` Stefan Beller
  2018-05-02  0:31 ` [PATCH v2 2/3] upload-pack: read config when serving protocol v2 Jonathan Tan
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Jonathan Tan @ 2018-05-02  0:31 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan, bmwill

Fix a typo in an error message.

Also, this line was introduced in 3145ea957d2c ("upload-pack: introduce
fetch server command", 2018-03-15), which did not contain a test for the
case which causes this error to be printed, so introduce a test.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 t/t5701-git-serve.sh | 14 ++++++++++++++
 upload-pack.c        |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh
index 72d7bc562..1b4b13cc2 100755
--- a/t/t5701-git-serve.sh
+++ b/t/t5701-git-serve.sh
@@ -173,4 +173,18 @@ test_expect_success 'symrefs parameter' '
 	test_cmp actual expect
 '
 
+test_expect_success 'unexpected lines are not allowed in fetch request' '
+	git init server &&
+
+	test-pkt-line pack >in <<-EOF &&
+	command=fetch
+	0001
+	this-is-not-a-command
+	0000
+	EOF
+
+	test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err &&
+	grep "unexpected line: .this-is-not-a-command." err
+'
+
 test_done
diff --git a/upload-pack.c b/upload-pack.c
index 87b4d32a6..c4456bb88 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1252,7 +1252,7 @@ static void process_args(struct packet_reader *request,
 		}
 
 		/* ignore unknown lines maybe? */
-		die("unexpect line: '%s'", arg);
+		die("unexpected line: '%s'", arg);
 	}
 }
 
-- 
2.17.0.441.gb46fe60e1d-goog


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

* [PATCH v2 2/3] upload-pack: read config when serving protocol v2
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
                   ` (3 preceding siblings ...)
  2018-05-02  0:31 ` [PATCH v2 1/3] upload-pack: fix error message typo Jonathan Tan
@ 2018-05-02  0:31 ` Jonathan Tan
  2018-05-03 19:08   ` Stefan Beller
  2018-05-02  0:31 ` [PATCH v2 3/3] {fetch,upload}-pack: support filter in " Jonathan Tan
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Jonathan Tan @ 2018-05-02  0:31 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan, bmwill

The upload-pack code paths never call git_config() with
upload_pack_config() when protocol v2 is used, causing options like
uploadpack.packobjectshook to not take effect. Ensure that this function
is called.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 t/t5702-protocol-v2.sh | 14 ++++++++++++++
 upload-pack.c          |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 56f7c3c32..0ead99993 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -201,6 +201,20 @@ test_expect_success 'ref advertisment is filtered during fetch using protocol v2
 	! grep "refs/tags/three" log
 '
 
+test_expect_success 'upload-pack respects config using protocol v2' '
+	git init server &&
+	write_script server/.git/hook <<-\EOF &&
+		touch hookout
+		"$@"
+	EOF
+	test_commit -C server one &&
+
+	test_config_global uploadpack.packobjectshook ./hook &&
+	test ! -f server/.git/hookout &&
+	GIT_TRACE=/tmp/y git -c protocol.version=2 clone "file://$(pwd)/server" client &&
+	test -f server/.git/hookout
+'
+
 # Test protocol v2 with 'http://' transport
 #
 . "$TEST_DIRECTORY"/lib-httpd.sh
diff --git a/upload-pack.c b/upload-pack.c
index c4456bb88..113edd32d 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1376,6 +1376,8 @@ int upload_pack_v2(struct repository *r, struct argv_array *keys,
 	enum fetch_state state = FETCH_PROCESS_ARGS;
 	struct upload_pack_data data;
 
+	git_config(upload_pack_config, NULL);
+
 	upload_pack_data_init(&data);
 	use_sideband = LARGE_PACKET_MAX;
 
-- 
2.17.0.441.gb46fe60e1d-goog


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

* [PATCH v2 3/3] {fetch,upload}-pack: support filter in protocol v2
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
                   ` (4 preceding siblings ...)
  2018-05-02  0:31 ` [PATCH v2 2/3] upload-pack: read config when serving protocol v2 Jonathan Tan
@ 2018-05-02  0:31 ` Jonathan Tan
  2018-05-03 20:15   ` Stefan Beller
  2018-05-03 23:46 ` [PATCH v3 0/3] Supporting partial clones " Jonathan Tan
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Jonathan Tan @ 2018-05-02  0:31 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan, bmwill

The fetch-pack/upload-pack protocol v2 was developed independently of
the filter parameter (used in partial fetches), thus it did not include
support for it. Add support for the filter parameter.

Like in the legacy protocol, the server advertises and supports "filter"
only if uploadpack.allowfilter is configured.

Like in the legacy protocol, the client continues with a warning if
"--filter" is specified, but the server does not advertise it.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 Documentation/technical/protocol-v2.txt |  9 +++
 fetch-pack.c                            | 23 +++++-
 t/t5702-protocol-v2.sh                  | 98 +++++++++++++++++++++++++
 upload-pack.c                           | 15 +++-
 4 files changed, 140 insertions(+), 5 deletions(-)

diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt
index 136179d7d..38d24fd2b 100644
--- a/Documentation/technical/protocol-v2.txt
+++ b/Documentation/technical/protocol-v2.txt
@@ -290,6 +290,15 @@ included in the clients request as well as the potential addition of the
 	Cannot be used with "deepen", but can be used with
 	"deepen-since".
 
+If the 'filter' feature is advertised, the following argument can be
+included in the client's request:
+
+    filter <filter-spec>
+	Request that various objects from the packfile be omitted
+	using one of several filtering techniques. These are intended
+	for use with partial clone and partial fetch operations. See
+	`rev-list` for possible "filter-spec" values.
+
 The response of `fetch` is broken into a number of sections separated by
 delimiter packets (0001), with each section beginning with its section
 header.
diff --git a/fetch-pack.c b/fetch-pack.c
index f93723fec..3ed40aa46 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1191,14 +1191,29 @@ static int send_fetch_request(int fd_out, const struct fetch_pack_args *args,
 	else if (is_repository_shallow() || args->deepen)
 		die(_("Server does not support shallow requests"));
 
+	/* Add filter */
+	if (server_supports_feature("fetch", "filter", 0) &&
+	    args->filter_options.choice) {
+		print_verbose(args, _("Server supports filter"));
+		packet_buf_write(&req_buf, "filter %s",
+				 args->filter_options.filter_spec);
+	} else if (args->filter_options.choice) {
+		warning("filtering not recognized by server, ignoring");
+	}
+
 	/* add wants */
 	add_wants(wants, &req_buf);
 
-	/* Add all of the common commits we've found in previous rounds */
-	add_common(&req_buf, common);
+	if (args->no_dependents) {
+		packet_buf_write(&req_buf, "done");
+		ret = 1;
+	} else {
+		/* Add all of the common commits we've found in previous rounds */
+		add_common(&req_buf, common);
 
-	/* Add initial haves */
-	ret = add_haves(&req_buf, haves_to_send, in_vain);
+		/* Add initial haves */
+		ret = add_haves(&req_buf, haves_to_send, in_vain);
+	}
 
 	/* Send request */
 	packet_buf_flush(&req_buf);
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 0ead99993..858d3bb2d 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -215,6 +215,104 @@ test_expect_success 'upload-pack respects config using protocol v2' '
 	test -f server/.git/hookout
 '
 
+test_expect_success 'setup filter tests' '
+	rm -rf server client &&
+	git init server &&
+
+	# 1 commit to create a file, and 1 commit to modify it
+	test_commit -C server message1 a.txt &&
+	test_commit -C server message2 a.txt &&
+	git -C server config protocol.version 2 &&
+	git -C server config uploadpack.allowfilter 1 &&
+	git -C server config uploadpack.allowanysha1inwant 1 &&
+	git -C server config protocol.version 2
+'
+
+test_expect_success 'partial clone' '
+	GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 \
+		clone --filter=blob:none "file://$(pwd)/server" client &&
+	grep "version 2" trace &&
+
+	# Ensure that the old version of the file is missing
+	git -C client rev-list master --quiet --objects --missing=print \
+		>observed.oids &&
+	grep "$(git -C server rev-parse message1:a.txt)" observed.oids &&
+
+	# Ensure that client passes fsck
+	git -C client fsck
+'
+
+test_expect_success 'dynamically fetch missing object' '
+	rm "$(pwd)/trace" &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
+		cat-file -p $(git -C server rev-parse message1:a.txt) &&
+	grep "version 2" trace
+'
+
+test_expect_success 'partial fetch' '
+	rm -rf client "$(pwd)/trace" &&
+	git init client &&
+	SERVER="file://$(pwd)/server" &&
+	test_config -C client extensions.partialClone "$SERVER" &&
+
+	GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
+		fetch --filter=blob:none "$SERVER" master:refs/heads/other &&
+	grep "version 2" trace &&
+
+	# Ensure that the old version of the file is missing
+	git -C client rev-list other --quiet --objects --missing=print \
+		>observed.oids &&
+	grep "$(git -C server rev-parse message1:a.txt)" observed.oids &&
+
+	# Ensure that client passes fsck
+	git -C client fsck
+'
+
+test_expect_success 'do not advertise filter if not configured to do so' '
+	SERVER="file://$(pwd)/server" &&
+
+	rm "$(pwd)/trace" &&
+	git -C server config uploadpack.allowfilter 1 &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 \
+		ls-remote "$SERVER" &&
+	grep "fetch=.*filter" trace &&
+
+	rm "$(pwd)/trace" &&
+	git -C server config uploadpack.allowfilter 0 &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 \
+		ls-remote "$SERVER" &&
+	grep "fetch=" trace >fetch_capabilities &&
+	! grep filter fetch_capabilities
+'
+
+test_expect_success 'partial clone warns if filter is not advertised' '
+	rm -rf client &&
+	git -C server config uploadpack.allowfilter 0 &&
+	git -c protocol.version=2 \
+		clone --filter=blob:none "file://$(pwd)/server" client 2>err &&
+	test_i18ngrep "filtering not recognized by server, ignoring" err
+'
+
+test_expect_success 'even with handcrafted request, filter does not work if not advertised' '
+	git -C server config uploadpack.allowfilter 0 &&
+
+	# Custom request that tries to filter even though it is not advertised.
+	test-pkt-line pack >in <<-EOF &&
+	command=fetch
+	0001
+	want $(git -C server rev-parse master)
+	filter blob:none
+	0000
+	EOF
+
+	test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err &&
+	grep "unexpected line: .filter blob:none." err &&
+
+	# Exercise to ensure that if advertised, filter works
+	git -C server config uploadpack.allowfilter 1 &&
+	git -C server serve --stateless-rpc <in >/dev/null
+'
+
 # Test protocol v2 with 'http://' transport
 #
 . "$TEST_DIRECTORY"/lib-httpd.sh
diff --git a/upload-pack.c b/upload-pack.c
index 113edd32d..82c16cae3 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1205,6 +1205,7 @@ static void process_args(struct packet_reader *request,
 {
 	while (packet_reader_read(request) != PACKET_READ_FLUSH) {
 		const char *arg = request->line;
+		const char *p;
 
 		/* process want */
 		if (parse_want(arg))
@@ -1251,6 +1252,11 @@ static void process_args(struct packet_reader *request,
 			continue;
 		}
 
+		if (allow_filter && skip_prefix(arg, "filter ", &p)) {
+			parse_list_objects_filter(&filter_options, p);
+			continue;
+		}
+
 		/* ignore unknown lines maybe? */
 		die("unexpected line: '%s'", arg);
 	}
@@ -1430,7 +1436,14 @@ int upload_pack_v2(struct repository *r, struct argv_array *keys,
 int upload_pack_advertise(struct repository *r,
 			  struct strbuf *value)
 {
-	if (value)
+	if (value) {
+		int allow_filter_value;
 		strbuf_addstr(value, "shallow");
+		if (!repo_config_get_bool(the_repository,
+					 "uploadpack.allowfilter",
+					 &allow_filter_value) &&
+		    allow_filter_value)
+			strbuf_addstr(value, " filter");
+	}
 	return 1;
 }
-- 
2.17.0.441.gb46fe60e1d-goog


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

* Re: [PATCH v2 1/3] upload-pack: fix error message typo
  2018-05-02  0:31 ` [PATCH v2 1/3] upload-pack: fix error message typo Jonathan Tan
@ 2018-05-03 18:58   ` Stefan Beller
  2018-05-03 23:41     ` Jonathan Tan
  0 siblings, 1 reply; 20+ messages in thread
From: Stefan Beller @ 2018-05-03 18:58 UTC (permalink / raw)
  To: Jonathan Tan; +Cc: git, Brandon Williams

On Tue, May 1, 2018 at 5:31 PM, Jonathan Tan <jonathantanmy@google.com> wrote:
> Fix a typo in an error message.
>
> Also, this line was introduced in 3145ea957d2c ("upload-pack: introduce
> fetch server command", 2018-03-15), which did not contain a test for the
> case which causes this error to be printed, so introduce a test.
>
> Signed-off-by: Jonathan Tan <jonathantanmy@google.com>

This is Reviewed-by: Stefan Beller <sbeller@google.com>

> ---
>  t/t5701-git-serve.sh | 14 ++++++++++++++
>  upload-pack.c        |  2 +-
>  2 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh
> index 72d7bc562..1b4b13cc2 100755
> --- a/t/t5701-git-serve.sh
> +++ b/t/t5701-git-serve.sh
> @@ -173,4 +173,18 @@ test_expect_success 'symrefs parameter' '
>         test_cmp actual expect
>  '
>
> +test_expect_success 'unexpected lines are not allowed in fetch request' '
> +       git init server &&
> +
> +       test-pkt-line pack >in <<-EOF &&
> +       command=fetch
> +       0001
> +       this-is-not-a-command
> +       0000
> +       EOF
> +
> +       test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err &&

Minor nit:
Why do we pipe stdout to /dev/null ?

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

* Re: [PATCH v2 2/3] upload-pack: read config when serving protocol v2
  2018-05-02  0:31 ` [PATCH v2 2/3] upload-pack: read config when serving protocol v2 Jonathan Tan
@ 2018-05-03 19:08   ` Stefan Beller
  2018-05-03 23:45     ` Jonathan Tan
  0 siblings, 1 reply; 20+ messages in thread
From: Stefan Beller @ 2018-05-03 19:08 UTC (permalink / raw)
  To: Jonathan Tan; +Cc: git, Brandon Williams

On Tue, May 1, 2018 at 5:31 PM, Jonathan Tan <jonathantanmy@google.com> wrote:
> The upload-pack code paths never call git_config() with
> upload_pack_config() when protocol v2 is used, causing options like
> uploadpack.packobjectshook to not take effect. Ensure that this function
> is called.
>
> Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
> ---
>  t/t5702-protocol-v2.sh | 14 ++++++++++++++
>  upload-pack.c          |  2 ++
>  2 files changed, 16 insertions(+)
>
> diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
> index 56f7c3c32..0ead99993 100755
> --- a/t/t5702-protocol-v2.sh
> +++ b/t/t5702-protocol-v2.sh
> @@ -201,6 +201,20 @@ test_expect_success 'ref advertisment is filtered during fetch using protocol v2
>         ! grep "refs/tags/three" log
>  '
>
> +test_expect_success 'upload-pack respects config using protocol v2' '
> +       git init server &&
> +       write_script server/.git/hook <<-\EOF &&
> +               touch hookout
> +               "$@"
> +       EOF
> +       test_commit -C server one &&
> +
> +       test_config_global uploadpack.packobjectshook ./hook &&
> +       test ! -f server/.git/hookout &&

test_path_is_missing ?


> +       GIT_TRACE=/tmp/y git -c protocol.version=2 clone "file://$(pwd)/server" client &&

Why do we redirect GIT_TRACE outside the test suite? do we read that
back or want to read it out of the hook?

Is it possible to redirect to  /$(pwd)/trace or such?

> +       test -f server/.git/hookout

test_path_is_file ?


> +'
> +
>  # Test protocol v2 with 'http://' transport
>  #
>  . "$TEST_DIRECTORY"/lib-httpd.sh
> diff --git a/upload-pack.c b/upload-pack.c
> index c4456bb88..113edd32d 100644
> --- a/upload-pack.c
> +++ b/upload-pack.c
> @@ -1376,6 +1376,8 @@ int upload_pack_v2(struct repository *r, struct argv_array *keys,
>         enum fetch_state state = FETCH_PROCESS_ARGS;
>         struct upload_pack_data data;
>
> +       git_config(upload_pack_config, NULL);
> +
>         upload_pack_data_init(&data);
>         use_sideband = LARGE_PACKET_MAX;
>
> --
> 2.17.0.441.gb46fe60e1d-goog
>

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

* Re: [PATCH v2 3/3] {fetch,upload}-pack: support filter in protocol v2
  2018-05-02  0:31 ` [PATCH v2 3/3] {fetch,upload}-pack: support filter in " Jonathan Tan
@ 2018-05-03 20:15   ` Stefan Beller
  0 siblings, 0 replies; 20+ messages in thread
From: Stefan Beller @ 2018-05-03 20:15 UTC (permalink / raw)
  To: Jonathan Tan; +Cc: git, Brandon Williams

Hi Jonathan,

On Tue, May 1, 2018 at 5:31 PM, Jonathan Tan <jonathantanmy@google.com> wrote:
> The fetch-pack/upload-pack protocol v2 was developed independently of
> the filter parameter (used in partial fetches), thus it did not include
> support for it. Add support for the filter parameter.
>
> Like in the legacy protocol, the server advertises and supports "filter"
> only if uploadpack.allowfilter is configured.
>
> Like in the legacy protocol, the client continues with a warning if
> "--filter" is specified, but the server does not advertise it.
>
> Signed-off-by: Jonathan Tan <jonathantanmy@google.com>

The whole series looks good,

Thanks,
Stefan

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

* Re: [PATCH v2 1/3] upload-pack: fix error message typo
  2018-05-03 18:58   ` Stefan Beller
@ 2018-05-03 23:41     ` Jonathan Tan
  2018-05-04  2:24       ` Junio C Hamano
  0 siblings, 1 reply; 20+ messages in thread
From: Jonathan Tan @ 2018-05-03 23:41 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, Brandon Williams

On Thu, 3 May 2018 11:58:59 -0700
Stefan Beller <sbeller@google.com> wrote:

> > +       test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err &&
> 
> Minor nit:
> Why do we pipe stdout to /dev/null ?

Usually there's a binary packfile produced, but not in this case. I'll
remove it.

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

* Re: [PATCH v2 2/3] upload-pack: read config when serving protocol v2
  2018-05-03 19:08   ` Stefan Beller
@ 2018-05-03 23:45     ` Jonathan Tan
  0 siblings, 0 replies; 20+ messages in thread
From: Jonathan Tan @ 2018-05-03 23:45 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git, Brandon Williams

On Thu, 3 May 2018 12:08:16 -0700
Stefan Beller <sbeller@google.com> wrote:

> test_path_is_missing ?

Thanks for the pointer. Done.

> > +       GIT_TRACE=/tmp/y git -c protocol.version=2 clone "file://$(pwd)/server" client &&
> 
> Why do we redirect GIT_TRACE outside the test suite? do we read that
> back or want to read it out of the hook?
> 
> Is it possible to redirect to  /$(pwd)/trace or such?

Good catch - that was a leftover from debugging. I've just removed it.

> > +       test -f server/.git/hookout
> 
> test_path_is_file ?

Done.

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

* [PATCH v3 0/3] Supporting partial clones in protocol v2
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
                   ` (5 preceding siblings ...)
  2018-05-02  0:31 ` [PATCH v2 3/3] {fetch,upload}-pack: support filter in " Jonathan Tan
@ 2018-05-03 23:46 ` Jonathan Tan
  2018-05-03 23:46 ` [PATCH v3 1/3] upload-pack: fix error message typo Jonathan Tan
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Jonathan Tan @ 2018-05-03 23:46 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan, sbeller

Changes from v2: followed all Stefan's comments.

Jonathan Tan (3):
  upload-pack: fix error message typo
  upload-pack: read config when serving protocol v2
  {fetch,upload}-pack: support filter in protocol v2

 Documentation/technical/protocol-v2.txt |   9 ++
 fetch-pack.c                            |  23 ++++-
 t/t5701-git-serve.sh                    |  14 +++
 t/t5702-protocol-v2.sh                  | 112 ++++++++++++++++++++++++
 upload-pack.c                           |  19 +++-
 5 files changed, 171 insertions(+), 6 deletions(-)

-- 
2.17.0.441.gb46fe60e1d-goog


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

* [PATCH v3 1/3] upload-pack: fix error message typo
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
                   ` (6 preceding siblings ...)
  2018-05-03 23:46 ` [PATCH v3 0/3] Supporting partial clones " Jonathan Tan
@ 2018-05-03 23:46 ` Jonathan Tan
  2018-05-03 23:46 ` [PATCH v3 2/3] upload-pack: read config when serving protocol v2 Jonathan Tan
  2018-05-03 23:46 ` [PATCH v3 3/3] {fetch,upload}-pack: support filter in " Jonathan Tan
  9 siblings, 0 replies; 20+ messages in thread
From: Jonathan Tan @ 2018-05-03 23:46 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan, sbeller

Fix a typo in an error message.

Also, this line was introduced in 3145ea957d2c ("upload-pack: introduce
fetch server command", 2018-03-15), which did not contain a test for the
case which causes this error to be printed, so introduce a test.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 t/t5701-git-serve.sh | 14 ++++++++++++++
 upload-pack.c        |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh
index 72d7bc562..6439f7792 100755
--- a/t/t5701-git-serve.sh
+++ b/t/t5701-git-serve.sh
@@ -173,4 +173,18 @@ test_expect_success 'symrefs parameter' '
 	test_cmp actual expect
 '
 
+test_expect_success 'unexpected lines are not allowed in fetch request' '
+	git init server &&
+
+	test-pkt-line pack >in <<-EOF &&
+	command=fetch
+	0001
+	this-is-not-a-command
+	0000
+	EOF
+
+	test_must_fail git -C server serve --stateless-rpc <in 2>err &&
+	grep "unexpected line: .this-is-not-a-command." err
+'
+
 test_done
diff --git a/upload-pack.c b/upload-pack.c
index 87b4d32a6..c4456bb88 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1252,7 +1252,7 @@ static void process_args(struct packet_reader *request,
 		}
 
 		/* ignore unknown lines maybe? */
-		die("unexpect line: '%s'", arg);
+		die("unexpected line: '%s'", arg);
 	}
 }
 
-- 
2.17.0.441.gb46fe60e1d-goog


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

* [PATCH v3 2/3] upload-pack: read config when serving protocol v2
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
                   ` (7 preceding siblings ...)
  2018-05-03 23:46 ` [PATCH v3 1/3] upload-pack: fix error message typo Jonathan Tan
@ 2018-05-03 23:46 ` Jonathan Tan
  2018-05-03 23:46 ` [PATCH v3 3/3] {fetch,upload}-pack: support filter in " Jonathan Tan
  9 siblings, 0 replies; 20+ messages in thread
From: Jonathan Tan @ 2018-05-03 23:46 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan, sbeller

The upload-pack code paths never call git_config() with
upload_pack_config() when protocol v2 is used, causing options like
uploadpack.packobjectshook to not take effect. Ensure that this function
is called.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 t/t5702-protocol-v2.sh | 14 ++++++++++++++
 upload-pack.c          |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 56f7c3c32..abb15cd6d 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -201,6 +201,20 @@ test_expect_success 'ref advertisment is filtered during fetch using protocol v2
 	! grep "refs/tags/three" log
 '
 
+test_expect_success 'upload-pack respects config using protocol v2' '
+	git init server &&
+	write_script server/.git/hook <<-\EOF &&
+		touch hookout
+		"$@"
+	EOF
+	test_commit -C server one &&
+
+	test_config_global uploadpack.packobjectshook ./hook &&
+	test_path_is_missing server/.git/hookout &&
+	git -c protocol.version=2 clone "file://$(pwd)/server" client &&
+	test_path_is_file server/.git/hookout
+'
+
 # Test protocol v2 with 'http://' transport
 #
 . "$TEST_DIRECTORY"/lib-httpd.sh
diff --git a/upload-pack.c b/upload-pack.c
index c4456bb88..113edd32d 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1376,6 +1376,8 @@ int upload_pack_v2(struct repository *r, struct argv_array *keys,
 	enum fetch_state state = FETCH_PROCESS_ARGS;
 	struct upload_pack_data data;
 
+	git_config(upload_pack_config, NULL);
+
 	upload_pack_data_init(&data);
 	use_sideband = LARGE_PACKET_MAX;
 
-- 
2.17.0.441.gb46fe60e1d-goog


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

* [PATCH v3 3/3] {fetch,upload}-pack: support filter in protocol v2
  2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
                   ` (8 preceding siblings ...)
  2018-05-03 23:46 ` [PATCH v3 2/3] upload-pack: read config when serving protocol v2 Jonathan Tan
@ 2018-05-03 23:46 ` Jonathan Tan
  9 siblings, 0 replies; 20+ messages in thread
From: Jonathan Tan @ 2018-05-03 23:46 UTC (permalink / raw)
  To: git; +Cc: Jonathan Tan, sbeller

The fetch-pack/upload-pack protocol v2 was developed independently of
the filter parameter (used in partial fetches), thus it did not include
support for it. Add support for the filter parameter.

Like in the legacy protocol, the server advertises and supports "filter"
only if uploadpack.allowfilter is configured.

Like in the legacy protocol, the client continues with a warning if
"--filter" is specified, but the server does not advertise it.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 Documentation/technical/protocol-v2.txt |  9 +++
 fetch-pack.c                            | 23 +++++-
 t/t5702-protocol-v2.sh                  | 98 +++++++++++++++++++++++++
 upload-pack.c                           | 15 +++-
 4 files changed, 140 insertions(+), 5 deletions(-)

diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt
index 136179d7d..38d24fd2b 100644
--- a/Documentation/technical/protocol-v2.txt
+++ b/Documentation/technical/protocol-v2.txt
@@ -290,6 +290,15 @@ included in the clients request as well as the potential addition of the
 	Cannot be used with "deepen", but can be used with
 	"deepen-since".
 
+If the 'filter' feature is advertised, the following argument can be
+included in the client's request:
+
+    filter <filter-spec>
+	Request that various objects from the packfile be omitted
+	using one of several filtering techniques. These are intended
+	for use with partial clone and partial fetch operations. See
+	`rev-list` for possible "filter-spec" values.
+
 The response of `fetch` is broken into a number of sections separated by
 delimiter packets (0001), with each section beginning with its section
 header.
diff --git a/fetch-pack.c b/fetch-pack.c
index f93723fec..3ed40aa46 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1191,14 +1191,29 @@ static int send_fetch_request(int fd_out, const struct fetch_pack_args *args,
 	else if (is_repository_shallow() || args->deepen)
 		die(_("Server does not support shallow requests"));
 
+	/* Add filter */
+	if (server_supports_feature("fetch", "filter", 0) &&
+	    args->filter_options.choice) {
+		print_verbose(args, _("Server supports filter"));
+		packet_buf_write(&req_buf, "filter %s",
+				 args->filter_options.filter_spec);
+	} else if (args->filter_options.choice) {
+		warning("filtering not recognized by server, ignoring");
+	}
+
 	/* add wants */
 	add_wants(wants, &req_buf);
 
-	/* Add all of the common commits we've found in previous rounds */
-	add_common(&req_buf, common);
+	if (args->no_dependents) {
+		packet_buf_write(&req_buf, "done");
+		ret = 1;
+	} else {
+		/* Add all of the common commits we've found in previous rounds */
+		add_common(&req_buf, common);
 
-	/* Add initial haves */
-	ret = add_haves(&req_buf, haves_to_send, in_vain);
+		/* Add initial haves */
+		ret = add_haves(&req_buf, haves_to_send, in_vain);
+	}
 
 	/* Send request */
 	packet_buf_flush(&req_buf);
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index abb15cd6d..25bf046b3 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -215,6 +215,104 @@ test_expect_success 'upload-pack respects config using protocol v2' '
 	test_path_is_file server/.git/hookout
 '
 
+test_expect_success 'setup filter tests' '
+	rm -rf server client &&
+	git init server &&
+
+	# 1 commit to create a file, and 1 commit to modify it
+	test_commit -C server message1 a.txt &&
+	test_commit -C server message2 a.txt &&
+	git -C server config protocol.version 2 &&
+	git -C server config uploadpack.allowfilter 1 &&
+	git -C server config uploadpack.allowanysha1inwant 1 &&
+	git -C server config protocol.version 2
+'
+
+test_expect_success 'partial clone' '
+	GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 \
+		clone --filter=blob:none "file://$(pwd)/server" client &&
+	grep "version 2" trace &&
+
+	# Ensure that the old version of the file is missing
+	git -C client rev-list master --quiet --objects --missing=print \
+		>observed.oids &&
+	grep "$(git -C server rev-parse message1:a.txt)" observed.oids &&
+
+	# Ensure that client passes fsck
+	git -C client fsck
+'
+
+test_expect_success 'dynamically fetch missing object' '
+	rm "$(pwd)/trace" &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
+		cat-file -p $(git -C server rev-parse message1:a.txt) &&
+	grep "version 2" trace
+'
+
+test_expect_success 'partial fetch' '
+	rm -rf client "$(pwd)/trace" &&
+	git init client &&
+	SERVER="file://$(pwd)/server" &&
+	test_config -C client extensions.partialClone "$SERVER" &&
+
+	GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
+		fetch --filter=blob:none "$SERVER" master:refs/heads/other &&
+	grep "version 2" trace &&
+
+	# Ensure that the old version of the file is missing
+	git -C client rev-list other --quiet --objects --missing=print \
+		>observed.oids &&
+	grep "$(git -C server rev-parse message1:a.txt)" observed.oids &&
+
+	# Ensure that client passes fsck
+	git -C client fsck
+'
+
+test_expect_success 'do not advertise filter if not configured to do so' '
+	SERVER="file://$(pwd)/server" &&
+
+	rm "$(pwd)/trace" &&
+	git -C server config uploadpack.allowfilter 1 &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 \
+		ls-remote "$SERVER" &&
+	grep "fetch=.*filter" trace &&
+
+	rm "$(pwd)/trace" &&
+	git -C server config uploadpack.allowfilter 0 &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -c protocol.version=2 \
+		ls-remote "$SERVER" &&
+	grep "fetch=" trace >fetch_capabilities &&
+	! grep filter fetch_capabilities
+'
+
+test_expect_success 'partial clone warns if filter is not advertised' '
+	rm -rf client &&
+	git -C server config uploadpack.allowfilter 0 &&
+	git -c protocol.version=2 \
+		clone --filter=blob:none "file://$(pwd)/server" client 2>err &&
+	test_i18ngrep "filtering not recognized by server, ignoring" err
+'
+
+test_expect_success 'even with handcrafted request, filter does not work if not advertised' '
+	git -C server config uploadpack.allowfilter 0 &&
+
+	# Custom request that tries to filter even though it is not advertised.
+	test-pkt-line pack >in <<-EOF &&
+	command=fetch
+	0001
+	want $(git -C server rev-parse master)
+	filter blob:none
+	0000
+	EOF
+
+	test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err &&
+	grep "unexpected line: .filter blob:none." err &&
+
+	# Exercise to ensure that if advertised, filter works
+	git -C server config uploadpack.allowfilter 1 &&
+	git -C server serve --stateless-rpc <in >/dev/null
+'
+
 # Test protocol v2 with 'http://' transport
 #
 . "$TEST_DIRECTORY"/lib-httpd.sh
diff --git a/upload-pack.c b/upload-pack.c
index 113edd32d..82c16cae3 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1205,6 +1205,7 @@ static void process_args(struct packet_reader *request,
 {
 	while (packet_reader_read(request) != PACKET_READ_FLUSH) {
 		const char *arg = request->line;
+		const char *p;
 
 		/* process want */
 		if (parse_want(arg))
@@ -1251,6 +1252,11 @@ static void process_args(struct packet_reader *request,
 			continue;
 		}
 
+		if (allow_filter && skip_prefix(arg, "filter ", &p)) {
+			parse_list_objects_filter(&filter_options, p);
+			continue;
+		}
+
 		/* ignore unknown lines maybe? */
 		die("unexpected line: '%s'", arg);
 	}
@@ -1430,7 +1436,14 @@ int upload_pack_v2(struct repository *r, struct argv_array *keys,
 int upload_pack_advertise(struct repository *r,
 			  struct strbuf *value)
 {
-	if (value)
+	if (value) {
+		int allow_filter_value;
 		strbuf_addstr(value, "shallow");
+		if (!repo_config_get_bool(the_repository,
+					 "uploadpack.allowfilter",
+					 &allow_filter_value) &&
+		    allow_filter_value)
+			strbuf_addstr(value, " filter");
+	}
 	return 1;
 }
-- 
2.17.0.441.gb46fe60e1d-goog


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

* Re: [PATCH v2 1/3] upload-pack: fix error message typo
  2018-05-03 23:41     ` Jonathan Tan
@ 2018-05-04  2:24       ` Junio C Hamano
  2018-05-04 16:10         ` Jonathan Tan
  0 siblings, 1 reply; 20+ messages in thread
From: Junio C Hamano @ 2018-05-04  2:24 UTC (permalink / raw)
  To: Jonathan Tan; +Cc: Stefan Beller, git, Brandon Williams

Jonathan Tan <jonathantanmy@google.com> writes:

> On Thu, 3 May 2018 11:58:59 -0700
> Stefan Beller <sbeller@google.com> wrote:
>
>> > +       test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err &&
>> 
>> Minor nit:
>> Why do we pipe stdout to /dev/null ?
>
> Usually there's a binary packfile produced, but not in this case. I'll
> remove it.

Hmm, when somebody breaks "git server serve", we probably would not
want to see the binary spewed to the output while debugging it.  So
I'd probably keep the redirection---it may be an improvement to use
">out" and then checking it is empty after the expected failure.

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

* Re: [PATCH v2 1/3] upload-pack: fix error message typo
  2018-05-04  2:24       ` Junio C Hamano
@ 2018-05-04 16:10         ` Jonathan Tan
  0 siblings, 0 replies; 20+ messages in thread
From: Jonathan Tan @ 2018-05-04 16:10 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Stefan Beller, git, Brandon Williams

On Fri, 04 May 2018 11:24:39 +0900
Junio C Hamano <gitster@pobox.com> wrote:

> Hmm, when somebody breaks "git server serve", we probably would not
> want to see the binary spewed to the output while debugging it.  So
> I'd probably keep the redirection---it may be an improvement to use
> ">out" and then checking it is empty after the expected failure.

That's a good point - I've readded the redirection in my local copy.
I'll send out the new version if needed.

I checked the other patches and patch 3 has a similar situation but
still has the >/dev/null because I forgot to remove it when I removed it
in patch 1, so nothing needs to be changed in patch 3.

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

end of thread, other threads:[~2018-05-04 16:10 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-01 22:22 [PATCH 0/2] Supporting partial clones in protocol v2 Jonathan Tan
2018-05-01 22:22 ` [PATCH 1/2] upload-pack: fix error message typo Jonathan Tan
2018-05-01 22:25   ` Jonathan Tan
2018-05-01 22:22 ` [PATCH 2/2] {fetch,upload}-pack: support filter in protocol v2 Jonathan Tan
2018-05-01 22:36   ` Brandon Williams
2018-05-02  0:31 ` [PATCH v2 0/3] Supporting partial clones " Jonathan Tan
2018-05-02  0:31 ` [PATCH v2 1/3] upload-pack: fix error message typo Jonathan Tan
2018-05-03 18:58   ` Stefan Beller
2018-05-03 23:41     ` Jonathan Tan
2018-05-04  2:24       ` Junio C Hamano
2018-05-04 16:10         ` Jonathan Tan
2018-05-02  0:31 ` [PATCH v2 2/3] upload-pack: read config when serving protocol v2 Jonathan Tan
2018-05-03 19:08   ` Stefan Beller
2018-05-03 23:45     ` Jonathan Tan
2018-05-02  0:31 ` [PATCH v2 3/3] {fetch,upload}-pack: support filter in " Jonathan Tan
2018-05-03 20:15   ` Stefan Beller
2018-05-03 23:46 ` [PATCH v3 0/3] Supporting partial clones " Jonathan Tan
2018-05-03 23:46 ` [PATCH v3 1/3] upload-pack: fix error message typo Jonathan Tan
2018-05-03 23:46 ` [PATCH v3 2/3] upload-pack: read config when serving protocol v2 Jonathan Tan
2018-05-03 23:46 ` [PATCH v3 3/3] {fetch,upload}-pack: support filter in " Jonathan Tan

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).