upload-pack.c 15.0 KB
Newer Older
1 2 3
#include "cache.h"
#include "refs.h"
#include "pkt-line.h"
4
#include "sideband.h"
5 6
#include "tag.h"
#include "object.h"
7
#include "commit.h"
8
#include "exec_cmd.h"
9 10 11
#include "diff.h"
#include "revision.h"
#include "list-objects.h"
12
#include "run-command.h"
13

14
static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=nn] <dir>";
15

16 17 18 19 20 21 22
/* bits #0..7 in revision.h, #8..10 in commit.c */
#define THEY_HAVE	(1u << 11)
#define OUR_REF		(1u << 12)
#define WANTED		(1u << 13)
#define COMMON_KNOWN	(1u << 14)
#define REACHABLE	(1u << 15)

23 24 25 26
#define SHALLOW		(1u << 16)
#define NOT_SHALLOW	(1u << 17)
#define CLIENT_SHALLOW	(1u << 18)

J
Junio C Hamano 已提交
27
static unsigned long oldest_have;
28

29
static int multi_ack, nr_our_refs;
30
static int use_thin_pack, use_ofs_delta, no_progress;
31 32
static struct object_array have_obj;
static struct object_array want_obj;
33
static unsigned int timeout;
34 35 36
/* 0 for no sideband,
 * otherwise maximum packet size (up to 65520 bytes).
 */
37
static int use_sideband;
38 39 40 41 42

static void reset_timeout(void)
{
	alarm(timeout);
}
43

44 45 46 47 48 49 50
static int strip(char *line, int len)
{
	if (len && line[len-1] == '\n')
		line[--len] = 0;
	return len;
}

51 52
static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
{
53
	if (use_sideband)
54
		return send_sideband(1, fd, data, sz, use_sideband);
55 56 57 58
	if (fd == 3)
		/* emergency quit */
		fd = 2;
	if (fd == 2) {
59
		/* XXX: are we happy to lose stuff here? */
60 61
		xwrite(fd, data, sz);
		return sz;
62
	}
63
	return safe_write(fd, data, sz);
64 65
}

J
Junio C Hamano 已提交
66
static FILE *pack_pipe = NULL;
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
static void show_commit(struct commit *commit)
{
	if (commit->object.flags & BOUNDARY)
		fputc('-', pack_pipe);
	if (fputs(sha1_to_hex(commit->object.sha1), pack_pipe) < 0)
		die("broken output pipe");
	fputc('\n', pack_pipe);
	fflush(pack_pipe);
	free(commit->buffer);
	commit->buffer = NULL;
}

static void show_object(struct object_array_entry *p)
{
	/* An object with name "foo\n0000000..." can be used to
	 * confuse downstream git-pack-objects very badly.
	 */
	const char *ep = strchr(p->name, '\n');
	if (ep) {
		fprintf(pack_pipe, "%s %.*s\n", sha1_to_hex(p->item->sha1),
		       (int) (ep - p->name),
		       p->name);
	}
	else
		fprintf(pack_pipe, "%s %s\n",
				sha1_to_hex(p->item->sha1), p->name);
}

static void show_edge(struct commit *commit)
{
	fprintf(pack_pipe, "-%s\n", sha1_to_hex(commit->object.sha1));
}

100
static int do_rev_list(int fd, void *create_full_pack)
101 102 103 104
{
	int i;
	struct rev_info revs;

105
	pack_pipe = fdopen(fd, "w");
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
	if (create_full_pack)
		use_thin_pack = 0; /* no point doing it */
	init_revisions(&revs, NULL);
	revs.tag_objects = 1;
	revs.tree_objects = 1;
	revs.blob_objects = 1;
	if (use_thin_pack)
		revs.edge_hint = 1;

	if (create_full_pack) {
		const char *args[] = {"rev-list", "--all", NULL};
		setup_revisions(2, args, &revs, NULL);
	} else {
		for (i = 0; i < want_obj.nr; i++) {
			struct object *o = want_obj.objects[i].item;
			/* why??? */
			o->flags &= ~UNINTERESTING;
			add_pending_object(&revs, o, NULL);
		}
		for (i = 0; i < have_obj.nr; i++) {
			struct object *o = have_obj.objects[i].item;
			o->flags |= UNINTERESTING;
			add_pending_object(&revs, o, NULL);
		}
		setup_revisions(0, NULL, &revs, NULL);
	}
	prepare_revision_walk(&revs);
	mark_edges_uninteresting(revs.commits, &revs, show_edge);
	traverse_commit_list(&revs, show_commit, show_object);
135
	return 0;
136 137
}

