push.c 6.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/*
 * "git push"
 */
#include "cache.h"
#include "refs.h"
#include "run-command.h"
#include "builtin.h"
8
#include "remote.h"
9
#include "transport.h"
D
Daniel Barkalow 已提交
10
#include "parse-options.h"
L
Linus Torvalds 已提交
11

D
Daniel Barkalow 已提交
12
static const char * const push_usage[] = {
T
Tay Ray Chuan 已提交
13
	"git push [<options>] [<repository> [<refspec>...]]",
D
Daniel Barkalow 已提交
14 15
	NULL,
};
L
Linus Torvalds 已提交
16

17
static int thin;
18
static int deleterefs;
19
static const char *receivepack;
20
static int verbosity;
T
Tay Ray Chuan 已提交
21
static int progress;
L
Linus Torvalds 已提交
22

23 24
static const char **refspec;
static int refspec_nr;
25
static int refspec_alloc;
L
Linus Torvalds 已提交
26 27 28

static void add_refspec(const char *ref)
{
29 30 31
	refspec_nr++;
	ALLOC_GROW(refspec, refspec_nr, refspec_alloc);
	refspec[refspec_nr-1] = ref;
L
Linus Torvalds 已提交
32 33 34 35
}

static void set_refspecs(const char **refs, int nr)
{
36 37 38 39 40 41 42 43 44
	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;
45 46 47 48 49 50 51
			if (deleterefs) {
				tag = xmalloc(len+1);
				strcpy(tag, ":refs/tags/");
			} else {
				tag = xmalloc(len);
				strcpy(tag, "refs/tags/");
			}
52 53
			strcat(tag, refs[i]);
			ref = tag;
54 55 56
		} else if (deleterefs && !strchr(ref, ':')) {
			char *delref;
			int len = strlen(ref)+1;
J
Jeff King 已提交
57
			delref = xmalloc(len+1);
58 59 60 61 62
			strcpy(delref, ":");
			strcat(delref, ref);
			ref = delref;
		} else if (deleterefs)
			die("--delete only accepts plain target ref names");
63
		add_refspec(ref);
L
Linus Torvalds 已提交
64 65 66
	}
}

67
static void setup_push_upstream(void)
68 69 70 71 72
{
	struct strbuf refspec = STRBUF_INIT;
	struct branch *branch = branch_get(NULL);
	if (!branch)
		die("You are not currently on a branch.");
J
Jeff King 已提交
73
	if (!branch->merge_nr || !branch->merge)
74
		die("The current branch %s has no upstream branch.",
75 76
		    branch->name);
	if (branch->merge_nr != 1)
77
		die("The current branch %s has multiple upstream branches, "
78 79 80 81 82 83 84 85
		    "refusing to push.", branch->name);
	strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
	add_refspec(refspec.buf);
}

static void setup_default_push_refspecs(void)
{
	switch (push_default) {
86
	default:
87 88 89 90
	case PUSH_DEFAULT_MATCHING:
		add_refspec(":");
		break;

91 92
	case PUSH_DEFAULT_UPSTREAM:
		setup_push_upstream();
93 94 95 96 97 98 99 100 101 102 103 104 105
		break;

	case PUSH_DEFAULT_CURRENT:
		add_refspec("HEAD");
		break;

	case PUSH_DEFAULT_NOTHING:
		die("You didn't specify any refspecs to push, and "
		    "push.default is \"nothing\".");
		break;
	}
}

106 107 108 109
static int push_with_options(struct transport *transport, int flags)
{
	int err;
	int nonfastforward;
110

T
Tay Ray Chuan 已提交
111
	transport_set_verbosity(transport, verbosity, progress);
112

113 114 115 116 117 118
	if (receivepack)
		transport_set_option(transport,
				     TRANS_OPT_RECEIVEPACK, receivepack);
	if (thin)
		transport_set_option(transport, TRANS_OPT_THIN, "yes");

119
	if (verbosity > 0)
120 121 122
		fprintf(stderr, "Pushing to %s\n", transport->url);
	err = transport_push(transport, refspec_nr, refspec, flags,
			     &nonfastforward);
123 124 125
	if (err != 0)
		error("failed to push some refs to '%s'", transport->url);

126 127 128 129 130 131
	err |= transport_disconnect(transport);

	if (!err)
		return 0;

	if (nonfastforward && advice_push_nonfastforward) {
132
		fprintf(stderr, "To prevent you from losing history, non-fast-forward updates were rejected\n"
133 134
				"Merge the remote changes (e.g. 'git pull') before pushing again.  See the\n"
				"'Note about fast-forwards' section of 'git push --help' for details.\n");
135 136 137 138 139
	}

	return 1;
}

