Merge branch 'jc/capabilities'
Some capabilities were asked by fetch-pack even when upload-pack did not advertise that they are available. Fix fetch-pack not to do so. * jc/capabilities: fetch-pack: mention server version with verbose output parse_feature_request: make it easier to see feature values fetch-pack: do not ask for unadvertised capabilities do not send client agent unless server does first send-pack: fix capability-sending logic include agent identifier in capability string
This commit is contained in:
@ -10,6 +10,7 @@
|
|||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
#include "run-command.h"
|
#include "run-command.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
static int transfer_unpack_limit = -1;
|
static int transfer_unpack_limit = -1;
|
||||||
static int fetch_unpack_limit = -1;
|
static int fetch_unpack_limit = -1;
|
||||||
@ -18,6 +19,7 @@ static int prefer_ofs_delta = 1;
|
|||||||
static int no_done;
|
static int no_done;
|
||||||
static int fetch_fsck_objects = -1;
|
static int fetch_fsck_objects = -1;
|
||||||
static int transfer_fsck_objects = -1;
|
static int transfer_fsck_objects = -1;
|
||||||
|
static int agent_supported;
|
||||||
static struct fetch_pack_args args = {
|
static struct fetch_pack_args args = {
|
||||||
/* .uploadpack = */ "git-upload-pack",
|
/* .uploadpack = */ "git-upload-pack",
|
||||||
};
|
};
|
||||||
@ -327,6 +329,8 @@ static int find_common(int fd[2], unsigned char *result_sha1,
|
|||||||
if (args.no_progress) strbuf_addstr(&c, " no-progress");
|
if (args.no_progress) strbuf_addstr(&c, " no-progress");
|
||||||
if (args.include_tag) strbuf_addstr(&c, " include-tag");
|
if (args.include_tag) strbuf_addstr(&c, " include-tag");
|
||||||
if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta");
|
if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta");
|
||||||
|
if (agent_supported) strbuf_addf(&c, " agent=%s",
|
||||||
|
git_user_agent_sanitized());
|
||||||
packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
|
packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
|
||||||
strbuf_release(&c);
|
strbuf_release(&c);
|
||||||
} else
|
} else
|
||||||
@ -783,6 +787,8 @@ static struct ref *do_fetch_pack(int fd[2],
|
|||||||
{
|
{
|
||||||
struct ref *ref = copy_ref_list(orig_ref);
|
struct ref *ref = copy_ref_list(orig_ref);
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
|
const char *agent_feature;
|
||||||
|
int agent_len;
|
||||||
|
|
||||||
sort_ref_list(&ref, ref_compare_name);
|
sort_ref_list(&ref, ref_compare_name);
|
||||||
|
|
||||||
@ -814,11 +820,25 @@ static struct ref *do_fetch_pack(int fd[2],
|
|||||||
fprintf(stderr, "Server supports side-band\n");
|
fprintf(stderr, "Server supports side-band\n");
|
||||||
use_sideband = 1;
|
use_sideband = 1;
|
||||||
}
|
}
|
||||||
|
if (!server_supports("thin-pack"))
|
||||||
|
args.use_thin_pack = 0;
|
||||||
|
if (!server_supports("no-progress"))
|
||||||
|
args.no_progress = 0;
|
||||||
|
if (!server_supports("include-tag"))
|
||||||
|
args.include_tag = 0;
|
||||||
if (server_supports("ofs-delta")) {
|
if (server_supports("ofs-delta")) {
|
||||||
if (args.verbose)
|
if (args.verbose)
|
||||||
fprintf(stderr, "Server supports ofs-delta\n");
|
fprintf(stderr, "Server supports ofs-delta\n");
|
||||||
} else
|
} else
|
||||||
prefer_ofs_delta = 0;
|
prefer_ofs_delta = 0;
|
||||||
|
|
||||||
|
if ((agent_feature = server_feature_value("agent", &agent_len))) {
|
||||||
|
agent_supported = 1;
|
||||||
|
if (args.verbose && agent_len)
|
||||||
|
fprintf(stderr, "Server version is %.*s\n",
|
||||||
|
agent_len, agent_feature);
|
||||||
|
}
|
||||||
|
|
||||||
if (everything_local(&ref, nr_match, match)) {
|
if (everything_local(&ref, nr_match, match)) {
|
||||||
packet_flush(fd[1]);
|
packet_flush(fd[1]);
|
||||||
goto all_done;
|
goto all_done;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
#include "sha1-array.h"
|
#include "sha1-array.h"
|
||||||
#include "connected.h"
|
#include "connected.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
static const char receive_pack_usage[] = "git receive-pack <git-dir>";
|
static const char receive_pack_usage[] = "git receive-pack <git-dir>";
|
||||||
|
|
||||||
@ -121,10 +122,11 @@ static void show_ref(const char *path, const unsigned char *sha1)
|
|||||||
if (sent_capabilities)
|
if (sent_capabilities)
|
||||||
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
|
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
|
||||||
else
|
else
|
||||||
packet_write(1, "%s %s%c%s%s\n",
|
packet_write(1, "%s %s%c%s%s agent=%s\n",
|
||||||
sha1_to_hex(sha1), path, 0,
|
sha1_to_hex(sha1), path, 0,
|
||||||
" report-status delete-refs side-band-64k quiet",
|
" report-status delete-refs side-band-64k quiet",
|
||||||
prefer_ofs_delta ? " ofs-delta" : "");
|
prefer_ofs_delta ? " ofs-delta" : "",
|
||||||
|
git_user_agent_sanitized());
|
||||||
sent_capabilities = 1;
|
sent_capabilities = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "send-pack.h"
|
#include "send-pack.h"
|
||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
static const char send_pack_usage[] =
|
static const char send_pack_usage[] =
|
||||||
"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
|
"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
|
||||||
@ -251,6 +252,7 @@ int send_pack(struct send_pack_args *args,
|
|||||||
int status_report = 0;
|
int status_report = 0;
|
||||||
int use_sideband = 0;
|
int use_sideband = 0;
|
||||||
int quiet_supported = 0;
|
int quiet_supported = 0;
|
||||||
|
int agent_supported = 0;
|
||||||
unsigned cmds_sent = 0;
|
unsigned cmds_sent = 0;
|
||||||
int ret;
|
int ret;
|
||||||
struct async demux;
|
struct async demux;
|
||||||
@ -266,6 +268,8 @@ int send_pack(struct send_pack_args *args,
|
|||||||
use_sideband = 1;
|
use_sideband = 1;
|
||||||
if (server_supports("quiet"))
|
if (server_supports("quiet"))
|
||||||
quiet_supported = 1;
|
quiet_supported = 1;
|
||||||
|
if (server_supports("agent"))
|
||||||
|
agent_supported = 1;
|
||||||
|
|
||||||
if (!remote_refs) {
|
if (!remote_refs) {
|
||||||
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
|
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
|
||||||
@ -305,12 +309,17 @@ int send_pack(struct send_pack_args *args,
|
|||||||
char *new_hex = sha1_to_hex(ref->new_sha1);
|
char *new_hex = sha1_to_hex(ref->new_sha1);
|
||||||
int quiet = quiet_supported && (args->quiet || !args->progress);
|
int quiet = quiet_supported && (args->quiet || !args->progress);
|
||||||
|
|
||||||
if (!cmds_sent && (status_report || use_sideband || args->quiet)) {
|
if (!cmds_sent && (status_report || use_sideband ||
|
||||||
packet_buf_write(&req_buf, "%s %s %s%c%s%s%s",
|
quiet || agent_supported)) {
|
||||||
|
packet_buf_write(&req_buf,
|
||||||
|
"%s %s %s%c%s%s%s%s%s",
|
||||||
old_hex, new_hex, ref->name, 0,
|
old_hex, new_hex, ref->name, 0,
|
||||||
status_report ? " report-status" : "",
|
status_report ? " report-status" : "",
|
||||||
use_sideband ? " side-band-64k" : "",
|
use_sideband ? " side-band-64k" : "",
|
||||||
quiet ? " quiet" : "");
|
quiet ? " quiet" : "",
|
||||||
|
agent_supported ? " agent=" : "",
|
||||||
|
agent_supported ? git_user_agent_sanitized() : ""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
packet_buf_write(&req_buf, "%s %s %s",
|
packet_buf_write(&req_buf, "%s %s %s",
|
||||||
|
4
cache.h
4
cache.h
@ -1038,7 +1038,9 @@ struct extra_have_objects {
|
|||||||
};
|
};
|
||||||
extern struct ref **get_remote_heads(int in, struct ref **list, unsigned int flags, struct extra_have_objects *);
|
extern struct ref **get_remote_heads(int in, struct ref **list, unsigned int flags, struct extra_have_objects *);
|
||||||
extern int server_supports(const char *feature);
|
extern int server_supports(const char *feature);
|
||||||
extern const char *parse_feature_request(const char *features, const char *feature);
|
extern int parse_feature_request(const char *features, const char *feature);
|
||||||
|
extern const char *server_feature_value(const char *feature, int *len_ret);
|
||||||
|
extern const char *parse_feature_value(const char *feature_list, const char *feature, int *len_ret);
|
||||||
|
|
||||||
extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
|
extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
|
||||||
|
|
||||||
|
45
connect.c
45
connect.c
@ -115,12 +115,7 @@ struct ref **get_remote_heads(int in, struct ref **list,
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
int server_supports(const char *feature)
|
const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp)
|
||||||
{
|
|
||||||
return !!parse_feature_request(server_capabilities, feature);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *parse_feature_request(const char *feature_list, const char *feature)
|
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
@ -132,14 +127,46 @@ const char *parse_feature_request(const char *feature_list, const char *feature)
|
|||||||
const char *found = strstr(feature_list, feature);
|
const char *found = strstr(feature_list, feature);
|
||||||
if (!found)
|
if (!found)
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((feature_list == found || isspace(found[-1])) &&
|
if (feature_list == found || isspace(found[-1])) {
|
||||||
(!found[len] || isspace(found[len]) || found[len] == '='))
|
const char *value = found + len;
|
||||||
return found;
|
/* feature with no value (e.g., "thin-pack") */
|
||||||
|
if (!*value || isspace(*value)) {
|
||||||
|
if (lenp)
|
||||||
|
*lenp = 0;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/* feature with a value (e.g., "agent=git/1.2.3") */
|
||||||
|
else if (*value == '=') {
|
||||||
|
value++;
|
||||||
|
if (lenp)
|
||||||
|
*lenp = strcspn(value, " \t\n");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* otherwise we matched a substring of another feature;
|
||||||
|
* keep looking
|
||||||
|
*/
|
||||||
|
}
|
||||||
feature_list = found + 1;
|
feature_list = found + 1;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parse_feature_request(const char *feature_list, const char *feature)
|
||||||
|
{
|
||||||
|
return !!parse_feature_value(feature_list, feature, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *server_feature_value(const char *feature, int *len)
|
||||||
|
{
|
||||||
|
return parse_feature_value(server_capabilities, feature, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int server_supports(const char *feature)
|
||||||
|
{
|
||||||
|
return !!server_feature_value(feature, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
enum protocol {
|
enum protocol {
|
||||||
PROTO_LOCAL = 1,
|
PROTO_LOCAL = 1,
|
||||||
PROTO_SSH,
|
PROTO_SSH,
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "list-objects.h"
|
#include "list-objects.h"
|
||||||
#include "run-command.h"
|
#include "run-command.h"
|
||||||
#include "sigchain.h"
|
#include "sigchain.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<n>] <dir>";
|
static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<n>] <dir>";
|
||||||
|
|
||||||
@ -734,9 +735,11 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (capabilities)
|
if (capabilities)
|
||||||
packet_write(1, "%s %s%c%s%s\n", sha1_to_hex(sha1), refname_nons,
|
packet_write(1, "%s %s%c%s%s agent=%s\n",
|
||||||
|
sha1_to_hex(sha1), refname_nons,
|
||||||
0, capabilities,
|
0, capabilities,
|
||||||
stateless_rpc ? " no-done" : "");
|
stateless_rpc ? " no-done" : "",
|
||||||
|
git_user_agent_sanitized());
|
||||||
else
|
else
|
||||||
packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname_nons);
|
packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname_nons);
|
||||||
capabilities = NULL;
|
capabilities = NULL;
|
||||||
|
21
version.c
21
version.c
@ -1,5 +1,6 @@
|
|||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "strbuf.h"
|
||||||
|
|
||||||
const char git_version_string[] = GIT_VERSION;
|
const char git_version_string[] = GIT_VERSION;
|
||||||
|
|
||||||
@ -15,3 +16,23 @@ const char *git_user_agent(void)
|
|||||||
|
|
||||||
return agent;
|
return agent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *git_user_agent_sanitized(void)
|
||||||
|
{
|
||||||
|
static const char *agent = NULL;
|
||||||
|
|
||||||
|
if (!agent) {
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
strbuf_addstr(&buf, git_user_agent());
|
||||||
|
strbuf_trim(&buf);
|
||||||
|
for (i = 0; i < buf.len; i++) {
|
||||||
|
if (buf.buf[i] <= 32 || buf.buf[i] >= 127)
|
||||||
|
buf.buf[i] = '.';
|
||||||
|
}
|
||||||
|
agent = buf.buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return agent;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user