transport.c 29.5 KB
Newer Older
1 2 3
#include "cache.h"
#include "transport.h"
#include "run-command.h"
4 5
#include "pkt-line.h"
#include "fetch-pack.h"
D
Daniel Barkalow 已提交
6
#include "send-pack.h"
7
#include "walker.h"
J
Johannes Schindelin 已提交
8
#include "bundle.h"
9 10
#include "dir.h"
#include "refs.h"
I
Ilari Liusvaara 已提交
11
#include "branch.h"
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

/* rsync support */

/*
 * We copy packed-refs and refs/ into a temporary file, then read the
 * loose refs recursively (sorting whenever possible), and then inserting
 * those packed refs that are not yet in the list (not validating, but
 * assuming that the file is sorted).
 *
 * Appears refactoring this from refs.c is too cumbersome.
 */

static int str_cmp(const void *a, const void *b)
{
	const char *s1 = a;
	const char *s2 = b;

	return strcmp(s1, s2);
}

/* path->buf + name_offset is expected to point to "refs/" */

static int read_loose_refs(struct strbuf *path, int name_offset,
		struct ref **tail)
{
	DIR *dir = opendir(path->buf);
	struct dirent *de;
	struct {
		char **entries;
		int nr, alloc;
	} list;
	int i, pathlen;

	if (!dir)
		return -1;

	memset (&list, 0, sizeof(list));

	while ((de = readdir(dir))) {
51
		if (is_dot_or_dotdot(de->d_name))
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
			continue;
		ALLOC_GROW(list.entries, list.nr + 1, list.alloc);
		list.entries[list.nr++] = xstrdup(de->d_name);
	}
	closedir(dir);

	/* sort the list */

	qsort(list.entries, list.nr, sizeof(char *), str_cmp);

	pathlen = path->len;
	strbuf_addch(path, '/');

	for (i = 0; i < list.nr; i++, strbuf_setlen(path, pathlen + 1)) {
		strbuf_addstr(path, list.entries[i]);
		if (read_loose_refs(path, name_offset, tail)) {
			int fd = open(path->buf, O_RDONLY);
			char buffer[40];
			struct ref *next;

			if (fd < 0)
				continue;
74
			next = alloc_ref(path->buf + name_offset);
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 100 101 102 103 104 105
			if (read_in_full(fd, buffer, 40) != 40 ||
					get_sha1_hex(buffer, next->old_sha1)) {
				close(fd);
				free(next);
				continue;
			}
			close(fd);
			(*tail)->next = next;
			*tail = next;
		}
	}
	strbuf_setlen(path, pathlen);

	for (i = 0; i < list.nr; i++)
		free(list.entries[i]);
	free(list.entries);

	return 0;
}

/* insert the packed refs for which no loose refs were found */

static void insert_packed_refs(const char *packed_refs, struct ref **list)
{
	FILE *f = fopen(packed_refs, "r");
	static char buffer[PATH_MAX];

	if (!f)
		return;

	for (;;) {
106
		int cmp = cmp, len;
107 108 109 110 111 112 113 114 115

		if (!fgets(buffer, sizeof(buffer), f)) {
			fclose(f);
			return;
		}

		if (hexval(buffer[0]) > 0xf)
			continue;
		len = strlen(buffer);
116
		if (len && buffer[len - 1] == '\n')
117 118 119 120 121 122 123 124
			buffer[--len] = '\0';
		if (len < 41)
			continue;
		while ((*list)->next &&
				(cmp = strcmp(buffer + 41,
				      (*list)->next->name)) > 0)
			list = &(*list)->next;
		if (!(*list)->next || cmp < 0) {
125
			struct ref *next = alloc_ref(buffer + 41);
126 127 128 129 130 131 132 133 134 135 136 137 138
			buffer[40] = '\0';
			if (get_sha1_hex(buffer, next->old_sha1)) {
				warning ("invalid SHA-1: %s", buffer);
				free(next);
				continue;
			}
			next->next = (*list)->next;
			(*list)->next = next;
			list = &(*list)->next;
		}
	}
}

I
Ilari Liusvaara 已提交
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
static void set_upstreams(struct transport *transport, struct ref *refs,
	int pretend)
{
	struct ref *ref;
	for (ref = refs; ref; ref = ref->next) {
		const char *localname;
		const char *tmp;
		const char *remotename;
		unsigned char sha[20];
		int flag = 0;
		/*
		 * Check suitability for tracking. Must be successful /
		 * already up-to-date ref create/modify (not delete).
		 */
		if (ref->status != REF_STATUS_OK &&
			ref->status != REF_STATUS_UPTODATE)
			continue;
		if (!ref->peer_ref)
			continue;
		if (!ref->new_sha1 || is_null_sha1(ref->new_sha1))
			continue;

		/* Follow symbolic refs (mainly for HEAD). */
		localname = ref->peer_ref->name;
		remotename = ref->name;
		tmp = resolve_ref(localname, sha, 1, &flag);
		if (tmp && flag & REF_ISSYMREF &&
			!prefixcmp(tmp, "refs/heads/"))
			localname = tmp;

		/* Both source and destination must be local branches. */
		if (!localname || prefixcmp(localname, "refs/heads/"))
			continue;
		if (!remotename || prefixcmp(remotename, "refs/heads/"))
			continue;

		if (!pretend)
			install_branch_config(BRANCH_CONFIG_VERBOSE,
				localname + 11, transport->remote->name,
				remotename);
		else
			printf("Would set upstream of '%s' to '%s' of '%s'\n",
				localname + 11, remotename + 11,
				transport->remote->name);
	}
}

