mirror of
https://github.com/git/git
synced 2024-11-05 18:59:29 +00:00
upload-pack: add object filtering for partial clone
Teach upload-pack to negotiate object filtering over the protocol and to send filter parameters to pack-objects. This is intended for partial clone and fetch. The idea to make upload-pack configurable using uploadpack.allowFilter comes from Jonathan Tan's work in [1]. [1] https://public-inbox.org/git/f211093280b422c32cc1b7034130072f35c5ed51.1506714999.git.jonathantanmy@google.com/ Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
0c16cd499d
commit
10ac85c785
4 changed files with 45 additions and 1 deletions
|
@ -3268,6 +3268,10 @@ uploadpack.packObjectsHook::
|
||||||
was run. I.e., `upload-pack` will feed input intended for
|
was run. I.e., `upload-pack` will feed input intended for
|
||||||
`pack-objects` to the hook, and expects a completed packfile on
|
`pack-objects` to the hook, and expects a completed packfile on
|
||||||
stdout.
|
stdout.
|
||||||
|
|
||||||
|
uploadpack.allowFilter::
|
||||||
|
If this option is set, `upload-pack` will advertise partial
|
||||||
|
clone and partial fetch object filtering.
|
||||||
+
|
+
|
||||||
Note that this configuration variable is ignored if it is seen in the
|
Note that this configuration variable is ignored if it is seen in the
|
||||||
repository-level config (this is a safety measure against fetching from
|
repository-level config (this is a safety measure against fetching from
|
||||||
|
|
|
@ -212,6 +212,7 @@ out of what the server said it could do with the first 'want' line.
|
||||||
upload-request = want-list
|
upload-request = want-list
|
||||||
*shallow-line
|
*shallow-line
|
||||||
*1depth-request
|
*1depth-request
|
||||||
|
[filter-request]
|
||||||
flush-pkt
|
flush-pkt
|
||||||
|
|
||||||
want-list = first-want
|
want-list = first-want
|
||||||
|
@ -227,6 +228,8 @@ out of what the server said it could do with the first 'want' line.
|
||||||
additional-want = PKT-LINE("want" SP obj-id)
|
additional-want = PKT-LINE("want" SP obj-id)
|
||||||
|
|
||||||
depth = 1*DIGIT
|
depth = 1*DIGIT
|
||||||
|
|
||||||
|
filter-request = PKT-LINE("filter" SP filter-spec)
|
||||||
----
|
----
|
||||||
|
|
||||||
Clients MUST send all the obj-ids it wants from the reference
|
Clients MUST send all the obj-ids it wants from the reference
|
||||||
|
@ -249,6 +252,11 @@ complete those commits. Commits whose parents are not received as a
|
||||||
result are defined as shallow and marked as such in the server. This
|
result are defined as shallow and marked as such in the server. This
|
||||||
information is sent back to the client in the next step.
|
information is sent back to the client in the next step.
|
||||||
|
|
||||||
|
The client can optionally request that pack-objects omit various
|
||||||
|
objects from the packfile 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.
|
||||||
|
|
||||||
Once all the 'want's and 'shallow's (and optional 'deepen') are
|
Once all the 'want's and 'shallow's (and optional 'deepen') are
|
||||||
transferred, clients MUST send a flush-pkt, to tell the server side
|
transferred, clients MUST send a flush-pkt, to tell the server side
|
||||||
that it is done sending the list.
|
that it is done sending the list.
|
||||||
|
|
|
@ -309,3 +309,11 @@ to accept a signed push certificate, and asks the <nonce> to be
|
||||||
included in the push certificate. A send-pack client MUST NOT
|
included in the push certificate. A send-pack client MUST NOT
|
||||||
send a push-cert packet unless the receive-pack server advertises
|
send a push-cert packet unless the receive-pack server advertises
|
||||||
this capability.
|
this capability.
|
||||||
|
|
||||||
|
filter
|
||||||
|
------
|
||||||
|
|
||||||
|
If the upload-pack server advertises the 'filter' capability,
|
||||||
|
fetch-pack may send "filter" commands to request a partial clone
|
||||||
|
or partial fetch and request that the server omit various objects
|
||||||
|
from the packfile.
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "diff.h"
|
#include "diff.h"
|
||||||
#include "revision.h"
|
#include "revision.h"
|
||||||
#include "list-objects.h"
|
#include "list-objects.h"
|
||||||
|
#include "list-objects-filter.h"
|
||||||
|
#include "list-objects-filter-options.h"
|
||||||
#include "run-command.h"
|
#include "run-command.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "sigchain.h"
|
#include "sigchain.h"
|
||||||
|
@ -18,6 +20,7 @@
|
||||||
#include "parse-options.h"
|
#include "parse-options.h"
|
||||||
#include "argv-array.h"
|
#include "argv-array.h"
|
||||||
#include "prio-queue.h"
|
#include "prio-queue.h"
|
||||||
|
#include "quote.h"
|
||||||
|
|
||||||
static const char * const upload_pack_usage[] = {
|
static const char * const upload_pack_usage[] = {
|
||||||
N_("git upload-pack [<options>] <dir>"),
|
N_("git upload-pack [<options>] <dir>"),
|
||||||
|
@ -64,6 +67,10 @@ static int advertise_refs;
|
||||||
static int stateless_rpc;
|
static int stateless_rpc;
|
||||||
static const char *pack_objects_hook;
|
static const char *pack_objects_hook;
|
||||||
|
|
||||||
|
static int filter_capability_requested;
|
||||||
|
static int filter_advertise;
|
||||||
|
static struct list_objects_filter_options filter_options;
|
||||||
|
|
||||||
static void reset_timeout(void)
|
static void reset_timeout(void)
|
||||||
{
|
{
|
||||||
alarm(timeout);
|
alarm(timeout);
|
||||||
|
@ -131,6 +138,12 @@ static void create_pack_file(void)
|
||||||
argv_array_push(&pack_objects.args, "--delta-base-offset");
|
argv_array_push(&pack_objects.args, "--delta-base-offset");
|
||||||
if (use_include_tag)
|
if (use_include_tag)
|
||||||
argv_array_push(&pack_objects.args, "--include-tag");
|
argv_array_push(&pack_objects.args, "--include-tag");
|
||||||
|
if (filter_options.filter_spec) {
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
sq_quote_buf(&buf, filter_options.filter_spec);
|
||||||
|
argv_array_pushf(&pack_objects.args, "--filter=%s", buf.buf);
|
||||||
|
strbuf_release(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
pack_objects.in = -1;
|
pack_objects.in = -1;
|
||||||
pack_objects.out = -1;
|
pack_objects.out = -1;
|
||||||
|
@ -794,6 +807,12 @@ static void receive_needs(void)
|
||||||
deepen_rev_list = 1;
|
deepen_rev_list = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (skip_prefix(line, "filter ", &arg)) {
|
||||||
|
if (!filter_capability_requested)
|
||||||
|
die("git upload-pack: filtering capability not negotiated");
|
||||||
|
parse_list_objects_filter(&filter_options, arg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!skip_prefix(line, "want ", &arg) ||
|
if (!skip_prefix(line, "want ", &arg) ||
|
||||||
get_oid_hex(arg, &oid_buf))
|
get_oid_hex(arg, &oid_buf))
|
||||||
die("git upload-pack: protocol error, "
|
die("git upload-pack: protocol error, "
|
||||||
|
@ -821,6 +840,8 @@ static void receive_needs(void)
|
||||||
no_progress = 1;
|
no_progress = 1;
|
||||||
if (parse_feature_request(features, "include-tag"))
|
if (parse_feature_request(features, "include-tag"))
|
||||||
use_include_tag = 1;
|
use_include_tag = 1;
|
||||||
|
if (parse_feature_request(features, "filter"))
|
||||||
|
filter_capability_requested = 1;
|
||||||
|
|
||||||
o = parse_object(&oid_buf);
|
o = parse_object(&oid_buf);
|
||||||
if (!o) {
|
if (!o) {
|
||||||
|
@ -940,7 +961,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
|
||||||
struct strbuf symref_info = STRBUF_INIT;
|
struct strbuf symref_info = STRBUF_INIT;
|
||||||
|
|
||||||
format_symref_info(&symref_info, cb_data);
|
format_symref_info(&symref_info, cb_data);
|
||||||
packet_write_fmt(1, "%s %s%c%s%s%s%s%s agent=%s\n",
|
packet_write_fmt(1, "%s %s%c%s%s%s%s%s%s agent=%s\n",
|
||||||
oid_to_hex(oid), refname_nons,
|
oid_to_hex(oid), refname_nons,
|
||||||
0, capabilities,
|
0, capabilities,
|
||||||
(allow_unadvertised_object_request & ALLOW_TIP_SHA1) ?
|
(allow_unadvertised_object_request & ALLOW_TIP_SHA1) ?
|
||||||
|
@ -949,6 +970,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
|
||||||
" allow-reachable-sha1-in-want" : "",
|
" allow-reachable-sha1-in-want" : "",
|
||||||
stateless_rpc ? " no-done" : "",
|
stateless_rpc ? " no-done" : "",
|
||||||
symref_info.buf,
|
symref_info.buf,
|
||||||
|
filter_advertise ? " filter" : "",
|
||||||
git_user_agent_sanitized());
|
git_user_agent_sanitized());
|
||||||
strbuf_release(&symref_info);
|
strbuf_release(&symref_info);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1027,6 +1049,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
|
||||||
} else if (current_config_scope() != CONFIG_SCOPE_REPO) {
|
} else if (current_config_scope() != CONFIG_SCOPE_REPO) {
|
||||||
if (!strcmp("uploadpack.packobjectshook", var))
|
if (!strcmp("uploadpack.packobjectshook", var))
|
||||||
return git_config_string(&pack_objects_hook, var, value);
|
return git_config_string(&pack_objects_hook, var, value);
|
||||||
|
} else if (!strcmp("uploadpack.allowfilter", var)) {
|
||||||
|
filter_advertise = git_config_bool(var, value);
|
||||||
}
|
}
|
||||||
return parse_hide_refs_config(var, value, "uploadpack");
|
return parse_hide_refs_config(var, value, "uploadpack");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue