Merge branch 'jk/remote-wo-url'
Memory ownership rules for the in-core representation of remote.*.url configuration values have been straightened out, which resulted in a few leak fixes and code clarification. * jk/remote-wo-url: remote: drop checks for zero-url case remote: always require at least one url in a remote t5801: test remote.*.vcs config t5801: make remote-testgit GIT_DIR setup more robust remote: allow resetting url list config: document remote.*.url/pushurl interaction remote: simplify url/pushurl selection remote: use strvecs to store remote url/pushurl remote: transfer ownership of memory in add_url(), etc remote: refactor alias_url() memory ownership archive: fix check for missing url
This commit is contained in:
@ -5,10 +5,19 @@ remote.pushDefault::
|
|||||||
|
|
||||||
remote.<name>.url::
|
remote.<name>.url::
|
||||||
The URL of a remote repository. See linkgit:git-fetch[1] or
|
The URL of a remote repository. See linkgit:git-fetch[1] or
|
||||||
linkgit:git-push[1].
|
linkgit:git-push[1]. A configured remote can have multiple URLs;
|
||||||
|
in this case the first is used for fetching, and all are used
|
||||||
|
for pushing (assuming no `remote.<name>.pushurl` is defined).
|
||||||
|
Setting this key to the empty string clears the list of urls,
|
||||||
|
allowing you to override earlier config.
|
||||||
|
|
||||||
remote.<name>.pushurl::
|
remote.<name>.pushurl::
|
||||||
The push URL of a remote repository. See linkgit:git-push[1].
|
The push URL of a remote repository. See linkgit:git-push[1].
|
||||||
|
If a `pushurl` option is present in a configured remote, it
|
||||||
|
is used for pushing instead of `remote.<name>.url`. A configured
|
||||||
|
remote can have multiple push URLs; in this case a push goes to
|
||||||
|
all of them. Setting this key to the empty string clears the
|
||||||
|
list of urls, allowing you to override earlier config.
|
||||||
|
|
||||||
remote.<name>.proxy::
|
remote.<name>.proxy::
|
||||||
For remotes that require curl (http, https and ftp), the URL to
|
For remotes that require curl (http, https and ftp), the URL to
|
||||||
|
@ -31,9 +31,7 @@ static int run_remote_archiver(int argc, const char **argv,
|
|||||||
struct packet_reader reader;
|
struct packet_reader reader;
|
||||||
|
|
||||||
_remote = remote_get(remote);
|
_remote = remote_get(remote);
|
||||||
if (!_remote->url[0])
|
transport = transport_get(_remote, _remote->url.v[0]);
|
||||||
die(_("git archive: Remote with no URL"));
|
|
||||||
transport = transport_get(_remote, _remote->url[0]);
|
|
||||||
transport_connect(transport, "git-upload-archive", exec, fd);
|
transport_connect(transport, "git-upload-archive", exec, fd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1294,7 +1294,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||||||
refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
|
refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
|
||||||
branch_top.buf);
|
branch_top.buf);
|
||||||
|
|
||||||
path = get_repo_path(remote->url[0], &is_bundle);
|
path = get_repo_path(remote->url.v[0], &is_bundle);
|
||||||
is_local = option_local != 0 && path && !is_bundle;
|
is_local = option_local != 0 && path && !is_bundle;
|
||||||
if (is_local) {
|
if (is_local) {
|
||||||
if (option_depth)
|
if (option_depth)
|
||||||
@ -1316,7 +1316,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||||||
if (option_local > 0 && !is_local)
|
if (option_local > 0 && !is_local)
|
||||||
warning(_("--local is ignored"));
|
warning(_("--local is ignored"));
|
||||||
|
|
||||||
transport = transport_get(remote, path ? path : remote->url[0]);
|
transport = transport_get(remote, path ? path : remote->url.v[0]);
|
||||||
transport_set_verbosity(transport, option_verbosity, option_progress);
|
transport_set_verbosity(transport, option_verbosity, option_progress);
|
||||||
transport->family = family;
|
transport->family = family;
|
||||||
transport->cloning = 1;
|
transport->cloning = 1;
|
||||||
|
@ -112,11 +112,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
|
|||||||
die("bad repository '%s'", dest);
|
die("bad repository '%s'", dest);
|
||||||
die("No remote configured to list refs from.");
|
die("No remote configured to list refs from.");
|
||||||
}
|
}
|
||||||
if (!remote->url_nr)
|
|
||||||
die("remote %s has no configured URL", dest);
|
|
||||||
|
|
||||||
if (get_url) {
|
if (get_url) {
|
||||||
printf("%s\n", *remote->url);
|
printf("%s\n", remote->url.v[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +131,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dest && !quiet)
|
if (!dest && !quiet)
|
||||||
fprintf(stderr, "From %s\n", *remote->url);
|
fprintf(stderr, "From %s\n", remote->url.v[0]);
|
||||||
for ( ; ref; ref = ref->next) {
|
for ( ; ref; ref = ref->next) {
|
||||||
struct ref_array_item *item;
|
struct ref_array_item *item;
|
||||||
if (!check_ref_type(ref, flags))
|
if (!check_ref_type(ref, flags))
|
||||||
|
@ -141,16 +141,6 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
|
|||||||
free_refs(local_refs);
|
free_refs(local_refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push_url_of_remote(struct remote *remote, const char ***url_p)
|
|
||||||
{
|
|
||||||
if (remote->pushurl_nr) {
|
|
||||||
*url_p = remote->pushurl;
|
|
||||||
return remote->pushurl_nr;
|
|
||||||
}
|
|
||||||
*url_p = remote->url;
|
|
||||||
return remote->url_nr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NORETURN void die_push_simple(struct branch *branch,
|
static NORETURN void die_push_simple(struct branch *branch,
|
||||||
struct remote *remote)
|
struct remote *remote)
|
||||||
{
|
{
|
||||||
@ -434,8 +424,7 @@ static int do_push(int flags,
|
|||||||
struct remote *remote)
|
struct remote *remote)
|
||||||
{
|
{
|
||||||
int i, errs;
|
int i, errs;
|
||||||
const char **url;
|
struct strvec *url;
|
||||||
int url_nr;
|
|
||||||
struct refspec *push_refspec = &rs;
|
struct refspec *push_refspec = &rs;
|
||||||
|
|
||||||
if (push_options->nr)
|
if (push_options->nr)
|
||||||
@ -448,19 +437,10 @@ static int do_push(int flags,
|
|||||||
setup_default_push_refspecs(&flags, remote);
|
setup_default_push_refspecs(&flags, remote);
|
||||||
}
|
}
|
||||||
errs = 0;
|
errs = 0;
|
||||||
url_nr = push_url_of_remote(remote, &url);
|
url = push_url_of_remote(remote);
|
||||||
if (url_nr) {
|
for (i = 0; i < url->nr; i++) {
|
||||||
for (i = 0; i < url_nr; i++) {
|
|
||||||
struct transport *transport =
|
|
||||||
transport_get(remote, url[i]);
|
|
||||||
if (flags & TRANSPORT_PUSH_OPTIONS)
|
|
||||||
transport->push_options = push_options;
|
|
||||||
if (push_with_options(transport, push_refspec, flags))
|
|
||||||
errs++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
struct transport *transport =
|
struct transport *transport =
|
||||||
transport_get(remote, NULL);
|
transport_get(remote, url->v[i]);
|
||||||
if (flags & TRANSPORT_PUSH_OPTIONS)
|
if (flags & TRANSPORT_PUSH_OPTIONS)
|
||||||
transport->push_options = push_options;
|
transport->push_options = push_options;
|
||||||
if (push_with_options(transport, push_refspec, flags))
|
if (push_with_options(transport, push_refspec, flags))
|
||||||
|
@ -619,8 +619,8 @@ static int migrate_file(struct remote *remote)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
strbuf_addf(&buf, "remote.%s.url", remote->name);
|
strbuf_addf(&buf, "remote.%s.url", remote->name);
|
||||||
for (i = 0; i < remote->url_nr; i++)
|
for (i = 0; i < remote->url.nr; i++)
|
||||||
git_config_set_multivar(buf.buf, remote->url[i], "^$", 0);
|
git_config_set_multivar(buf.buf, remote->url.v[i], "^$", 0);
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(&buf);
|
||||||
strbuf_addf(&buf, "remote.%s.push", remote->name);
|
strbuf_addf(&buf, "remote.%s.push", remote->name);
|
||||||
for (i = 0; i < remote->push.raw_nr; i++)
|
for (i = 0; i < remote->push.raw_nr; i++)
|
||||||
@ -1002,8 +1002,7 @@ static int get_remote_ref_states(const char *name,
|
|||||||
struct transport *transport;
|
struct transport *transport;
|
||||||
const struct ref *remote_refs;
|
const struct ref *remote_refs;
|
||||||
|
|
||||||
transport = transport_get(states->remote, states->remote->url_nr > 0 ?
|
transport = transport_get(states->remote, states->remote->url.v[0]);
|
||||||
states->remote->url[0] : NULL);
|
|
||||||
remote_refs = transport_get_remote_refs(transport, NULL);
|
remote_refs = transport_get_remote_refs(transport, NULL);
|
||||||
|
|
||||||
states->queried = 1;
|
states->queried = 1;
|
||||||
@ -1213,15 +1212,15 @@ static int get_one_entry(struct remote *remote, void *priv)
|
|||||||
{
|
{
|
||||||
struct string_list *list = priv;
|
struct string_list *list = priv;
|
||||||
struct strbuf remote_info_buf = STRBUF_INIT;
|
struct strbuf remote_info_buf = STRBUF_INIT;
|
||||||
const char **url;
|
struct strvec *url;
|
||||||
int i, url_nr;
|
int i;
|
||||||
|
|
||||||
if (remote->url_nr > 0) {
|
if (remote->url.nr > 0) {
|
||||||
struct strbuf promisor_config = STRBUF_INIT;
|
struct strbuf promisor_config = STRBUF_INIT;
|
||||||
const char *partial_clone_filter = NULL;
|
const char *partial_clone_filter = NULL;
|
||||||
|
|
||||||
strbuf_addf(&promisor_config, "remote.%s.partialclonefilter", remote->name);
|
strbuf_addf(&promisor_config, "remote.%s.partialclonefilter", remote->name);
|
||||||
strbuf_addf(&remote_info_buf, "%s (fetch)", remote->url[0]);
|
strbuf_addf(&remote_info_buf, "%s (fetch)", remote->url.v[0]);
|
||||||
if (!git_config_get_string_tmp(promisor_config.buf, &partial_clone_filter))
|
if (!git_config_get_string_tmp(promisor_config.buf, &partial_clone_filter))
|
||||||
strbuf_addf(&remote_info_buf, " [%s]", partial_clone_filter);
|
strbuf_addf(&remote_info_buf, " [%s]", partial_clone_filter);
|
||||||
|
|
||||||
@ -1230,16 +1229,10 @@ static int get_one_entry(struct remote *remote, void *priv)
|
|||||||
strbuf_detach(&remote_info_buf, NULL);
|
strbuf_detach(&remote_info_buf, NULL);
|
||||||
} else
|
} else
|
||||||
string_list_append(list, remote->name)->util = NULL;
|
string_list_append(list, remote->name)->util = NULL;
|
||||||
if (remote->pushurl_nr) {
|
url = push_url_of_remote(remote);
|
||||||
url = remote->pushurl;
|
for (i = 0; i < url->nr; i++)
|
||||||
url_nr = remote->pushurl_nr;
|
|
||||||
} else {
|
|
||||||
url = remote->url;
|
|
||||||
url_nr = remote->url_nr;
|
|
||||||
}
|
|
||||||
for (i = 0; i < url_nr; i++)
|
|
||||||
{
|
{
|
||||||
strbuf_addf(&remote_info_buf, "%s (push)", url[i]);
|
strbuf_addf(&remote_info_buf, "%s (push)", url->v[i]);
|
||||||
string_list_append(list, remote->name)->util =
|
string_list_append(list, remote->name)->util =
|
||||||
strbuf_detach(&remote_info_buf, NULL);
|
strbuf_detach(&remote_info_buf, NULL);
|
||||||
}
|
}
|
||||||
@ -1295,28 +1288,20 @@ static int show(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
for (; argc; argc--, argv++) {
|
for (; argc; argc--, argv++) {
|
||||||
int i;
|
int i;
|
||||||
const char **url;
|
struct strvec *url;
|
||||||
int url_nr;
|
|
||||||
|
|
||||||
get_remote_ref_states(*argv, &info.states, query_flag);
|
get_remote_ref_states(*argv, &info.states, query_flag);
|
||||||
|
|
||||||
printf_ln(_("* remote %s"), *argv);
|
printf_ln(_("* remote %s"), *argv);
|
||||||
printf_ln(_(" Fetch URL: %s"), info.states.remote->url_nr > 0 ?
|
printf_ln(_(" Fetch URL: %s"), info.states.remote->url.v[0]);
|
||||||
info.states.remote->url[0] : _("(no URL)"));
|
url = push_url_of_remote(info.states.remote);
|
||||||
if (info.states.remote->pushurl_nr) {
|
for (i = 0; i < url->nr; i++)
|
||||||
url = info.states.remote->pushurl;
|
|
||||||
url_nr = info.states.remote->pushurl_nr;
|
|
||||||
} else {
|
|
||||||
url = info.states.remote->url;
|
|
||||||
url_nr = info.states.remote->url_nr;
|
|
||||||
}
|
|
||||||
for (i = 0; i < url_nr; i++)
|
|
||||||
/*
|
/*
|
||||||
* TRANSLATORS: the colon ':' should align
|
* TRANSLATORS: the colon ':' should align
|
||||||
* with the one in " Fetch URL: %s"
|
* with the one in " Fetch URL: %s"
|
||||||
* translation.
|
* translation.
|
||||||
*/
|
*/
|
||||||
printf_ln(_(" Push URL: %s"), url[i]);
|
printf_ln(_(" Push URL: %s"), url->v[i]);
|
||||||
if (!i)
|
if (!i)
|
||||||
printf_ln(_(" Push URL: %s"), _("(no URL)"));
|
printf_ln(_(" Push URL: %s"), _("(no URL)"));
|
||||||
if (no_query)
|
if (no_query)
|
||||||
@ -1453,10 +1438,7 @@ static int prune_remote(const char *remote, int dry_run)
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf_ln(_("Pruning %s"), remote);
|
printf_ln(_("Pruning %s"), remote);
|
||||||
printf_ln(_("URL: %s"),
|
printf_ln(_("URL: %s"), states.remote->url.v[0]);
|
||||||
states.remote->url_nr
|
|
||||||
? states.remote->url[0]
|
|
||||||
: _("(no URL)"));
|
|
||||||
|
|
||||||
for_each_string_list_item(item, &states.stale)
|
for_each_string_list_item(item, &states.stale)
|
||||||
string_list_append(&refs_to_prune, item->util);
|
string_list_append(&refs_to_prune, item->util);
|
||||||
@ -1622,8 +1604,7 @@ static int get_url(int argc, const char **argv, const char *prefix)
|
|||||||
int i, push_mode = 0, all_mode = 0;
|
int i, push_mode = 0, all_mode = 0;
|
||||||
const char *remotename = NULL;
|
const char *remotename = NULL;
|
||||||
struct remote *remote;
|
struct remote *remote;
|
||||||
const char **url;
|
struct strvec *url;
|
||||||
int url_nr;
|
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOL('\0', "push", &push_mode,
|
OPT_BOOL('\0', "push", &push_mode,
|
||||||
N_("query push URLs rather than fetch URLs")),
|
N_("query push URLs rather than fetch URLs")),
|
||||||
@ -1645,27 +1626,13 @@ static int get_url(int argc, const char **argv, const char *prefix)
|
|||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
url_nr = 0;
|
url = push_mode ? push_url_of_remote(remote) : &remote->url;
|
||||||
if (push_mode) {
|
|
||||||
url = remote->pushurl;
|
|
||||||
url_nr = remote->pushurl_nr;
|
|
||||||
}
|
|
||||||
/* else fetch mode */
|
|
||||||
|
|
||||||
/* Use the fetch URL when no push URLs were found or requested. */
|
|
||||||
if (!url_nr) {
|
|
||||||
url = remote->url;
|
|
||||||
url_nr = remote->url_nr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!url_nr)
|
|
||||||
die(_("no URLs configured for remote '%s'"), remotename);
|
|
||||||
|
|
||||||
if (all_mode) {
|
if (all_mode) {
|
||||||
for (i = 0; i < url_nr; i++)
|
for (i = 0; i < url->nr; i++)
|
||||||
printf_ln("%s", url[i]);
|
printf_ln("%s", url->v[i]);
|
||||||
} else {
|
} else {
|
||||||
printf_ln("%s", *url);
|
printf_ln("%s", url->v[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1680,8 +1647,7 @@ static int set_url(int argc, const char **argv, const char *prefix)
|
|||||||
const char *oldurl = NULL;
|
const char *oldurl = NULL;
|
||||||
struct remote *remote;
|
struct remote *remote;
|
||||||
regex_t old_regex;
|
regex_t old_regex;
|
||||||
const char **urlset;
|
struct strvec *urlset;
|
||||||
int urlset_nr;
|
|
||||||
struct strbuf name_buf = STRBUF_INIT;
|
struct strbuf name_buf = STRBUF_INIT;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOL('\0', "push", &push_mode,
|
OPT_BOOL('\0', "push", &push_mode,
|
||||||
@ -1718,12 +1684,10 @@ static int set_url(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
if (push_mode) {
|
if (push_mode) {
|
||||||
strbuf_addf(&name_buf, "remote.%s.pushurl", remotename);
|
strbuf_addf(&name_buf, "remote.%s.pushurl", remotename);
|
||||||
urlset = remote->pushurl;
|
urlset = &remote->pushurl;
|
||||||
urlset_nr = remote->pushurl_nr;
|
|
||||||
} else {
|
} else {
|
||||||
strbuf_addf(&name_buf, "remote.%s.url", remotename);
|
strbuf_addf(&name_buf, "remote.%s.url", remotename);
|
||||||
urlset = remote->url;
|
urlset = &remote->url;
|
||||||
urlset_nr = remote->url_nr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Special cases that add new entry. */
|
/* Special cases that add new entry. */
|
||||||
@ -1740,8 +1704,8 @@ static int set_url(int argc, const char **argv, const char *prefix)
|
|||||||
if (regcomp(&old_regex, oldurl, REG_EXTENDED))
|
if (regcomp(&old_regex, oldurl, REG_EXTENDED))
|
||||||
die(_("Invalid old URL pattern: %s"), oldurl);
|
die(_("Invalid old URL pattern: %s"), oldurl);
|
||||||
|
|
||||||
for (i = 0; i < urlset_nr; i++)
|
for (i = 0; i < urlset->nr; i++)
|
||||||
if (!regexec(&old_regex, urlset[i], 0, NULL, 0))
|
if (!regexec(&old_regex, urlset->v[i], 0, NULL, 0))
|
||||||
matches++;
|
matches++;
|
||||||
else
|
else
|
||||||
negative_matches++;
|
negative_matches++;
|
||||||
|
@ -1576,7 +1576,7 @@ int cmd_main(int argc, const char **argv)
|
|||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
end_url_with_slash(&url, argv[2]);
|
end_url_with_slash(&url, argv[2]);
|
||||||
} else {
|
} else {
|
||||||
end_url_with_slash(&url, remote->url[0]);
|
end_url_with_slash(&url, remote->url.v[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
http_init(remote, url.buf, 0);
|
http_init(remote, url.buf, 0);
|
||||||
|
94
remote.c
94
remote.c
@ -34,10 +34,10 @@ struct counted_string {
|
|||||||
|
|
||||||
static int valid_remote(const struct remote *remote)
|
static int valid_remote(const struct remote *remote)
|
||||||
{
|
{
|
||||||
return (!!remote->url) || (!!remote->foreign_vcs);
|
return !!remote->url.nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *alias_url(const char *url, struct rewrites *r)
|
static char *alias_url(const char *url, struct rewrites *r)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
struct counted_string *longest;
|
struct counted_string *longest;
|
||||||
@ -58,36 +58,43 @@ static const char *alias_url(const char *url, struct rewrites *r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!longest)
|
if (!longest)
|
||||||
return url;
|
return NULL;
|
||||||
|
|
||||||
return xstrfmt("%s%s", r->rewrite[longest_i]->base, url + longest->len);
|
return xstrfmt("%s%s", r->rewrite[longest_i]->base, url + longest->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_url(struct remote *remote, const char *url)
|
static void add_url(struct remote *remote, const char *url)
|
||||||
{
|
{
|
||||||
ALLOC_GROW(remote->url, remote->url_nr + 1, remote->url_alloc);
|
if (*url)
|
||||||
remote->url[remote->url_nr++] = url;
|
strvec_push(&remote->url, url);
|
||||||
|
else
|
||||||
|
strvec_clear(&remote->url);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_pushurl(struct remote *remote, const char *pushurl)
|
static void add_pushurl(struct remote *remote, const char *pushurl)
|
||||||
{
|
{
|
||||||
ALLOC_GROW(remote->pushurl, remote->pushurl_nr + 1, remote->pushurl_alloc);
|
if (*pushurl)
|
||||||
remote->pushurl[remote->pushurl_nr++] = pushurl;
|
strvec_push(&remote->pushurl, pushurl);
|
||||||
|
else
|
||||||
|
strvec_clear(&remote->pushurl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_pushurl_alias(struct remote_state *remote_state,
|
static void add_pushurl_alias(struct remote_state *remote_state,
|
||||||
struct remote *remote, const char *url)
|
struct remote *remote, const char *url)
|
||||||
{
|
{
|
||||||
const char *pushurl = alias_url(url, &remote_state->rewrites_push);
|
char *alias = alias_url(url, &remote_state->rewrites_push);
|
||||||
if (pushurl != url)
|
if (alias)
|
||||||
add_pushurl(remote, pushurl);
|
add_pushurl(remote, alias);
|
||||||
|
free(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_url_alias(struct remote_state *remote_state,
|
static void add_url_alias(struct remote_state *remote_state,
|
||||||
struct remote *remote, const char *url)
|
struct remote *remote, const char *url)
|
||||||
{
|
{
|
||||||
add_url(remote, alias_url(url, &remote_state->rewrites));
|
char *alias = alias_url(url, &remote_state->rewrites);
|
||||||
|
add_url(remote, alias ? alias : url);
|
||||||
add_pushurl_alias(remote_state, remote, url);
|
add_pushurl_alias(remote_state, remote, url);
|
||||||
|
free(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct remotes_hash_key {
|
struct remotes_hash_key {
|
||||||
@ -149,18 +156,12 @@ static struct remote *make_remote(struct remote_state *remote_state,
|
|||||||
|
|
||||||
static void remote_clear(struct remote *remote)
|
static void remote_clear(struct remote *remote)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
free((char *)remote->name);
|
free((char *)remote->name);
|
||||||
free((char *)remote->foreign_vcs);
|
free((char *)remote->foreign_vcs);
|
||||||
|
|
||||||
for (i = 0; i < remote->url_nr; i++)
|
strvec_clear(&remote->url);
|
||||||
free((char *)remote->url[i]);
|
strvec_clear(&remote->pushurl);
|
||||||
FREE_AND_NULL(remote->url);
|
|
||||||
|
|
||||||
for (i = 0; i < remote->pushurl_nr; i++)
|
|
||||||
free((char *)remote->pushurl[i]);
|
|
||||||
FREE_AND_NULL(remote->pushurl);
|
|
||||||
free((char *)remote->receivepack);
|
free((char *)remote->receivepack);
|
||||||
free((char *)remote->uploadpack);
|
free((char *)remote->uploadpack);
|
||||||
FREE_AND_NULL(remote->http_proxy);
|
FREE_AND_NULL(remote->http_proxy);
|
||||||
@ -294,7 +295,7 @@ static void read_remotes_file(struct remote_state *remote_state,
|
|||||||
|
|
||||||
if (skip_prefix(buf.buf, "URL:", &v))
|
if (skip_prefix(buf.buf, "URL:", &v))
|
||||||
add_url_alias(remote_state, remote,
|
add_url_alias(remote_state, remote,
|
||||||
xstrdup(skip_spaces(v)));
|
skip_spaces(v));
|
||||||
else if (skip_prefix(buf.buf, "Push:", &v))
|
else if (skip_prefix(buf.buf, "Push:", &v))
|
||||||
refspec_append(&remote->push, skip_spaces(v));
|
refspec_append(&remote->push, skip_spaces(v));
|
||||||
else if (skip_prefix(buf.buf, "Pull:", &v))
|
else if (skip_prefix(buf.buf, "Pull:", &v))
|
||||||
@ -337,7 +338,7 @@ static void read_branches_file(struct remote_state *remote_state,
|
|||||||
else
|
else
|
||||||
frag = to_free = repo_default_branch_name(the_repository, 0);
|
frag = to_free = repo_default_branch_name(the_repository, 0);
|
||||||
|
|
||||||
add_url_alias(remote_state, remote, strbuf_detach(&buf, NULL));
|
add_url_alias(remote_state, remote, buf.buf);
|
||||||
refspec_appendf(&remote->fetch, "refs/heads/%s:refs/heads/%s",
|
refspec_appendf(&remote->fetch, "refs/heads/%s:refs/heads/%s",
|
||||||
frag, remote->name);
|
frag, remote->name);
|
||||||
|
|
||||||
@ -348,6 +349,7 @@ static void read_branches_file(struct remote_state *remote_state,
|
|||||||
refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag);
|
refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag);
|
||||||
remote->fetch_tags = 1; /* always auto-follow */
|
remote->fetch_tags = 1; /* always auto-follow */
|
||||||
|
|
||||||
|
strbuf_release(&buf);
|
||||||
free(to_free);
|
free(to_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,15 +434,13 @@ static int handle_config(const char *key, const char *value,
|
|||||||
else if (!strcmp(subkey, "prunetags"))
|
else if (!strcmp(subkey, "prunetags"))
|
||||||
remote->prune_tags = git_config_bool(key, value);
|
remote->prune_tags = git_config_bool(key, value);
|
||||||
else if (!strcmp(subkey, "url")) {
|
else if (!strcmp(subkey, "url")) {
|
||||||
char *v;
|
if (!value)
|
||||||
if (git_config_string(&v, key, value))
|
return config_error_nonbool(key);
|
||||||
return -1;
|
add_url(remote, value);
|
||||||
add_url(remote, v);
|
|
||||||
} else if (!strcmp(subkey, "pushurl")) {
|
} else if (!strcmp(subkey, "pushurl")) {
|
||||||
char *v;
|
if (!value)
|
||||||
if (git_config_string(&v, key, value))
|
return config_error_nonbool(key);
|
||||||
return -1;
|
add_pushurl(remote, value);
|
||||||
add_pushurl(remote, v);
|
|
||||||
} else if (!strcmp(subkey, "push")) {
|
} else if (!strcmp(subkey, "push")) {
|
||||||
char *v;
|
char *v;
|
||||||
if (git_config_string(&v, key, value))
|
if (git_config_string(&v, key, value))
|
||||||
@ -493,20 +493,25 @@ static void alias_all_urls(struct remote_state *remote_state)
|
|||||||
int add_pushurl_aliases;
|
int add_pushurl_aliases;
|
||||||
if (!remote_state->remotes[i])
|
if (!remote_state->remotes[i])
|
||||||
continue;
|
continue;
|
||||||
for (j = 0; j < remote_state->remotes[i]->pushurl_nr; j++) {
|
for (j = 0; j < remote_state->remotes[i]->pushurl.nr; j++) {
|
||||||
remote_state->remotes[i]->pushurl[j] =
|
char *alias = alias_url(remote_state->remotes[i]->pushurl.v[j],
|
||||||
alias_url(remote_state->remotes[i]->pushurl[j],
|
&remote_state->rewrites);
|
||||||
&remote_state->rewrites);
|
if (alias)
|
||||||
|
strvec_replace(&remote_state->remotes[i]->pushurl,
|
||||||
|
j, alias);
|
||||||
}
|
}
|
||||||
add_pushurl_aliases = remote_state->remotes[i]->pushurl_nr == 0;
|
add_pushurl_aliases = remote_state->remotes[i]->pushurl.nr == 0;
|
||||||
for (j = 0; j < remote_state->remotes[i]->url_nr; j++) {
|
for (j = 0; j < remote_state->remotes[i]->url.nr; j++) {
|
||||||
|
char *alias;
|
||||||
if (add_pushurl_aliases)
|
if (add_pushurl_aliases)
|
||||||
add_pushurl_alias(
|
add_pushurl_alias(
|
||||||
remote_state, remote_state->remotes[i],
|
remote_state, remote_state->remotes[i],
|
||||||
remote_state->remotes[i]->url[j]);
|
remote_state->remotes[i]->url.v[j]);
|
||||||
remote_state->remotes[i]->url[j] =
|
alias = alias_url(remote_state->remotes[i]->url.v[j],
|
||||||
alias_url(remote_state->remotes[i]->url[j],
|
|
||||||
&remote_state->rewrites);
|
&remote_state->rewrites);
|
||||||
|
if (alias)
|
||||||
|
strvec_replace(&remote_state->remotes[i]->url,
|
||||||
|
j, alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -646,10 +651,10 @@ static void validate_remote_url(struct remote *remote)
|
|||||||
else
|
else
|
||||||
die(_("unrecognized value transfer.credentialsInUrl: '%s'"), value);
|
die(_("unrecognized value transfer.credentialsInUrl: '%s'"), value);
|
||||||
|
|
||||||
for (i = 0; i < remote->url_nr; i++) {
|
for (i = 0; i < remote->url.nr; i++) {
|
||||||
struct url_info url_info = { 0 };
|
struct url_info url_info = { 0 };
|
||||||
|
|
||||||
if (!url_normalize(remote->url[i], &url_info) ||
|
if (!url_normalize(remote->url.v[i], &url_info) ||
|
||||||
!url_info.passwd_off)
|
!url_info.passwd_off)
|
||||||
goto loop_cleanup;
|
goto loop_cleanup;
|
||||||
|
|
||||||
@ -823,13 +828,18 @@ struct ref *ref_remove_duplicates(struct ref *ref_map)
|
|||||||
int remote_has_url(struct remote *remote, const char *url)
|
int remote_has_url(struct remote *remote, const char *url)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < remote->url_nr; i++) {
|
for (i = 0; i < remote->url.nr; i++) {
|
||||||
if (!strcmp(remote->url[i], url))
|
if (!strcmp(remote->url.v[i], url))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct strvec *push_url_of_remote(struct remote *remote)
|
||||||
|
{
|
||||||
|
return remote->pushurl.nr ? &remote->pushurl : &remote->url;
|
||||||
|
}
|
||||||
|
|
||||||
static int match_name_with_pattern(const char *key, const char *name,
|
static int match_name_with_pattern(const char *key, const char *name,
|
||||||
const char *value, char **result)
|
const char *value, char **result)
|
||||||
{
|
{
|
||||||
|
13
remote.h
13
remote.h
@ -4,6 +4,7 @@
|
|||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "refspec.h"
|
#include "refspec.h"
|
||||||
|
#include "strvec.h"
|
||||||
|
|
||||||
struct option;
|
struct option;
|
||||||
struct transport_ls_refs_options;
|
struct transport_ls_refs_options;
|
||||||
@ -68,16 +69,9 @@ struct remote {
|
|||||||
char *foreign_vcs;
|
char *foreign_vcs;
|
||||||
|
|
||||||
/* An array of all of the url_nr URLs configured for the remote */
|
/* An array of all of the url_nr URLs configured for the remote */
|
||||||
const char **url;
|
struct strvec url;
|
||||||
|
|
||||||
int url_nr;
|
|
||||||
int url_alloc;
|
|
||||||
|
|
||||||
/* An array of all of the pushurl_nr push URLs configured for the remote */
|
/* An array of all of the pushurl_nr push URLs configured for the remote */
|
||||||
const char **pushurl;
|
struct strvec pushurl;
|
||||||
|
|
||||||
int pushurl_nr;
|
|
||||||
int pushurl_alloc;
|
|
||||||
|
|
||||||
struct refspec push;
|
struct refspec push;
|
||||||
|
|
||||||
@ -129,6 +123,7 @@ typedef int each_remote_fn(struct remote *remote, void *priv);
|
|||||||
int for_each_remote(each_remote_fn fn, void *priv);
|
int for_each_remote(each_remote_fn fn, void *priv);
|
||||||
|
|
||||||
int remote_has_url(struct remote *remote, const char *url);
|
int remote_has_url(struct remote *remote, const char *url);
|
||||||
|
struct strvec *push_url_of_remote(struct remote *remote);
|
||||||
|
|
||||||
struct ref_push_report {
|
struct ref_push_report {
|
||||||
const char *ref_name;
|
const char *ref_name;
|
||||||
|
@ -88,8 +88,6 @@ static int cmd_ls_remote(int argc, const char **argv)
|
|||||||
die(_("bad repository '%s'"), dest);
|
die(_("bad repository '%s'"), dest);
|
||||||
die(_("no remote configured to get bundle URIs from"));
|
die(_("no remote configured to get bundle URIs from"));
|
||||||
}
|
}
|
||||||
if (!remote->url_nr)
|
|
||||||
die(_("remote '%s' has no configured URL"), dest);
|
|
||||||
|
|
||||||
transport = transport_get(remote, NULL);
|
transport = transport_get(remote, NULL);
|
||||||
if (transport_get_remote_bundle_uri(transport) < 0) {
|
if (transport_get_remote_bundle_uri(transport) < 0) {
|
||||||
|
@ -1492,4 +1492,40 @@ test_expect_success 'refs/remotes/* <src> refspec and unqualified <dst> DWIM and
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'empty config clears remote.*.url list' '
|
||||||
|
test_when_finished "git config --remove-section remote.multi" &&
|
||||||
|
git config --add remote.multi.url wrong-one &&
|
||||||
|
git config --add remote.multi.url wrong-two &&
|
||||||
|
git -c remote.multi.url= \
|
||||||
|
-c remote.multi.url=right-one \
|
||||||
|
-c remote.multi.url=right-two \
|
||||||
|
remote show -n multi >actual.raw &&
|
||||||
|
grep URL actual.raw >actual &&
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
Fetch URL: right-one
|
||||||
|
Push URL: right-one
|
||||||
|
Push URL: right-two
|
||||||
|
EOF
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'empty config clears remote.*.pushurl list' '
|
||||||
|
test_when_finished "git config --remove-section remote.multi" &&
|
||||||
|
git config --add remote.multi.url right &&
|
||||||
|
git config --add remote.multi.url will-be-ignored &&
|
||||||
|
git config --add remote.multi.pushurl wrong-push-one &&
|
||||||
|
git config --add remote.multi.pushurl wrong-push-two &&
|
||||||
|
git -c remote.multi.pushurl= \
|
||||||
|
-c remote.multi.pushurl=right-push-one \
|
||||||
|
-c remote.multi.pushurl=right-push-two \
|
||||||
|
remote show -n multi >actual.raw &&
|
||||||
|
grep URL actual.raw >actual &&
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
Fetch URL: right
|
||||||
|
Push URL: right-push-one
|
||||||
|
Push URL: right-push-two
|
||||||
|
EOF
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -38,6 +38,29 @@ test_expect_success 'cloning from local repo' '
|
|||||||
test_cmp server/file local/file
|
test_cmp server/file local/file
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'clone with remote.*.vcs config' '
|
||||||
|
GIT_TRACE=$PWD/vcs-clone.trace \
|
||||||
|
git clone --no-local -c remote.origin.vcs=testgit "$PWD/server" vcs-clone &&
|
||||||
|
test_grep remote-testgit vcs-clone.trace
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fetch with configured remote.*.vcs' '
|
||||||
|
git init vcs-fetch &&
|
||||||
|
git -C vcs-fetch config remote.origin.vcs testgit &&
|
||||||
|
git -C vcs-fetch config remote.origin.url "$PWD/server" &&
|
||||||
|
GIT_TRACE=$PWD/vcs-fetch.trace \
|
||||||
|
git -C vcs-fetch fetch origin &&
|
||||||
|
test_grep remote-testgit vcs-fetch.trace
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'vcs remote with no url' '
|
||||||
|
NOURL_UPSTREAM=$PWD/server &&
|
||||||
|
export NOURL_UPSTREAM &&
|
||||||
|
git init vcs-nourl &&
|
||||||
|
git -C vcs-nourl config remote.origin.vcs nourl &&
|
||||||
|
git -C vcs-nourl fetch origin
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'create new commit on remote' '
|
test_expect_success 'create new commit on remote' '
|
||||||
(cd server &&
|
(cd server &&
|
||||||
echo content >>file &&
|
echo content >>file &&
|
||||||
|
3
t/t5801/git-remote-nourl
Executable file
3
t/t5801/git-remote-nourl
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec git-remote-testgit "$1" "$NOURL_UPSTREAM"
|
@ -26,7 +26,8 @@ then
|
|||||||
t_refspec=""
|
t_refspec=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
GIT_DIR="$url/.git"
|
unset $(git rev-parse --local-env-vars)
|
||||||
|
GIT_DIR=$(git -C "$url" rev-parse --absolute-git-dir)
|
||||||
export GIT_DIR
|
export GIT_DIR
|
||||||
|
|
||||||
force=
|
force=
|
||||||
|
19
transport.c
19
transport.c
@ -1114,6 +1114,7 @@ static struct transport_vtable builtin_smart_vtable = {
|
|||||||
struct transport *transport_get(struct remote *remote, const char *url)
|
struct transport *transport_get(struct remote *remote, const char *url)
|
||||||
{
|
{
|
||||||
const char *helper;
|
const char *helper;
|
||||||
|
const char *p;
|
||||||
struct transport *ret = xcalloc(1, sizeof(*ret));
|
struct transport *ret = xcalloc(1, sizeof(*ret));
|
||||||
|
|
||||||
ret->progress = isatty(2);
|
ret->progress = isatty(2);
|
||||||
@ -1129,19 +1130,15 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
|||||||
ret->remote = remote;
|
ret->remote = remote;
|
||||||
helper = remote->foreign_vcs;
|
helper = remote->foreign_vcs;
|
||||||
|
|
||||||
if (!url && remote->url)
|
if (!url)
|
||||||
url = remote->url[0];
|
url = remote->url.v[0];
|
||||||
ret->url = url;
|
ret->url = url;
|
||||||
|
|
||||||
/* maybe it is a foreign URL? */
|
p = url;
|
||||||
if (url) {
|
while (is_urlschemechar(p == url, *p))
|
||||||
const char *p = url;
|
p++;
|
||||||
|
if (starts_with(p, "::"))
|
||||||
while (is_urlschemechar(p == url, *p))
|
helper = xstrndup(url, p - url);
|
||||||
p++;
|
|
||||||
if (starts_with(p, "::"))
|
|
||||||
helper = xstrndup(url, p - url);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (helper) {
|
if (helper) {
|
||||||
transport_helper_init(ret, helper);
|
transport_helper_init(ret, helper);
|
||||||
|
Reference in New Issue
Block a user