138 139
static void create_pack_file(void)
{
140
	struct async rev_list;
141
	struct child_process pack_objects;
142
	int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr);
143
	char data[8193], progress[128];
144 145
	char abort_msg[] = "aborting due to possible repository "
		"corruption on the remote side.";
146
	int buffered = -1;
147
	ssize_t sz;
148 149
	const char *argv[10];
	int arg = 0;
150

151 152 153 154
	rev_list.proc = do_rev_list;
	/* .data is just a boolean: any non-NULL value will do */
	rev_list.data = create_full_pack ? &rev_list : NULL;
	if (start_async(&rev_list))
155 156
		die("git-upload-pack: unable to fork git-rev-list");

157 158 159 160 161 162 163 164 165
	argv[arg++] = "pack-objects";
	argv[arg++] = "--stdout";
	if (!no_progress)
		argv[arg++] = "--progress";
	if (use_ofs_delta)
		argv[arg++] = "--delta-base-offset";
	argv[arg++] = NULL;

	memset(&pack_objects, 0, sizeof(pack_objects));
166
	pack_objects.in = rev_list.out;	/* start_command closes it */
167 168 169 170
	pack_objects.out = -1;
	pack_objects.err = -1;
	pack_objects.git_cmd = 1;
	pack_objects.argv = argv;
171

172
	if (start_command(&pack_objects))
173 174
		die("git-upload-pack: unable to fork git-pack-objects");

175 176
	/* We read from pack_objects.err to capture stderr output for
	 * progress bar, and pack_objects.out to capture the pack data.
177 178 179 180
	 */

	while (1) {
		struct pollfd pfd[2];
181
		int pe, pu, pollsize;
182

183 184
		reset_timeout();

185
		pollsize = 0;
186
		pe = pu = -1;
187

188 189
		if (0 <= pack_objects.out) {
			pfd[pollsize].fd = pack_objects.out;
190 191 192 193
			pfd[pollsize].events = POLLIN;
			pu = pollsize;
			pollsize++;
		}
194 195
		if (0 <= pack_objects.err) {
			pfd[pollsize].fd = pack_objects.err;
196 197 198 199
			pfd[pollsize].events = POLLIN;
			pe = pollsize;
			pollsize++;
		}
200

201 202 203 204 205 206 207 208
		if (!pollsize)
			break;

		if (poll(pfd, pollsize, -1) < 0) {
			if (errno != EINTR) {
				error("poll failed, resuming: %s",
				      strerror(errno));
				sleep(1);
209
			}
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
			continue;
		}
		if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
			/* Data ready; we keep the last byte to ourselves
			 * in case we detect broken rev-list, so that we
			 * can leave the stream corrupted.  This is
			 * unfortunate -- unpack-objects would happily
			 * accept a valid packdata with trailing garbage,
			 * so appending garbage after we pass all the
			 * pack data is not good enough to signal
			 * breakage to downstream.
			 */
			char *cp = data;
			ssize_t outsz = 0;
			if (0 <= buffered) {
				*cp++ = buffered;
				outsz++;
227
			}
228 229 230 231 232 233 234
			sz = xread(pack_objects.out, cp,
				  sizeof(data) - outsz);
			if (0 < sz)
					;
			else if (sz == 0) {
				close(pack_objects.out);
				pack_objects.out = -1;
235
			}
236 237 238 239 240 241
			else
				goto fail;
			sz += outsz;
			if (1 < sz) {
				buffered = data[sz-1] & 0xFF;
				sz--;
242
			}
243 244 245 246
			else
				buffered = -1;
			sz = send_client_data(1, data, sz);
			if (sz < 0)
247
				goto fail;
248 249 250 251 252 253 254 255 256 257 258 259
		}
		if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) {
			/* Status ready; we ship that in the side-band
			 * or dump to the standard error.
			 */
			sz = xread(pack_objects.err, progress,
				  sizeof(progress));
			if (0 < sz)
				send_client_data(2, progress, sz);
			else if (sz == 0) {
				close(pack_objects.err);
				pack_objects.err = -1;
260
			}
261 262
			else
				goto fail;
263
		}
