git/builtin-push.c
Daniel Barkalow fa685bdf45 Give error when no remote is configured
When there's no explicitly-named remote, we use the remote specified
for the current branch, which in turn defaults to "origin". But it
this case should require the remote to actually be configured, and not
fall back to the path "origin".

Possibly, the config file's "remote = something" should require the
something to be a configured remote instead of a bare repository URL,
but we actually test with a bare repository URL.

In fetch, we were giving the sensible error message when coming up
with a URL failed, but this wasn't actually reachable, so move that
error up and use it when appropriate.

In push, we need a new error message, because the old one (formerly
unreachable without a lot of help) used the repo name, which was NULL.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-03-10 23:14:20 -07:00

151 lines
3.8 KiB
C

/*
* "git push"
*/
#include "cache.h"
#include "refs.h"
#include "run-command.h"
#include "builtin.h"
#include "remote.h"
#include "transport.h"
#include "parse-options.h"
static const char * const push_usage[] = {
"git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
NULL,
};
static int thin;
static const char *receivepack;
static const char **refspec;
static int refspec_nr;
static void add_refspec(const char *ref)
{
int nr = refspec_nr + 1;
refspec = xrealloc(refspec, nr * sizeof(char *));
refspec[nr-1] = ref;
refspec_nr = nr;
}
static void set_refspecs(const char **refs, int nr)
{
int i;
for (i = 0; i < nr; i++) {
const char *ref = refs[i];
if (!strcmp("tag", ref)) {
char *tag;
int len;
if (nr <= ++i)
die("tag shorthand without <tag>");
len = strlen(refs[i]) + 11;
tag = xmalloc(len);
strcpy(tag, "refs/tags/");
strcat(tag, refs[i]);
ref = tag;
}
add_refspec(ref);
}
}
static int do_push(const char *repo, int flags)
{
int i, errs;
struct remote *remote = remote_get(repo);
if (!remote) {
if (repo)
die("bad repository '%s'", repo);
die("No destination configured to push to.");
}
if (remote->mirror)
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
if (!strcmp(*refspec, "refs/tags/*"))
return error("--all and --tags are incompatible");
return error("--all can't be combined with refspecs");
}
if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
if (!strcmp(*refspec, "refs/tags/*"))
return error("--mirror and --tags are incompatible");
return error("--mirror can't be combined with refspecs");
}
if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
return error("--all and --mirror are incompatible");
}
if (!refspec
&& !(flags & TRANSPORT_PUSH_ALL)
&& remote->push_refspec_nr) {
refspec = remote->push_refspec;
refspec_nr = remote->push_refspec_nr;
}
errs = 0;
for (i = 0; i < remote->url_nr; i++) {
struct transport *transport =
transport_get(remote, remote->url[i]);
int err;
if (receivepack)
transport_set_option(transport,
TRANS_OPT_RECEIVEPACK, receivepack);
if (thin)
transport_set_option(transport, TRANS_OPT_THIN, "yes");
if (flags & TRANSPORT_PUSH_VERBOSE)
fprintf(stderr, "Pushing to %s\n", remote->url[i]);
err = transport_push(transport, refspec_nr, refspec, flags);
err |= transport_disconnect(transport);
if (!err)
continue;
error("failed to push some refs to '%s'", remote->url[i]);
errs++;
}
return !!errs;
}
int cmd_push(int argc, const char **argv, const char *prefix)
{
int flags = 0;
int tags = 0;
int rc;
const char *repo = NULL; /* default repository */
struct option options[] = {
OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE),
OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
(TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
OPT_END()
};
argc = parse_options(argc, argv, options, push_usage, 0);
if (tags)
add_refspec("refs/tags/*");
if (argc > 0) {
repo = argv[0];
set_refspecs(argv + 1, argc - 1);
}
rc = do_push(repo, flags);
if (rc == -1)
usage_with_options(push_usage, options);
else
return rc;
}