blob: 2eabcd3bdfb3f5d5705125a8f74d21d4ab1deafc [file] [log] [blame]
Linus Torvalds755225d2006-04-29 21:22:49 -07001/*
2 * "git push"
3 */
4#include "cache.h"
5#include "refs.h"
6#include "run-command.h"
7#include "builtin.h"
Daniel Barkalow5751f492007-05-12 11:45:53 -04008#include "remote.h"
Daniel Barkalow9b288512007-09-10 23:03:04 -04009#include "transport.h"
Daniel Barkalow378c4832007-11-04 22:35:37 -050010#include "parse-options.h"
Linus Torvalds755225d2006-04-29 21:22:49 -070011
Daniel Barkalow378c4832007-11-04 22:35:37 -050012static const char * const push_usage[] = {
Johannes Sixtbf07cc52008-10-07 16:26:20 +020013 "git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
Daniel Barkalow378c4832007-11-04 22:35:37 -050014 NULL,
15};
Linus Torvalds755225d2006-04-29 21:22:49 -070016
Michele Ballabioc29c1b42008-07-20 14:02:20 +020017static int thin;
Uwe Kleine-Königd23842f2007-01-19 13:49:27 +010018static const char *receivepack;
Linus Torvalds755225d2006-04-29 21:22:49 -070019
David Rientjes96f1e582006-08-15 10:23:48 -070020static const char **refspec;
21static int refspec_nr;
Linus Torvalds755225d2006-04-29 21:22:49 -070022
23static void add_refspec(const char *ref)
24{
25 int nr = refspec_nr + 1;
26 refspec = xrealloc(refspec, nr * sizeof(char *));
27 refspec[nr-1] = ref;
28 refspec_nr = nr;
29}
30
Linus Torvalds755225d2006-04-29 21:22:49 -070031static void set_refspecs(const char **refs, int nr)
32{
Daniel Barkalow8558fd92007-05-25 01:20:56 -040033 int i;
34 for (i = 0; i < nr; i++) {
35 const char *ref = refs[i];
36 if (!strcmp("tag", ref)) {
37 char *tag;
38 int len;
39 if (nr <= ++i)
40 die("tag shorthand without <tag>");
41 len = strlen(refs[i]) + 11;
42 tag = xmalloc(len);
43 strcpy(tag, "refs/tags/");
44 strcat(tag, refs[i]);
45 ref = tag;
Junio C Hamano411fb8b2006-12-13 10:03:39 -080046 }
Daniel Barkalow8558fd92007-05-25 01:20:56 -040047 add_refspec(ref);
Linus Torvalds755225d2006-04-29 21:22:49 -070048 }
Linus Torvalds755225d2006-04-29 21:22:49 -070049}
50
Finn Arne Gangstad52153742009-03-16 16:42:51 +010051static void setup_push_tracking(void)
52{
53 struct strbuf refspec = STRBUF_INIT;
54 struct branch *branch = branch_get(NULL);
55 if (!branch)
56 die("You are not currently on a branch.");
57 if (!branch->merge_nr)
58 die("The current branch %s is not tracking anything.",
59 branch->name);
60 if (branch->merge_nr != 1)
61 die("The current branch %s is tracking multiple branches, "
62 "refusing to push.", branch->name);
63 strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
64 add_refspec(refspec.buf);
65}
66
Finn Arne Gangstad665d3e82009-03-16 16:42:52 +010067static const char *warn_unconfigured_push_msg[] = {
68 "You did not specify any refspecs to push, and the current remote",
69 "has not configured any push refspecs. The default action in this",
70 "case is to push all matching refspecs, that is, all branches",
71 "that exist both locally and remotely will be updated. This may",
72 "not necessarily be what you want to happen.",
73 "",
74 "You can specify what action you want to take in this case, and",
75 "avoid seeing this message again, by configuring 'push.default' to:",
Kevin Ballardb2655cd2009-03-25 13:14:03 -070076 " 'nothing' : Do not push anything",
Finn Arne Gangstad665d3e82009-03-16 16:42:52 +010077 " 'matching' : Push all matching branches (default)",
78 " 'tracking' : Push the current branch to whatever it is tracking",
79 " 'current' : Push the current branch"
80};
81
82static void warn_unconfigured_push(void)
83{
84 int i;
85 for (i = 0; i < ARRAY_SIZE(warn_unconfigured_push_msg); i++)
86 warning("%s", warn_unconfigured_push_msg[i]);
87}
88
Finn Arne Gangstad52153742009-03-16 16:42:51 +010089static void setup_default_push_refspecs(void)
90{
91 git_config(git_default_config, NULL);
92 switch (push_default) {
93 case PUSH_DEFAULT_UNSPECIFIED:
Finn Arne Gangstad665d3e82009-03-16 16:42:52 +010094 warn_unconfigured_push();
Finn Arne Gangstad52153742009-03-16 16:42:51 +010095 /* fallthrough */
96
97 case PUSH_DEFAULT_MATCHING:
98 add_refspec(":");
99 break;
100
101 case PUSH_DEFAULT_TRACKING:
102 setup_push_tracking();
103 break;
104
105 case PUSH_DEFAULT_CURRENT:
106 add_refspec("HEAD");
107 break;
108
109 case PUSH_DEFAULT_NOTHING:
110 die("You didn't specify any refspecs to push, and "
111 "push.default is \"nothing\".");
112 break;
113 }
114}
115
Daniel Barkalow9b288512007-09-10 23:03:04 -0400116static int do_push(const char *repo, int flags)
Linus Torvalds755225d2006-04-29 21:22:49 -0700117{
Daniel Barkalow5751f492007-05-12 11:45:53 -0400118 int i, errs;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400119 struct remote *remote = remote_get(repo);
Linus Torvalds755225d2006-04-29 21:22:49 -0700120
Daniel Barkalowfa685bd2009-03-11 01:47:20 -0400121 if (!remote) {
122 if (repo)
123 die("bad repository '%s'", repo);
124 die("No destination configured to push to.");
125 }
Linus Torvalds755225d2006-04-29 21:22:49 -0700126
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200127 if (remote->mirror)
128 flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
129
Marek Zawirskib259f092008-08-16 19:58:32 +0200130 if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
131 if (!strcmp(*refspec, "refs/tags/*"))
132 return error("--all and --tags are incompatible");
133 return error("--all can't be combined with refspecs");
134 }
135
136 if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
137 if (!strcmp(*refspec, "refs/tags/*"))
138 return error("--mirror and --tags are incompatible");
139 return error("--mirror can't be combined with refspecs");
140 }
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200141
142 if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
143 (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
144 return error("--all and --mirror are incompatible");
145 }
146
Finn Arne Gangstad52153742009-03-16 16:42:51 +0100147 if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
148 if (remote->push_refspec_nr) {
149 refspec = remote->push_refspec;
150 refspec_nr = remote->push_refspec_nr;
151 } else if (!(flags & TRANSPORT_PUSH_MIRROR))
152 setup_default_push_refspecs();
Daniel Barkalow5751f492007-05-12 11:45:53 -0400153 }
Junio C Hamanofd1d1b02007-04-06 23:04:53 -0700154 errs = 0;
Shawn O. Pearce28b91f82007-09-19 00:49:27 -0400155 for (i = 0; i < remote->url_nr; i++) {
Daniel Barkalow9b288512007-09-10 23:03:04 -0400156 struct transport *transport =
Shawn O. Pearce28b91f82007-09-19 00:49:27 -0400157 transport_get(remote, remote->url[i]);
Pierre Habouzit60b7f382006-08-23 12:39:10 +0200158 int err;
Daniel Barkalow9b288512007-09-10 23:03:04 -0400159 if (receivepack)
160 transport_set_option(transport,
161 TRANS_OPT_RECEIVEPACK, receivepack);
162 if (thin)
163 transport_set_option(transport, TRANS_OPT_THIN, "yes");
164
Michele Ballabioc29c1b42008-07-20 14:02:20 +0200165 if (flags & TRANSPORT_PUSH_VERBOSE)
Shawn O. Pearce28b91f82007-09-19 00:49:27 -0400166 fprintf(stderr, "Pushing to %s\n", remote->url[i]);
Daniel Barkalow9b288512007-09-10 23:03:04 -0400167 err = transport_push(transport, refspec_nr, refspec, flags);
168 err |= transport_disconnect(transport);
169
Pierre Habouzit60b7f382006-08-23 12:39:10 +0200170 if (!err)
Linus Torvalds755225d2006-04-29 21:22:49 -0700171 continue;
Junio C Hamano39878b02007-04-06 23:04:55 -0700172
Jeff King2b8130c2008-02-19 11:25:01 -0500173 error("failed to push some refs to '%s'", remote->url[i]);
Junio C Hamanofd1d1b02007-04-06 23:04:53 -0700174 errs++;
Linus Torvalds755225d2006-04-29 21:22:49 -0700175 }
Junio C Hamanofd1d1b02007-04-06 23:04:53 -0700176 return !!errs;
Linus Torvalds755225d2006-04-29 21:22:49 -0700177}
178
Linus Torvaldsa633fca2006-07-28 22:44:25 -0700179int cmd_push(int argc, const char **argv, const char *prefix)
Linus Torvalds755225d2006-04-29 21:22:49 -0700180{
Daniel Barkalow9b288512007-09-10 23:03:04 -0400181 int flags = 0;
Daniel Barkalow378c4832007-11-04 22:35:37 -0500182 int tags = 0;
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200183 int rc;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400184 const char *repo = NULL; /* default repository */
Linus Torvalds755225d2006-04-29 21:22:49 -0700185
Daniel Barkalow378c4832007-11-04 22:35:37 -0500186 struct option options[] = {
Michele Ballabioc29c1b42008-07-20 14:02:20 +0200187 OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE),
Daniel Barkalow378c4832007-11-04 22:35:37 -0500188 OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
Michele Ballabioc29c1b42008-07-20 14:02:20 +0200189 OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
190 OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
191 (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
Daniel Barkalow378c4832007-11-04 22:35:37 -0500192 OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
Michele Ballabioc29c1b42008-07-20 14:02:20 +0200193 OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
194 OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
Daniel Barkalow378c4832007-11-04 22:35:37 -0500195 OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
196 OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
197 OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
198 OPT_END()
199 };
Linus Torvalds755225d2006-04-29 21:22:49 -0700200
Daniel Barkalow378c4832007-11-04 22:35:37 -0500201 argc = parse_options(argc, argv, options, push_usage, 0);
202
Daniel Barkalow378c4832007-11-04 22:35:37 -0500203 if (tags)
204 add_refspec("refs/tags/*");
Daniel Barkalow378c4832007-11-04 22:35:37 -0500205
206 if (argc > 0) {
207 repo = argv[0];
208 set_refspecs(argv + 1, argc - 1);
Linus Torvalds755225d2006-04-29 21:22:49 -0700209 }
Daniel Barkalow8558fd92007-05-25 01:20:56 -0400210
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200211 rc = do_push(repo, flags);
212 if (rc == -1)
Andy Whitcroft94c89ba2007-11-09 23:32:25 +0000213 usage_with_options(push_usage, options);
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200214 else
215 return rc;
Linus Torvalds755225d2006-04-29 21:22:49 -0700216}