blob: 9cb9f716509b00ec394bb901b61d679eaa04045d [file] [log] [blame]
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +07001#include "builtin.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07002#include "config.h"
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +07003#include "commit.h"
4#include "refs.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -07005#include "object-store.h"
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +07006#include "pkt-line.h"
7#include "sideband.h"
8#include "run-command.h"
9#include "remote.h"
Junio C Hamano47a59182013-07-08 13:56:53 -070010#include "connect.h"
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070011#include "send-pack.h"
12#include "quote.h"
13#include "transport.h"
14#include "version.h"
Jeff Kingfe299ec2020-03-30 10:03:46 -040015#include "oid-array.h"
Junio C Hamanoa85b3772014-09-12 11:17:07 -070016#include "gpg-interface.h"
Dave Borowitz30261092015-08-19 11:26:46 -040017#include "cache.h"
Taylor Blau120ad2b2020-04-30 13:48:50 -060018#include "shallow.h"
Dave Borowitz30261092015-08-19 11:26:46 -040019
20int option_parse_push_signed(const struct option *opt,
21 const char *arg, int unset)
22{
23 if (unset) {
24 *(int *)(opt->value) = SEND_PACK_PUSH_CERT_NEVER;
25 return 0;
26 }
27 switch (git_parse_maybe_bool(arg)) {
28 case 1:
29 *(int *)(opt->value) = SEND_PACK_PUSH_CERT_ALWAYS;
30 return 0;
31 case 0:
32 *(int *)(opt->value) = SEND_PACK_PUSH_CERT_NEVER;
33 return 0;
34 }
35 if (!strcasecmp("if-asked", arg)) {
36 *(int *)(opt->value) = SEND_PACK_PUSH_CERT_IF_ASKED;
37 return 0;
38 }
39 die("bad %s argument: %s", opt->long_name, arg);
40}
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070041
brian m. carlson246d7402018-03-12 02:27:32 +000042static void feed_object(const struct object_id *oid, FILE *fh, int negative)
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070043{
Jonathan Tand8bc1a52019-10-08 11:37:39 -070044 if (negative &&
Jeff King5cf7a172019-11-27 07:32:11 -050045 !has_object_file_with_flags(oid,
46 OBJECT_INFO_SKIP_FETCH_OBJECT |
47 OBJECT_INFO_QUICK))
Jeff Kingf0bca722016-06-08 15:42:16 -040048 return;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070049
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070050 if (negative)
Jeff Kingf0bca722016-06-08 15:42:16 -040051 putc('^', fh);
brian m. carlson246d7402018-03-12 02:27:32 +000052 fputs(oid_to_hex(oid), fh);
Jeff Kingf0bca722016-06-08 15:42:16 -040053 putc('\n', fh);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070054}
55
56/*
57 * Make a pack stream and spit it out into file descriptor fd
58 */
Jonathan Tan477673d2021-05-04 14:16:02 -070059static int pack_objects(int fd, struct ref *refs, struct oid_array *advertised,
60 struct oid_array *negotiated,
61 struct send_pack_args *args)
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070062{
63 /*
64 * The child becomes pack-objects --revs; we feed
65 * the revision parameters to it via its stdin and
66 * let its stdout go back to the other end.
67 */
René Scharfed3180272014-08-19 21:09:35 +020068 struct child_process po = CHILD_PROCESS_INIT;
Jeff Kingf0bca722016-06-08 15:42:16 -040069 FILE *po_in;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070070 int i;
Jeff Kingd1a13d32017-03-07 08:39:48 -050071 int rc;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070072
Jeff Kingc972bf42020-07-28 16:25:12 -040073 strvec_push(&po.args, "pack-objects");
74 strvec_push(&po.args, "--all-progress-implied");
75 strvec_push(&po.args, "--revs");
76 strvec_push(&po.args, "--stdout");
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070077 if (args->use_thin_pack)
Jeff Kingc972bf42020-07-28 16:25:12 -040078 strvec_push(&po.args, "--thin");
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070079 if (args->use_ofs_delta)
Jeff Kingc972bf42020-07-28 16:25:12 -040080 strvec_push(&po.args, "--delta-base-offset");
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070081 if (args->quiet || !args->progress)
Jeff Kingc972bf42020-07-28 16:25:12 -040082 strvec_push(&po.args, "-q");
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070083 if (args->progress)
Jeff Kingc972bf42020-07-28 16:25:12 -040084 strvec_push(&po.args, "--progress");
Stefan Bellerc8813482018-05-17 15:51:46 -070085 if (is_repository_shallow(the_repository))
Jeff Kingc972bf42020-07-28 16:25:12 -040086 strvec_push(&po.args, "--shallow");
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070087 po.in = -1;
88 po.out = args->stateless_rpc ? -1 : fd;
89 po.git_cmd = 1;
Jeff King8b599352020-11-20 19:29:21 -050090 po.clean_on_exit = 1;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +070091 if (start_command(&po))
92 die_errno("git pack-objects failed");
93
94 /*
95 * We feed the pack-objects we just spawned with revision
96 * parameters by writing to the pipe.
97 */
Jeff Kingf0bca722016-06-08 15:42:16 -040098 po_in = xfdopen(po.in, "w");
Jonathan Tan477673d2021-05-04 14:16:02 -070099 for (i = 0; i < advertised->nr; i++)
100 feed_object(&advertised->oid[i], po_in, 1);
101 for (i = 0; i < negotiated->nr; i++)
102 feed_object(&negotiated->oid[i], po_in, 1);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700103
104 while (refs) {
Jeff Kingf0bca722016-06-08 15:42:16 -0400105 if (!is_null_oid(&refs->old_oid))
brian m. carlson246d7402018-03-12 02:27:32 +0000106 feed_object(&refs->old_oid, po_in, 1);
Jeff Kingf0bca722016-06-08 15:42:16 -0400107 if (!is_null_oid(&refs->new_oid))
brian m. carlson246d7402018-03-12 02:27:32 +0000108 feed_object(&refs->new_oid, po_in, 0);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700109 refs = refs->next;
110 }
111
Jeff Kingf0bca722016-06-08 15:42:16 -0400112 fflush(po_in);
113 if (ferror(po_in))
114 die_errno("error writing to pack-objects");
115 fclose(po_in);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700116
117 if (args->stateless_rpc) {
118 char *buf = xmalloc(LARGE_PACKET_MAX);
119 while (1) {
120 ssize_t n = xread(po.out, buf, LARGE_PACKET_MAX);
121 if (n <= 0)
122 break;
123 send_sideband(fd, -1, buf, n, LARGE_PACKET_MAX);
124 }
125 free(buf);
126 close(po.out);
127 po.out = -1;
128 }
129
Jeff Kingd1a13d32017-03-07 08:39:48 -0500130 rc = finish_command(&po);
131 if (rc) {
132 /*
133 * For a normal non-zero exit, we assume pack-objects wrote
134 * something useful to stderr. For death by signal, though,
135 * we should mention it to the user. The exception is SIGPIPE
Ville Skyttä64127572017-06-25 13:20:41 +0300136 * (141), because that's a normal occurrence if the remote end
Jeff Kingd1a13d32017-03-07 08:39:48 -0500137 * hangs up (and we'll report that by trying to read the unpack
138 * status).
139 */
140 if (rc > 128 && rc != 141)
141 error("pack-objects died of signal %d", rc - 128);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700142 return -1;
Jeff Kingd1a13d32017-03-07 08:39:48 -0500143 }
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700144 return 0;
145}
146
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800147static int receive_unpack_status(struct packet_reader *reader)
Jeff King7c39df22017-03-07 08:35:57 -0500148{
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800149 if (packet_reader_read(reader) != PACKET_READ_NORMAL)
Jon Simonsbb1356d2018-02-08 13:47:50 -0500150 return error(_("unexpected flush packet while reading remote unpack status"));
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800151 if (!skip_prefix(reader->line, "unpack ", &reader->line))
152 return error(_("unable to parse remote unpack status: %s"), reader->line);
153 if (strcmp(reader->line, "ok"))
154 return error(_("remote unpack failed: %s"), reader->line);
Jeff King7c39df22017-03-07 08:35:57 -0500155 return 0;
156}
157
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800158static int receive_status(struct packet_reader *reader, struct ref *refs)
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700159{
160 struct ref *hint;
Jeff King7c39df22017-03-07 08:35:57 -0500161 int ret;
Jiang Xin63518a52020-08-27 11:45:46 -0400162 struct ref_push_report *report = NULL;
163 int new_report = 0;
164 int once = 0;
Jeff King7c39df22017-03-07 08:35:57 -0500165
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700166 hint = NULL;
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800167 ret = receive_unpack_status(reader);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700168 while (1) {
Jiang Xin63518a52020-08-27 11:45:46 -0400169 struct object_id old_oid, new_oid;
170 const char *head;
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800171 const char *refname;
Jiang Xin63518a52020-08-27 11:45:46 -0400172 char *p;
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800173 if (packet_reader_read(reader) != PACKET_READ_NORMAL)
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700174 break;
Jiang Xin63518a52020-08-27 11:45:46 -0400175 head = reader->line;
176 p = strchr(head, ' ');
177 if (!p) {
178 error("invalid status line from remote: %s", reader->line);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700179 ret = -1;
180 break;
181 }
Jiang Xin63518a52020-08-27 11:45:46 -0400182 *p++ = '\0';
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700183
Jiang Xin63518a52020-08-27 11:45:46 -0400184 if (!strcmp(head, "option")) {
185 const char *key, *val;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700186
Jiang Xin63518a52020-08-27 11:45:46 -0400187 if (!hint || !(report || new_report)) {
188 if (!once++)
189 error("'option' without a matching 'ok/ng' directive");
190 ret = -1;
191 continue;
192 }
193 if (new_report) {
194 if (!hint->report) {
René Scharfeca56dad2021-03-13 17:17:22 +0100195 CALLOC_ARRAY(hint->report, 1);
Jiang Xin63518a52020-08-27 11:45:46 -0400196 report = hint->report;
197 } else {
198 report = hint->report;
199 while (report->next)
200 report = report->next;
René Scharfeca56dad2021-03-13 17:17:22 +0100201 CALLOC_ARRAY(report->next, 1);
Jiang Xin63518a52020-08-27 11:45:46 -0400202 report = report->next;
203 }
204 new_report = 0;
205 }
206 key = p;
207 p = strchr(key, ' ');
208 if (p)
209 *p++ = '\0';
210 val = p;
211 if (!strcmp(key, "refname"))
212 report->ref_name = xstrdup_or_null(val);
213 else if (!strcmp(key, "old-oid") && val &&
214 !parse_oid_hex(val, &old_oid, &val))
215 report->old_oid = oiddup(&old_oid);
216 else if (!strcmp(key, "new-oid") && val &&
217 !parse_oid_hex(val, &new_oid, &val))
218 report->new_oid = oiddup(&new_oid);
219 else if (!strcmp(key, "forced-update"))
220 report->forced_update = 1;
221 continue;
222 }
223
224 report = NULL;
225 new_report = 0;
226 if (strcmp(head, "ok") && strcmp(head, "ng")) {
227 error("invalid ref status from remote: %s", head);
228 ret = -1;
229 break;
230 }
231 refname = p;
232 p = strchr(refname, ' ');
233 if (p)
234 *p++ = '\0';
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700235 /* first try searching at our hint, falling back to all refs */
236 if (hint)
237 hint = find_ref_by_name(hint, refname);
238 if (!hint)
239 hint = find_ref_by_name(refs, refname);
240 if (!hint) {
241 warning("remote reported status on unknown ref: %s",
Jiang Xin63518a52020-08-27 11:45:46 -0400242 refname);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700243 continue;
244 }
Jiang Xin63518a52020-08-27 11:45:46 -0400245 if (hint->status != REF_STATUS_EXPECTING_REPORT &&
246 hint->status != REF_STATUS_OK &&
247 hint->status != REF_STATUS_REMOTE_REJECT) {
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700248 warning("remote reported status on unexpected ref: %s",
Jiang Xin63518a52020-08-27 11:45:46 -0400249 refname);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700250 continue;
251 }
Jiang Xin63518a52020-08-27 11:45:46 -0400252 if (!strcmp(head, "ng")) {
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700253 hint->status = REF_STATUS_REMOTE_REJECT;
Jiang Xin63518a52020-08-27 11:45:46 -0400254 if (p)
255 hint->remote_status = xstrdup(p);
256 else
257 hint->remote_status = "failed";
258 } else {
259 hint->status = REF_STATUS_OK;
260 hint->remote_status = xstrdup_or_null(p);
261 new_report = 1;
262 }
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700263 }
264 return ret;
265}
266
267static int sideband_demux(int in, int out, void *data)
268{
269 int *fd = data, ret;
Nguyễn Thái Ngọc Duyc0e40a22018-11-03 09:48:39 +0100270 if (async_with_fork())
271 close(fd[1]);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700272 ret = recv_sideband("send-pack", fd[0], out);
273 close(out);
274 return ret;
275}
276
Nguyễn Thái Ngọc Duyf2c681c2013-12-05 20:02:52 +0700277static int advertise_shallow_grafts_cb(const struct commit_graft *graft, void *cb)
278{
279 struct strbuf *sb = cb;
280 if (graft->nr_parent == -1)
brian m. carlson7683e2e2015-03-13 23:39:34 +0000281 packet_buf_write(sb, "shallow %s\n", oid_to_hex(&graft->oid));
Nguyễn Thái Ngọc Duyf2c681c2013-12-05 20:02:52 +0700282 return 0;
283}
284
Ramsay Jones16a27432014-01-05 23:55:01 +0000285static void advertise_shallow_grafts_buf(struct strbuf *sb)
Nguyễn Thái Ngọc Duyf2c681c2013-12-05 20:02:52 +0700286{
Stefan Bellerc8813482018-05-17 15:51:46 -0700287 if (!is_repository_shallow(the_repository))
Nguyễn Thái Ngọc Duyf2c681c2013-12-05 20:02:52 +0700288 return;
289 for_each_commit_graft(advertise_shallow_grafts_cb, sb);
290}
291
Stefan Beller7582e932015-01-07 19:23:21 -0800292#define CHECK_REF_NO_PUSH -1
293#define CHECK_REF_STATUS_REJECTED -2
294#define CHECK_REF_UPTODATE -3
295static int check_to_send_update(const struct ref *ref, const struct send_pack_args *args)
Junio C Hamanoe40671a2014-08-12 15:40:00 -0700296{
297 if (!ref->peer_ref && !args->send_mirror)
Stefan Beller7582e932015-01-07 19:23:21 -0800298 return CHECK_REF_NO_PUSH;
Junio C Hamanoe40671a2014-08-12 15:40:00 -0700299
300 /* Check for statuses set by set_ref_status_for_push() */
301 switch (ref->status) {
302 case REF_STATUS_REJECT_NONFASTFORWARD:
303 case REF_STATUS_REJECT_ALREADY_EXISTS:
304 case REF_STATUS_REJECT_FETCH_FIRST:
305 case REF_STATUS_REJECT_NEEDS_FORCE:
306 case REF_STATUS_REJECT_STALE:
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +0530307 case REF_STATUS_REJECT_REMOTE_UPDATED:
Junio C Hamanoe40671a2014-08-12 15:40:00 -0700308 case REF_STATUS_REJECT_NODELETE:
Stefan Beller7582e932015-01-07 19:23:21 -0800309 return CHECK_REF_STATUS_REJECTED;
Junio C Hamanoe40671a2014-08-12 15:40:00 -0700310 case REF_STATUS_UPTODATE:
Stefan Beller7582e932015-01-07 19:23:21 -0800311 return CHECK_REF_UPTODATE;
Han Xina4f324a2020-09-19 22:47:50 +0800312
Junio C Hamanoe40671a2014-08-12 15:40:00 -0700313 default:
Han Xina4f324a2020-09-19 22:47:50 +0800314 case REF_STATUS_EXPECTING_REPORT:
315 /* already passed checks on the local side */
316 case REF_STATUS_OK:
317 /* of course this is OK */
Stefan Beller7582e932015-01-07 19:23:21 -0800318 return 0;
Junio C Hamanoe40671a2014-08-12 15:40:00 -0700319 }
320}
321
Junio C Hamanoa85b3772014-09-12 11:17:07 -0700322/*
323 * the beginning of the next line, or the end of buffer.
324 *
325 * NEEDSWORK: perhaps move this to git-compat-util.h or somewhere and
326 * convert many similar uses found by "git grep -A4 memchr".
327 */
328static const char *next_line(const char *line, size_t len)
329{
330 const char *nl = memchr(line, '\n', len);
331 if (!nl)
332 return line + len; /* incomplete line */
333 return nl + 1;
334}
335
Junio C Hamano20a75582014-08-18 13:46:58 -0700336static int generate_push_cert(struct strbuf *req_buf,
337 const struct ref *remote_refs,
338 struct send_pack_args *args,
Junio C Hamanob89363e2014-08-21 16:45:30 -0700339 const char *cap_string,
340 const char *push_cert_nonce)
Junio C Hamanoa85b3772014-09-12 11:17:07 -0700341{
342 const struct ref *ref;
Stefan Bellerf6a4e612016-07-14 14:49:47 -0700343 struct string_list_item *item;
Junio C Hamanoa85b3772014-09-12 11:17:07 -0700344 char *signing_key = xstrdup(get_signing_key());
345 const char *cp, *np;
346 struct strbuf cert = STRBUF_INIT;
347 int update_seen = 0;
348
René Scharfe02962d32016-07-30 19:36:23 +0200349 strbuf_addstr(&cert, "certificate version 0.1\n");
Junio C Hamanofb06b522014-10-08 13:05:15 -0700350 strbuf_addf(&cert, "pusher %s ", signing_key);
351 datestamp(&cert);
352 strbuf_addch(&cert, '\n');
Junio C Hamano9be89162014-08-22 18:15:24 -0700353 if (args->url && *args->url) {
354 char *anon_url = transport_anonymize_url(args->url);
355 strbuf_addf(&cert, "pushee %s\n", anon_url);
356 free(anon_url);
357 }
Junio C Hamanob89363e2014-08-21 16:45:30 -0700358 if (push_cert_nonce[0])
359 strbuf_addf(&cert, "nonce %s\n", push_cert_nonce);
Stefan Bellerf6a4e612016-07-14 14:49:47 -0700360 if (args->push_options)
361 for_each_string_list_item(item, args->push_options)
362 strbuf_addf(&cert, "push-option %s\n", item->string);
Junio C Hamanoa85b3772014-09-12 11:17:07 -0700363 strbuf_addstr(&cert, "\n");
364
365 for (ref = remote_refs; ref; ref = ref->next) {
Stefan Beller7582e932015-01-07 19:23:21 -0800366 if (check_to_send_update(ref, args) < 0)
Junio C Hamanoa85b3772014-09-12 11:17:07 -0700367 continue;
368 update_seen = 1;
369 strbuf_addf(&cert, "%s %s %s\n",
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000370 oid_to_hex(&ref->old_oid),
371 oid_to_hex(&ref->new_oid),
Junio C Hamanoa85b3772014-09-12 11:17:07 -0700372 ref->name);
373 }
374 if (!update_seen)
375 goto free_return;
376
377 if (sign_buffer(&cert, &cert, signing_key))
378 die(_("failed to sign the push certificate"));
379
Junio C Hamano20a75582014-08-18 13:46:58 -0700380 packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string);
Junio C Hamanoa85b3772014-09-12 11:17:07 -0700381 for (cp = cert.buf; cp < cert.buf + cert.len; cp = np) {
382 np = next_line(cp, cert.buf + cert.len - cp);
383 packet_buf_write(req_buf,
384 "%.*s", (int)(np - cp), cp);
385 }
386 packet_buf_write(req_buf, "push-cert-end\n");
387
388free_return:
389 free(signing_key);
390 strbuf_release(&cert);
Junio C Hamano20a75582014-08-18 13:46:58 -0700391 return update_seen;
Junio C Hamanoa85b3772014-09-12 11:17:07 -0700392}
393
Junio C Hamanoafcb6ee2015-04-01 18:00:36 -0700394#define NONCE_LEN_LIMIT 256
395
396static void reject_invalid_nonce(const char *nonce, int len)
397{
398 int i = 0;
399
400 if (NONCE_LEN_LIMIT <= len)
401 die("the receiving end asked to sign an invalid nonce <%.*s>",
402 len, nonce);
403
404 for (i = 0; i < len; i++) {
405 int ch = nonce[i] & 0xFF;
406 if (isalnum(ch) ||
407 ch == '-' || ch == '.' ||
408 ch == '/' || ch == '+' ||
409 ch == '=' || ch == '_')
410 continue;
411 die("the receiving end asked to sign an invalid nonce <%.*s>",
412 len, nonce);
413 }
414}
415
Jonathan Tan477673d2021-05-04 14:16:02 -0700416static void get_commons_through_negotiation(const char *url,
417 const struct ref *remote_refs,
418 struct oid_array *commons)
419{
420 struct child_process child = CHILD_PROCESS_INIT;
421 const struct ref *ref;
422 int len = the_hash_algo->hexsz + 1; /* hash + NL */
423
424 child.git_cmd = 1;
425 child.no_stdin = 1;
426 child.out = -1;
427 strvec_pushl(&child.args, "fetch", "--negotiate-only", NULL);
428 for (ref = remote_refs; ref; ref = ref->next)
429 strvec_pushf(&child.args, "--negotiation-tip=%s", oid_to_hex(&ref->new_oid));
430 strvec_push(&child.args, url);
431
432 if (start_command(&child))
433 die(_("send-pack: unable to fork off fetch subprocess"));
434
435 do {
436 char hex_hash[GIT_MAX_HEXSZ + 1];
437 int read_len = read_in_full(child.out, hex_hash, len);
438 struct object_id oid;
439 const char *end;
440
441 if (!read_len)
442 break;
443 if (read_len != len)
444 die("invalid length read %d", read_len);
445 if (parse_oid_hex(hex_hash, &oid, &end) || *end != '\n')
446 die("invalid hash");
447 oid_array_append(commons, &oid);
448 } while (1);
449
450 if (finish_command(&child)) {
451 /*
452 * The information that push negotiation provides is useful but
453 * not mandatory.
454 */
455 warning(_("push negotiation failed; proceeding anyway with push"));
456 }
457}
458
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700459int send_pack(struct send_pack_args *args,
460 int fd[], struct child_process *conn,
461 struct ref *remote_refs,
brian m. carlson910650d2017-03-31 01:40:00 +0000462 struct oid_array *extra_have)
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700463{
Jonathan Tan477673d2021-05-04 14:16:02 -0700464 struct oid_array commons = OID_ARRAY_INIT;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700465 int in = fd[0];
466 int out = fd[1];
467 struct strbuf req_buf = STRBUF_INIT;
Junio C Hamano887f3532014-08-15 11:37:01 -0700468 struct strbuf cap_buf = STRBUF_INIT;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700469 struct ref *ref;
Junio C Hamanoab2b0c92014-08-15 12:23:51 -0700470 int need_pack_data = 0;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700471 int allow_deleting_refs = 0;
472 int status_report = 0;
473 int use_sideband = 0;
474 int quiet_supported = 0;
475 int agent_supported = 0;
Josh Steadmon8c487002020-11-11 15:29:33 -0800476 int advertise_sid = 0;
Jonathan Tan477673d2021-05-04 14:16:02 -0700477 int push_negotiate = 0;
Ronnie Sahlberg4ff17f12015-01-07 19:23:22 -0800478 int use_atomic = 0;
479 int atomic_supported = 0;
Stefan Bellerf6a4e612016-07-14 14:49:47 -0700480 int use_push_options = 0;
481 int push_options_supported = 0;
brian m. carlson82db03a2020-05-25 19:58:57 +0000482 int object_format_supported = 0;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700483 unsigned cmds_sent = 0;
484 int ret;
485 struct async demux;
Junio C Hamanob89363e2014-08-21 16:45:30 -0700486 const char *push_cert_nonce = NULL;
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800487 struct packet_reader reader;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700488
Jonathan Tan477673d2021-05-04 14:16:02 -0700489 git_config_get_bool("push.negotiate", &push_negotiate);
490 if (push_negotiate)
491 get_commons_through_negotiation(args->url, remote_refs, &commons);
492
Josh Steadmon8c487002020-11-11 15:29:33 -0800493 git_config_get_bool("transfer.advertisesid", &advertise_sid);
494
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700495 /* Does the other end support the reporting? */
Jiang Xin63518a52020-08-27 11:45:46 -0400496 if (server_supports("report-status-v2"))
497 status_report = 2;
498 else if (server_supports("report-status"))
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700499 status_report = 1;
500 if (server_supports("delete-refs"))
501 allow_deleting_refs = 1;
502 if (server_supports("ofs-delta"))
503 args->use_ofs_delta = 1;
504 if (server_supports("side-band-64k"))
505 use_sideband = 1;
506 if (server_supports("quiet"))
507 quiet_supported = 1;
508 if (server_supports("agent"))
509 agent_supported = 1;
Josh Steadmon8c487002020-11-11 15:29:33 -0800510 if (!server_supports("session-id"))
511 advertise_sid = 0;
Carlos Martín Nieto1ba98a72013-11-23 17:07:55 +0100512 if (server_supports("no-thin"))
513 args->use_thin_pack = 0;
Ronnie Sahlberg4ff17f12015-01-07 19:23:22 -0800514 if (server_supports("atomic"))
515 atomic_supported = 1;
Stefan Bellerf6a4e612016-07-14 14:49:47 -0700516 if (server_supports("push-options"))
517 push_options_supported = 1;
Junio C Hamanob89363e2014-08-21 16:45:30 -0700518
brian m. carlson82db03a2020-05-25 19:58:57 +0000519 if (!server_supports_hash(the_hash_algo->name, &object_format_supported))
520 die(_("the receiving end does not support this repository's hash algorithm"));
521
Dave Borowitz30261092015-08-19 11:26:46 -0400522 if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {
523 int len;
Junio C Hamanob89363e2014-08-21 16:45:30 -0700524 push_cert_nonce = server_feature_value("push-cert", &len);
Dave Borowitz30261092015-08-19 11:26:46 -0400525 if (push_cert_nonce) {
526 reject_invalid_nonce(push_cert_nonce, len);
527 push_cert_nonce = xmemdupz(push_cert_nonce, len);
528 } else if (args->push_cert == SEND_PACK_PUSH_CERT_ALWAYS) {
Junio C Hamanob89363e2014-08-21 16:45:30 -0700529 die(_("the receiving end does not support --signed push"));
Dave Borowitz30261092015-08-19 11:26:46 -0400530 } else if (args->push_cert == SEND_PACK_PUSH_CERT_IF_ASKED) {
531 warning(_("not sending a push certificate since the"
532 " receiving end does not support --signed"
533 " push"));
534 }
Junio C Hamanob89363e2014-08-21 16:45:30 -0700535 }
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700536
537 if (!remote_refs) {
538 fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
Johannes Schindelin4d046582020-06-24 14:46:29 +0000539 "Perhaps you should specify a branch.\n");
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700540 return 0;
541 }
Ronnie Sahlberg4ff17f12015-01-07 19:23:22 -0800542 if (args->atomic && !atomic_supported)
Ralf Thielowc8b8f222015-04-02 19:28:48 +0200543 die(_("the receiving end does not support --atomic push"));
Ronnie Sahlberg4ff17f12015-01-07 19:23:22 -0800544
545 use_atomic = atomic_supported && args->atomic;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700546
Stefan Bellerf6a4e612016-07-14 14:49:47 -0700547 if (args->push_options && !push_options_supported)
548 die(_("the receiving end does not support push options"));
549
550 use_push_options = push_options_supported && args->push_options;
551
Jiang Xin63518a52020-08-27 11:45:46 -0400552 if (status_report == 1)
Junio C Hamano887f3532014-08-15 11:37:01 -0700553 strbuf_addstr(&cap_buf, " report-status");
Jiang Xin63518a52020-08-27 11:45:46 -0400554 else if (status_report == 2)
555 strbuf_addstr(&cap_buf, " report-status-v2");
Junio C Hamano887f3532014-08-15 11:37:01 -0700556 if (use_sideband)
557 strbuf_addstr(&cap_buf, " side-band-64k");
558 if (quiet_supported && (args->quiet || !args->progress))
559 strbuf_addstr(&cap_buf, " quiet");
Ronnie Sahlberg4ff17f12015-01-07 19:23:22 -0800560 if (use_atomic)
561 strbuf_addstr(&cap_buf, " atomic");
Stefan Bellerf6a4e612016-07-14 14:49:47 -0700562 if (use_push_options)
563 strbuf_addstr(&cap_buf, " push-options");
brian m. carlson82db03a2020-05-25 19:58:57 +0000564 if (object_format_supported)
565 strbuf_addf(&cap_buf, " object-format=%s", the_hash_algo->name);
Junio C Hamano887f3532014-08-15 11:37:01 -0700566 if (agent_supported)
567 strbuf_addf(&cap_buf, " agent=%s", git_user_agent_sanitized());
Josh Steadmon8c487002020-11-11 15:29:33 -0800568 if (advertise_sid)
569 strbuf_addf(&cap_buf, " session-id=%s", trace2_session_id());
Junio C Hamano887f3532014-08-15 11:37:01 -0700570
Junio C Hamano621b0592014-08-12 15:04:17 -0700571 /*
572 * NEEDSWORK: why does delete-refs have to be so specific to
573 * send-pack machinery that set_ref_status_for_push() cannot
574 * set this bit for us???
575 */
576 for (ref = remote_refs; ref; ref = ref->next)
577 if (ref->deletion && !allow_deleting_refs)
578 ref->status = REF_STATUS_REJECT_NODELETE;
579
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700580 /*
Junio C Hamanob783aa72014-08-15 12:29:42 -0700581 * Clear the status for each ref and see if we need to send
582 * the pack data.
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700583 */
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700584 for (ref = remote_refs; ref; ref = ref->next) {
Ronnie Sahlberg4ff17f12015-01-07 19:23:22 -0800585 switch (check_to_send_update(ref, args)) {
586 case 0: /* no error */
587 break;
588 case CHECK_REF_STATUS_REJECTED:
589 /*
590 * When we know the server would reject a ref update if
591 * we were to send it and we're trying to send the refs
592 * atomically, abort the whole operation.
593 */
Rene Scharfe872d6512017-08-30 20:00:28 +0200594 if (use_atomic) {
595 strbuf_release(&req_buf);
596 strbuf_release(&cap_buf);
Jiang Xindfe1b7f2020-04-17 05:45:36 -0400597 reject_atomic_push(remote_refs, args->send_mirror);
598 error("atomic push failed for ref %s. status: %d\n",
599 ref->name, ref->status);
Jiang Xin7dcbeaa2020-04-17 05:45:32 -0400600 return args->porcelain ? 0 : -1;
Rene Scharfe872d6512017-08-30 20:00:28 +0200601 }
Jeff King1cf01a32017-09-21 02:25:41 -0400602 /* else fallthrough */
Ronnie Sahlberg4ff17f12015-01-07 19:23:22 -0800603 default:
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700604 continue;
Ronnie Sahlberg4ff17f12015-01-07 19:23:22 -0800605 }
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700606 if (!ref->deletion)
Junio C Hamanoab2b0c92014-08-15 12:23:51 -0700607 need_pack_data = 1;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700608
Junio C Hamanob783aa72014-08-15 12:29:42 -0700609 if (args->dry_run || !status_report)
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700610 ref->status = REF_STATUS_OK;
Junio C Hamanob783aa72014-08-15 12:29:42 -0700611 else
612 ref->status = REF_STATUS_EXPECTING_REPORT;
613 }
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700614
Han Xina4f324a2020-09-19 22:47:50 +0800615 if (!args->dry_run)
616 advertise_shallow_grafts_buf(&req_buf);
617
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700618 /*
619 * Finally, tell the other end!
620 */
Han Xina4f324a2020-09-19 22:47:50 +0800621 if (!args->dry_run && push_cert_nonce)
622 cmds_sent = generate_push_cert(&req_buf, remote_refs, args,
623 cap_buf.buf, push_cert_nonce);
624 else if (!args->dry_run)
625 for (ref = remote_refs; ref; ref = ref->next) {
626 char *old_hex, *new_hex;
Junio C Hamanob783aa72014-08-15 12:29:42 -0700627
Han Xina4f324a2020-09-19 22:47:50 +0800628 if (check_to_send_update(ref, args) < 0)
629 continue;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700630
Han Xina4f324a2020-09-19 22:47:50 +0800631 old_hex = oid_to_hex(&ref->old_oid);
632 new_hex = oid_to_hex(&ref->new_oid);
633 if (!cmds_sent) {
634 packet_buf_write(&req_buf,
635 "%s %s %s%c%s",
636 old_hex, new_hex, ref->name, 0,
637 cap_buf.buf);
638 cmds_sent = 1;
639 } else {
640 packet_buf_write(&req_buf, "%s %s %s",
641 old_hex, new_hex, ref->name);
642 }
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700643 }
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700644
Brandon Williamseb7b9742017-03-22 15:21:59 -0700645 if (use_push_options) {
646 struct string_list_item *item;
647
648 packet_buf_flush(&req_buf);
649 for_each_string_list_item(item, args->push_options)
650 packet_buf_write(&req_buf, "%s", item->string);
651 }
652
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700653 if (args->stateless_rpc) {
Stefan Bellerc8813482018-05-17 15:51:46 -0700654 if (!args->dry_run && (cmds_sent || is_repository_shallow(the_repository))) {
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700655 packet_buf_flush(&req_buf);
656 send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX);
657 }
658 } else {
Jeff Kingcdf4fb82013-02-20 15:01:56 -0500659 write_or_die(out, req_buf.buf, req_buf.len);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700660 packet_flush(out);
661 }
662 strbuf_release(&req_buf);
Junio C Hamano887f3532014-08-15 11:37:01 -0700663 strbuf_release(&cap_buf);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700664
665 if (use_sideband && cmds_sent) {
666 memset(&demux, 0, sizeof(demux));
667 demux.proc = sideband_demux;
668 demux.data = fd;
669 demux.out = -1;
Jeff King3e8b06d2016-04-19 18:50:17 -0400670 demux.isolate_sigpipe = 1;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700671 if (start_async(&demux))
672 die("send-pack: unable to fork off sideband demultiplexer");
673 in = demux.out;
674 }
675
Masaya Suzuki2d103c32018-12-29 13:19:15 -0800676 packet_reader_init(&reader, in, NULL, 0,
677 PACKET_READ_CHOMP_NEWLINE |
678 PACKET_READ_DIE_ON_ERR_PACKET);
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800679
Junio C Hamanoab2b0c92014-08-15 12:23:51 -0700680 if (need_pack_data && cmds_sent) {
Jonathan Tan477673d2021-05-04 14:16:02 -0700681 if (pack_objects(out, remote_refs, extra_have, &commons, args) < 0) {
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700682 if (args->stateless_rpc)
683 close(out);
684 if (git_connection_is_socket(conn))
685 shutdown(fd[0], SHUT_WR);
Jeff Kingba69f922017-03-07 08:38:51 -0500686
687 /*
688 * Do not even bother with the return value; we know we
Jeff Kingad7a4032019-11-12 21:07:19 -0500689 * are failing, and just want the error() side effects,
690 * as well as marking refs with their remote status (if
691 * we get one).
Jeff Kingba69f922017-03-07 08:38:51 -0500692 */
693 if (status_report)
Jeff Kingad7a4032019-11-12 21:07:19 -0500694 receive_status(&reader, remote_refs);
Jeff Kingba69f922017-03-07 08:38:51 -0500695
Jeff King739cf492016-04-19 18:45:17 -0400696 if (use_sideband) {
697 close(demux.out);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700698 finish_async(&demux);
Jeff King739cf492016-04-19 18:45:17 -0400699 }
Jens Lindstrom37cb1dd2013-10-22 15:36:02 +0200700 fd[1] = -1;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700701 return -1;
702 }
Jens Lindstrom37cb1dd2013-10-22 15:36:02 +0200703 if (!args->stateless_rpc)
704 /* Closed by pack_objects() via start_command() */
705 fd[1] = -1;
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700706 }
707 if (args->stateless_rpc && cmds_sent)
708 packet_flush(out);
709
710 if (status_report && cmds_sent)
Masaya Suzuki01f9ec62018-12-29 13:19:14 -0800711 ret = receive_status(&reader, remote_refs);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700712 else
713 ret = 0;
714 if (args->stateless_rpc)
715 packet_flush(out);
716
717 if (use_sideband && cmds_sent) {
Jeff King739cf492016-04-19 18:45:17 -0400718 close(demux.out);
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700719 if (finish_async(&demux)) {
720 error("error in sideband demultiplexer");
721 ret = -1;
722 }
Nguyễn Thái Ngọc Duyf5d942e2012-10-26 22:53:53 +0700723 }
724
725 if (ret < 0)
726 return ret;
727
728 if (args->porcelain)
729 return 0;
730
731 for (ref = remote_refs; ref; ref = ref->next) {
732 switch (ref->status) {
733 case REF_STATUS_NONE:
734 case REF_STATUS_UPTODATE:
735 case REF_STATUS_OK:
736 break;
737 default:
738 return -1;
739 }
740 }
741 return 0;
742}