blob: 2612f07f74855ad6dec8ccd605279ab3a502e5e2 [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"
Linus Torvalds755225d2006-04-29 21:22:49 -07009
Uwe Kleine-Königd23842f2007-01-19 13:49:27 +010010static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
Linus Torvalds755225d2006-04-29 21:22:49 -070011
Daniel Barkalow8558fd92007-05-25 01:20:56 -040012static int all, force, thin = 1, verbose;
Uwe Kleine-Königd23842f2007-01-19 13:49:27 +010013static const char *receivepack;
Linus Torvalds755225d2006-04-29 21:22:49 -070014
David Rientjes96f1e582006-08-15 10:23:48 -070015static const char **refspec;
16static int refspec_nr;
Linus Torvalds755225d2006-04-29 21:22:49 -070017
18static void add_refspec(const char *ref)
19{
20 int nr = refspec_nr + 1;
21 refspec = xrealloc(refspec, nr * sizeof(char *));
22 refspec[nr-1] = ref;
23 refspec_nr = nr;
24}
25
Linus Torvalds755225d2006-04-29 21:22:49 -070026static void set_refspecs(const char **refs, int nr)
27{
Daniel Barkalow8558fd92007-05-25 01:20:56 -040028 int i;
29 for (i = 0; i < nr; i++) {
30 const char *ref = refs[i];
31 if (!strcmp("tag", ref)) {
32 char *tag;
33 int len;
34 if (nr <= ++i)
35 die("tag shorthand without <tag>");
36 len = strlen(refs[i]) + 11;
37 tag = xmalloc(len);
38 strcpy(tag, "refs/tags/");
39 strcat(tag, refs[i]);
40 ref = tag;
Junio C Hamano411fb8b2006-12-13 10:03:39 -080041 }
Daniel Barkalow8558fd92007-05-25 01:20:56 -040042 add_refspec(ref);
Linus Torvalds755225d2006-04-29 21:22:49 -070043 }
Linus Torvalds755225d2006-04-29 21:22:49 -070044}
45
Linus Torvalds755225d2006-04-29 21:22:49 -070046static int do_push(const char *repo)
47{
Daniel Barkalow5751f492007-05-12 11:45:53 -040048 int i, errs;
Nick Hengeveld441c8232006-06-05 13:02:29 -070049 int common_argc;
Linus Torvalds755225d2006-04-29 21:22:49 -070050 const char **argv;
51 int argc;
Daniel Barkalow5751f492007-05-12 11:45:53 -040052 struct remote *remote = remote_get(repo);
Linus Torvalds755225d2006-04-29 21:22:49 -070053
Daniel Barkalow5751f492007-05-12 11:45:53 -040054 if (!remote)
Linus Torvalds755225d2006-04-29 21:22:49 -070055 die("bad repository '%s'", repo);
56
Daniel Barkalow5751f492007-05-12 11:45:53 -040057 if (remote->receivepack) {
58 char *rp = xmalloc(strlen(remote->receivepack) + 16);
59 sprintf(rp, "--receive-pack=%s", remote->receivepack);
60 receivepack = rp;
61 }
Daniel Barkalow8558fd92007-05-25 01:20:56 -040062 if (!refspec && !all && remote->push_refspec_nr) {
63 refspec = remote->push_refspec;
64 refspec_nr = remote->push_refspec_nr;
Daniel Barkalow5751f492007-05-12 11:45:53 -040065 }
66
Linus Torvalds755225d2006-04-29 21:22:49 -070067 argv = xmalloc((refspec_nr + 10) * sizeof(char *));
68 argv[0] = "dummy-send-pack";
69 argc = 1;
70 if (all)
71 argv[argc++] = "--all";
72 if (force)
73 argv[argc++] = "--force";
Uwe Kleine-Königd23842f2007-01-19 13:49:27 +010074 if (receivepack)
75 argv[argc++] = receivepack;
Nick Hengeveld441c8232006-06-05 13:02:29 -070076 common_argc = argc;
Linus Torvalds755225d2006-04-29 21:22:49 -070077
Junio C Hamanofd1d1b02007-04-06 23:04:53 -070078 errs = 0;
Daniel Barkalow5751f492007-05-12 11:45:53 -040079 for (i = 0; i < remote->uri_nr; i++) {
Pierre Habouzit60b7f382006-08-23 12:39:10 +020080 int err;
Nick Hengeveld441c8232006-06-05 13:02:29 -070081 int dest_argc = common_argc;
82 int dest_refspec_nr = refspec_nr;
83 const char **dest_refspec = refspec;
Daniel Barkalow5751f492007-05-12 11:45:53 -040084 const char *dest = remote->uri[i];
Shawn O. Pearcedf91ba32007-03-12 19:00:15 -040085 const char *sender = "send-pack";
Junio C Hamanocc44c762007-02-20 01:53:29 -080086 if (!prefixcmp(dest, "http://") ||
87 !prefixcmp(dest, "https://"))
Shawn O. Pearcedf91ba32007-03-12 19:00:15 -040088 sender = "http-push";
Daniel Barkalowb5169682007-05-15 22:50:19 -040089 else {
90 char *rem = xmalloc(strlen(remote->name) + 10);
91 sprintf(rem, "--remote=%s", remote->name);
92 argv[dest_argc++] = rem;
93 if (thin)
94 argv[dest_argc++] = "--thin";
95 }
Linus Torvalds755225d2006-04-29 21:22:49 -070096 argv[0] = sender;
Nick Hengeveld441c8232006-06-05 13:02:29 -070097 argv[dest_argc++] = dest;
98 while (dest_refspec_nr--)
99 argv[dest_argc++] = *dest_refspec++;
100 argv[dest_argc] = NULL;
Linus Torvaldsbcc785f2006-10-30 08:28:59 -0800101 if (verbose)
102 fprintf(stderr, "Pushing to %s\n", dest);
Shawn O. Pearcedf91ba32007-03-12 19:00:15 -0400103 err = run_command_v_opt(argv, RUN_GIT_CMD);
Pierre Habouzit60b7f382006-08-23 12:39:10 +0200104 if (!err)
Linus Torvalds755225d2006-04-29 21:22:49 -0700105 continue;
Junio C Hamano39878b02007-04-06 23:04:55 -0700106
Daniel Barkalow5751f492007-05-12 11:45:53 -0400107 error("failed to push to '%s'", remote->uri[i]);
Pierre Habouzit60b7f382006-08-23 12:39:10 +0200108 switch (err) {
Linus Torvalds755225d2006-04-29 21:22:49 -0700109 case -ERR_RUN_COMMAND_FORK:
Junio C Hamanofd1d1b02007-04-06 23:04:53 -0700110 error("unable to fork for %s", sender);
Linus Torvalds755225d2006-04-29 21:22:49 -0700111 case -ERR_RUN_COMMAND_EXEC:
Junio C Hamanofd1d1b02007-04-06 23:04:53 -0700112 error("unable to exec %s", sender);
113 break;
Linus Torvalds755225d2006-04-29 21:22:49 -0700114 case -ERR_RUN_COMMAND_WAITPID:
115 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
116 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
117 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
Junio C Hamanofd1d1b02007-04-06 23:04:53 -0700118 error("%s died with strange error", sender);
Linus Torvalds755225d2006-04-29 21:22:49 -0700119 }
Junio C Hamanofd1d1b02007-04-06 23:04:53 -0700120 errs++;
Linus Torvalds755225d2006-04-29 21:22:49 -0700121 }
Junio C Hamanofd1d1b02007-04-06 23:04:53 -0700122 return !!errs;
Linus Torvalds755225d2006-04-29 21:22:49 -0700123}
124
Linus Torvaldsa633fca2006-07-28 22:44:25 -0700125int cmd_push(int argc, const char **argv, const char *prefix)
Linus Torvalds755225d2006-04-29 21:22:49 -0700126{
127 int i;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400128 const char *repo = NULL; /* default repository */
Linus Torvalds755225d2006-04-29 21:22:49 -0700129
130 for (i = 1; i < argc; i++) {
131 const char *arg = argv[i];
132
133 if (arg[0] != '-') {
134 repo = arg;
135 i++;
136 break;
137 }
Linus Torvaldsbcc785f2006-10-30 08:28:59 -0800138 if (!strcmp(arg, "-v")) {
139 verbose=1;
140 continue;
141 }
Junio C Hamanocc44c762007-02-20 01:53:29 -0800142 if (!prefixcmp(arg, "--repo=")) {
Linus Torvaldsbcc785f2006-10-30 08:28:59 -0800143 repo = arg+7;
144 continue;
145 }
Linus Torvalds755225d2006-04-29 21:22:49 -0700146 if (!strcmp(arg, "--all")) {
147 all = 1;
148 continue;
149 }
150 if (!strcmp(arg, "--tags")) {
Daniel Barkalow8558fd92007-05-25 01:20:56 -0400151 add_refspec("refs/tags/*");
Linus Torvalds755225d2006-04-29 21:22:49 -0700152 continue;
153 }
Jeff King8f615492006-08-02 11:28:16 -0400154 if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
Linus Torvalds755225d2006-04-29 21:22:49 -0700155 force = 1;
156 continue;
157 }
158 if (!strcmp(arg, "--thin")) {
159 thin = 1;
160 continue;
161 }
162 if (!strcmp(arg, "--no-thin")) {
163 thin = 0;
164 continue;
165 }
Junio C Hamanocc44c762007-02-20 01:53:29 -0800166 if (!prefixcmp(arg, "--receive-pack=")) {
Uwe Kleine-Königd23842f2007-01-19 13:49:27 +0100167 receivepack = arg;
168 continue;
169 }
Junio C Hamanocc44c762007-02-20 01:53:29 -0800170 if (!prefixcmp(arg, "--exec=")) {
Uwe Kleine-Königd23842f2007-01-19 13:49:27 +0100171 receivepack = arg;
Linus Torvalds755225d2006-04-29 21:22:49 -0700172 continue;
173 }
174 usage(push_usage);
175 }
176 set_refspecs(argv + i, argc - i);
Daniel Barkalow8558fd92007-05-25 01:20:56 -0400177 if (all && refspec)
178 usage(push_usage);
179
Linus Torvalds755225d2006-04-29 21:22:49 -0700180 return do_push(repo);
181}