186 187 188 189 190
static const char *rsync_url(const char *url)
{
	return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
}

191
static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
192 193
{
	struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
194
	struct ref dummy = {0}, *tail = &dummy;
195 196 197 198
	struct child_process rsync;
	const char *args[5];
	int temp_dir_len;

199 200 201
	if (for_push)
		return NULL;

202 203 204 205
	/* copy the refs to the temporary directory */

	strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
	if (!mkdtemp(temp_dir.buf))
206
		die_errno ("Could not make temporary directory");
207 208
	temp_dir_len = temp_dir.len;

209
	strbuf_addstr(&buf, rsync_url(transport->url));
210 211 212 213 214 215
	strbuf_addstr(&buf, "/refs");

	memset(&rsync, 0, sizeof(rsync));
	rsync.argv = args;
	rsync.stdout_to_stderr = 1;
	args[0] = "rsync";
216
	args[1] = (transport->verbose > 0) ? "-rv" : "-r";
217 218 219 220 221 222 223 224
	args[2] = buf.buf;
	args[3] = temp_dir.buf;
	args[4] = NULL;

	if (run_command(&rsync))
		die ("Could not run rsync to get refs");

	strbuf_reset(&buf);
225
	strbuf_addstr(&buf, rsync_url(transport->url));
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
	strbuf_addstr(&buf, "/packed-refs");

	args[2] = buf.buf;

	if (run_command(&rsync))
		die ("Could not run rsync to get refs");

	/* read the copied refs */

	strbuf_addstr(&temp_dir, "/refs");
	read_loose_refs(&temp_dir, temp_dir_len + 1, &tail);
	strbuf_setlen(&temp_dir, temp_dir_len);

	tail = &dummy;
	strbuf_addstr(&temp_dir, "/packed-refs");
	insert_packed_refs(temp_dir.buf, &tail);
	strbuf_setlen(&temp_dir, temp_dir_len);

	if (remove_dir_recursively(&temp_dir, 0))
		warning ("Error removing temporary directory %s.",
				temp_dir.buf);

	strbuf_release(&buf);
	strbuf_release(&temp_dir);

	return dummy.next;
}

static int fetch_objs_via_rsync(struct transport *transport,
D
Daniel Barkalow 已提交
255
				int nr_objs, struct ref **to_fetch)
256 257 258 259 260 261
{
	struct strbuf buf = STRBUF_INIT;
	struct child_process rsync;
	const char *args[8];
	int result;

262
	strbuf_addstr(&buf, rsync_url(transport->url));
263 264 265 266 267 268
	strbuf_addstr(&buf, "/objects/");

	memset(&rsync, 0, sizeof(rsync));
	rsync.argv = args;
	rsync.stdout_to_stderr = 1;
	args[0] = "rsync";
269
	args[1] = (transport->verbose > 0) ? "-rv" : "-r";
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
	args[2] = "--ignore-existing";
	args[3] = "--exclude";
	args[4] = "info";
	args[5] = buf.buf;
	args[6] = get_object_directory();
	args[7] = NULL;

	/* NEEDSWORK: handle one level of alternates */
	result = run_command(&rsync);

	strbuf_release(&buf);

	return result;
}

static int write_one_ref(const char *name, const unsigned char *sha1,
		int flags, void *data)
{
	struct strbuf *buf = data;
	int len = buf->len;
	FILE *f;

	/* when called via for_each_ref(), flags is non-zero */
	if (flags && prefixcmp(name, "refs/heads/") &&
			prefixcmp(name, "refs/tags/"))
		return 0;

	strbuf_addstr(buf, name);
	if (safe_create_leading_directories(buf->buf) ||
			!(f = fopen(buf->buf, "w")) ||
			fprintf(f, "%s\n", sha1_to_hex(sha1)) < 0 ||
			fclose(f))
		return error("problems writing temporary file %s", buf->buf);
	strbuf_setlen(buf, len);
	return 0;
}

static int write_refs_to_temp_dir(struct strbuf *temp_dir,
		int refspec_nr, const char **refspec)
{
	int i;

	for (i = 0; i < refspec_nr; i++) {
		unsigned char sha1[20];
		char *ref;

		if (dwim_ref(refspec[i], strlen(refspec[i]), sha1, &ref) != 1)
			return error("Could not get ref %s", refspec[i]);

		if (write_one_ref(ref, sha1, 0, temp_dir)) {
			free(ref);
			return -1;
		}
		free(ref);
	}
	return 0;
}