264
	}
265

266 267 268 269 270 271
	if (finish_command(&pack_objects)) {
		error("git-upload-pack: git-pack-objects died with error.");
		goto fail;
	}
	if (finish_async(&rev_list))
		goto fail;	/* error was already reported */
272

273 274 275 276 277 278 279
	/* flush the data */
	if (0 <= buffered) {
		data[0] = buffered;
		sz = send_client_data(1, data, 1);
		if (sz < 0)
			goto fail;
		fprintf(stderr, "flushed.\n");
280
	}
281 282 283 284
	if (use_sideband)
		packet_flush(1);
	return;

285
 fail:
286 287
	send_client_data(3, abort_msg, sizeof(abort_msg));
	die("git-upload-pack: %s", abort_msg);
288 289
}

290 291
static int got_sha1(char *hex, unsigned char *sha1)
{
292
	struct object *o;
293
	int we_knew_they_have = 0;
294

295 296
	if (get_sha1_hex(hex, sha1))
		die("git-upload-pack: expected SHA1 object, got '%s'", hex);
297
	if (!has_sha1_file(sha1))
298
		return -1;
299 300 301 302 303 304

	o = lookup_object(sha1);
	if (!(o && o->parsed))
		o = parse_object(sha1);
	if (!o)
		die("oops (%s)", sha1_to_hex(sha1));
J
Junio C Hamano 已提交
305
	if (o->type == OBJ_COMMIT) {
306
		struct commit_list *parents;
307
		struct commit *commit = (struct commit *)o;
308
		if (o->flags & THEY_HAVE)
309 310 311 312 313 314
			we_knew_they_have = 1;
		else
			o->flags |= THEY_HAVE;
		if (!oldest_have || (commit->date < oldest_have))
			oldest_have = commit->date;
		for (parents = commit->parents;
315 316 317
		     parents;
		     parents = parents->next)
			parents->item->object.flags |= THEY_HAVE;
318
	}
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
	if (!we_knew_they_have) {
		add_object_array(o, NULL, &have_obj);
		return 1;
	}
	return 0;
}

static int reachable(struct commit *want)
{
	struct commit_list *work = NULL;

	insert_by_date(want, &work);
	while (work) {
		struct commit_list *list = work->next;
		struct commit *commit = work->item;
		free(work);
		work = list;

		if (commit->object.flags & THEY_HAVE) {
			want->object.flags |= COMMON_KNOWN;
			break;
		}
		if (!commit->object.parsed)
			parse_object(commit->object.sha1);
		if (commit->object.flags & REACHABLE)
			continue;
		commit->object.flags |= REACHABLE;
		if (commit->date < oldest_have)
			continue;
		for (list = commit->parents; list; list = list->next) {
			struct commit *parent = list->item;
			if (!(parent->object.flags & REACHABLE))
				insert_by_date(parent, &work);
		}
	}
	want->object.flags |= REACHABLE;
	clear_commit_marks(want, REACHABLE);
	free_commit_list(work);
	return (want->object.flags & COMMON_KNOWN);
}

static int ok_to_give_up(void)
{
	int i;

	if (!have_obj.nr)
		return 0;

	for (i = 0; i < want_obj.nr; i++) {
		struct object *want = want_obj.objects[i].item;

		if (want->flags & COMMON_KNOWN)
			continue;
		want = deref_tag(want, "a want line", 0);
		if (!want || want->type != OBJ_COMMIT) {
			/* no way to tell if this is reachable by
			 * looking at the ancestry chain alone, so
			 * leave a note to ourselves not to worry about
			 * this object anymore.
			 */
			want_obj.objects[i].item->flags |= COMMON_KNOWN;
			continue;
		}
		if (!reachable((struct commit *)want))
			return 0;
	}
385
	return 1;
386 387 388 389 390
}

