transport.c 35.1 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"
6 7
#include "remote.h"
#include "connect.h"
D
Daniel Barkalow 已提交
8
#include "send-pack.h"
9
#include "walker.h"
J
Johannes Schindelin 已提交
10
#include "bundle.h"
11 12
#include "dir.h"
#include "refs.h"
I
Ilari Liusvaara 已提交
13
#include "branch.h"
J
Jeff King 已提交
14
#include "url.h"
15
#include "submodule.h"
16
#include "string-list.h"
17
#include "sha1-array.h"
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 51 52 53 54 55 56

/* 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))) {
57
		if (is_dot_or_dotdot(de->d_name))
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
			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;
80
			next = alloc_ref(path->buf + name_offset);
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 106 107 108 109 110 111
			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 (;;) {
112 113
		int cmp = 0; /* assigned before used */
		int len;
114 115 116 117 118 119 120 121 122

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

		if (hexval(buffer[0]) > 0xf)
			continue;
		len = strlen(buffer);
123
		if (len && buffer[len - 1] == '\n')
124 125 126 127 128 129 130 131
			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) {
132
			struct ref *next = alloc_ref(buffer + 41);
133 134 135 136 137 138 139 140 141 142 143 144 145
			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 已提交
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
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;
165
		if (is_null_sha1(ref->new_sha1))
I
Ilari Liusvaara 已提交
166 167 168 169 170
			continue;

		/* Follow symbolic refs (mainly for HEAD). */
		localname = ref->peer_ref->name;
		remotename = ref->name;
171
		tmp = resolve_ref_unsafe(localname, sha, 1, &flag);
I
Ilari Liusvaara 已提交
172
		if (tmp && flag & REF_ISSYMREF &&
173
			starts_with(tmp, "refs/heads/"))
I
Ilari Liusvaara 已提交
174 175 176
			localname = tmp;

		/* Both source and destination must be local branches. */
177
		if (!localname || !starts_with(localname, "refs/heads/"))
I
Ilari Liusvaara 已提交
178
			continue;
179
		if (!remotename || !starts_with(remotename, "refs/heads/"))
I
Ilari Liusvaara 已提交
180 181 182 183 184 185 186 187 188 189 190 191 192
			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);
	}
}

193 194
static const char *rsync_url(const char *url)
{
195 196 197
	if (!starts_with(url, "rsync://"))
		skip_prefix(url, "rsync:", &url);
	return url;
198 199
}

200
static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
201 202
{
	struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
S
Stephen Boyd 已提交
203
	struct ref dummy = {NULL}, *tail = &dummy;
204
	struct child_process rsync = CHILD_PROCESS_INIT;
205 206 207
	const char *args[5];
	int temp_dir_len;

208 209 210
	if (for_push)
		return NULL;

211 212 213 214
	/* copy the refs to the temporary directory */

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

218
	strbuf_addstr(&buf, rsync_url(transport->url));
219 220 221 222 223
	strbuf_addstr(&buf, "/refs");

	rsync.argv = args;
	rsync.stdout_to_stderr = 1;
	args[0] = "rsync";
J
Jeff King 已提交
224
	args[1] = (transport->verbose > 1) ? "-rv" : "-r";
225 226 227 228 229 230 231 232
	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);
233
	strbuf_addstr(&buf, rsync_url(transport->url));
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
	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 已提交
263
				int nr_objs, struct ref **to_fetch)
264
{
265
	struct child_process rsync = CHILD_PROCESS_INIT;
266 267

	rsync.stdout_to_stderr = 1;
268 269 270 271 272 273 274
	argv_array_push(&rsync.args, "rsync");
	argv_array_push(&rsync.args, (transport->verbose > 1) ? "-rv" : "-r");
	argv_array_push(&rsync.args, "--ignore-existing");
	argv_array_push(&rsync.args, "--exclude");
	argv_array_push(&rsync.args, "info");
	argv_array_pushf(&rsync.args, "%s/objects/", rsync_url(transport->url));
	argv_array_push(&rsync.args, get_object_directory());
275 276

	/* NEEDSWORK: handle one level of alternates */
277
	return run_command(&rsync);
278 279 280 281 282 283 284 285 286 287
}

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 */
288 289
	if (flags && !starts_with(name, "refs/heads/") &&
			!starts_with(name, "refs/tags/"))
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
		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;