static int rsync_transport_push(struct transport *transport,
		int refspec_nr, const char **refspec, int flags)
{
	struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
	int result = 0, i;
	struct child_process rsync;
334
	const char *args[10];
335

A
Andy Whitcroft 已提交
336 337 338
	if (flags & TRANSPORT_PUSH_MIRROR)
		return error("rsync transport does not support mirror mode");

339 340
	/* first push the objects */

341
	strbuf_addstr(&buf, rsync_url(transport->url));
342 343 344 345 346
	strbuf_addch(&buf, '/');

	memset(&rsync, 0, sizeof(rsync));
	rsync.argv = args;
	rsync.stdout_to_stderr = 1;
347 348 349 350 351 352 353 354 355 356 357 358 359
	i = 0;
	args[i++] = "rsync";
	args[i++] = "-a";
	if (flags & TRANSPORT_PUSH_DRY_RUN)
		args[i++] = "--dry-run";
	if (transport->verbose > 0)
		args[i++] = "-v";
	args[i++] = "--ignore-existing";
	args[i++] = "--exclude";
	args[i++] = "info";
	args[i++] = get_object_directory();
	args[i++] = buf.buf;
	args[i++] = NULL;
360 361

	if (run_command(&rsync))
362 363
		return error("Could not push objects to %s",
				rsync_url(transport->url));
364 365 366 367 368

	/* copy the refs to the temporary directory; they could be packed. */

	strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
	if (!mkdtemp(temp_dir.buf))
369
		die_errno ("Could not make temporary directory");
370 371 372 373 374 375 376 377
	strbuf_addch(&temp_dir, '/');

	if (flags & TRANSPORT_PUSH_ALL) {
		if (for_each_ref(write_one_ref, &temp_dir))
			return -1;
	} else if (write_refs_to_temp_dir(&temp_dir, refspec_nr, refspec))
		return -1;

378 379 380 381 382
	i = 2;
	if (flags & TRANSPORT_PUSH_DRY_RUN)
		args[i++] = "--dry-run";
	if (!(flags & TRANSPORT_PUSH_FORCE))
		args[i++] = "--ignore-existing";
383
	args[i++] = temp_dir.buf;
384
	args[i++] = rsync_url(transport->url);
385 386
	args[i++] = NULL;
	if (run_command(&rsync))
387 388
		result = error("Could not push to %s",
				rsync_url(transport->url));
389 390 391 392 393 394 395 396 397 398

	if (remove_dir_recursively(&temp_dir, 0))
		warning ("Could not remove temporary directory %s.",
				temp_dir.buf);

	strbuf_release(&buf);
	strbuf_release(&temp_dir);

	return result;
}
399

J
Johannes Schindelin 已提交
400 401 402 403 404
struct bundle_transport_data {
	int fd;
	struct bundle_header header;
};

405
static struct ref *get_refs_from_bundle(struct transport *transport, int for_push)
J
Johannes Schindelin 已提交
406 407 408 409 410
{
	struct bundle_transport_data *data = transport->data;
	struct ref *result = NULL;
	int i;

411 412 413
	if (for_push)
		return NULL;

J
Johannes Schindelin 已提交
414 415 416 417 418 419 420
	if (data->fd > 0)
		close(data->fd);
	data->fd = read_bundle_header(transport->url, &data->header);
	if (data->fd < 0)
		die ("Could not read bundle '%s'.", transport->url);
	for (i = 0; i < data->header.references.nr; i++) {
		struct ref_list_entry *e = data->header.references.list + i;
421
		struct ref *ref = alloc_ref(e->name);
J
Johannes Schindelin 已提交
422 423 424 425 426 427 428
		hashcpy(ref->old_sha1, e->sha1);
		ref->next = result;
		result = ref;
	}
	return result;
}

429
static int fetch_refs_from_bundle(struct transport *transport,
D
Daniel Barkalow 已提交
430
			       int nr_heads, struct ref **to_fetch)
J
Johannes Schindelin 已提交
431 432 433 434 435 436 437 438 439 440
{
	struct bundle_transport_data *data = transport->data;
	return unbundle(&data->header, data->fd);
}

static int close_bundle(struct transport *transport)
{
	struct bundle_transport_data *data = transport->data;
	if (data->fd > 0)
		close(data->fd);
441
	free(data);
J
Johannes Schindelin 已提交
442 443 444
	return 0;
}

445
struct git_transport_data {
446
	struct git_transport_options options;
447 448
	struct child_process *conn;
	int fd[2];
I
Ilari Liusvaara 已提交
449
	unsigned got_remote_heads : 1;
450
	struct extra_have_objects extra_have;
451 452
};

453
static int set_git_option(struct git_transport_options *opts,
454 455
			  const char *name, const char *value)
{
456
	if (!strcmp(name, TRANS_OPT_UPLOADPACK)) {
457
		opts->uploadpack = value;
458 459
		return 0;
	} else if (!strcmp(name, TRANS_OPT_RECEIVEPACK)) {
460
		opts->receivepack = value;
461 462
		return 0;
	} else if (!strcmp(name, TRANS_OPT_THIN)) {
463
		opts->thin = !!value;
464
		return 0;
465
	} else if (!strcmp(name, TRANS_OPT_FOLLOWTAGS)) {
466
		opts->followtags = !!value;
467
		return 0;
468
	} else if (!strcmp(name, TRANS_OPT_KEEP)) {
469
		opts->keep = !!value;
470 471 472
		return 0;
	} else if (!strcmp(name, TRANS_OPT_DEPTH)) {
		if (!value)
473
			opts->depth = 0;
474
		else
475
			opts->depth = atoi(value);
476
		return 0;
477 478 479 480
	}
	return 1;
}

