aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2008-02-24 22:25:04 -0800
committerJunio C Hamano <gitster@pobox.com>2008-02-24 22:34:13 -0800
commit844112cac07d6413b9bb42d38527d2f7ca7c7801 (patch)
tree87413bdc1d9a5c1e85213cd54f7e5454d37e7b2b
parent55029ae4dac07942437c0c715ea7c8ac60dd3576 (diff)
downloadgit-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.txt5
-rw-r--r--remote.c54
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.
diff --git a/remote.c b/remote.c
index 0012954b6..1f8369675 100644
--- a/remote.c
+++ b/remote.c
@@ -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)