@matheusbsbs / matheus-bagliano / commits / 844112cac0
Fork 0

url rewriting: take longest and first match

Earlier we had a cop-out in the documentation to make the behaviour "undefined" if configuration had more than one insteadOf that would match the target URL, like this: [url "git://git.or.cz/"] insteadOf = "git.or.cz:" ; (1) insteadOf = "repo.or.cz:" ; (2) [url "/local/mirror/"] insteadOf = "git.or.cz:myrepo" ; (3) insteadOf = "repo.or.cz:" ; (4) It would be most natural to take the longest and first match, i.e. - rewrite "git.or.cz:frotz" to "git://git.or.cz/frotz" by using (1), - rewrite "git.or.cz:myrepo/xyzzy" to "/local/mirror/xyzzy" by favoring (3) over (1), and - rewrite "repo.or.cz:frotz" to "git://git.or.cz/frotz" by favoring (2) over (4). Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Feb 24, 2008 at 22:25 UTC 844112cac07d6413b9bb42d38527d2f7ca7c7801
2 files changed +40 -19
Documentation/config.txt
+2 -3
@@ -894,9 +894,8 @@ url.<base>.insteadOf::
894 methods, this feature allows people to specify any of the
895 equivalent URLs and have git automatically rewrite the URL to
896 the best alternative for the particular user, even for a
897 - never-before-seen repository on the site. The effect of
898 - having multiple `insteadOf` values from different
899 - `<base>` match to an URL is undefined.
897 + never-before-seen repository on the site. When more than one
898 + insteadOf strings match a given URL, the longest match is used.
899
900 user.email::
901 Your email address to be recorded in any newly created commits.
remote.c
+38 -16
@@ -2,9 +2,14 @@
2 #include "remote.h"
3 #include "refs.h"
4
5 +struct counted_string {
6 + size_t len;
7 + const char *s;
8 +};
9 struct rewrite {
10 const char *base;
7 - const char **instead_of;
11 + size_t baselen;
12 + struct counted_string *instead_of;
13 int instead_of_nr;
14 int instead_of_alloc;
15 };
@@ -30,21 +35,32 @@ static char buffer[BUF_SIZE];
35 static const char *alias_url(const char *url)
36 {
37 int i, j;
38 + char *ret;
39 + struct counted_string *longest;
40 + int longest_i;
41 +
42 + longest = NULL;
43 + longest_i = -1;
44 for (i = 0; i < rewrite_nr; i++) {
45 if (!rewrite[i])
46 continue;
47 for (j = 0; j < rewrite[i]->instead_of_nr; j++) {
37 - if (!prefixcmp(url, rewrite[i]->instead_of[j])) {
38 - char *ret = malloc(strlen(rewrite[i]->base) -
39 - strlen(rewrite[i]->instead_of[j]) +
40 - strlen(url) + 1);
41 - strcpy(ret, rewrite[i]->base);
42 - strcat(ret, url + strlen(rewrite[i]->instead_of[j]));
43 - return ret;
48 + if (!prefixcmp(url, rewrite[i]->instead_of[j].s) &&
49 + (!longest ||
50 + longest->len < rewrite[i]->instead_of[j].len)) {
51 + longest = &(rewrite[i]->instead_of[j]);
52 + longest_i = i;
53 }
54 }
55 }
47 - return url;
56 + if (!longest)
57 + return url;
58 +
59 + ret = malloc(rewrite[longest_i]->baselen +
60 + (strlen(url) - longest->len) + 1);
61 + strcpy(ret, rewrite[longest_i]->base);
62 + strcpy(ret + rewrite[longest_i]->baselen, url + longest->len);
63 + return ret;
64 }
65
66 static void add_push_refspec(struct remote *remote, const char *ref)
@@ -137,27 +153,33 @@ static struct rewrite *make_rewrite(const char *base, int len)
153 int i;
154
155 for (i = 0; i < rewrite_nr; i++) {
140 - if (len ? (!strncmp(base, rewrite[i]->base, len) &&
141 - !rewrite[i]->base[len]) :
142 - !strcmp(base, rewrite[i]->base))
156 + if (len
157 + ? (len == rewrite[i]->baselen &&
158 + !strncmp(base, rewrite[i]->base, len))
159 + : !strcmp(base, rewrite[i]->base))
160 return rewrite[i];
161 }
162
163 ALLOC_GROW(rewrite, rewrite_nr + 1, rewrite_alloc);
164 ret = xcalloc(1, sizeof(struct rewrite));
165 rewrite[rewrite_nr++] = ret;
149 - if (len)
166 + if (len) {
167 ret->base = xstrndup(base, len);
151 - else
168 + ret->baselen = len;
169 + }
170 + else {
171 ret->base = xstrdup(base);
153 -
172 + ret->baselen = strlen(base);
173 + }
174 return ret;
175 }
176
177 static void add_instead_of(struct rewrite *rewrite, const char *instead_of)
178 {
179 ALLOC_GROW(rewrite->instead_of, rewrite->instead_of_nr + 1, rewrite->instead_of_alloc);
160 - rewrite->instead_of[rewrite->instead_of_nr++] = instead_of;
180 + rewrite->instead_of[rewrite->instead_of_nr].s = instead_of;
181 + rewrite->instead_of[rewrite->instead_of_nr].len = strlen(instead_of);
182 + rewrite->instead_of_nr++;
183 }
184
185 static void read_remotes_file(struct remote *remote)