481
static int connect_setup(struct transport *transport, int for_push, int verbose)
482 483
{
	struct git_transport_data *data = transport->data;
I
Ilari Liusvaara 已提交
484 485 486 487

	if (data->conn)
		return 0;

488
	data->conn = git_connect(data->fd, transport->url,
489 490
				 for_push ? data->options.receivepack :
				 data->options.uploadpack,
491
				 verbose ? CONNECT_VERBOSE : 0);
I
Ilari Liusvaara 已提交
492

493 494 495
	return 0;
}

496
static struct ref *get_refs_via_connect(struct transport *transport, int for_push)
497 498 499 500
{
	struct git_transport_data *data = transport->data;
	struct ref *refs;

501 502 503
	connect_setup(transport, for_push, 0);
	get_remote_heads(data->fd[0], &refs, 0, NULL,
			 for_push ? REF_NORMAL : 0, &data->extra_have);
I
Ilari Liusvaara 已提交
504
	data->got_remote_heads = 1;
505 506 507 508

	return refs;
}

509
static int fetch_refs_via_pack(struct transport *transport,
D
Daniel Barkalow 已提交
510
			       int nr_heads, struct ref **to_fetch)
511 512
{
	struct git_transport_data *data = transport->data;
513
	char **heads = xmalloc(nr_heads * sizeof(*heads));
514
	char **origh = xmalloc(nr_heads * sizeof(*origh));
515
	const struct ref *refs;
516 517
	char *dest = xstrdup(transport->url);
	struct fetch_pack_args args;
518
	int i;
519
	struct ref *refs_tmp = NULL;
520

521
	memset(&args, 0, sizeof(args));
522 523
	args.uploadpack = data->options.uploadpack;
	args.keep_pack = data->options.keep;
524
	args.lock_pack = 1;
525 526
	args.use_thin_pack = data->options.thin;
	args.include_tag = data->options.followtags;
527
	args.verbose = (transport->verbose > 0);
528
	args.quiet = (transport->verbose < 0);
529
	args.no_progress = args.quiet || (!transport->progress && !isatty(2));
530
	args.depth = data->options.depth;
531

532
	for (i = 0; i < nr_heads; i++)
533
		origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
534

I
Ilari Liusvaara 已提交
535
	if (!data->got_remote_heads) {
536
		connect_setup(transport, 0, 0);
537
		get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
I
Ilari Liusvaara 已提交
538
		data->got_remote_heads = 1;
539 540
	}

541 542
	refs = fetch_pack(&args, data->fd, data->conn,
			  refs_tmp ? refs_tmp : transport->remote_refs,
543 544 545 546 547 548
			  dest, nr_heads, heads, &transport->pack_lockfile);
	close(data->fd[0]);
	close(data->fd[1]);
	if (finish_connect(data->conn))
		refs = NULL;
	data->conn = NULL;
I
Ilari Liusvaara 已提交
549
	data->got_remote_heads = 0;
550

551 552
	free_refs(refs_tmp);

553
	for (i = 0; i < nr_heads; i++)
554 555 556
		free(origh[i]);
	free(origh);
	free(heads);
557
	free(dest);
558
	return (refs ? 0 : -1);
559 560
}

561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
static int push_had_errors(struct ref *ref)
{
	for (; ref; ref = ref->next) {
		switch (ref->status) {
		case REF_STATUS_NONE:
		case REF_STATUS_UPTODATE:
		case REF_STATUS_OK:
			break;
		default:
			return 1;
		}
	}
	return 0;
}

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
static int refs_pushed(struct ref *ref)
{
	for (; ref; ref = ref->next) {
		switch(ref->status) {
		case REF_STATUS_NONE:
		case REF_STATUS_UPTODATE:
			break;
		default:
			return 1;
		}
	}
	return 0;
}

static void update_tracking_ref(struct remote *remote, struct ref *ref, int verbose)
{
	struct refspec rs;

	if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
		return;

	rs.src = ref->name;
	rs.dst = NULL;

	if (!remote_find_tracking(remote, &rs)) {
		if (verbose)
			fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
		if (ref->deletion) {
			delete_ref(rs.dst, NULL, 0);
		} else
			update_ref("update by push", rs.dst,
					ref->new_sha1, NULL, 0, 0);
		free(rs.dst);
	}
}

#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)

