mirror of
https://github.com/git/git.git
synced 2024-11-25 19:04:18 +08:00
e5f4e21463
We don't actually need to know at the time of transport_get if the caller wants to fetch, push, or do both on the returned object. It is easier to just delay the initialization of the HTTP walker until we know we will need it by providing a CURL specific fetch function in the curl_transport that makes sure the walker instance is initialized before use. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
142 lines
2.9 KiB
C
142 lines
2.9 KiB
C
/*
|
|
* "git push"
|
|
*/
|
|
#include "cache.h"
|
|
#include "refs.h"
|
|
#include "run-command.h"
|
|
#include "builtin.h"
|
|
#include "remote.h"
|
|
#include "transport.h"
|
|
|
|
static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
|
|
|
|
static int all, thin, verbose;
|
|
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)
|
|
die("bad repository '%s'", repo);
|
|
|
|
if (!refspec && !all && remote->push_refspec_nr) {
|
|
refspec = remote->push_refspec;
|
|
refspec_nr = remote->push_refspec_nr;
|
|
}
|
|
errs = 0;
|
|
for (i = 0; i < remote->uri_nr; i++) {
|
|
struct transport *transport =
|
|
transport_get(remote, remote->uri[i]);
|
|
int err;
|
|
if (receivepack)
|
|
transport_set_option(transport,
|
|
TRANS_OPT_RECEIVEPACK, receivepack);
|
|
if (thin)
|
|
transport_set_option(transport, TRANS_OPT_THIN, "yes");
|
|
|
|
if (verbose)
|
|
fprintf(stderr, "Pushing to %s\n", remote->uri[i]);
|
|
err = transport_push(transport, refspec_nr, refspec, flags);
|
|
err |= transport_disconnect(transport);
|
|
|
|
if (!err)
|
|
continue;
|
|
|
|
error("failed to push to '%s'", remote->uri[i]);
|
|
errs++;
|
|
}
|
|
return !!errs;
|
|
}
|
|
|
|
int cmd_push(int argc, const char **argv, const char *prefix)
|
|
{
|
|
int i;
|
|
int flags = 0;
|
|
const char *repo = NULL; /* default repository */
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
const char *arg = argv[i];
|
|
|
|
if (arg[0] != '-') {
|
|
repo = arg;
|
|
i++;
|
|
break;
|
|
}
|
|
if (!strcmp(arg, "-v")) {
|
|
verbose=1;
|
|
continue;
|
|
}
|
|
if (!prefixcmp(arg, "--repo=")) {
|
|
repo = arg+7;
|
|
continue;
|
|
}
|
|
if (!strcmp(arg, "--all")) {
|
|
flags |= TRANSPORT_PUSH_ALL;
|
|
continue;
|
|
}
|
|
if (!strcmp(arg, "--tags")) {
|
|
add_refspec("refs/tags/*");
|
|
continue;
|
|
}
|
|
if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
|
|
flags |= TRANSPORT_PUSH_FORCE;
|
|
continue;
|
|
}
|
|
if (!strcmp(arg, "--thin")) {
|
|
thin = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(arg, "--no-thin")) {
|
|
thin = 0;
|
|
continue;
|
|
}
|
|
if (!prefixcmp(arg, "--receive-pack=")) {
|
|
receivepack = arg + 15;
|
|
continue;
|
|
}
|
|
if (!prefixcmp(arg, "--exec=")) {
|
|
receivepack = arg + 7;
|
|
continue;
|
|
}
|
|
usage(push_usage);
|
|
}
|
|
set_refspecs(argv + i, argc - i);
|
|
if (all && refspec)
|
|
usage(push_usage);
|
|
|
|
return do_push(repo, flags);
|
|
}
|