]> git.ipfire.org Git - thirdparty/git.git/blame - builtin-push.c
Make fetch-pack a builtin with an internal API
[thirdparty/git.git] / builtin-push.c
CommitLineData
755225de
LT
1/*
2 * "git push"
3 */
4#include "cache.h"
5#include "refs.h"
6#include "run-command.h"
7#include "builtin.h"
5751f490 8#include "remote.h"
755225de 9
d23842fd 10static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
755225de 11
a4503a15 12static int all, force, thin, verbose;
d23842fd 13static const char *receivepack;
755225de 14
96f1e58f
DR
15static const char **refspec;
16static int refspec_nr;
755225de
LT
17
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
755225de
LT
26static void set_refspecs(const char **refs, int nr)
27{
8558fd9e
DB
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;
411fb8ba 41 }
8558fd9e 42 add_refspec(ref);
755225de 43 }
755225de
LT
44}
45
755225de
LT
46static int do_push(const char *repo)
47{
5751f490 48 int i, errs;
441c823e 49 int common_argc;
755225de
LT
50 const char **argv;
51 int argc;
5751f490 52 struct remote *remote = remote_get(repo);
755225de 53
5751f490 54 if (!remote)
755225de
LT
55 die("bad repository '%s'", repo);
56
5751f490
DB
57 if (remote->receivepack) {
58 char *rp = xmalloc(strlen(remote->receivepack) + 16);
59 sprintf(rp, "--receive-pack=%s", remote->receivepack);
60 receivepack = rp;
61 }
8558fd9e
DB
62 if (!refspec && !all && remote->push_refspec_nr) {
63 refspec = remote->push_refspec;
64 refspec_nr = remote->push_refspec_nr;
5751f490
DB
65 }
66
755225de
LT
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 (force)
73 argv[argc++] = "--force";
d23842fd
UKK
74 if (receivepack)
75 argv[argc++] = receivepack;
441c823e 76 common_argc = argc;
755225de 77
fd1d1b05 78 errs = 0;
5751f490 79 for (i = 0; i < remote->uri_nr; i++) {
60b7f38e 80 int err;
441c823e
NH
81 int dest_argc = common_argc;
82 int dest_refspec_nr = refspec_nr;
83 const char **dest_refspec = refspec;
5751f490 84 const char *dest = remote->uri[i];
df91ba36 85 const char *sender = "send-pack";
cc44c765
JH
86 if (!prefixcmp(dest, "http://") ||
87 !prefixcmp(dest, "https://"))
df91ba36 88 sender = "http-push";
b516968f
DB
89 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 }
755225de 96 argv[0] = sender;
441c823e
NH
97 argv[dest_argc++] = dest;
98 while (dest_refspec_nr--)
99 argv[dest_argc++] = *dest_refspec++;
100 argv[dest_argc] = NULL;
bcc785f6
LT
101 if (verbose)
102 fprintf(stderr, "Pushing to %s\n", dest);
df91ba36 103 err = run_command_v_opt(argv, RUN_GIT_CMD);
60b7f38e 104 if (!err)
755225de 105 continue;
39878b0c 106
5751f490 107 error("failed to push to '%s'", remote->uri[i]);
60b7f38e 108 switch (err) {
755225de 109 case -ERR_RUN_COMMAND_FORK:
fd1d1b05 110 error("unable to fork for %s", sender);
755225de 111 case -ERR_RUN_COMMAND_EXEC:
fd1d1b05
JH
112 error("unable to exec %s", sender);
113 break;
755225de
LT
114 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:
fd1d1b05 118 error("%s died with strange error", sender);
755225de 119 }
fd1d1b05 120 errs++;
755225de 121 }
fd1d1b05 122 return !!errs;
755225de
LT
123}
124
a633fca0 125int cmd_push(int argc, const char **argv, const char *prefix)
755225de
LT
126{
127 int i;
5751f490 128 const char *repo = NULL; /* default repository */
755225de
LT
129
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 }
bcc785f6
LT
138 if (!strcmp(arg, "-v")) {
139 verbose=1;
140 continue;
141 }
cc44c765 142 if (!prefixcmp(arg, "--repo=")) {
bcc785f6
LT
143 repo = arg+7;
144 continue;
145 }
755225de
LT
146 if (!strcmp(arg, "--all")) {
147 all = 1;
148 continue;
149 }
150 if (!strcmp(arg, "--tags")) {
8558fd9e 151 add_refspec("refs/tags/*");
755225de
LT
152 continue;
153 }
8f615493 154 if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
755225de
LT
155 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 }
cc44c765 166 if (!prefixcmp(arg, "--receive-pack=")) {
d23842fd
UKK
167 receivepack = arg;
168 continue;
169 }
cc44c765 170 if (!prefixcmp(arg, "--exec=")) {
d23842fd 171 receivepack = arg;
755225de
LT
172 continue;
173 }
174 usage(push_usage);
175 }
176 set_refspecs(argv + i, argc - i);
8558fd9e
DB
177 if (all && refspec)
178 usage(push_usage);
179
755225de
LT
180 return do_push(repo);
181}