Skip to content

Commit 6a56993

Browse files
mackylegitster
authored andcommitted
config: parse http.<url>.<variable> using urlmatch
Use the urlmatch_config_entry() to wrap the underlying http_options() two-level variable parser in order to set http.<variable> to the value with the most specific URL in the configuration. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Kyle J. McKay <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 836b6fb commit 6a56993

19 files changed

+309
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@
198198
/test-string-list
199199
/test-subprocess
200200
/test-svn-fe
201+
/test-urlmatch-normalization
201202
/test-wildmatch
202203
/common-cmds.h
203204
*.tar.gz

Documentation/config.txt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,6 +1513,51 @@ http.useragent::
15131513
of common USER_AGENT strings (but not including those like git/1.7.1).
15141514
Can be overridden by the 'GIT_HTTP_USER_AGENT' environment variable.
15151515

1516+
http.<url>.*::
1517+
Any of the http.* options above can be applied selectively to some urls.
1518+
For a config key to match a URL, each element of the config key is
1519+
compared to that of the URL, in the following order:
1520+
+
1521+
--
1522+
. Scheme (e.g., `https` in `https://example.com/`). This field
1523+
must match exactly between the config key and the URL.
1524+
1525+
. Host/domain name (e.g., `example.com` in `https://example.com/`).
1526+
This field must match exactly between the config key and the URL.
1527+
1528+
. Port number (e.g., `8080` in `http://example.com:8080/`).
1529+
This field must match exactly between the config key and the URL.
1530+
Omitted port numbers are automatically converted to the correct
1531+
default for the scheme before matching.
1532+
1533+
. Path (e.g., `repo.git` in `https://example.com/repo.git`). The
1534+
path field of the config key must match the path field of the URL
1535+
either exactly or as a prefix of slash-delimited path elements. This means
1536+
a config key with path `foo/` matches URL path `foo/bar`. A prefix can only
1537+
match on a slash (`/`) boundary. Longer matches take precedence (so a config
1538+
key with path `foo/bar` is a better match to URL path `foo/bar` than a config
1539+
key with just path `foo/`).
1540+
1541+
. User name (e.g., `user` in `https://[email protected]/repo.git`). If
1542+
the config key has a user name it must match the user name in the
1543+
URL exactly. If the config key does not have a user name, that
1544+
config key will match a URL with any user name (including none),
1545+
but at a lower precedence than a config key with a user name.
1546+
--
1547+
+
1548+
The list above is ordered by decreasing precedence; a URL that matches
1549+
a config key's path is preferred to one that matches its user name. For example,
1550+
if the URL is `https://[email protected]/foo/bar` a config key match of
1551+
`https://example.com/foo` will be preferred over a config key match of
1552+
1553+
+
1554+
All URLs are normalized before attempting any matching (the password part,
1555+
if embedded in the URL, is always ignored for matching purposes) so that
1556+
equivalent urls that are simply spelled differently will match properly.
1557+
Environment variable settings always override any matches. The urls that are
1558+
matched against are those given directly to Git commands. This means any URLs
1559+
visited as a result of a redirection do not participate in matching.
1560+
15161561
i18n.commitEncoding::
15171562
Character encoding the commit messages are stored in; Git itself
15181563
does not care per se, but this information is necessary e.g. when

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ TEST_PROGRAMS_NEED_X += test-sigchain
567567
TEST_PROGRAMS_NEED_X += test-string-list
568568
TEST_PROGRAMS_NEED_X += test-subprocess
569569
TEST_PROGRAMS_NEED_X += test-svn-fe
570+
TEST_PROGRAMS_NEED_X += test-urlmatch-normalization
570571
TEST_PROGRAMS_NEED_X += test-wildmatch
571572

572573
TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
@@ -721,6 +722,7 @@ LIB_H += tree-walk.h
721722
LIB_H += tree.h
722723
LIB_H += unpack-trees.h
723724
LIB_H += url.h
725+
LIB_H += urlmatch.h
724726
LIB_H += userdiff.h
725727
LIB_H += utf8.h
726728
LIB_H += varint.h
@@ -868,6 +870,7 @@ LIB_OBJS += tree.o
868870
LIB_OBJS += tree-walk.o
869871
LIB_OBJS += unpack-trees.o
870872
LIB_OBJS += url.o
873+
LIB_OBJS += urlmatch.o
871874
LIB_OBJS += usage.o
872875
LIB_OBJS += userdiff.o
873876
LIB_OBJS += utf8.o