614
static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain)
615
{
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
	if (porcelain) {
		if (from)
			fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to->name);
		else
			fprintf(stdout, "%c\t:%s\t", flag, to->name);
		if (msg)
			fprintf(stdout, "%s (%s)\n", summary, msg);
		else
			fprintf(stdout, "%s\n", summary);
	} else {
		fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
		if (from)
			fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
		else
			fputs(prettify_refname(to->name), stderr);
		if (msg) {
			fputs(" (", stderr);
			fputs(msg, stderr);
			fputc(')', stderr);
		}
		fputc('\n', stderr);
637 638 639 640 641 642 643 644
	}
}

static const char *status_abbrev(unsigned char sha1[20])
{
	return find_unique_abbrev(sha1, DEFAULT_ABBREV);
}

645
static void print_ok_ref_status(struct ref *ref, int porcelain)
646 647
{
	if (ref->deletion)
648
		print_ref_status('-', "[deleted]", ref, NULL, NULL, porcelain);
649 650 651
	else if (is_null_sha1(ref->old_sha1))
		print_ref_status('*',
			(!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
652 653
			"[new branch]"),
			ref, ref->peer_ref, NULL, porcelain);
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
	else {
		char quickref[84];
		char type;
		const char *msg;

		strcpy(quickref, status_abbrev(ref->old_sha1));
		if (ref->nonfastforward) {
			strcat(quickref, "...");
			type = '+';
			msg = "forced update";
		} else {
			strcat(quickref, "..");
			type = ' ';
			msg = NULL;
		}
		strcat(quickref, status_abbrev(ref->new_sha1));

671
		print_ref_status(type, quickref, ref, ref->peer_ref, msg, porcelain);
672 673 674
	}
}

675
static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain)
676 677 678 679 680 681
{
	if (!count)
		fprintf(stderr, "To %s\n", dest);

	switch(ref->status) {
	case REF_STATUS_NONE:
682
		print_ref_status('X', "[no match]", ref, NULL, NULL, porcelain);
683 684 685
		break;
	case REF_STATUS_REJECT_NODELETE:
		print_ref_status('!', "[rejected]", ref, NULL,
686
						 "remote does not support deleting refs", porcelain);
687 688 689
		break;
	case REF_STATUS_UPTODATE:
		print_ref_status('=', "[up to date]", ref,
690
						 ref->peer_ref, NULL, porcelain);
691 692 693
		break;
	case REF_STATUS_REJECT_NONFASTFORWARD:
		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
694
						 "non-fast-forward", porcelain);
695 696 697
		break;
	case REF_STATUS_REMOTE_REJECT:
		print_ref_status('!', "[remote rejected]", ref,
698 699
						 ref->deletion ? NULL : ref->peer_ref,
						 ref->remote_status, porcelain);
700 701 702
		break;
	case REF_STATUS_EXPECTING_REPORT:
		print_ref_status('!', "[remote failure]", ref,
703 704
						 ref->deletion ? NULL : ref->peer_ref,
						 "remote failed to report status", porcelain);
705 706
		break;
	case REF_STATUS_OK:
707
		print_ok_ref_status(ref, porcelain);
708 709 710 711 712 713
		break;
	}

	return 1;
}

714
static void print_push_status(const char *dest, struct ref *refs,
715
			      int verbose, int porcelain, int * nonfastforward)
716 717 718 719 720 721 722
{
	struct ref *ref;
	int n = 0;

	if (verbose) {
		for (ref = refs; ref; ref = ref->next)
			if (ref->status == REF_STATUS_UPTODATE)
723
				n += print_one_push_status(ref, dest, n, porcelain);
724 725 726 727
	}

	for (ref = refs; ref; ref = ref->next)
		if (ref->status == REF_STATUS_OK)
728
			n += print_one_push_status(ref, dest, n, porcelain);
729

730
	*nonfastforward = 0;
731 732 733 734
	for (ref = refs; ref; ref = ref->next) {
		if (ref->status != REF_STATUS_NONE &&
		    ref->status != REF_STATUS_UPTODATE &&
		    ref->status != REF_STATUS_OK)
735
			n += print_one_push_status(ref, dest, n, porcelain);
736 737
		if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD)
			*nonfastforward = 1;
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
	}
}

static void verify_remote_names(int nr_heads, const char **heads)
{
	int i;

	for (i = 0; i < nr_heads; i++) {
		const char *local = heads[i];
		const char *remote = strrchr(heads[i], ':');

		if (*local == '+')
			local++;

		/* A matching refspec is okay.  */
		if (remote == local && remote[1] == '\0')
			continue;

		remote = remote ? (remote + 1) : local;
		switch (check_ref_format(remote)) {
		case 0: /* ok */
		case CHECK_REF_FORMAT_ONELEVEL:
			/* ok but a single level -- that is fine for
			 * a match pattern.
			 */
		case CHECK_REF_FORMAT_WILDCARD:
			/* ok but ends with a pattern-match character */
			continue;
		}
		die("remote part of refspec is not a valid name in %s",
		    heads[i]);
	}
}