328
	struct child_process rsync = CHILD_PROCESS_INIT;
329
	const char *args[10];
330

A
Andy Whitcroft 已提交
331 332 333
	if (flags & TRANSPORT_PUSH_MIRROR)
		return error("rsync transport does not support mirror mode");

334 335
	/* first push the objects */

336
	strbuf_addstr(&buf, rsync_url(transport->url));
337 338 339 340
	strbuf_addch(&buf, '/');

	rsync.argv = args;
	rsync.stdout_to_stderr = 1;
341 342 343 344 345
	i = 0;
	args[i++] = "rsync";
	args[i++] = "-a";
	if (flags & TRANSPORT_PUSH_DRY_RUN)
		args[i++] = "--dry-run";
J
Jeff King 已提交
346
	if (transport->verbose > 1)
347 348 349 350 351 352 353
		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;
354 355

	if (run_command(&rsync))
356 357
		return error("Could not push objects to %s",
				rsync_url(transport->url));
358 359 360 361 362

	/* 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))
363
		die_errno ("Could not make temporary directory");
364 365 366 367 368 369 370 371
	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;

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

	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;
}
393

J
Johannes Schindelin 已提交
394 395 396 397 398
struct bundle_transport_data {
	int fd;
	struct bundle_header header;
};

399
static struct ref *get_refs_from_bundle(struct transport *transport, int for_push)
J
Johannes Schindelin 已提交
400 401 402 403 404
{
	struct bundle_transport_data *data = transport->data;
	struct ref *result = NULL;
	int i;

405 406 407
	if (for_push)
		return NULL;

J
Johannes Schindelin 已提交
408 409 410 411 412 413 414
	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;
415
		struct ref *ref = alloc_ref(e->name);
J
Johannes Schindelin 已提交
416 417 418 419 420 421 422
		hashcpy(ref->old_sha1, e->sha1);
		ref->next = result;
		result = ref;
	}
	return result;
}

423
static int fetch_refs_from_bundle(struct transport *transport,
D
Daniel Barkalow 已提交
424
			       int nr_heads, struct ref **to_fetch)
J
Johannes Schindelin 已提交
425 426
{
	struct bundle_transport_data *data = transport->data;
427 428
	return unbundle(&data->header, data->fd,
			transport->progress ? BUNDLE_VERBOSE : 0);
J
Johannes Schindelin 已提交
429 430 431 432 433 434 435
}

static int close_bundle(struct transport *transport)
{
	struct bundle_transport_data *data = transport->data;
	if (data->fd > 0)
		close(data->fd);
436
	free(data);
J
Johannes Schindelin 已提交
437 438 439
	return 0;
}

440
struct git_transport_data {
441
	struct git_transport_options options;
442 443
	struct child_process *conn;
	int fd[2];
I
Ilari Liusvaara 已提交
444
	unsigned got_remote_heads : 1;
445
	struct sha1_array extra_have;
446
	struct sha1_array shallow;
447 448
};

449
static int set_git_option(struct git_transport_options *opts,
450 451
			  const char *name, const char *value)
{
452
	if (!strcmp(name, TRANS_OPT_UPLOADPACK)) {
453
		opts->uploadpack = value;
454 455
		return 0;
	} else if (!strcmp(name, TRANS_OPT_RECEIVEPACK)) {
456
		opts->receivepack = value;
457 458
		return 0;
	} else if (!strcmp(name, TRANS_OPT_THIN)) {
459
		opts->thin = !!value;
460
		return 0;
461
	} else if (!strcmp(name, TRANS_OPT_FOLLOWTAGS)) {
462
		opts->followtags = !!value;
463
		return 0;
464
	} else if (!strcmp(name, TRANS_OPT_KEEP)) {
465
		opts->keep = !!value;
466
		return 0;
467 468 469
	} else if (!strcmp(name, TRANS_OPT_UPDATE_SHALLOW)) {
		opts->update_shallow = !!value;
		return 0;
470 471
	} else if (!strcmp(name, TRANS_OPT_DEPTH)) {
		if (!value)
472
			opts->depth = 0;
473 474 475 476 477 478
		else {
			char *end;
			opts->depth = strtol(value, &end, 0);
			if (*end)
				die("transport: invalid depth option '%s'", value);
		}
479
		return 0;
480 481 482
	} else if (!strcmp(name, TRANS_OPT_PUSH_CERT)) {
		opts->push_cert = !!value;
		return 0;
483 484 485 486
	}
	return 1;
}

487
static int connect_setup(struct transport *transport, int for_push, int verbose)
488 489
{
	struct git_transport_data *data = transport->data;
I
Ilari Liusvaara 已提交
490 491 492 493

	if (data->conn)
		return 0;

494 495 496
	data->conn = git_connect(data->fd, transport->url,
				 for_push ? data->options.receivepack :
				 data->options.uploadpack,
497
				 verbose ? CONNECT_VERBOSE : 0);
I
Ilari Liusvaara 已提交
498

499 500 501
	return 0;
}

502
static struct ref *get_refs_via_connect(struct transport *transport, int for_push)
503 504 505 506
{
	struct git_transport_data *data = transport->data;
	struct ref *refs;

507
	connect_setup(transport, for_push, 0);
508
	get_remote_heads(data->fd[0], NULL, 0, &refs,
509 510
			 for_push ? REF_NORMAL : 0,
			 &data->extra_have,
511
			 &data->shallow);
I
Ilari Liusvaara 已提交
512
	data->got_remote_heads = 1;
513 514 515 516

	return refs;
}

517
static int fetch_refs_via_pack(struct transport *transport,
D
Daniel Barkalow 已提交
518
			       int nr_heads, struct ref **to_fetch)
519 520
{
	struct git_transport_data *data = transport->data;
521
	const struct ref *refs;
522 523
	char *dest = xstrdup(transport->url);
	struct fetch_pack_args args;
524
	struct ref *refs_tmp = NULL;
525

526
	memset(&args, 0, sizeof(args));
527 528
	args.uploadpack = data->options.uploadpack;
	args.keep_pack = data->options.keep;
529
	args.lock_pack = 1;
530 531
	args.use_thin_pack = data->options.thin;
	args.include_tag = data->options.followtags;
J
Jeff King 已提交
532
	args.verbose = (transport->verbose > 1);
533
	args.quiet = (transport->verbose < 0);
534
	args.no_progress = !transport->progress;
535
	args.depth = data->options.depth;
536 537
	args.check_self_contained_and_connected =
		data->options.check_self_contained_and_connected;
538
	args.cloning = transport->cloning;
539
	args.update_shallow = data->options.update_shallow;
540

I
Ilari Liusvaara 已提交
541
	if (!data->got_remote_heads) {
542
		connect_setup(transport, 0, 0);
543
		get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0,
544
				 NULL, &data->shallow);
I
Ilari Liusvaara 已提交
545
		data->got_remote_heads = 1;
546 547
	}

548 549
	refs = fetch_pack(&args, data->fd, data->conn,
			  refs_tmp ? refs_tmp : transport->remote_refs,
550
			  dest, to_fetch, nr_heads, &data->shallow,
551
			  &transport->pack_lockfile);
552 553 554 555 556
	close(data->fd[0]);
	close(data->fd[1]);
	if (finish_connect(data->conn))
		refs = NULL;
	data->conn = NULL;
I
Ilari Liusvaara 已提交
557
	data->got_remote_heads = 0;
558 559
	data->options.self_contained_and_connected =
		args.self_contained_and_connected;
560

561 562
	free_refs(refs_tmp);

563
	free(dest);
564
	return (refs ? 0 : -1);
565 566
}

567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
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;
}

582
int transport_refs_pushed(struct ref *ref)
583 584 585 586 587 588 589 590 591 592 593 594 595
{
	for (; ref; ref = ref->next) {
		switch(ref->status) {
		case REF_STATUS_NONE:
		case REF_STATUS_UPTODATE:
			break;
		default:
			return 1;
		}
	}
	return 0;
}

596
void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose)
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
{
	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);
	}
}

618
static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain)
619
{
620 621 622 623 624 625 626 627 628 629
	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 {
630
		fprintf(stderr, " %c %-*s ", flag, TRANSPORT_SUMMARY_WIDTH, summary);
631 632 633 634 635 636 637 638 639 640
		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);
641 642 643 644 645 646 647 648
	}
}

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

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

		strcpy(quickref, status_abbrev(ref->old_sha1));
664
		if (ref->forced_update) {
665 666 667 668 669 670 671 672 673 674
			strcat(quickref, "...");
			type = '+';
			msg = "forced update";
		} else {
			strcat(quickref, "..");
			type = ' ';
			msg = NULL;
		}
		strcat(quickref, status_abbrev(ref->new_sha1));

675
		print_ref_status(type, quickref, ref, ref->peer_ref, msg, porcelain);
676 677 678
	}
}

679
static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain)
680 681
{
	if (!count)
682
		fprintf(porcelain ? stdout : stderr, "To %s\n", dest);
683 684 685

	switch(ref->status) {
	case REF_STATUS_NONE:
686
		print_ref_status('X', "[no match]", ref, NULL, NULL, porcelain);
687 688 689
		break;
	case REF_STATUS_REJECT_NODELETE:
		print_ref_status('!', "[rejected]", ref, NULL,
690
						 "remote does not support deleting refs", porcelain);
691 692 693
		break;
	case REF_STATUS_UPTODATE:
		print_ref_status('=', "[up to date]", ref,
694
						 ref->peer_ref, NULL, porcelain);
695 696 697
		break;
	case REF_STATUS_REJECT_NONFASTFORWARD:
		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
698
						 "non-fast-forward", porcelain);
699
		break;
700 701 702 703
	case REF_STATUS_REJECT_ALREADY_EXISTS:
		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
						 "already exists", porcelain);
		break;
704 705 706 707 708 709 710 711
	case REF_STATUS_REJECT_FETCH_FIRST:
		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
						 "fetch first", porcelain);
		break;
	case REF_STATUS_REJECT_NEEDS_FORCE:
		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
						 "needs force", porcelain);
		break;
712 713 714 715
	case REF_STATUS_REJECT_STALE:
		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
						 "stale info", porcelain);
		break;
716 717 718 719
	case REF_STATUS_REJECT_SHALLOW:
		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
						 "new shallow roots not allowed", porcelain);
		break;
720 721
	case REF_STATUS_REMOTE_REJECT:
		print_ref_status('!', "[remote rejected]", ref,
722 723
						 ref->deletion ? NULL : ref->peer_ref,
						 ref->remote_status, porcelain);
724 725 726
		break;
	case REF_STATUS_EXPECTING_REPORT:
		print_ref_status('!', "[remote failure]", ref,
727 728
						 ref->deletion ? NULL : ref->peer_ref,
						 "remote failed to report status", porcelain);
729 730
		break;
	case REF_STATUS_OK:
731
		print_ok_ref_status(ref, porcelain);
732 733 734 735 736 737
		break;
	}

	return 1;
}

738
void transport_print_push_status(const char *dest, struct ref *refs,
739
				  int verbose, int porcelain, unsigned int *reject_reasons)
740 741 742
{
	struct ref *ref;
	int n = 0;
743 744 745 746
	unsigned char head_sha1[20];
	char *head;

	head = resolve_refdup("HEAD", head_sha1, 1, NULL);
747 748 749 750

	if (verbose) {
		for (ref = refs; ref; ref = ref->next)
			if (ref->status == REF_STATUS_UPTODATE)
751
				n += print_one_push_status(ref, dest, n, porcelain);
752 753 754 755
	}

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

758
	*reject_reasons = 0;
759 760 761 762
	for (ref = refs; ref; ref = ref->next) {
		if (ref->status != REF_STATUS_NONE &&
		    ref->status != REF_STATUS_UPTODATE &&
		    ref->status != REF_STATUS_OK)
763
			n += print_one_push_status(ref, dest, n, porcelain);
764
		if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD) {
765
			if (head != NULL && !strcmp(head, ref->name))
766
				*reject_reasons |= REJECT_NON_FF_HEAD;
767
			else
768
				*reject_reasons |= REJECT_NON_FF_OTHER;
769 770
		} else if (ref->status == REF_STATUS_REJECT_ALREADY_EXISTS) {
			*reject_reasons |= REJECT_ALREADY_EXISTS;
771 772 773 774
		} else if (ref->status == REF_STATUS_REJECT_FETCH_FIRST) {
			*reject_reasons |= REJECT_FETCH_FIRST;
		} else if (ref->status == REF_STATUS_REJECT_NEEDS_FORCE) {
			*reject_reasons |= REJECT_NEEDS_FORCE;
775
		}
776 777 778
	}
}

779
void transport_verify_remote_names(int nr_heads, const char **heads)
780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
{
	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;
795 796 797 798
		if (check_refname_format(remote,
				REFNAME_ALLOW_ONELEVEL|REFNAME_REFSPEC_PATTERN))
			die("remote part of refspec is not a valid name in %s",
				heads[i]);
799 800 801 802
	}
}

static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
803
{
804
	struct git_transport_data *data = transport->data;
D
Daniel Barkalow 已提交
805
	struct send_pack_args args;
806 807
	int ret;

I
Ilari Liusvaara 已提交
808
	if (!data->got_remote_heads) {
809 810 811
		struct ref *tmp_refs;
		connect_setup(transport, 1, 0);

812 813
		get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL,
				 NULL, &data->shallow);
I
Ilari Liusvaara 已提交
814
		data->got_remote_heads = 1;
815
	}
816

817
	memset(&args, 0, sizeof(args));
A
Andy Whitcroft 已提交
818
	args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
D
Daniel Barkalow 已提交
819
	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
820
	args.use_thin_pack = data->options.thin;
821 822
	args.verbose = (transport->verbose > 0);
	args.quiet = (transport->verbose < 0);
823
	args.progress = transport->progress;
D
Daniel Barkalow 已提交
824
	args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
825
	args.porcelain = !!(flags & TRANSPORT_PUSH_PORCELAIN);
826
	args.push_cert = !!(flags & TRANSPORT_PUSH_CERT);
827
	args.url = transport->url;
D
Daniel Barkalow 已提交
828

829 830 831 832 833 834 835
	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 已提交
836
	data->got_remote_heads = 0;
837 838

	return ret;
839 840
}

841 842 843 844 845 846 847 848 849 850 851
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;
}

852 853
static int disconnect_git(struct transport *transport)
{
854 855
	struct git_transport_data *data = transport->data;
	if (data->conn) {
I
Ilari Liusvaara 已提交
856 857
		if (data->got_remote_heads)
			packet_flush(data->fd[1]);
858 859 860 861 862 863
		close(data->fd[0]);
		close(data->fd[1]);
		finish_connect(data->conn);
	}

	free(data);
864 865 866
	return 0;
}

I
Ilari Liusvaara 已提交
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
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);
891 892

	transport->cannot_reuse = 1;
I
Ilari Liusvaara 已提交
893 894
}

895 896 897 898 899 900 901 902
static int is_file(const char *url)
{
	struct stat buf;
	if (stat(url, &buf))
		return 0;
	return S_ISREG(buf.st_mode);
}

903 904 905 906 907
static int external_specification_len(const char *url)
{
	return strchr(url, ':') - url;
}

908
struct transport *transport_get(struct remote *remote, const char *url)
909
{
I
Ilari Liusvaara 已提交
910
	const char *helper;
911 912
	struct transport *ret = xcalloc(1, sizeof(*ret));

913 914
	ret->progress = isatty(2);

915 916 917
	if (!remote)
		die("No remote provided to transport_get()");

918
	ret->got_remote_refs = 0;
919
	ret->remote = remote;
I
Ilari Liusvaara 已提交
920
	helper = remote->foreign_vcs;
921

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

926 927 928 929
	/* maybe it is a foreign URL? */
	if (url) {
		const char *p = url;

J
Jeff King 已提交
930
		while (is_urlschemechar(p == url, *p))
931
			p++;
932
		if (starts_with(p, "::"))
I
Ilari Liusvaara 已提交
933
			helper = xstrndup(url, p - url);
934 935
	}

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

