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 172
		tmp = resolve_ref_unsafe(localname, RESOLVE_REF_READING,
					 sha, &flag);
I
Ilari Liusvaara 已提交
173
		if (tmp && flag & REF_ISSYMREF &&
174
			starts_with(tmp, "refs/heads/"))
I
Ilari Liusvaara 已提交
175 176 177
			localname = tmp;

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

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

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

209 210 211
	if (for_push)
		return NULL;

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

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

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

	rsync.argv = args;
	rsync.stdout_to_stderr = 1;
	args[0] = "rsync";
J
Jeff King 已提交
225
	args[1] = (transport->verbose > 1) ? "-rv" : "-r";
226 227 228 229 230 231 232 233
	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);
234
	strbuf_addstr(&buf, rsync_url(transport->url));
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 263
	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 已提交
264
				int nr_objs, struct ref **to_fetch)
265
{
266
	struct child_process rsync = CHILD_PROCESS_INIT;
267 268

	rsync.stdout_to_stderr = 1;
269 270 271 272 273 274 275
	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());
276 277

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

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

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

335 336
	/* first push the objects */

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

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

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

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

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

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

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

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

406 407 408
	if (for_push)
		return NULL;

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

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

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

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

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

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

	if (data->conn)
		return 0;

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

500 501 502
	return 0;
}

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

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

	return refs;
}

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

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

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

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

562 563
	free_refs(refs_tmp);

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

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

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

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

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

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

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

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

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

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

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

	return 1;
}

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

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

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

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

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

781
void transport_verify_remote_names(int nr_heads, const char **heads)
782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
{
	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;
797 798 799 800
		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]);
801 802 803 804
	}
}

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

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

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

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

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

	return ret;
841 842
}

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

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

	free(data);
866 867 868
	return 0;
}

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

	transport->cannot_reuse = 1;
I
Ilari Liusvaara 已提交
895 896
}

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

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

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

915 916
	ret->progress = isatty(2);

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

920
	ret->got_remote_refs = 0;
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
	/* maybe it is a foreign URL? */
	if (url) {
		const char *p = url;

J
Jeff King 已提交
932
		while (is_urlschemechar(p == url, *p))
933
			p++;
934
		if (starts_with(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 (starts_with(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 (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) {
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
	} else if (!is_url(url)
953 954 955 956 957
		|| starts_with(url, "file://")
		|| starts_with(url, "git://")
		|| starts_with(url, "ssh://")
		|| starts_with(url, "git+ssh://")
		|| starts_with(url, "ssh+git://")) {
958
		/* 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
void transport_set_verbosity(struct transport *transport, int verbosity,
	int force_progress)
1018
{
J
Jeff King 已提交
1019
	if (verbosity >= 1)
1020 1021 1022
		transport->verbose = verbosity <= 3 ? verbosity : 3;
	if (verbosity < 0)
		transport->verbose = -1;
1023 1024 1025 1026 1027

	/**
	 * Rules used to determine whether to report progress (processing aborts
	 * when a rule is satisfied):
	 *
1028 1029 1030 1031
	 *   . 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.
1032
	 **/
1033 1034 1035 1036
	if (force_progress >= 0)
		transport->progress = !!force_progress;
	else
		transport->progress = verbosity >= 0 && isatty(2);
1037 1038
}

1039 1040 1041 1042 1043 1044 1045 1046
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);
1047 1048 1049 1050 1051
	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");
1052 1053 1054 1055 1056 1057

	string_list_clear(needs_pushing, 0);

	die("Aborting.");
}

1058 1059 1060 1061 1062
static int run_pre_push_hook(struct transport *transport,
			     struct ref *remote_refs)
{
	int ret = 0, x;
	struct ref *r;
1063
	struct child_process proc = CHILD_PROCESS_INIT;
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
	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;
1087
		if (r->status == REF_STATUS_REJECT_STALE) continue;
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
		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;
}

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

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

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

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

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

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

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

1156 1157 1158 1159 1160 1161
		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);

1162 1163 1164 1165
		set_ref_status_for_push(remote_refs,
			flags & TRANSPORT_PUSH_MIRROR,
			flags & TRANSPORT_PUSH_FORCE);

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

1170
		if ((flags & TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND) && !is_bare_repository()) {
1171 1172 1173
			struct ref *ref = remote_refs;
			for (; ref; ref = ref->next)
				if (!is_null_sha1(ref->new_sha1) &&
1174 1175 1176 1177 1178 1179 1180
				    !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()) {
1181
			struct ref *ref = remote_refs;
1182
			struct string_list needs_pushing = STRING_LIST_INIT_DUP;
1183

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

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

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

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

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

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

1214 1215 1216
		return ret;
	}
	return 1;
1217 1218
}

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

1226 1227 1228
	return transport->remote_refs;
}

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

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

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

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

1261
	free(heads);
1262
	return rc;
1263 1264
}

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

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

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

/*
J
Jim Meyering 已提交
1293
 * Strip username (and password) from a URL and return
1294 1295 1296 1297 1298 1299 1300 1301
 * 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, '@');
1302
	if (url_is_local_not_ssh(url) || !anon_part)
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 1337 1338
		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);
}
1339

1340 1341 1342 1343 1344 1345 1346
struct alternate_refs_data {
	alternate_ref_fn *fn;
	void *data;
};

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

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

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

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