Junio C Hamano <gitster@xxxxxxxxx> writes: > Clemens Buchacher <drizzd@xxxxxx> writes: > ... >> @@ -636,6 +637,8 @@ static struct command *read_head_info(void) >> report_status = 1; >> if (strstr(refname + reflen + 1, "side-band-64k")) >> use_sideband = LARGE_PACKET_MAX; >> + if (strstr(refname + reflen + 1, "quiet")) >> + quiet = 1; > > Side note. > > We may want to make sure that this is not part of a different token word > (if we knew better, we would have written the other side so that we can > just test against " quiet ", but that is not possible, sigh...). ... but we can do this. -- >8 -- Subject: [PATCH] server_supports(): parse feature list more carefully We have been carefully choosing feature names used in the protocol extensions so that the vocabulary does not contain a word that is a substring of another word, so it is not a real problem, but we have recently added "quiet" feature word, which would mean we cannot later add some other word with "quiet" (e.g. "quiet-push"), which is awkward. Let's make sure that we can eventually be able to do so by teaching the clients and servers that feature words consist of non whitespace letters. This parser also allows us to later add features with parameters e.g. "feature=1.5" (parameter values need to be quoted for whitespaces, but we will worry about the detauls when we do introduce them). Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- builtin/receive-pack.c | 7 ++++--- cache.h | 1 + connect.c | 23 +++++++++++++++++++++-- upload-pack.c | 22 +++++++++++++--------- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index b71a1ca..927f307 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -600,11 +600,12 @@ static struct command *read_head_info(void) refname = line + 82; reflen = strlen(refname); if (reflen + 82 < len) { - if (strstr(refname + reflen + 1, "report-status")) + const char *feature_list = refname + reflen + 1; + if (parse_feature_request(feature_list, "report-status")) report_status = 1; - if (strstr(refname + reflen + 1, "side-band-64k")) + if (parse_feature_request(feature_list, "side-band-64k")) use_sideband = LARGE_PACKET_MAX; - if (strstr(refname + reflen + 1, "quiet")) + if (parse_feature_request(feature_list, "quiet")) quiet = 1; } cmd = xcalloc(1, sizeof(struct command) + len - 80); diff --git a/cache.h b/cache.h index e11cf6a..2933d04 100644 --- a/cache.h +++ b/cache.h @@ -996,6 +996,7 @@ struct extra_have_objects { }; extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags, struct extra_have_objects *); extern int server_supports(const char *feature); +extern const char *parse_feature_request(const char *features, const char *feature); extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path); diff --git a/connect.c b/connect.c index 2119c3f..2184fd8 100644 --- a/connect.c +++ b/connect.c @@ -104,8 +104,27 @@ struct ref **get_remote_heads(int in, struct ref **list, int server_supports(const char *feature) { - return server_capabilities && - strstr(server_capabilities, feature) != NULL; + return !!parse_feature_request(server_capabilities, feature); +} + +const char *parse_feature_request(const char *feature_list, const char *feature) +{ + int len; + + if (!feature_list) + return NULL; + + len = strlen(feature); + while (*feature_list) { + const char *found = strstr(feature_list, feature); + if (!found) + return NULL; + if ((feature_list == found || isspace(found[-1])) && + (!found[len] || isspace(found[len]) || found[len] == '=')) + return found; + feature_list = found + 1; + } + return NULL; } int path_match(const char *path, int nr, char **match) diff --git a/upload-pack.c b/upload-pack.c index ce5cbbe..a47a556 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -509,6 +509,7 @@ static void receive_needs(void) write_str_in_full(debug_fd, "#S\n"); for (;;) { struct object *o; + const char *features; unsigned char sha1_buf[20]; len = packet_read_line(0, line, sizeof(line)); reset_timeout(); @@ -540,23 +541,26 @@ static void receive_needs(void) get_sha1_hex(line+5, sha1_buf)) die("git upload-pack: protocol error, " "expected to get sha, not '%s'", line); - if (strstr(line+45, "multi_ack_detailed")) + + features = line + 45; + + if (parse_feature_request(features, "multi_ack_detailed")) multi_ack = 2; - else if (strstr(line+45, "multi_ack")) + else if (parse_feature_request(features, "multi_ack")) multi_ack = 1; - if (strstr(line+45, "no-done")) + if (parse_feature_request(features, "no-done")) no_done = 1; - if (strstr(line+45, "thin-pack")) + if (parse_feature_request(features, "thin-pack")) use_thin_pack = 1; - if (strstr(line+45, "ofs-delta")) + if (parse_feature_request(features, "ofs-delta")) use_ofs_delta = 1; - if (strstr(line+45, "side-band-64k")) + if (parse_feature_request(features, "side-band-64k")) use_sideband = LARGE_PACKET_MAX; - else if (strstr(line+45, "side-band")) + else if (parse_feature_request(features, "side-band")) use_sideband = DEFAULT_PACKET_MAX; - if (strstr(line+45, "no-progress")) + if (parse_feature_request(features, "no-progress")) no_progress = 1; - if (strstr(line+45, "include-tag")) + if (parse_feature_request(features, "include-tag")) use_include_tag = 1; /* We have sent all our refs already, and the other end -- 1.7.7.rc0.175.gb3212 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html