967
		data->conn = NULL;
I
Ilari Liusvaara 已提交
968
		data->got_remote_heads = 0;
969 970 971 972 973 974 975
	} 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);
976
	}
977

978 979 980 981 982 983 984 985 986 987
	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;
	}

988 989 990 991 992 993
	return ret;
}

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

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

1000
	if (transport->set_option)
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
		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. */
1011
	return 1;
1012 1013
}

1014 1015
void transport_set_verbosity(struct transport *transport, int verbosity,
	int force_progress)
1016
{
J
Jeff King 已提交
1017
	if (verbosity >= 1)
1018 1019 1020
		transport->verbose = verbosity <= 3 ? verbosity : 3;
	if (verbosity < 0)
		transport->verbose = -1;
1021 1022 1023 1024 1025

	/**
	 * Rules used to determine whether to report progress (processing aborts
	 * when a rule is satisfied):
	 *
1026 1027 1028 1029
	 *   . Report progress, if force_progress is 1 (ie. --progress).
	 *   . Don't report progress, if force_progress is 0 (ie. --no-progress).
	 *   . Don't report progress, if verbosity < 0 (ie. -q/--quiet ).
	 *   . Report progress if isatty(2) is 1.
1030
	 **/
1031 1032 1033 1034
	if (force_progress >= 0)
		transport->progress = !!force_progress;
	else
		transport->progress = verbosity >= 0 && isatty(2);
1035 1036
}

