diff options
author | Junio C Hamano <gitster@pobox.com> | 2008-02-24 22:25:04 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-02-24 22:34:13 -0800 |
commit | 844112cac07d6413b9bb42d38527d2f7ca7c7801 (patch) | |
tree | 87413bdc1d9a5c1e85213cd54f7e5454d37e7b2b | |
parent | 55029ae4dac07942437c0c715ea7c8ac60dd3576 (diff) | |
download | git-844112cac07d6413b9bb42d38527d2f7ca7c7801.tar.gz git-844112cac07d6413b9bb42d38527d2f7ca7c7801.tar.xz |
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>
-rw-r--r-- | Documentation/config.txt | 5 | ||||
-rw-r--r-- | remote.c | 54 |
2 files changed, 40 insertions, 19 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt index 298138917..57b9b9986 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -894,9 +894,8 @@ url.<base>.insteadOf:: 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. @@ -2,9 +2,14 @@ #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; }; @@ -30,21 +35,32 @@ static char buffer[BUF_SIZE]; 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) @@ -137,27 +153,33 @@ static struct rewrite *make_rewrite(const char *base, int len) 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) |