140
static int do_push(const char *repo, int flags)
L
Linus Torvalds 已提交
141
{
142 143
	int i, errs;
	struct remote *remote = remote_get(repo);
144 145
	const char **url;
	int url_nr;
L
Linus Torvalds 已提交
146

147 148 149 150 151
	if (!remote) {
		if (repo)
			die("bad repository '%s'", repo);
		die("No destination configured to push to.");
	}
L
Linus Torvalds 已提交
152

153 154 155
	if (remote->mirror)
		flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);

156 157 158 159 160 161 162 163 164 165 166
	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");
	}
167 168 169 170 171 172

	if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
				(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
		return error("--all and --mirror are incompatible");
	}

173 174 175 176 177 178
	if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
		if (remote->push_refspec_nr) {
			refspec = remote->push_refspec;
			refspec_nr = remote->push_refspec_nr;
		} else if (!(flags & TRANSPORT_PUSH_MIRROR))
			setup_default_push_refspecs();
179
	}
180
	errs = 0;
181 182 183 184 185 186 187
	if (remote->pushurl_nr) {
		url = remote->pushurl;
		url_nr = remote->pushurl_nr;
	} else {
		url = remote->url;
		url_nr = remote->url_nr;
	}
188 189 190 191 192 193
	if (url_nr) {
		for (i = 0; i < url_nr; i++) {
			struct transport *transport =
				transport_get(remote, url[i]);
			if (push_with_options(transport, flags))
				errs++;
194
		}
195 196 197 198 199 200
	} else {
		struct transport *transport =
			transport_get(remote, NULL);

		if (push_with_options(transport, flags))
			errs++;
L
Linus Torvalds 已提交
201
	}
202
	return !!errs;
L
Linus Torvalds 已提交
203 204
}

205
int cmd_push(int argc, const char **argv, const char *prefix)
L
Linus Torvalds 已提交
206
{
207
	int flags = 0;
D
Daniel Barkalow 已提交
208
	int tags = 0;
209
	int rc;
210
	const char *repo = NULL;	/* default repository */
D
Daniel Barkalow 已提交
211
	struct option options[] = {
212
		OPT__VERBOSITY(&verbosity),
D
Daniel Barkalow 已提交
213
		OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
214 215 216
		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)),
217
		OPT_BOOLEAN( 0, "delete", &deleterefs, "delete refs"),
J
Jeff King 已提交
218
		OPT_BOOLEAN( 0 , "tags", &tags, "push tags (can't be used with --all or --mirror)"),
219
		OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
220
		OPT_BIT( 0,  "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
221
		OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
D
Daniel Barkalow 已提交
222 223 224
		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"),
I
Ilari Liusvaara 已提交
225 226
		OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status",
			TRANSPORT_PUSH_SET_UPSTREAM),
T
Tay Ray Chuan 已提交
227
		OPT_BOOLEAN(0, "progress", &progress, "force progress reporting"),
D
Daniel Barkalow 已提交
228 229
		OPT_END()
	};
L
Linus Torvalds 已提交
230

J
Jeff King 已提交
231
	git_config(git_default_config, NULL);
232
	argc = parse_options(argc, argv, prefix, options, push_usage, 0);
D
Daniel Barkalow 已提交
233

234 235 236 237 238
	if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
		die("--delete is incompatible with --all, --mirror and --tags");
	if (deleterefs && argc < 2)
		die("--delete doesn't make sense without any refs");

D
Daniel Barkalow 已提交
239 240 241 242 243 244
	if (tags)
		add_refspec("refs/tags/*");

	if (argc > 0) {
		repo = argv[0];
		set_refspecs(argv + 1, argc - 1);
L
Linus Torvalds 已提交
245
	}
246

247 248
	rc = do_push(repo, flags);
	if (rc == -1)
A
Andy Whitcroft 已提交
249
		usage_with_options(push_usage, options);
250 251
	else
		return rc;
L
Linus Torvalds 已提交
252
}