Merge branch 'mg/pushurl'
* mg/pushurl: avoid NULL dereference on failed malloc builtin-remote: Make "remote -v" display push urls builtin-remote: Show push urls as well technical/api-remote: Describe new struct remote member pushurl t5516: Check pushurl config setting Allow push and fetch urls to be different
This commit is contained in:
commit
deded16d15
@ -1319,6 +1319,9 @@ 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].
|
||||||
|
|
||||||
|
remote.<name>.pushurl::
|
||||||
|
The push URL of a remote repository. See linkgit:git-push[1].
|
||||||
|
|
||||||
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
|
||||||
the proxy to use for that remote. Set to the empty string to
|
the proxy to use for that remote. Set to the empty string to
|
||||||
|
@ -18,6 +18,10 @@ struct remote
|
|||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
`pushurl`::
|
||||||
|
|
||||||
|
An array of all of the pushurl_nr push URLs configured for the remote
|
||||||
|
|
||||||
`push`::
|
`push`::
|
||||||
|
|
||||||
An array of refspecs configured for pushing, with
|
An array of refspecs configured for pushing, with
|
||||||
|
@ -27,10 +27,13 @@ config file would appear like this:
|
|||||||
------------
|
------------
|
||||||
[remote "<name>"]
|
[remote "<name>"]
|
||||||
url = <url>
|
url = <url>
|
||||||
|
pushurl = <pushurl>
|
||||||
push = <refspec>
|
push = <refspec>
|
||||||
fetch = <refspec>
|
fetch = <refspec>
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
The `<pushurl>` is used for pushes only. It is optional and defaults
|
||||||
|
to `<url>`.
|
||||||
|
|
||||||
Named file in `$GIT_DIR/remotes`
|
Named file in `$GIT_DIR/remotes`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -117,6 +117,8 @@ static int do_push(const char *repo, int flags)
|
|||||||
{
|
{
|
||||||
int i, errs;
|
int i, errs;
|
||||||
struct remote *remote = remote_get(repo);
|
struct remote *remote = remote_get(repo);
|
||||||
|
const char **url;
|
||||||
|
int url_nr;
|
||||||
|
|
||||||
if (!remote) {
|
if (!remote) {
|
||||||
if (repo)
|
if (repo)
|
||||||
@ -152,9 +154,16 @@ static int do_push(const char *repo, int flags)
|
|||||||
setup_default_push_refspecs();
|
setup_default_push_refspecs();
|
||||||
}
|
}
|
||||||
errs = 0;
|
errs = 0;
|
||||||
for (i = 0; i < remote->url_nr; i++) {
|
if (remote->pushurl_nr) {
|
||||||
|
url = remote->pushurl;
|
||||||
|
url_nr = remote->pushurl_nr;
|
||||||
|
} else {
|
||||||
|
url = remote->url;
|
||||||
|
url_nr = remote->url_nr;
|
||||||
|
}
|
||||||
|
for (i = 0; i < url_nr; i++) {
|
||||||
struct transport *transport =
|
struct transport *transport =
|
||||||
transport_get(remote, remote->url[i]);
|
transport_get(remote, url[i]);
|
||||||
int err;
|
int err;
|
||||||
if (receivepack)
|
if (receivepack)
|
||||||
transport_set_option(transport,
|
transport_set_option(transport,
|
||||||
@ -163,14 +172,14 @@ static int do_push(const char *repo, int flags)
|
|||||||
transport_set_option(transport, TRANS_OPT_THIN, "yes");
|
transport_set_option(transport, TRANS_OPT_THIN, "yes");
|
||||||
|
|
||||||
if (flags & TRANSPORT_PUSH_VERBOSE)
|
if (flags & TRANSPORT_PUSH_VERBOSE)
|
||||||
fprintf(stderr, "Pushing to %s\n", remote->url[i]);
|
fprintf(stderr, "Pushing to %s\n", url[i]);
|
||||||
err = transport_push(transport, refspec_nr, refspec, flags);
|
err = transport_push(transport, refspec_nr, refspec, flags);
|
||||||
err |= transport_disconnect(transport);
|
err |= transport_disconnect(transport);
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error("failed to push some refs to '%s'", remote->url[i]);
|
error("failed to push some refs to '%s'", url[i]);
|
||||||
errs++;
|
errs++;
|
||||||
}
|
}
|
||||||
return !!errs;
|
return !!errs;
|
||||||
|
@ -999,15 +999,25 @@ static int show(int argc, const char **argv)
|
|||||||
info.list = &info_list;
|
info.list = &info_list;
|
||||||
for (; argc; argc--, argv++) {
|
for (; argc; argc--, argv++) {
|
||||||
int i;
|
int i;
|
||||||
|
const char **url;
|
||||||
|
int url_nr;
|
||||||
|
|
||||||
get_remote_ref_states(*argv, &states, query_flag);
|
get_remote_ref_states(*argv, &states, query_flag);
|
||||||
|
|
||||||
printf("* remote %s\n", *argv);
|
printf("* remote %s\n", *argv);
|
||||||
if (states.remote->url_nr) {
|
printf(" Fetch URL: %s\n", states.remote->url_nr > 0 ?
|
||||||
for (i=0; i < states.remote->url_nr; i++)
|
states.remote->url[0] : "(no URL)");
|
||||||
printf(" URL: %s\n", states.remote->url[i]);
|
if (states.remote->pushurl_nr) {
|
||||||
} else
|
url = states.remote->pushurl;
|
||||||
printf(" URL: %s\n", "(no URL)");
|
url_nr = states.remote->pushurl_nr;
|
||||||
|
} else {
|
||||||
|
url = states.remote->url;
|
||||||
|
url_nr = states.remote->url_nr;
|
||||||
|
}
|
||||||
|
for (i=0; i < url_nr; i++)
|
||||||
|
printf(" Push URL: %s\n", url[i]);
|
||||||
|
if (!i)
|
||||||
|
printf(" Push URL: %s\n", "(no URL)");
|
||||||
if (no_query)
|
if (no_query)
|
||||||
printf(" HEAD branch: (not queried)\n");
|
printf(" HEAD branch: (not queried)\n");
|
||||||
else if (!states.heads.nr)
|
else if (!states.heads.nr)
|
||||||
@ -1266,14 +1276,31 @@ static int update(int argc, const char **argv)
|
|||||||
static int get_one_entry(struct remote *remote, void *priv)
|
static int get_one_entry(struct remote *remote, void *priv)
|
||||||
{
|
{
|
||||||
struct string_list *list = priv;
|
struct string_list *list = priv;
|
||||||
|
const char **url;
|
||||||
|
int i, url_nr;
|
||||||
|
void **utilp;
|
||||||
|
|
||||||
if (remote->url_nr > 0) {
|
if (remote->url_nr > 0) {
|
||||||
int i;
|
utilp = &(string_list_append(remote->name, list)->util);
|
||||||
|
*utilp = xmalloc(strlen(remote->url[0])+strlen(" (fetch)")+1);
|
||||||
for (i = 0; i < remote->url_nr; i++)
|
strcpy((char *) *utilp, remote->url[0]);
|
||||||
string_list_append(remote->name, list)->util = (void *)remote->url[i];
|
strcat((char *) *utilp, " (fetch)");
|
||||||
} else
|
} else
|
||||||
string_list_append(remote->name, list)->util = NULL;
|
string_list_append(remote->name, list)->util = NULL;
|
||||||
|
if (remote->pushurl_nr) {
|
||||||
|
url = remote->pushurl;
|
||||||
|
url_nr = remote->pushurl_nr;
|
||||||
|
} else {
|
||||||
|
url = remote->url;
|
||||||
|
url_nr = remote->url_nr;
|
||||||
|
}
|
||||||
|
for (i = 0; i < url_nr; i++)
|
||||||
|
{
|
||||||
|
utilp = &(string_list_append(remote->name, list)->util);
|
||||||
|
*utilp = xmalloc(strlen(url[i])+strlen(" (push)")+1);
|
||||||
|
strcpy((char *) *utilp, url[i]);
|
||||||
|
strcat((char *) *utilp, " (push)");
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1281,7 +1308,10 @@ static int get_one_entry(struct remote *remote, void *priv)
|
|||||||
static int show_all(void)
|
static int show_all(void)
|
||||||
{
|
{
|
||||||
struct string_list list = { NULL, 0, 0 };
|
struct string_list list = { NULL, 0, 0 };
|
||||||
int result = for_each_remote(get_one_entry, &list);
|
int result;
|
||||||
|
|
||||||
|
list.strdup_strings = 1;
|
||||||
|
result = for_each_remote(get_one_entry, &list);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
int i;
|
int i;
|
||||||
@ -1299,6 +1329,7 @@ static int show_all(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
string_list_clear(&list, 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
remote.c
14
remote.c
@ -106,6 +106,12 @@ static void add_url_alias(struct remote *remote, const char *url)
|
|||||||
add_url(remote, alias_url(url));
|
add_url(remote, alias_url(url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_pushurl(struct remote *remote, const char *pushurl)
|
||||||
|
{
|
||||||
|
ALLOC_GROW(remote->pushurl, remote->pushurl_nr + 1, remote->pushurl_alloc);
|
||||||
|
remote->pushurl[remote->pushurl_nr++] = pushurl;
|
||||||
|
}
|
||||||
|
|
||||||
static struct remote *make_remote(const char *name, int len)
|
static struct remote *make_remote(const char *name, int len)
|
||||||
{
|
{
|
||||||
struct remote *ret;
|
struct remote *ret;
|
||||||
@ -379,6 +385,11 @@ static int handle_config(const char *key, const char *value, void *cb)
|
|||||||
if (git_config_string(&v, key, value))
|
if (git_config_string(&v, key, value))
|
||||||
return -1;
|
return -1;
|
||||||
add_url(remote, v);
|
add_url(remote, v);
|
||||||
|
} else if (!strcmp(subkey, ".pushurl")) {
|
||||||
|
const char *v;
|
||||||
|
if (git_config_string(&v, key, value))
|
||||||
|
return -1;
|
||||||
|
add_pushurl(remote, v);
|
||||||
} else if (!strcmp(subkey, ".push")) {
|
} else if (!strcmp(subkey, ".push")) {
|
||||||
const char *v;
|
const char *v;
|
||||||
if (git_config_string(&v, key, value))
|
if (git_config_string(&v, key, value))
|
||||||
@ -424,6 +435,9 @@ static void alias_all_urls(void)
|
|||||||
for (j = 0; j < remotes[i]->url_nr; j++) {
|
for (j = 0; j < remotes[i]->url_nr; j++) {
|
||||||
remotes[i]->url[j] = alias_url(remotes[i]->url[j]);
|
remotes[i]->url[j] = alias_url(remotes[i]->url[j]);
|
||||||
}
|
}
|
||||||
|
for (j = 0; j < remotes[i]->pushurl_nr; j++) {
|
||||||
|
remotes[i]->pushurl[j] = alias_url(remotes[i]->pushurl[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
remote.h
4
remote.h
@ -15,6 +15,10 @@ struct remote {
|
|||||||
int url_nr;
|
int url_nr;
|
||||||
int url_alloc;
|
int url_alloc;
|
||||||
|
|
||||||
|
const char **pushurl;
|
||||||
|
int pushurl_nr;
|
||||||
|
int pushurl_alloc;
|
||||||
|
|
||||||
const char **push_refspec;
|
const char **push_refspec;
|
||||||
struct refspec *push;
|
struct refspec *push;
|
||||||
int push_refspec_nr;
|
int push_refspec_nr;
|
||||||
|
@ -135,7 +135,8 @@ EOF
|
|||||||
|
|
||||||
cat > test/expect << EOF
|
cat > test/expect << EOF
|
||||||
* remote origin
|
* remote origin
|
||||||
URL: $(pwd)/one
|
Fetch URL: $(pwd)/one
|
||||||
|
Push URL: $(pwd)/one
|
||||||
HEAD branch: master
|
HEAD branch: master
|
||||||
Remote branches:
|
Remote branches:
|
||||||
master new (next fetch will store in remotes/origin)
|
master new (next fetch will store in remotes/origin)
|
||||||
@ -151,7 +152,8 @@ cat > test/expect << EOF
|
|||||||
master pushes to master (local out of date)
|
master pushes to master (local out of date)
|
||||||
master pushes to upstream (create)
|
master pushes to upstream (create)
|
||||||
* remote two
|
* remote two
|
||||||
URL: ../two
|
Fetch URL: ../two
|
||||||
|
Push URL: ../three
|
||||||
HEAD branch (remote HEAD is ambiguous, may be one of the following):
|
HEAD branch (remote HEAD is ambiguous, may be one of the following):
|
||||||
another
|
another
|
||||||
master
|
master
|
||||||
@ -173,6 +175,7 @@ test_expect_success 'show' '
|
|||||||
git branch --track rebase origin/master &&
|
git branch --track rebase origin/master &&
|
||||||
git branch -d -r origin/master &&
|
git branch -d -r origin/master &&
|
||||||
git config --add remote.two.url ../two &&
|
git config --add remote.two.url ../two &&
|
||||||
|
git config --add remote.two.pushurl ../three &&
|
||||||
git config branch.rebase.rebase true &&
|
git config branch.rebase.rebase true &&
|
||||||
git config branch.octopus.merge "topic-a topic-b topic-c" &&
|
git config branch.octopus.merge "topic-a topic-b topic-c" &&
|
||||||
(cd ../one &&
|
(cd ../one &&
|
||||||
@ -191,7 +194,8 @@ test_expect_success 'show' '
|
|||||||
|
|
||||||
cat > test/expect << EOF
|
cat > test/expect << EOF
|
||||||
* remote origin
|
* remote origin
|
||||||
URL: $(pwd)/one
|
Fetch URL: $(pwd)/one
|
||||||
|
Push URL: $(pwd)/one
|
||||||
HEAD branch: (not queried)
|
HEAD branch: (not queried)
|
||||||
Remote branches: (status not queried)
|
Remote branches: (status not queried)
|
||||||
master
|
master
|
||||||
|
@ -419,6 +419,19 @@ test_expect_success 'push with config remote.*.push = HEAD' '
|
|||||||
git config --remove-section remote.there
|
git config --remove-section remote.there
|
||||||
git config --remove-section branch.master
|
git config --remove-section branch.master
|
||||||
|
|
||||||
|
test_expect_success 'push with config remote.*.pushurl' '
|
||||||
|
|
||||||
|
mk_test heads/master &&
|
||||||
|
git checkout master &&
|
||||||
|
git config remote.there.url test2repo &&
|
||||||
|
git config remote.there.pushurl testrepo &&
|
||||||
|
git push there &&
|
||||||
|
check_push_result $the_commit heads/master
|
||||||
|
'
|
||||||
|
|
||||||
|
# clean up the cruft left with the previous one
|
||||||
|
git config --remove-section remote.there
|
||||||
|
|
||||||
test_expect_success 'push with dry-run' '
|
test_expect_success 'push with dry-run' '
|
||||||
|
|
||||||
mk_test heads/master &&
|
mk_test heads/master &&
|
||||||
|
Loading…
Reference in New Issue
Block a user