1037 1038 1039 1040 1041 1042 1043 1044
static void die_with_unpushed_submodules(struct string_list *needs_pushing)
{
	int i;

	fprintf(stderr, "The following submodule paths contain changes that can\n"
			"not be found on any remote:\n");
	for (i = 0; i < needs_pushing->nr; i++)
		printf("  %s\n", needs_pushing->items[i].string);
1045 1046 1047 1048 1049
	fprintf(stderr, "\nPlease try\n\n"
			"	git push --recurse-submodules=on-demand\n\n"
			"or cd to the path and use\n\n"
			"	git push\n\n"
			"to push them to a remote.\n\n");
1050 1051 1052 1053 1054 1055

	string_list_clear(needs_pushing, 0);

	die("Aborting.");
}

1056 1057 1058 1059 1060
static int run_pre_push_hook(struct transport *transport,
			     struct ref *remote_refs)
{
	int ret = 0, x;
	struct ref *r;
1061
	struct child_process proc = CHILD_PROCESS_INIT;
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
	struct strbuf buf;
	const char *argv[4];

	if (!(argv[0] = find_hook("pre-push")))
		return 0;

	argv[1] = transport->remote->name;
	argv[2] = transport->url;
	argv[3] = NULL;

	proc.argv = argv;
	proc.in = -1;

