1#include "builtin.h"
2#include "commit.h"
3#include "refs.h"
4#include "pkt-line.h"
5#include "sideband.h"
6#include "run-command.h"
7#include "remote.h"
8#include "send-pack.h"
9#include "quote.h"
10#include "transport.h"
11#include "version.h"
1213
static const char send_pack_usage[] =
14"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
15" --all and explicit <ref> specification are mutually exclusive.";
1617
static struct send_pack_args args;
1819
static void print_helper_status(struct ref *ref)
20{
21struct strbuf buf = STRBUF_INIT;
2223
for (; ref; ref = ref->next) {
24const char *msg = NULL;
25const char *res;
2627
switch(ref->status) {
28case REF_STATUS_NONE:
29res = "error";
30msg = "no match";
31break;
3233
case REF_STATUS_OK:
34res = "ok";
35break;
3637
case REF_STATUS_UPTODATE:
38res = "ok";
39msg = "up to date";
40break;
4142
case REF_STATUS_REJECT_NONFASTFORWARD:
43res = "error";
44msg = "non-fast forward";
45break;
4647
case REF_STATUS_REJECT_NODELETE:
48case REF_STATUS_REMOTE_REJECT:
49res = "error";
50break;
5152
case REF_STATUS_EXPECTING_REPORT:
53default:
54continue;
55}
5657
strbuf_reset(&buf);
58strbuf_addf(&buf, "%s %s", res, ref->name);
59if (ref->remote_status)
60msg = ref->remote_status;
61if (msg) {
62strbuf_addch(&buf, ' ');
63quote_two_c_style(&buf, "", msg, 0);
64}
65strbuf_addch(&buf, '\n');
6667
safe_write(1, buf.buf, buf.len);
68}
69strbuf_release(&buf);
70}
7172
int cmd_send_pack(int argc, const char **argv, const char *prefix)
73{
74int i, nr_refspecs = 0;
75const char **refspecs = NULL;
76const char *remote_name = NULL;
77struct remote *remote = NULL;
78const char *dest = NULL;
79int fd[2];
80struct child_process *conn;
81struct extra_have_objects extra_have;
82struct ref *remote_refs, *local_refs;
83int ret;
84int helper_status = 0;
85int send_all = 0;
86const char *receivepack = "git-receive-pack";
87int flags;
88int nonfastforward = 0;
89int progress = -1;
9091
argv++;
92for (i = 1; i < argc; i++, argv++) {
93const char *arg = *argv;
9495
if (*arg == '-') {
96if (!prefixcmp(arg, "--receive-pack=")) {
97receivepack = arg + 15;
98continue;
99}
100if (!prefixcmp(arg, "--exec=")) {
101receivepack = arg + 7;
102continue;
103}
104if (!prefixcmp(arg, "--remote=")) {
105remote_name = arg + 9;
106continue;
107}
108if (!strcmp(arg, "--all")) {
109send_all = 1;
110continue;
111}
112if (!strcmp(arg, "--dry-run")) {
113args.dry_run = 1;
114continue;
115}
116if (!strcmp(arg, "--mirror")) {
117args.send_mirror = 1;
118continue;
119}
120if (!strcmp(arg, "--force")) {
121args.force_update = 1;
122continue;
123}
124if (!strcmp(arg, "--quiet")) {
125args.quiet = 1;
126continue;
127}
128if (!strcmp(arg, "--verbose")) {
129args.verbose = 1;
130continue;
131}
132if (!strcmp(arg, "--progress")) {
133progress = 1;
134continue;
135}
136if (!strcmp(arg, "--no-progress")) {
137progress = 0;
138continue;
139}
140if (!strcmp(arg, "--thin")) {
141args.use_thin_pack = 1;
142continue;
143}
144if (!strcmp(arg, "--stateless-rpc")) {
145args.stateless_rpc = 1;
146continue;
147}
148if (!strcmp(arg, "--helper-status")) {
149helper_status = 1;
150continue;
151}
152usage(send_pack_usage);
153}
154if (!dest) {
155dest = arg;
156continue;
157}
158refspecs = (const char **) argv;
159nr_refspecs = argc - i;
160break;
161}
162if (!dest)
163usage(send_pack_usage);
164/*
165* --all and --mirror are incompatible; neither makes sense
166* with any refspecs.
167*/
168if ((refspecs && (send_all || args.send_mirror)) ||
169(send_all && args.send_mirror))
170usage(send_pack_usage);
171172
if (remote_name) {
173remote = remote_get(remote_name);
174if (!remote_has_url(remote, dest)) {
175die("Destination %s is not a uri for %s",
176dest, remote_name);
177}
178}
179180
if (progress == -1)
181progress = !args.quiet && isatty(2);
182args.progress = progress;
183184
if (args.stateless_rpc) {
185conn = NULL;
186fd[0] = 0;
187fd[1] = 1;
188} else {
189conn = git_connect(fd, dest, receivepack,
190args.verbose ? CONNECT_VERBOSE : 0);
191}
192193
memset(&extra_have, 0, sizeof(extra_have));
194195
get_remote_heads(fd[0], &remote_refs, REF_NORMAL, &extra_have);
196197
transport_verify_remote_names(nr_refspecs, refspecs);
198199
local_refs = get_local_heads();
200201
flags = MATCH_REFS_NONE;
202203
if (send_all)
204flags |= MATCH_REFS_ALL;
205if (args.send_mirror)
206flags |= MATCH_REFS_MIRROR;
207208
/* match them up */
209if (match_push_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
210return -1;
211212
set_ref_status_for_push(remote_refs, args.send_mirror,
213args.force_update);
214215
ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
216217
if (helper_status)
218print_helper_status(remote_refs);
219220
close(fd[1]);
221close(fd[0]);
222223
ret |= finish_connect(conn);
224225
if (!helper_status)
226transport_print_push_status(dest, remote_refs, args.verbose, 0, &nonfastforward);
227228
if (!args.dry_run && remote) {
229struct ref *ref;
230for (ref = remote_refs; ref; ref = ref->next)
231transport_update_tracking_ref(remote, ref, args.verbose);
232}
233234
if (!ret && !transport_refs_pushed(remote_refs))
235fprintf(stderr, "Everything up-to-date\n");
236237
return ret;
238}