static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
773
{
774
	struct git_transport_data *data = transport->data;
D
Daniel Barkalow 已提交
775
	struct send_pack_args args;
776 777
	int ret;

I
Ilari Liusvaara 已提交
778
	if (!data->got_remote_heads) {
779 780 781 782 783
		struct ref *tmp_refs;
		connect_setup(transport, 1, 0);

		get_remote_heads(data->fd[0], &tmp_refs, 0, NULL, REF_NORMAL,
				 NULL);
I
Ilari Liusvaara 已提交
784
		data->got_remote_heads = 1;
785
	}
786

787
	memset(&args, 0, sizeof(args));
A
Andy Whitcroft 已提交
788
	args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
D
Daniel Barkalow 已提交
789
	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
790
	args.use_thin_pack = data->options.thin;
791 792
	args.verbose = (transport->verbose > 0);
	args.quiet = (transport->verbose < 0);
D
Daniel Barkalow 已提交
793 794
	args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);

795 796 797 798 799 800 801
	ret = send_pack(&args, data->fd, data->conn, remote_refs,
			&data->extra_have);

	close(data->fd[1]);
	close(data->fd[0]);
	ret |= finish_connect(data->conn);
	data->conn = NULL;
I
Ilari Liusvaara 已提交
802
	data->got_remote_heads = 0;
803 804

	return ret;
805 806
}

807 808 809 810 811 812 813 814 815 816 817
static int connect_git(struct transport *transport, const char *name,
		       const char *executable, int fd[2])
{
	struct git_transport_data *data = transport->data;
	data->conn = git_connect(data->fd, transport->url,
				 executable, 0);
	fd[0] = data->fd[0];
	fd[1] = data->fd[1];
	return 0;
}

818 819
static int disconnect_git(struct transport *transport)
{
820 821
	struct git_transport_data *data = transport->data;
	if (data->conn) {
I
Ilari Liusvaara 已提交
822 823
		if (data->got_remote_heads)
			packet_flush(data->fd[1]);
824 825 826 827 828 829
		close(data->fd[0]);
		close(data->fd[1]);
		finish_connect(data->conn);
	}

	free(data);
830 831 832
	return 0;
}

I
Ilari Liusvaara 已提交
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
void transport_take_over(struct transport *transport,
			 struct child_process *child)
{
	struct git_transport_data *data;

	if (!transport->smart_options)
		die("Bug detected: Taking over transport requires non-NULL "
		    "smart_options field.");

	data = xcalloc(1, sizeof(*data));
	data->options = *transport->smart_options;
	data->conn = child;
	data->fd[0] = data->conn->out;
	data->fd[1] = data->conn->in;
	data->got_remote_heads = 0;
	transport->data = data;

	transport->set_option = NULL;
	transport->get_refs_list = get_refs_via_connect;
	transport->fetch = fetch_refs_via_pack;
	transport->push = NULL;
	transport->push_refs = git_transport_push;
	transport->disconnect = disconnect_git;
	transport->smart_options = &(data->options);
}

859 860 861 862
static int is_local(const char *url)
{
	const char *colon = strchr(url, ':');
	const char *slash = strchr(url, '/');
863 864
	return !colon || (slash && slash < colon) ||
		has_dos_drive_prefix(url);
865 866 867 868 869 870 871 872 873 874
}

static int is_file(const char *url)
{
	struct stat buf;
	if (stat(url, &buf))
		return 0;
	return S_ISREG(buf.st_mode);
}

875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
static int is_url(const char *url)
{
	const char *url2, *first_slash;

	if (!url)
		return 0;
	url2 = url;
	first_slash = strchr(url, '/');

	/* Input with no slash at all or slash first can't be URL. */
	if (!first_slash || first_slash == url)
		return 0;
	/* Character before must be : and next must be /. */
	if (first_slash[-1] != ':' || first_slash[1] != '/')
		return 0;
	/* There must be something before the :// */
	if (first_slash == url + 1)
		return 0;
	/*
	 * Check all characters up to first slash - 1. Only alphanum
	 * is allowed.
	 */
	url2 = url;
	while (url2 < first_slash - 1) {
		if (!isalnum((unsigned char)*url2))
			return 0;
		url2++;
	}

	/* Valid enough. */
	return 1;
}

static int external_specification_len(const char *url)
{
	return strchr(url, ':') - url;
}