static int get_common_commits(void)
{
	static char line[1000];
391 392
	unsigned char sha1[20];
	char hex[41], last_hex[41];
393 394
	int len;

395 396 397
	track_object_refs = 0;
	save_commit_buffer = 0;

398 399
	for(;;) {
		len = packet_read_line(0, line, sizeof(line));
400
		reset_timeout();
401 402

		if (!len) {
403
			if (have_obj.nr == 0 || multi_ack)
404
				packet_write(1, "NAK\n");
405 406
			continue;
		}
407
		len = strip(line, len);
408
		if (!prefixcmp(line, "have ")) {
409 410 411 412 413 414 415
			switch (got_sha1(line+5, sha1)) {
			case -1: /* they have what we do not */
				if (multi_ack && ok_to_give_up())
					packet_write(1, "ACK %s continue\n",
						     sha1_to_hex(sha1));
				break;
			default:
416 417 418 419 420 421 422 423
				memcpy(hex, sha1_to_hex(sha1), 41);
				if (multi_ack) {
					const char *msg = "ACK %s continue\n";
					packet_write(1, msg, hex);
					memcpy(last_hex, hex, 41);
				}
				else if (have_obj.nr == 1)
					packet_write(1, "ACK %s\n", hex);
424
				break;
425
			}
426 427 428
			continue;
		}
		if (!strcmp(line, "done")) {
429
			if (have_obj.nr > 0) {
430
				if (multi_ack)
431
					packet_write(1, "ACK %s\n", last_hex);
432 433
				return 0;
			}
434 435 436 437 438 439 440
			packet_write(1, "NAK\n");
			return -1;
		}
		die("git-upload-pack: expected SHA1 list, got '%s'", line);
	}
}

441
static void receive_needs(void)
442
{
443
	struct object_array shallows = {0, 0, NULL};
444
	static char line[1000];
445
	int len, depth = 0;
446 447

	for (;;) {
448
		struct object *o;
449
		unsigned char sha1_buf[20];
450
		len = packet_read_line(0, line, sizeof(line));
451
		reset_timeout();
452
		if (!len)
453
			break;
454

455
		if (!prefixcmp(line, "shallow ")) {
456 457
			unsigned char sha1[20];
			struct object *object;
458
			use_thin_pack = 0;
459 460 461 462 463
			if (get_sha1(line + 8, sha1))
				die("invalid shallow line: %s", line);
			object = parse_object(sha1);
			if (!object)
				die("did not find object for %s", line);
464
			object->flags |= CLIENT_SHALLOW;
465 466 467
			add_object_array(object, NULL, &shallows);
			continue;
		}
468
		if (!prefixcmp(line, "deepen ")) {
469
			char *end;
470
			use_thin_pack = 0;
471 472 473 474 475
			depth = strtol(line + 7, &end, 0);
			if (end == line + 7 || depth <= 0)
				die("Invalid deepen: %s", line);
			continue;
		}
476
		if (prefixcmp(line, "want ") ||
477
		    get_sha1_hex(line+5, sha1_buf))
478 479
			die("git-upload-pack: protocol error, "
			    "expected to get sha, not '%s'", line);
480 481
		if (strstr(line+45, "multi_ack"))
			multi_ack = 1;
482 483
		if (strstr(line+45, "thin-pack"))
			use_thin_pack = 1;
484 485
		if (strstr(line+45, "ofs-delta"))
			use_ofs_delta = 1;
486 487 488 489
		if (strstr(line+45, "side-band-64k"))
			use_sideband = LARGE_PACKET_MAX;
		else if (strstr(line+45, "side-band"))
			use_sideband = DEFAULT_PACKET_MAX;
490 491
		if (strstr(line+45, "no-progress"))
			no_progress = 1;
492 493 494 495 496 497 498 499 500 501 502 503 504 505

		/* We have sent all our refs already, and the other end
		 * should have chosen out of them; otherwise they are
		 * asking for nonsense.
		 *
		 * Hmph.  We may later want to allow "want" line that
		 * asks for something like "master~10" (symbolic)...
		 * would it make sense?  I don't know.
		 */
		o = lookup_object(sha1_buf);
		if (!o || !(o->flags & OUR_REF))
			die("git-upload-pack: not our ref %s", line+5);
		if (!(o->flags & WANTED)) {
			o->flags |= WANTED;
506
			add_object_array(o, NULL, &want_obj);
507
		}
508
	}
509 510
	if (depth == 0 && shallows.nr == 0)
		return;
511 512
	if (depth > 0) {
		struct commit_list *result, *backup;
513 514 515
		int i;
		backup = result = get_shallow_commits(&want_obj, depth,
			SHALLOW, NOT_SHALLOW);
516
		while (result) {
517
			struct object *object = &result->item->object;
518
			if (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) {
519 520 521 522
				packet_write(1, "shallow %s",
						sha1_to_hex(object->sha1));
				register_shallow(object->sha1);
			}
523 524 525
			result = result->next;
		}
		free_commit_list(backup);
526 527 528 529 530 531 532 533 534
		for (i = 0; i < shallows.nr; i++) {
			struct object *object = shallows.objects[i].item;
			if (object->flags & NOT_SHALLOW) {
				struct commit_list *parents;
				packet_write(1, "unshallow %s",
					sha1_to_hex(object->sha1));
				object->flags &= ~CLIENT_SHALLOW;
				/* make sure the real parents are parsed */
				unregister_shallow(object->sha1);
535
				object->parsed = 0;
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
				parse_commit((struct commit *)object);
				parents = ((struct commit *)object)->parents;
				while (parents) {
					add_object_array(&parents->item->object,
							NULL, &want_obj);
					parents = parents->next;
				}
			}
			/* make sure commit traversal conforms to client */
			register_shallow(object->sha1);
		}
		packet_flush(1);
	} else
		if (shallows.nr > 0) {
			int i;
			for (i = 0; i < shallows.nr; i++)
				register_shallow(shallows.objects[i].item->sha1);
		}
	free(shallows.objects);
555 556
}