http.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "sideband.h"
44
#include "run-command.h"
55
#include "url.h"
6+
#include "urlmatch.h"
67
#include "credential.h"
78
#include "version.h"
89
#include "pkt-line.h"
@@ -334,10 +335,20 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
334335
{
335336
char *low_speed_limit;
336337
char *low_speed_time;
338+
char *normalized_url;
339+
struct urlmatch_config config = { STRING_LIST_INIT_DUP };
340+
341+
config.section = "http";
342+
config.key = NULL;
343+
config.collect_fn = http_options;
344+
config.cascade_fn = git_default_config;
345+
config.cb = NULL;
337346

338347
http_is_verbose = 0;
348+
normalized_url = url_normalize(url, &config.url);
339349

340-
git_config(http_options, NULL);
350+
git_config(urlmatch_config_entry, &config);
351+
free(normalized_url);
341352

342353
curl_global_init(CURL_GLOBAL_ALL);
343354

t/.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
t[0-9][0-9][0-9][0-9]/* -whitespace
2+
t0110/url-* binary

t/t0110-urlmatch-normalization.sh

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#!/bin/sh
2+
3+
test_description='urlmatch URL normalization'
4+
. ./test-lib.sh
5+
6+
# The base name of the test url files
7+
tu="$TEST_DIRECTORY/t0110/url"
8+
9+
# Note that only file: URLs should be allowed without a host
10+
11+
test_expect_success 'url scheme' '
12+
! test-urlmatch-normalization "" &&
13+
! test-urlmatch-normalization "_" &&
14+
! test-urlmatch-normalization "scheme" &&
15+
! test-urlmatch-normalization "scheme:" &&
16+
! test-urlmatch-normalization "scheme:/" &&
17+
! test-urlmatch-normalization "scheme://" &&
18+
! test-urlmatch-normalization "file" &&
19+
! test-urlmatch-normalization "file:" &&
20+
! test-urlmatch-normalization "file:/" &&
21+
test-urlmatch-normalization "file://" &&
22+
! test-urlmatch-normalization "://acme.co" &&
23+
! test-urlmatch-normalization "x_test://acme.co" &&
24+
! test-urlmatch-normalization "-test://acme.co" &&
25+
! test-urlmatch-normalization "0test://acme.co" &&
26+
! test-urlmatch-normalization "+test://acme.co" &&
27+
! test-urlmatch-normalization ".test://acme.co" &&
28+
! test-urlmatch-normalization "schem%6e://" &&
29+
test-urlmatch-normalization "x-Test+v1.0://acme.co" &&
30+
test "$(test-urlmatch-normalization -p "AbCdeF://x.Y")" = "abcdef://x.y/"
31+
'
32+
33+
test_expect_success 'url authority' '
34+
! test-urlmatch-normalization "scheme://user:pass@" &&
35+
! test-urlmatch-normalization "scheme://?" &&
36+
! test-urlmatch-normalization "scheme://#" &&
37+
! test-urlmatch-normalization "scheme:///" &&
38+
! test-urlmatch-normalization "scheme://:" &&
39+
! test-urlmatch-normalization "scheme://:555" &&
40+
test-urlmatch-normalization "file://user:pass@" &&
41+
test-urlmatch-normalization "file://?" &&
42+
test-urlmatch-normalization "file://#" &&
43+
test-urlmatch-normalization "file:///" &&
44+
test-urlmatch-normalization "file://:" &&
45+
! test-urlmatch-normalization "file://:555" &&
46+
test-urlmatch-normalization "scheme://user:pass@host" &&
47+
test-urlmatch-normalization "scheme://@host" &&
48+
test-urlmatch-normalization "scheme://%00@host" &&
49+
! test-urlmatch-normalization "scheme://%%@host" &&
50+
! test-urlmatch-normalization "scheme://host_" &&
51+
test-urlmatch-normalization "scheme://user:pass@host/" &&
52+
test-urlmatch-normalization "scheme://@host/" &&
53+
test-urlmatch-normalization "scheme://host/" &&
54+
test-urlmatch-normalization "scheme://host?x" &&
55+
test-urlmatch-normalization "scheme://host#x" &&
56+
test-urlmatch-normalization "scheme://host/@" &&
57+
test-urlmatch-normalization "scheme://host?@x" &&
58+
test-urlmatch-normalization "scheme://host#@x" &&
59+
test-urlmatch-normalization "scheme://[::1]" &&
60+
test-urlmatch-normalization "scheme://[::1]/" &&
61+
! test-urlmatch-normalization "scheme://hos%41/" &&
62+
test-urlmatch-normalization "scheme://[invalid....:/" &&
63+
test-urlmatch-normalization "scheme://invalid....:]/" &&
64+
! test-urlmatch-normalization "scheme://invalid....:[/" &&
65+
! test-urlmatch-normalization "scheme://invalid....:["
66+
'
67+
68+
test_expect_success 'url port checks' '
69+
test-urlmatch-normalization "xyz://[email protected]:" &&
70+
test-urlmatch-normalization "xyz://[email protected]:456/" &&
71+
! test-urlmatch-normalization "xyz://[email protected]:0" &&
72+
! test-urlmatch-normalization "xyz://[email protected]:0000000" &&
73+
test-urlmatch-normalization "xyz://[email protected]:0000001?" &&
74+
test-urlmatch-normalization "xyz://[email protected]:065535#" &&
75+
test-urlmatch-normalization "xyz://[email protected]:65535" &&
76+
! test-urlmatch-normalization "xyz://[email protected]:65536" &&
77+
! test-urlmatch-normalization "xyz://[email protected]:99999" &&
78+
! test-urlmatch-normalization "xyz://[email protected]:100000" &&
79+
! test-urlmatch-normalization "xyz://[email protected]:100001" &&
80+
test-urlmatch-normalization "http://[email protected]:80" &&
81+
test-urlmatch-normalization "https://[email protected]:443" &&
82+
test-urlmatch-normalization "http://[email protected]:80/" &&
83+
test-urlmatch-normalization "https://[email protected]:443?" &&
84+
! test-urlmatch-normalization "http://q@:8008" &&
85+
! test-urlmatch-normalization "http://:8080" &&
86+
! test-urlmatch-normalization "http://:" &&
87+
test-urlmatch-normalization "xyz://[email protected]:456/" &&
88+
test-urlmatch-normalization "xyz://[::1]:456/" &&
89+
test-urlmatch-normalization "xyz://[::1]:/" &&
90+
! test-urlmatch-normalization "xyz://[::1]:000/" &&
91+
! test-urlmatch-normalization "xyz://[::1]:0%300/" &&
92+
! test-urlmatch-normalization "xyz://[::1]:0x80/" &&
93+
! test-urlmatch-normalization "xyz://[::1]:4294967297/" &&
94+
! test-urlmatch-normalization "xyz://[::1]:030f/"
95+
'
96+
97+
test_expect_success 'url port normalization' '
98+
test "$(test-urlmatch-normalization -p "http://x:800")" = "http://x:800/" &&
99+
test "$(test-urlmatch-normalization -p "http://x:0800")" = "http://x:800/" &&
100+
test "$(test-urlmatch-normalization -p "http://x:00000800")" = "http://x:800/" &&
101+
test "$(test-urlmatch-normalization -p "http://x:065535")" = "http://x:65535/" &&
102+
test "$(test-urlmatch-normalization -p "http://x:1")" = "http://x:1/" &&
103+
test "$(test-urlmatch-normalization -p "http://x:80")" = "http://x/" &&
104+
test "$(test-urlmatch-normalization -p "http://x:080")" = "http://x/" &&
105+
test "$(test-urlmatch-normalization -p "http://x:000000080")" = "http://x/" &&
106+
test "$(test-urlmatch-normalization -p "https://x:443")" = "https://x/" &&
107+
test "$(test-urlmatch-normalization -p "https://x:0443")" = "https://x/" &&
108+
test "$(test-urlmatch-normalization -p "https://x:000000443")" = "https://x/"
109+
'
110+
111+
test_expect_success 'url general escapes' '
112+
! test-urlmatch-normalization "http://x.y?%fg" &&
113+
test "$(test-urlmatch-normalization -p "X://W/%7e%41^%3a")" = "x://w/~A%5E%3A" &&
114+
test "$(test-urlmatch-normalization -p "X://W/:/?#[]@")" = "x://w/:/?#[]@" &&
115+
test "$(test-urlmatch-normalization -p "X://W/$&()*+,;=")" = "x://w/$&()*+,;=" &&
116+
test "$(test-urlmatch-normalization -p "X://W/'\''")" = "x://w/'\''" &&
117+
test "$(test-urlmatch-normalization -p "X://W?'\!'")" = "x://w/?'\!'"
118+
'
119+
120+
test_expect_success 'url high-bit escapes' '
121+
test "$(test-urlmatch-normalization -p "$(cat "$tu-1")")" = "x://q/%01%02%03%04%05%06%07%08%0E%0F%10%11%12" &&
122+
test "$(test-urlmatch-normalization -p "$(cat "$tu-2")")" = "x://q/%13%14%15%16%17%18%19%1B%1C%1D%1E%1F%7F" &&
123+
test "$(test-urlmatch-normalization -p "$(cat "$tu-3")")" = "x://q/%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F" &&
124+
test "$(test-urlmatch-normalization -p "$(cat "$tu-4")")" = "x://q/%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F" &&
125+
test "$(test-urlmatch-normalization -p "$(cat "$tu-5")")" = "x://q/%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF" &&
126+
test "$(test-urlmatch-normalization -p "$(cat "$tu-6")")" = "x://q/%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF" &&
127+
test "$(test-urlmatch-normalization -p "$(cat "$tu-7")")" = "x://q/%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF" &&
128+
test "$(test-urlmatch-normalization -p "$(cat "$tu-8")")" = "x://q/%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF" &&
129+
test "$(test-urlmatch-normalization -p "$(cat "$tu-9")")" = "x://q/%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" &&
130+
test "$(test-urlmatch-normalization -p "$(cat "$tu-10")")" = "x://q/%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF" &&
131+
test "$(test-urlmatch-normalization -p "$(cat "$tu-11")")" = "x://q/%C2%80%DF%BF%E0%A0%80%EF%BF%BD%F0%90%80%80%F0%AF%BF%BD"
132+
'
133+
134+
test_expect_success 'url username/password escapes' '
135+
test "$(test-urlmatch-normalization -p "x://%41%62(^):%70+d@foo")" = "x://Ab(%5E):p+d@foo/"
136+
'
137+
138+
test_expect_success 'url normalized lengths' '
139+
test "$(test-urlmatch-normalization -l "Http://%4d%65:%4d^%[email protected]")" = 25 &&
140+
test "$(test-urlmatch-normalization -l "http://%41:%[email protected]/%61/")" = 17 &&
141+
test "$(test-urlmatch-normalization -l "http://@x.y/^")" = 15
142+
'
143+
144+
test_expect_success 'url . and .. segments' '
145+
test "$(test-urlmatch-normalization -p "x://y/.")" = "x://y/" &&
146+
test "$(test-urlmatch-normalization -p "x://y/./")" = "x://y/" &&
147+
test "$(test-urlmatch-normalization -p "x://y/a/.")" = "x://y/a" &&
148+
test "$(test-urlmatch-normalization -p "x://y/a/./")" = "x://y/a/" &&
149+
test "$(test-urlmatch-normalization -p "x://y/.?")" = "x://y/?" &&
150+
test "$(test-urlmatch-normalization -p "x://y/./?")" = "x://y/?" &&
151+
test "$(test-urlmatch-normalization -p "x://y/a/.?")" = "x://y/a?" &&
152+
test "$(test-urlmatch-normalization -p "x://y/a/./?")" = "x://y/a/?" &&
153+
test "$(test-urlmatch-normalization -p "x://y/a/./b/.././../c")" = "x://y/c" &&
154+
test "$(test-urlmatch-normalization -p "x://y/a/./b/../.././c/")" = "x://y/c/" &&
155+
test "$(test-urlmatch-normalization -p "x://y/a/./b/.././../c/././.././.")" = "x://y/" &&
156+
! test-urlmatch-normalization "x://y/a/./b/.././../c/././.././.." &&
157+
test "$(test-urlmatch-normalization -p "x://y/a/./?/././..")" = "x://y/a/?/././.." &&
158+
test "$(test-urlmatch-normalization -p "x://y/%2e/")" = "x://y/" &&
159+
test "$(test-urlmatch-normalization -p "x://y/%2E/")" = "x://y/" &&
160+
test "$(test-urlmatch-normalization -p "x://y/a/%2e./")" = "x://y/" &&
161+
test "$(test-urlmatch-normalization -p "x://y/b/.%2E/")" = "x://y/" &&
162+
test "$(test-urlmatch-normalization -p "x://y/c/%2e%2E/")" = "x://y/"
163+
'
164+
165+
# http://@foo specifies an empty user name but does not specify a password
166+
# http://foo specifies neither a user name nor a password
167+
# So they should not be equivalent
168+
test_expect_success 'url equivalents' '
169+
test-urlmatch-normalization "httP://x" "Http://X/" &&
170+
test-urlmatch-normalization "Http://%4d%65:%4d^%[email protected]" "hTTP://Me:%4D^[email protected]:80/" &&
171+
! test-urlmatch-normalization "https://@x.y/^" "httpS://x.y:443/^" &&
172+
test-urlmatch-normalization "https://@x.y/^" "httpS://@x.y:0443/^" &&
173+
test-urlmatch-normalization "https://@x.y/^/../abc" "httpS://@x.y:0443/abc" &&
174+
test-urlmatch-normalization "https://@x.y/^/.." "httpS://@x.y:0443/"
175+
'
176+
177+
test_done

t/t0110/README

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
The url data files in this directory contain URLs with characters
2+
in the range 0x01-0x1f and 0x7f-0xff to test the proper normalization
3+
of unprintable characters.
4+
5+
A select few characters in the 0x01-0x1f range are skipped to help
6+
avoid problems running the test itself.
7+
8+
The urls are in test files in this directory rather than being
9+
embedded in the test script for portability.

t/t0110/url-1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
x://q/

t/t0110/url-10

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
x://q/����������������

t/t0110/url-11

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
x://q/€߿ࠀ�𐀀𯿽

0 commit comments

Comments
 (0)