913
struct transport *transport_get(struct remote *remote, const char *url)
914
{
I
Ilari Liusvaara 已提交
915
	const char *helper;
916 917
	struct transport *ret = xcalloc(1, sizeof(*ret));

918 919 920
	if (!remote)
		die("No remote provided to transport_get()");

921
	ret->remote = remote;
I
Ilari Liusvaara 已提交
922
	helper = remote->foreign_vcs;
923

924
	if (!url && remote->url)
925
		url = remote->url[0];
926 927
	ret->url = url;

928 929 930 931 932 933 934
	/* maybe it is a foreign URL? */
	if (url) {
		const char *p = url;

		while (isalnum(*p))
			p++;
		if (!prefixcmp(p, "::"))
I
Ilari Liusvaara 已提交
935
			helper = xstrndup(url, p - url);
936 937
	}

I
Ilari Liusvaara 已提交
938 939
	if (helper) {
		transport_helper_init(ret, helper);
940
	} else if (!prefixcmp(url, "rsync:")) {
941 942 943
		ret->get_refs_list = get_refs_via_rsync;
		ret->fetch = fetch_objs_via_rsync;
		ret->push = rsync_transport_push;
944
		ret->smart_options = NULL;
945
	} else if (is_local(url) && is_file(url)) {
J
Johannes Schindelin 已提交
946 947
		struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
		ret->data = data;
948 949 950
		ret->get_refs_list = get_refs_from_bundle;
		ret->fetch = fetch_refs_from_bundle;
		ret->disconnect = close_bundle;
951
		ret->smart_options = NULL;
952 953 954 955 956 957 958
	} else if (!is_url(url)
		|| !prefixcmp(url, "file://")
		|| !prefixcmp(url, "git://")
		|| !prefixcmp(url, "ssh://")
		|| !prefixcmp(url, "git+ssh://")
		|| !prefixcmp(url, "ssh+git://")) {
		/* These are builtin smart transports. */
959 960
		struct git_transport_data *data = xcalloc(1, sizeof(*data));
		ret->data = data;
961
		ret->set_option = NULL;
962 963
		ret->get_refs_list = get_refs_via_connect;
		ret->fetch = fetch_refs_via_pack;
964
		ret->push_refs = git_transport_push;
965
		ret->connect = connect_git;
966
		ret->disconnect = disconnect_git;
967
		ret->smart_options = &(data->options);
968

969
		data->conn = NULL;
I
Ilari Liusvaara 已提交
970
		data->got_remote_heads = 0;
971 972 973 974 975 976 977
	} else {
		/* Unknown protocol in URL. Pass to external handler. */
		int len = external_specification_len(url);
		char *handler = xmalloc(len + 1);
		handler[len] = 0;
		strncpy(handler, url, len);
		transport_helper_init(ret, handler);
978
	}
979

980 981 982 983 984 985 986 987 988 989
	if (ret->smart_options) {
		ret->smart_options->thin = 1;
		ret->smart_options->uploadpack = "git-upload-pack";
		if (remote->uploadpack)
			ret->smart_options->uploadpack = remote->uploadpack;
		ret->smart_options->receivepack = "git-receive-pack";
		if (remote->receivepack)
			ret->smart_options->receivepack = remote->receivepack;
	}

990 991 992 993 994 995
	return ret;
}

int transport_set_option(struct transport *transport,
			 const char *name, const char *value)
{
996 997 998 999 1000 1001
	int git_reports = 1, protocol_reports = 1;

	if (transport->smart_options)
		git_reports = set_git_option(transport->smart_options,
					     name, value);

1002
	if (transport->set_option)
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
		protocol_reports = transport->set_option(transport, name,
							value);

	/* If either report is 0, report 0 (success). */
	if (!git_reports || !protocol_reports)
		return 0;
	/* If either reports -1 (invalid value), report -1. */
	if ((git_reports == -1) || (protocol_reports == -1))
		return -1;
	/* Otherwise if both report unknown, report unknown. */
1013
	return 1;
1014 1015
}

1016 1017 1018 1019 1020 1021 1022 1023
void transport_set_verbosity(struct transport *transport, int verbosity)
{
	if (verbosity >= 2)
		transport->verbose = verbosity <= 3 ? verbosity : 3;
	if (verbosity < 0)
		transport->verbose = -1;
}

1024
int transport_push(struct transport *transport,
1025
		   int refspec_nr, const char **refspec, int flags,
1026
		   int *nonfastforward)
1027
{
1028
	*nonfastforward = 0;
1029 1030
	verify_remote_names(refspec_nr, refspec);

I
Ilari Liusvaara 已提交
1031
	if (transport->push) {
I
Ilari Liusvaara 已提交
1032 1033 1034 1035
		/* Maybe FIXME. But no important transport uses this case. */
		if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
			die("This transport does not support using --set-upstream");

1036
		return transport->push(transport, refspec_nr, refspec, flags);
I
Ilari Liusvaara 已提交
1037
	} else if (transport->push_refs) {
1038 1039 1040 1041
		struct ref *remote_refs =
			transport->get_refs_list(transport, 1);
		struct ref *local_refs = get_local_heads();
		int match_flags = MATCH_REFS_NONE;
1042 1043
		int verbose = (transport->verbose > 0);
		int quiet = (transport->verbose < 0);
1044
		int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
I
Ilari Liusvaara 已提交
1045
		int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
1046
		int ret, err;
1047 1048 1049 1050 1051 1052

		if (flags & TRANSPORT_PUSH_ALL)
			match_flags |= MATCH_REFS_ALL;
		if (flags & TRANSPORT_PUSH_MIRROR)
			match_flags |= MATCH_REFS_MIRROR;

1053
		if (match_refs(local_refs, &remote_refs,
1054 1055 1056 1057
			       refspec_nr, refspec, match_flags)) {
			return -1;
		}

1058 1059 1060 1061
		set_ref_status_for_push(remote_refs,
			flags & TRANSPORT_PUSH_MIRROR,
			flags & TRANSPORT_PUSH_FORCE);

1062
		ret = transport->push_refs(transport, remote_refs, flags);
1063
		err = push_had_errors(remote_refs);
1064

1065
		ret |= err;
1066

1067
		if (!quiet || err)
1068
			print_push_status(transport->url, remote_refs,
J
Junio C Hamano 已提交
1069 1070
					verbose | porcelain, porcelain,
					nonfastforward);
1071

I
Ilari Liusvaara 已提交
1072 1073 1074
		if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
			set_upstreams(transport, remote_refs, pretend);

1075 1076 1077 1078 1079 1080
		if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
			struct ref *ref;
			for (ref = remote_refs; ref; ref = ref->next)
				update_tracking_ref(transport->remote, ref, verbose);
		}

1081
		if (!quiet && !ret && !refs_pushed(remote_refs))
1082 1083 1084 1085
			fprintf(stderr, "Everything up-to-date\n");
		return ret;
	}
	return 1;