	if (start_command(&proc)) {
		finish_command(&proc);
		return -1;
	}

	strbuf_init(&buf, 256);

	for (r = remote_refs; r; r = r->next) {
		if (!r->peer_ref) continue;
		if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue;
1085
		if (r->status == REF_STATUS_REJECT_STALE) continue;
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111
		if (r->status == REF_STATUS_UPTODATE) continue;

		strbuf_reset(&buf);
		strbuf_addf( &buf, "%s %s %s %s\n",
			 r->peer_ref->name, sha1_to_hex(r->new_sha1),
			 r->name, sha1_to_hex(r->old_sha1));

		if (write_in_full(proc.in, buf.buf, buf.len) != buf.len) {
			ret = -1;
			break;
		}
	}

	strbuf_release(&buf);

	x = close(proc.in);
	if (!ret)
		ret = x;

	x = finish_command(&proc);
	if (!ret)
		ret = x;

	return ret;
}

1112
int transport_push(struct transport *transport,
1113
		   int refspec_nr, const char **refspec, int flags,
1114
		   unsigned int *reject_reasons)
1115
{
1116
	*reject_reasons = 0;
1117
	transport_verify_remote_names(refspec_nr, refspec);
1118

I
Ilari Liusvaara 已提交
1119
	if (transport->push) {
I
Ilari Liusvaara 已提交
1120 1121 1122 1123
		/* Maybe FIXME. But no important transport uses this case. */
		if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
			die("This transport does not support using --set-upstream");

1124
		return transport->push(transport, refspec_nr, refspec, flags);
I
Ilari Liusvaara 已提交
1125
	} else if (transport->push_refs) {
1126
		struct ref *remote_refs;
1127 1128
		struct ref *local_refs = get_local_heads();
		int match_flags = MATCH_REFS_NONE;
1129 1130
		int verbose = (transport->verbose > 0);
		int quiet = (transport->verbose < 0);
1131
		int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
I
Ilari Liusvaara 已提交
1132
		int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
1133
		int push_ret, ret, err;
1134

1135 1136 1137 1138 1139
		if (check_push_refs(local_refs, refspec_nr, refspec) < 0)
			return -1;

		remote_refs = transport->get_refs_list(transport, 1);

1140 1141 1142 1143
		if (flags & TRANSPORT_PUSH_ALL)
			match_flags |= MATCH_REFS_ALL;
		if (flags & TRANSPORT_PUSH_MIRROR)
			match_flags |= MATCH_REFS_MIRROR;
F
Felipe Contreras 已提交
1144 1145
		if (flags & TRANSPORT_PUSH_PRUNE)
			match_flags |= MATCH_REFS_PRUNE;
J
Junio C Hamano 已提交
1146 1147
		if (flags & TRANSPORT_PUSH_FOLLOW_TAGS)
			match_flags |= MATCH_REFS_FOLLOW_TAGS;
1148

1149 1150
		if (match_push_refs(local_refs, &remote_refs,
				    refspec_nr, refspec, match_flags)) {
1151 1152 1153
			return -1;
		}

1154 1155 1156 1157 1158 1159
		if (transport->smart_options &&
		    transport->smart_options->cas &&
		    !is_empty_cas(transport->smart_options->cas))
			apply_push_cas(transport->smart_options->cas,
				       transport->remote, remote_refs);

1160 1161 1162 1163
		set_ref_status_for_push(remote_refs,
			flags & TRANSPORT_PUSH_MIRROR,
			flags & TRANSPORT_PUSH_FORCE);

1164 1165 1166 1167
		if (!(flags & TRANSPORT_PUSH_NO_HOOK))
			if (run_pre_push_hook(transport, remote_refs))
				return -1;

1168
		if ((flags & TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND) && !is_bare_repository()) {
1169 1170 1171
			struct ref *ref = remote_refs;
			for (; ref; ref = ref->next)
				if (!is_null_sha1(ref->new_sha1) &&
1172 1173 1174 1175 1176 1177 1178
				    !push_unpushed_submodules(ref->new_sha1,
					    transport->remote->name))
				    die ("Failed to push all needed submodules!");
		}

		if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
			      TRANSPORT_RECURSE_SUBMODULES_CHECK)) && !is_bare_repository()) {
1179
			struct ref *ref = remote_refs;
1180
			struct string_list needs_pushing = STRING_LIST_INIT_DUP;
1181

1182 1183
			for (; ref; ref = ref->next)
				if (!is_null_sha1(ref->new_sha1) &&
1184 1185 1186
				    find_unpushed_submodules(ref->new_sha1,
					    transport->remote->name, &needs_pushing))
					die_with_unpushed_submodules(&needs_pushing);
1187 1188
		}