557
static int send_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
558
{
559
	static const char *capabilities = "multi_ack thin-pack side-band"
560
		" side-band-64k ofs-delta shallow no-progress";
561 562
	struct object *o = parse_object(sha1);

563 564 565
	if (!o)
		die("git-upload-pack: cannot find object %s:", sha1_to_hex(sha1));

J
Johannes Schindelin 已提交
566 567 568 569 570 571
	if (capabilities)
		packet_write(1, "%s %s%c%s\n", sha1_to_hex(sha1), refname,
			0, capabilities);
	else
		packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname);
	capabilities = NULL;
572 573 574 575
	if (!(o->flags & OUR_REF)) {
		o->flags |= OUR_REF;
		nr_our_refs++;
	}
576
	if (o->type == OBJ_TAG) {
577
		o = deref_tag(o, refname, 0);
578 579
		packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname);
	}
580 581 582
	return 0;
}

583
static void upload_pack(void)
584
{
585
	reset_timeout();
586 587
	head_ref(send_ref, NULL);
	for_each_ref(send_ref, NULL);
588
	packet_flush(1);
589
	receive_needs();
590 591 592 593
	if (want_obj.nr) {
		get_common_commits();
		create_pack_file();
	}
594 595 596 597
}

int main(int argc, char **argv)
{
598
	char *dir;
599 600 601 602 603 604 605 606 607 608 609 610
	int i;
	int strict = 0;

	for (i = 1; i < argc; i++) {
		char *arg = argv[i];

		if (arg[0] != '-')
			break;
		if (!strcmp(arg, "--strict")) {
			strict = 1;
			continue;
		}
611
		if (!prefixcmp(arg, "--timeout=")) {
612 613 614 615 616 617 618 619
			timeout = atoi(arg+10);
			continue;
		}
		if (!strcmp(arg, "--")) {
			i++;
			break;
		}
	}
J
Junio C Hamano 已提交
620

621
	if (i != argc-1)
622
		usage(upload_pack_usage);
623
	dir = argv[i];
624

625 626
	if (!enter_repo(dir, strict))
		die("'%s': unable to chdir or not a git archive", dir);
627 628
	if (is_repository_shallow())
		die("attempt to fetch/clone from a shallow repository");
629 630 631
	upload_pack();
	return 0;
}