summaryrefslogtreecommitdiff
path: root/remote.c
diff options
context:
space:
mode:
Diffstat (limited to 'remote.c')
-rw-r--r--remote.c97
1 files changed, 94 insertions, 3 deletions
diff --git a/remote.c b/remote.c
index 457d8a4..0012954 100644
--- a/remote.c
+++ b/remote.c
@@ -2,6 +2,13 @@
#include "remote.h"
#include "refs.h"
+struct rewrite {
+ const char *base;
+ const char **instead_of;
+ int instead_of_nr;
+ int instead_of_alloc;
+};
+
static struct remote **remotes;
static int remotes_alloc;
static int remotes_nr;
@@ -13,9 +20,33 @@ static int branches_nr;
static struct branch *current_branch;
static const char *default_remote_name;
+static struct rewrite **rewrite;
+static int rewrite_alloc;
+static int rewrite_nr;
+
#define BUF_SIZE (2048)
static char buffer[BUF_SIZE];
+static const char *alias_url(const char *url)
+{
+ int i, j;
+ 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;
+ }
+ }
+ }
+ return url;
+}
+
static void add_push_refspec(struct remote *remote, const char *ref)
{
ALLOC_GROW(remote->push_refspec,
@@ -38,6 +69,11 @@ static void add_url(struct remote *remote, const char *url)
remote->url[remote->url_nr++] = url;
}
+static void add_url_alias(struct remote *remote, const char *url)
+{
+ add_url(remote, alias_url(url));
+}
+
static struct remote *make_remote(const char *name, int len)
{
struct remote *ret;
@@ -95,6 +131,35 @@ static struct branch *make_branch(const char *name, int len)
return ret;
}
+static struct rewrite *make_rewrite(const char *base, int len)
+{
+ struct rewrite *ret;
+ 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))
+ return rewrite[i];
+ }
+
+ ALLOC_GROW(rewrite, rewrite_nr + 1, rewrite_alloc);
+ ret = xcalloc(1, sizeof(struct rewrite));
+ rewrite[rewrite_nr++] = ret;
+ if (len)
+ ret->base = xstrndup(base, len);
+ else
+ ret->base = xstrdup(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;
+}
+
static void read_remotes_file(struct remote *remote)
{
FILE *f = fopen(git_path("remotes/%s", remote->name), "r");
@@ -128,7 +193,7 @@ static void read_remotes_file(struct remote *remote)
switch (value_list) {
case 0:
- add_url(remote, xstrdup(s));
+ add_url_alias(remote, xstrdup(s));
break;
case 1:
add_push_refspec(remote, xstrdup(s));
@@ -180,7 +245,7 @@ static void read_branches_file(struct remote *remote)
} else {
branch = "refs/heads/master";
}
- add_url(remote, p);
+ add_url_alias(remote, p);
add_fetch_refspec(remote, branch);
remote->fetch_tags = 1; /* always auto-follow */
}
@@ -210,6 +275,19 @@ static int handle_config(const char *key, const char *value)
}
return 0;
}
+ if (!prefixcmp(key, "url.")) {
+ struct rewrite *rewrite;
+ name = key + 5;
+ subkey = strrchr(name, '.');
+ if (!subkey)
+ return 0;
+ rewrite = make_rewrite(name, subkey - name);
+ if (!strcmp(subkey, ".insteadof")) {
+ if (!value)
+ return config_error_nonbool(key);
+ add_instead_of(rewrite, xstrdup(value));
+ }
+ }
if (prefixcmp(key, "remote."))
return 0;
name = key + 7;
@@ -261,6 +339,18 @@ static int handle_config(const char *key, const char *value)
return 0;
}
+static void alias_all_urls(void)
+{
+ int i, j;
+ for (i = 0; i < remotes_nr; i++) {
+ if (!remotes[i])
+ continue;
+ for (j = 0; j < remotes[i]->url_nr; j++) {
+ remotes[i]->url[j] = alias_url(remotes[i]->url[j]);
+ }
+ }
+}
+
static void read_config(void)
{
unsigned char sha1[20];
@@ -277,6 +367,7 @@ static void read_config(void)
make_branch(head_ref + strlen("refs/heads/"), 0);
}
git_config(handle_config);
+ alias_all_urls();
}
struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
@@ -342,7 +433,7 @@ struct remote *remote_get(const char *name)
read_branches_file(ret);
}
if (!ret->url)
- add_url(ret, name);
+ add_url_alias(ret, name);
if (!ret->url)
return NULL;
ret->fetch = parse_ref_spec(ret->fetch_refspec_nr, ret->fetch_refspec);