1189
		push_ret = transport->push_refs(transport, remote_refs, flags);
1190
		err = push_had_errors(remote_refs);
1191
		ret = push_ret | err;
1192

1193
		if (!quiet || err)
1194
			transport_print_push_status(transport->url, remote_refs,
J
Junio C Hamano 已提交
1195
					verbose | porcelain, porcelain,
1196
					reject_reasons);
1197

I
Ilari Liusvaara 已提交
1198 1199 1200
		if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
			set_upstreams(transport, remote_refs, pretend);

1201 1202 1203
		if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
			struct ref *ref;
			for (ref = remote_refs; ref; ref = ref->next)
1204
				transport_update_tracking_ref(transport->remote, ref, verbose);
1205 1206
		}

1207 1208
		if (porcelain && !push_ret)
			puts("Done");
1209
		else if (!quiet && !ret && !transport_refs_pushed(remote_refs))
1210
			fprintf(stderr, "Everything up-to-date\n");
1211

1212 1213 1214
		return ret;
	}
	return 1;
1215 1216
}

1217
const struct ref *transport_get_remote_refs(struct transport *transport)
1218
{
1219
	if (!transport->got_remote_refs) {
1220
		transport->remote_refs = transport->get_refs_list(transport, 0);
1221 1222
		transport->got_remote_refs = 1;
	}
I
Ilari Liusvaara 已提交
1223

1224 1225 1226
	return transport->remote_refs;
}

