Skip to content

Commit 9442710

Browse files
peffgitster
authored andcommitted
parse_feature_request: make it easier to see feature values
We already take care to parse key/value capabilities like "foo=bar", but the code does not provide a good way of actually finding out what is on the right-hand side of the "=". A server using "parse_feature_request" could accomplish this with some extra parsing. You must skip past the "key" portion manually, check for "=" versus NUL or space, and then find the length by searching for the next space (or NUL). But clients can't even do that, since the "server_supports" interface does not even return the pointer. Instead, let's have our parser share more information by providing a pointer to the value and its length. The "parse_feature_value" function returns a pointer to the feature's value portion, along with the length of the value. If the feature is missing, NULL is returned. If it does not have an "=", then a zero-length value is returned. Similarly, "server_feature_value" behaves in the same way, but always checks the static server_feature_list variable. We can then implement "server_supports" in terms of "server_feature_value". We cannot implement the original "parse_feature_request" in terms of our new function, because it returned a pointer to the beginning of the feature. However, no callers actually cared about the value of the returned pointer, so we can simplify it to a boolean just as we do for "server_supports". Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 74991a9 commit 9442710

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

cache.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,9 @@ struct extra_have_objects {
10301030
};
10311031
extern struct ref **get_remote_heads(int in, struct ref **list, unsigned int flags, struct extra_have_objects *);
10321032
extern int server_supports(const char *feature);
1033-
extern const char *parse_feature_request(const char *features, const char *feature);
1033+
extern int parse_feature_request(const char *features, const char *feature);
1034+
extern const char *server_feature_value(const char *feature, int *len_ret);
1035+
extern const char *parse_feature_value(const char *feature_list, const char *feature, int *len_ret);
10341036

10351037
extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
10361038

connect.c

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,7 @@ struct ref **get_remote_heads(int in, struct ref **list,
9999
return list;
100100
}
101101

102-
int server_supports(const char *feature)
103-
{
104-
return !!parse_feature_request(server_capabilities, feature);
105-
}
106-
107-
const char *parse_feature_request(const char *feature_list, const char *feature)
102+
const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp)
108103
{
109104
int len;
110105

@@ -116,14 +111,46 @@ const char *parse_feature_request(const char *feature_list, const char *feature)
116111
const char *found = strstr(feature_list, feature);
117112
if (!found)
118113
return NULL;
119-
if ((feature_list == found || isspace(found[-1])) &&
120-
(!found[len] || isspace(found[len]) || found[len] == '='))
121-
return found;
114+
if (feature_list == found || isspace(found[-1])) {
115+
const char *value = found + len;
116+
/* feature with no value (e.g., "thin-pack") */
117+
if (!*value || isspace(*value)) {
118+
if (lenp)
119+
*lenp = 0;
120+
return value;
121+
}
122+
/* feature with a value (e.g., "agent=git/1.2.3") */
123+
else if (*value == '=') {
124+
value++;
125+
if (lenp)
126+
*lenp = strcspn(value, " \t\n");
127+
return value;
128+
}
129+
/*
130+
* otherwise we matched a substring of another feature;
131+
* keep looking
132+
*/
133+
}
122134
feature_list = found + 1;
123135
}
124136
return NULL;
125137
}
126138

139+
int parse_feature_request(const char *feature_list, const char *feature)
140+
{
141+
return !!parse_feature_value(feature_list, feature, NULL);
142+
}
143+
144+
const char *server_feature_value(const char *feature, int *len)
145+
{
146+
return parse_feature_value(server_capabilities, feature, len);
147+
}
148+
149+
int server_supports(const char *feature)
150+
{
151+
return !!server_feature_value(feature, NULL);
152+
}
153+
127154
enum protocol {
128155
PROTO_LOCAL = 1,
129156
PROTO_SSH,

0 commit comments

Comments
 (0)