Turn unpack_trees_options.msgs into an array + enum
[git.git] / builtin / push.c
1 /*
2  * "git push"
3  */
4 #include "cache.h"
5 #include "refs.h"
6 #include "run-command.h"
7 #include "builtin.h"
8 #include "remote.h"
9 #include "transport.h"
10 #include "parse-options.h"
11
12 static const char * const push_usage[] = {
13         "git push [<options>] [<repository> [<refspec>...]]",
14         NULL,
15 };
16
17 static int thin;
18 static int deleterefs;
19 static const char *receivepack;
20 static int verbosity;
21 static int progress;
22
23 static const char **refspec;
24 static int refspec_nr;
25
26 static void add_refspec(const char *ref)
27 {
28         int nr = refspec_nr + 1;
29         refspec = xrealloc(refspec, nr * sizeof(char *));
30         refspec[nr-1] = ref;
31         refspec_nr = nr;
32 }
33
34 static void set_refspecs(const char **refs, int nr)
35 {
36         int i;
37         for (i = 0; i < nr; i++) {
38                 const char *ref = refs[i];
39                 if (!strcmp("tag", ref)) {
40                         char *tag;
41                         int len;
42                         if (nr <= ++i)
43                                 die("tag shorthand without <tag>");
44                         len = strlen(refs[i]) + 11;
45                         if (deleterefs) {
46                                 tag = xmalloc(len+1);
47                                 strcpy(tag, ":refs/tags/");
48                         } else {
49                                 tag = xmalloc(len);
50                                 strcpy(tag, "refs/tags/");
51                         }
52                         strcat(tag, refs[i]);
53                         ref = tag;
54                 } else if (deleterefs && !strchr(ref, ':')) {
55                         char *delref;
56                         int len = strlen(ref)+1;
57                         delref = xmalloc(len+1);
58                         strcpy(delref, ":");
59                         strcat(delref, ref);
60                         ref = delref;
61                 } else if (deleterefs)
62                         die("--delete only accepts plain target ref names");
63                 add_refspec(ref);
64         }
65 }
66
67 static void setup_push_tracking(void)
68 {
69         struct strbuf refspec = STRBUF_INIT;
70         struct branch *branch = branch_get(NULL);
71         if (!branch)
72                 die("You are not currently on a branch.");
73         if (!branch->merge_nr || !branch->merge)
74                 die("The current branch %s is not tracking anything.",
75                     branch->name);
76         if (branch->merge_nr != 1)
77                 die("The current branch %s is tracking multiple branches, "
78                     "refusing to push.", branch->name);
79         strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
80         add_refspec(refspec.buf);
81 }
82
83 static void setup_default_push_refspecs(void)
84 {
85         switch (push_default) {
86         default:
87         case PUSH_DEFAULT_MATCHING:
88                 add_refspec(":");
89                 break;
90
91         case PUSH_DEFAULT_TRACKING:
92                 setup_push_tracking();
93                 break;
94
95         case PUSH_DEFAULT_CURRENT:
96                 add_refspec("HEAD");
97                 break;
98
99         case PUSH_DEFAULT_NOTHING:
100                 die("You didn't specify any refspecs to push, and "
101                     "push.default is \"nothing\".");
102                 break;
103         }
104 }
105
106 static int push_with_options(struct transport *transport, int flags)
107 {
108         int err;
109         int nonfastforward;
110
111         transport_set_verbosity(transport, verbosity, progress);
112
113         if (receivepack)
114                 transport_set_option(transport,
115                                      TRANS_OPT_RECEIVEPACK, receivepack);
116         if (thin)
117                 transport_set_option(transport, TRANS_OPT_THIN, "yes");
118
119         if (verbosity > 0)
120                 fprintf(stderr, "Pushing to %s\n", transport->url);
121         err = transport_push(transport, refspec_nr, refspec, flags,
122                              &nonfastforward);
123         if (err != 0)
124                 error("failed to push some refs to '%s'", transport->url);
125
126         err |= transport_disconnect(transport);
127
128         if (!err)
129                 return 0;
130
131         if (nonfastforward && advice_push_nonfastforward) {
132                 fprintf(stderr, "To prevent you from losing history, non-fast-forward updates were rejected\n"
133                                 "Merge the remote changes before pushing again.  See the 'Note about\n"
134                                 "fast-forwards' section of 'git push --help' for details.\n");
135         }
136
137         return 1;
138 }
139
140 static int do_push(const char *repo, int flags)
141 {
142         int i, errs;
143         struct remote *remote = remote_get(repo);
144         const char **url;
145         int url_nr;
146
147         if (!remote) {
148                 if (repo)
149                         die("bad repository '%s'", repo);
150                 die("No destination configured to push to.");
151         }
152
153         if (remote->mirror)
154                 flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
155
156         if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
157                 if (!strcmp(*refspec, "refs/tags/*"))
158                         return error("--all and --tags are incompatible");
159                 return error("--all can't be combined with refspecs");
160         }
161
162         if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
163                 if (!strcmp(*refspec, "refs/tags/*"))
164                         return error("--mirror and --tags are incompatible");
165                 return error("--mirror can't be combined with refspecs");
166         }
167
168         if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
169                                 (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
170                 return error("--all and --mirror are incompatible");
171         }
172
173         if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
174                 if (remote->push_refspec_nr) {
175                         refspec = remote->push_refspec;
176                         refspec_nr = remote->push_refspec_nr;
177                 } else if (!(flags & TRANSPORT_PUSH_MIRROR))
178                         setup_default_push_refspecs();
179         }
180         errs = 0;
181         if (remote->pushurl_nr) {
182                 url = remote->pushurl;
183                 url_nr = remote->pushurl_nr;
184         } else {
185                 url = remote->url;
186                 url_nr = remote->url_nr;
187         }
188         if (url_nr) {
189                 for (i = 0; i < url_nr; i++) {
190                         struct transport *transport =
191                                 transport_get(remote, url[i]);
192                         if (push_with_options(transport, flags))
193                                 errs++;
194                 }
195         } else {
196                 struct transport *transport =
197                         transport_get(remote, NULL);
198
199                 if (push_with_options(transport, flags))
200                         errs++;
201         }
202         return !!errs;
203 }
204
205 int cmd_push(int argc, const char **argv, const char *prefix)
206 {
207         int flags = 0;
208         int tags = 0;
209         int rc;
210         const char *repo = NULL;        /* default repository */
211         struct option options[] = {
212                 OPT__VERBOSITY(&verbosity),
213                 OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
214                 OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
215                 OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
216                             (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
217                 OPT_BOOLEAN( 0, "delete", &deleterefs, "delete refs"),
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),
222                 OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
223                 OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
224                 OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
225                 OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status",
226                         TRANSPORT_PUSH_SET_UPSTREAM),
227                 OPT_BOOLEAN(0, "progress", &progress, "force progress reporting"),
228                 OPT_END()
229         };
230
231         git_config(git_default_config, NULL);
232         argc = parse_options(argc, argv, prefix, options, push_usage, 0);
233
234         if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
235                 die("--delete is incompatible with --all, --mirror and --tags");
236         if (deleterefs && argc < 2)
237                 die("--delete doesn't make sense without any refs");
238
239         if (tags)
240                 add_refspec("refs/tags/*");
241
242         if (argc > 0) {
243                 repo = argv[0];
244                 set_refspecs(argv + 1, argc - 1);
245         }
246
247         rc = do_push(repo, flags);
248         if (rc == -1)
249                 usage_with_options(push_usage, options);
250         else
251                 return rc;
252 }