D
Daniel Barkalow 已提交
1227
int transport_fetch_refs(struct transport *transport, struct ref *refs)
1228
{
1229
	int rc;
N
Nicolas Pitre 已提交
1230
	int nr_heads = 0, nr_alloc = 0, nr_refs = 0;
D
Daniel Barkalow 已提交
1231 1232
	struct ref **heads = NULL;
	struct ref *rm;
1233 1234

	for (rm = refs; rm; rm = rm->next) {
N
Nicolas Pitre 已提交
1235
		nr_refs++;
1236
		if (rm->peer_ref &&
D
Daniel Barkalow 已提交
1237
		    !is_null_sha1(rm->old_sha1) &&
1238 1239
		    !hashcmp(rm->peer_ref->old_sha1, rm->old_sha1))
			continue;
1240
		ALLOC_GROW(heads, nr_heads + 1, nr_alloc);
1241
		heads[nr_heads++] = rm;
1242 1243
	}

N
Nicolas Pitre 已提交
1244 1245 1246 1247 1248 1249
	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
1250
		 * (see builtin/fetch.c:quickfetch()).
N
Nicolas Pitre 已提交
1251 1252 1253 1254 1255 1256
		 */
		heads = xmalloc(nr_refs * sizeof(*heads));
		for (rm = refs; rm; rm = rm->next)
			heads[nr_heads++] = rm;
	}

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