1086 1087
}

1088
const struct ref *transport_get_remote_refs(struct transport *transport)
1089 1090
{
	if (!transport->remote_refs)
1091
		transport->remote_refs = transport->get_refs_list(transport, 0);
I
Ilari Liusvaara 已提交
1092

1093 1094 1095
	return transport->remote_refs;
}

D
Daniel Barkalow 已提交
1096
int transport_fetch_refs(struct transport *transport, struct ref *refs)
1097
{
1098
	int rc;
N
Nicolas Pitre 已提交
1099
	int nr_heads = 0, nr_alloc = 0, nr_refs = 0;
D
Daniel Barkalow 已提交
1100 1101
	struct ref **heads = NULL;
	struct ref *rm;
1102 1103

	for (rm = refs; rm; rm = rm->next) {
N
Nicolas Pitre 已提交
1104
		nr_refs++;
1105
		if (rm->peer_ref &&
D
Daniel Barkalow 已提交
1106
		    !is_null_sha1(rm->old_sha1) &&
1107 1108
		    !hashcmp(rm->peer_ref->old_sha1, rm->old_sha1))
			continue;
1109
		ALLOC_GROW(heads, nr_heads + 1, nr_alloc);
1110
		heads[nr_heads++] = rm;
1111 1112
	}

N
Nicolas Pitre 已提交
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
	if (!nr_heads) {
		/*
		 * When deepening of a shallow repository is requested,
		 * then local and remote refs are likely to still be equal.
		 * Just feed them all to the fetch method in that case.
		 * This condition shouldn't be met in a non-deepening fetch
		 * (see builtin-fetch.c:quickfetch()).
		 */
		heads = xmalloc(nr_refs * sizeof(*heads));
		for (rm = refs; rm; rm = rm->next)
			heads[nr_heads++] = rm;
	}

1126
	rc = transport->fetch(transport, nr_heads, heads);
I
Ilari Liusvaara 已提交
1127

1128
	free(heads);
1129
	return rc;
1130 1131
}

1132 1133 1134
void transport_unlock_pack(struct transport *transport)
{
	if (transport->pack_lockfile) {
1135
		unlink_or_warn(transport->pack_lockfile);
1136 1137 1138 1139 1140
		free(transport->pack_lockfile);
		transport->pack_lockfile = NULL;
	}
}

1141 1142 1143 1144 1145 1146 1147 1148 1149
int transport_connect(struct transport *transport, const char *name,
		      const char *exec, int fd[2])
{
	if (transport->connect)
		return transport->connect(transport, name, exec, fd);
	else
		die("Operation not supported by protocol");
}

1150 1151 1152
int transport_disconnect(struct transport *transport)
{
	int ret = 0;
1153 1154
	if (transport->disconnect)
		ret = transport->disconnect(transport);
1155 1156 1157
	free(transport);
	return ret;
}
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205

/*
 * Strip username (and password) from an url and return
 * it in a newly allocated string.
 */
char *transport_anonymize_url(const char *url)
{
	char *anon_url, *scheme_prefix, *anon_part;
	size_t anon_len, prefix_len = 0;

	anon_part = strchr(url, '@');
	if (is_local(url) || !anon_part)
		goto literal_copy;

	anon_len = strlen(++anon_part);
	scheme_prefix = strstr(url, "://");
	if (!scheme_prefix) {
		if (!strchr(anon_part, ':'))
			/* cannot be "me@there:/path/name" */
			goto literal_copy;
	} else {
		const char *cp;
		/* make sure scheme is reasonable */
		for (cp = url; cp < scheme_prefix; cp++) {
			switch (*cp) {
				/* RFC 1738 2.1 */
			case '+': case '.': case '-':
				break; /* ok */
			default:
				if (isalnum(*cp))
					break;
				/* it isn't */
				goto literal_copy;
			}
		}
		/* @ past the first slash does not count */
		cp = strchr(scheme_prefix + 3, '/');
		if (cp && cp < anon_part)
			goto literal_copy;
		prefix_len = scheme_prefix - url + 3;
	}
	anon_url = xcalloc(1, 1 + prefix_len + anon_len);
	memcpy(anon_url, url, prefix_len);
	memcpy(anon_url + prefix_len, anon_part, anon_len);
	return anon_url;
literal_copy:
	return xstrdup(url);
}