summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 55029ae)
raw | patch | inline | side by side (parent: 55029ae)
author | Junio C Hamano <gitster@pobox.com> | |
Mon, 25 Feb 2008 06:25:04 +0000 (22:25 -0800) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Mon, 25 Feb 2008 06:34:13 +0000 (22:34 -0800) |
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>
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>
Documentation/config.txt | patch | blob | history | |
remote.c | patch | blob | history |
index 298138917a3eb5a0f75ff11a09d286efef3d45b5..57b9b998639d509e0d092fa860ba1eaeee688c76 100644 (file)
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
methods, this feature allows people to specify any of the
equivalent URLs and have git automatically rewrite the URL to
the best alternative for the particular user, even for a
- never-before-seen repository on the site. The effect of
- having multiple `insteadOf` values from different
- `<base>` match to an URL is undefined.
+ never-before-seen repository on the site. When more than one
+ insteadOf strings match a given URL, the longest match is used.
user.email::
Your email address to be recorded in any newly created commits.
diff --git a/remote.c b/remote.c
index 0012954b6f795d75d442f4c58f29dc194888d022..1f836967588456b03c1390157ca04aad7b8e3eac 100644 (file)
--- a/remote.c
+++ b/remote.c
#include "remote.h"
#include "refs.h"
+struct counted_string {
+ size_t len;
+ const char *s;
+};
struct rewrite {
const char *base;
- const char **instead_of;
+ size_t baselen;
+ struct counted_string *instead_of;
int instead_of_nr;
int instead_of_alloc;
};
static const char *alias_url(const char *url)
{
int i, j;
+ char *ret;
+ struct counted_string *longest;
+ int longest_i;
+
+ longest = NULL;
+ longest_i = -1;
for (i = 0; i < rewrite_nr; i++) {
if (!rewrite[i])
continue;
for (j = 0; j < rewrite[i]->instead_of_nr; j++) {
- if (!prefixcmp(url, rewrite[i]->instead_of[j])) {
- char *ret = malloc(strlen(rewrite[i]->base) -
- strlen(rewrite[i]->instead_of[j]) +
- strlen(url) + 1);
- strcpy(ret, rewrite[i]->base);
- strcat(ret, url + strlen(rewrite[i]->instead_of[j]));
- return ret;
+ if (!prefixcmp(url, rewrite[i]->instead_of[j].s) &&
+ (!longest ||
+ longest->len < rewrite[i]->instead_of[j].len)) {
+ longest = &(rewrite[i]->instead_of[j]);
+ longest_i = i;
}
}
}
- return url;
+ if (!longest)
+ return url;
+
+ ret = malloc(rewrite[longest_i]->baselen +
+ (strlen(url) - longest->len) + 1);
+ strcpy(ret, rewrite[longest_i]->base);
+ strcpy(ret + rewrite[longest_i]->baselen, url + longest->len);
+ return ret;
}
static void add_push_refspec(struct remote *remote, const char *ref)
int i;
for (i = 0; i < rewrite_nr; i++) {
- if (len ? (!strncmp(base, rewrite[i]->base, len) &&
- !rewrite[i]->base[len]) :
- !strcmp(base, rewrite[i]->base))
+ if (len
+ ? (len == rewrite[i]->baselen &&
+ !strncmp(base, rewrite[i]->base, len))
+ : !strcmp(base, rewrite[i]->base))
return rewrite[i];
}
ALLOC_GROW(rewrite, rewrite_nr + 1, rewrite_alloc);
ret = xcalloc(1, sizeof(struct rewrite));
rewrite[rewrite_nr++] = ret;
- if (len)
+ if (len) {
ret->base = xstrndup(base, len);
- else
+ ret->baselen = len;
+ }
+ else {
ret->base = xstrdup(base);
-
+ ret->baselen = strlen(base);
+ }
return ret;
}
static void add_instead_of(struct rewrite *rewrite, const char *instead_of)
{
ALLOC_GROW(rewrite->instead_of, rewrite->instead_of_nr + 1, rewrite->instead_of_alloc);
- rewrite->instead_of[rewrite->instead_of_nr++] = instead_of;
+ rewrite->instead_of[rewrite->instead_of_nr].s = instead_of;
+ rewrite->instead_of[rewrite->instead_of_nr].len = strlen(instead_of);
+ rewrite->instead_of_nr++;
}
static void read_remotes_file(struct remote *remote)