1259
	free(heads);
1260
	return rc;
1261 1262
}

1263 1264 1265
void transport_unlock_pack(struct transport *transport)
{
	if (transport->pack_lockfile) {
1266
		unlink_or_warn(transport->pack_lockfile);
1267 1268 1269 1270 1271
		free(transport->pack_lockfile);
		transport->pack_lockfile = NULL;
	}
}

1272 1273 1274 1275 1276 1277 1278 1279 1280
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");
}

1281 1282 1283
int transport_disconnect(struct transport *transport)
{
	int ret = 0;
1284 1285
	if (transport->disconnect)
		ret = transport->disconnect(transport);
1286 1287 1288
	free(transport);
	return ret;
}
1289 1290

/*
J
Jim Meyering 已提交
1291
 * Strip username (and password) from a URL and return
1292 1293 1294 1295 1296 1297 1298 1299
 * 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, '@');
1300
	if (url_is_local_not_ssh(url) || !anon_part)
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
		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);
}
1337

1338 1339 1340 1341 1342 1343 1344
struct alternate_refs_data {
	alternate_ref_fn *fn;
	void *data;
};

static int refs_from_alternate_cb(struct alternate_object_database *e,
				  void *data)
1345 1346 1347 1348 1349 1350
{
	char *other;
	size_t len;
	struct remote *remote;
	struct transport *transport;
	const struct ref *extra;
1351
	struct alternate_refs_data *cb = data;
1352 1353

	e->name[-1] = '\0';
1354
	other = xstrdup(real_path(e->base));
1355 1356 1357 1358 1359 1360
	e->name[-1] = '/';
	len = strlen(other);

	while (other[len-1] == '/')
		other[--len] = '\0';
	if (len < 8 || memcmp(other + len - 8, "/objects", 8))
1361
		goto out;
1362 1363 1364
	/* Is this a git repository with refs? */
	memcpy(other + len - 8, "/refs", 6);
	if (!is_directory(other))
1365
		goto out;
1366 1367 1368 1369 1370 1371
	other[len - 8] = '\0';
	remote = remote_get(other);
	transport = transport_get(remote, other);
	for (extra = transport_get_remote_refs(transport);
	     extra;
	     extra = extra->next)
1372
		cb->fn(extra, cb->data);
1373
	transport_disconnect(transport);
1374
out:
1375 1376 1377
	free(other);
	return 0;
}
1378 1379 1380 1381 1382 1383 1384 1385

void for_each_alternate_ref(alternate_ref_fn fn, void *data)
{
	struct alternate_refs_data cb;
	cb.fn = fn;
	cb.data = data;
	foreach_alt_odb(refs_from_alternate_cb, &cb);
}