builtin-reflog.c: fix typo that accesses an unset variable
[git/dscho.git] / builtin-push.c
blob141380b852771e107ee5ae1df3f8b9e30cfcea6b
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"
10 static const char push_usage[] = "git-push [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
12 static int all, dry_run, force, thin, verbose;
13 static const char *receivepack;
15 static const char **refspec;
16 static int refspec_nr;
18 static void add_refspec(const char *ref)
20 int nr = refspec_nr + 1;
21 refspec = xrealloc(refspec, nr * sizeof(char *));
22 refspec[nr-1] = ref;
23 refspec_nr = nr;
26 static void set_refspecs(const char **refs, int nr)
28 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;
42 add_refspec(ref);
46 static int do_push(const char *repo)
48 int i, errs;
49 int common_argc;
50 const char **argv;
51 int argc;
52 struct remote *remote = remote_get(repo);
54 if (!remote)
55 die("bad repository '%s'", repo);
57 if (remote->receivepack) {
58 char *rp = xmalloc(strlen(remote->receivepack) + 16);
59 sprintf(rp, "--receive-pack=%s", remote->receivepack);
60 receivepack = rp;
62 if (!refspec && !all && remote->push_refspec_nr) {
63 refspec = remote->push_refspec;
64 refspec_nr = remote->push_refspec_nr;
67 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 (dry_run)
73 argv[argc++] = "--dry-run";
74 if (force)
75 argv[argc++] = "--force";
76 if (receivepack)
77 argv[argc++] = receivepack;
78 common_argc = argc;
80 errs = 0;
81 for (i = 0; i < remote->uri_nr; i++) {
82 int err;
83 int dest_argc = common_argc;
84 int dest_refspec_nr = refspec_nr;
85 const char **dest_refspec = refspec;
86 const char *dest = remote->uri[i];
87 const char *sender = "send-pack";
88 if (!prefixcmp(dest, "http://") ||
89 !prefixcmp(dest, "https://"))
90 sender = "http-push";
91 else {
92 char *rem = xmalloc(strlen(remote->name) + 10);
93 sprintf(rem, "--remote=%s", remote->name);
94 argv[dest_argc++] = rem;
95 if (thin)
96 argv[dest_argc++] = "--thin";
98 argv[0] = sender;
99 argv[dest_argc++] = dest;
100 while (dest_refspec_nr--)
101 argv[dest_argc++] = *dest_refspec++;
102 argv[dest_argc] = NULL;
103 if (verbose)
104 fprintf(stderr, "Pushing to %s\n", dest);
105 err = run_command_v_opt(argv, RUN_GIT_CMD);
106 if (!err)
107 continue;
109 error("failed to push to '%s'", remote->uri[i]);
110 switch (err) {
111 case -ERR_RUN_COMMAND_FORK:
112 error("unable to fork for %s", sender);
113 case -ERR_RUN_COMMAND_EXEC:
114 error("unable to exec %s", sender);
115 break;
116 case -ERR_RUN_COMMAND_WAITPID:
117 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
118 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
119 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
120 error("%s died with strange error", sender);
122 errs++;
124 return !!errs;
127 int cmd_push(int argc, const char **argv, const char *prefix)
129 int i;
130 const char *repo = NULL; /* default repository */
132 for (i = 1; i < argc; i++) {
133 const char *arg = argv[i];
135 if (arg[0] != '-') {
136 repo = arg;
137 i++;
138 break;
140 if (!strcmp(arg, "-v")) {
141 verbose=1;
142 continue;
144 if (!prefixcmp(arg, "--repo=")) {
145 repo = arg+7;
146 continue;
148 if (!strcmp(arg, "--all")) {
149 all = 1;
150 continue;
152 if (!strcmp(arg, "--dry-run")) {
153 dry_run = 1;
154 continue;
156 if (!strcmp(arg, "--tags")) {
157 add_refspec("refs/tags/*");
158 continue;
160 if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
161 force = 1;
162 continue;
164 if (!strcmp(arg, "--thin")) {
165 thin = 1;
166 continue;
168 if (!strcmp(arg, "--no-thin")) {
169 thin = 0;
170 continue;
172 if (!prefixcmp(arg, "--receive-pack=")) {
173 receivepack = arg;
174 continue;
176 if (!prefixcmp(arg, "--exec=")) {
177 receivepack = arg;
178 continue;
180 usage(push_usage);
182 set_refspecs(argv + i, argc - i);
183 if (all && refspec)
184 usage(push_usage);
186 return do_push(repo);