Beispiel #1
0
static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
{
	struct git_transport_data *data = transport->data;
	struct send_pack_args args;
	int ret;

	if (!data->got_remote_heads) {
		struct ref *tmp_refs;
		connect_setup(transport, 1, 0);

		get_remote_heads(data->fd[0], &tmp_refs, REF_NORMAL, NULL);
		data->got_remote_heads = 1;
	}

	memset(&args, 0, sizeof(args));
	args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
	args.use_thin_pack = data->options.thin;
	args.verbose = (transport->verbose > 0);
	args.quiet = (transport->verbose < 0);
	args.progress = transport->progress;
	args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
	args.porcelain = !!(flags & TRANSPORT_PUSH_PORCELAIN);

	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;
	data->got_remote_heads = 0;

	return ret;
}
Beispiel #2
0
static struct ref *get_refs_via_connect(struct transport *transport, int for_push,
					const struct argv_array *ref_prefixes)
{
	struct git_transport_data *data = transport->data;
	struct ref *refs = NULL;
	struct packet_reader reader;

	connect_setup(transport, for_push);

	packet_reader_init(&reader, data->fd[0], NULL, 0,
			   PACKET_READ_CHOMP_NEWLINE |
			   PACKET_READ_GENTLE_ON_EOF);

	data->version = discover_version(&reader);
	switch (data->version) {
	case protocol_v2:
		get_remote_refs(data->fd[1], &reader, &refs, for_push,
				ref_prefixes);
		break;
	case protocol_v1:
	case protocol_v0:
		get_remote_heads(&reader, &refs,
				 for_push ? REF_NORMAL : 0,
				 &data->extra_have,
				 &data->shallow);
		break;
	case protocol_unknown_version:
		BUG("unknown protocol version");
	}
	data->got_remote_heads = 1;

	return refs;
}
Beispiel #3
0
static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
{
	struct git_transport_data *data = transport->data;
	struct send_pack_args args;
	int ret;

	if (!data->conn) {
		struct ref *tmp_refs;
		connect_setup(transport, 1, 0);

		get_remote_heads(data->fd[0], &tmp_refs, 0, NULL, REF_NORMAL,
				 NULL);
	}

	args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
	args.use_thin_pack = data->thin;
	args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
	args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);

	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;

	return ret;
}
Beispiel #4
0
static int fetch_refs_via_pack(struct transport *transport,
			       int nr_heads, struct ref **to_fetch)
{
	int ret = 0;
	struct git_transport_data *data = transport->data;
	struct ref *refs;
	char *dest = xstrdup(transport->url);
	struct fetch_pack_args args;
	struct ref *refs_tmp = NULL;

	memset(&args, 0, sizeof(args));
	args.uploadpack = data->options.uploadpack;
	args.keep_pack = data->options.keep;
	args.lock_pack = 1;
	args.use_thin_pack = data->options.thin;
	args.include_tag = data->options.followtags;
	args.verbose = (transport->verbose > 1);
	args.quiet = (transport->verbose < 0);
	args.no_progress = !transport->progress;
	args.depth = data->options.depth;
	args.deepen_since = data->options.deepen_since;
	args.deepen_not = data->options.deepen_not;
	args.deepen_relative = data->options.deepen_relative;
	args.check_self_contained_and_connected =
		data->options.check_self_contained_and_connected;
	args.cloning = transport->cloning;
	args.update_shallow = data->options.update_shallow;

	if (!data->got_remote_heads) {
		connect_setup(transport, 0);
		get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0,
				 NULL, &data->shallow);
		data->got_remote_heads = 1;
	}

	refs = fetch_pack(&args, data->fd, data->conn,
			  refs_tmp ? refs_tmp : transport->remote_refs,
			  dest, to_fetch, nr_heads, &data->shallow,
			  &transport->pack_lockfile);
	close(data->fd[0]);
	close(data->fd[1]);
	if (finish_connect(data->conn))
		ret = -1;
	data->conn = NULL;
	data->got_remote_heads = 0;
	data->options.self_contained_and_connected =
		args.self_contained_and_connected;

	if (refs == NULL)
		ret = -1;
	if (report_unmatched_refs(to_fetch, nr_heads))
		ret = -1;

	free_refs(refs_tmp);
	free_refs(refs);
	free(dest);
	return ret;
}
Beispiel #5
0
static struct ref *get_refs_via_connect(struct transport *transport)
{
	struct git_transport_data *data = transport->data;
	struct ref *refs;

	connect_setup(transport);
	get_remote_heads(data->fd[0], &refs, 0, NULL, 0);

	return refs;
}
Beispiel #6
0
static struct ref *get_refs_via_connect(struct transport *transport, int for_push)
{
	struct git_transport_data *data = transport->data;
	struct ref *refs;

	connect_setup(transport, for_push, 0);
	get_remote_heads(data->fd[0], &refs, 0, NULL,
			 for_push ? REF_NORMAL : 0, &data->extra_have);

	return refs;
}
Beispiel #7
0
static int fetch_refs_via_pack(struct transport *transport,
			       int nr_heads, struct ref **to_fetch)
{
	struct git_transport_data *data = transport->data;
	char **heads = xmalloc(nr_heads * sizeof(*heads));
	char **origh = xmalloc(nr_heads * sizeof(*origh));
	const struct ref *refs;
	char *dest = xstrdup(transport->url);
	struct fetch_pack_args args;
	int i;
	struct ref *refs_tmp = NULL;

	memset(&args, 0, sizeof(args));
	args.uploadpack = data->options.uploadpack;
	args.keep_pack = data->options.keep;
	args.lock_pack = 1;
	args.use_thin_pack = data->options.thin;
	args.include_tag = data->options.followtags;
	args.verbose = (transport->verbose > 0);
	args.quiet = (transport->verbose < 0);
	args.no_progress = !transport->progress;
	args.depth = data->options.depth;

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

	if (!data->got_remote_heads) {
		connect_setup(transport, 0, 0);
		get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
		data->got_remote_heads = 1;
	}

	refs = fetch_pack(&args, data->fd, data->conn,
			  refs_tmp ? refs_tmp : transport->remote_refs,
			  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;
	data->got_remote_heads = 0;

	free_refs(refs_tmp);

	for (i = 0; i < nr_heads; i++)
		free(origh[i]);
	free(origh);
	free(heads);
	free(dest);
	return (refs ? 0 : -1);
}
Beispiel #8
0
static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
{
	struct git_transport_data *data = transport->data;
	struct send_pack_args args;
	int ret;

	if (!data->got_remote_heads) {
		struct ref *tmp_refs;
		connect_setup(transport, 1);

		get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL,
				 NULL, &data->shallow);
		data->got_remote_heads = 1;
	}

	memset(&args, 0, sizeof(args));
	args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
	args.use_thin_pack = data->options.thin;
	args.verbose = (transport->verbose > 0);
	args.quiet = (transport->verbose < 0);
	args.progress = transport->progress;
	args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
	args.porcelain = !!(flags & TRANSPORT_PUSH_PORCELAIN);
	args.atomic = !!(flags & TRANSPORT_PUSH_ATOMIC);
	args.push_options = transport->push_options;
	args.url = transport->url;

	if (flags & TRANSPORT_PUSH_CERT_ALWAYS)
		args.push_cert = SEND_PACK_PUSH_CERT_ALWAYS;
	else if (flags & TRANSPORT_PUSH_CERT_IF_ASKED)
		args.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
	else
		args.push_cert = SEND_PACK_PUSH_CERT_NEVER;

	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;
	data->got_remote_heads = 0;

	return ret;
}
Beispiel #9
0
/*
 * Obtains the protocol version from the transport and writes it to
 * transport->data->version, first connecting if not already connected.
 *
 * If the protocol version is one that allows skipping the listing of remote
 * refs, and must_list_refs is 0, the listing of remote refs is skipped and
 * this function returns NULL. Otherwise, this function returns the list of
 * remote refs.
 */
static struct ref *handshake(struct transport *transport, int for_push,
			     const struct argv_array *ref_prefixes,
			     int must_list_refs)
{
	struct git_transport_data *data = transport->data;
	struct ref *refs = NULL;
	struct packet_reader reader;

	connect_setup(transport, for_push);

	packet_reader_init(&reader, data->fd[0], NULL, 0,
			   PACKET_READ_CHOMP_NEWLINE |
			   PACKET_READ_GENTLE_ON_EOF |
			   PACKET_READ_DIE_ON_ERR_PACKET);

	data->version = discover_version(&reader);
	switch (data->version) {
	case protocol_v2:
		if (must_list_refs)
			get_remote_refs(data->fd[1], &reader, &refs, for_push,
					ref_prefixes,
					transport->server_options);
		break;
	case protocol_v1:
	case protocol_v0:
		die_if_server_options(transport);
		get_remote_heads(&reader, &refs,
				 for_push ? REF_NORMAL : 0,
				 &data->extra_have,
				 &data->shallow);
		break;
	case protocol_unknown_version:
		BUG("unknown protocol version");
	}
	data->got_remote_heads = 1;

	if (reader.line_peeked)
		BUG("buffer must be empty at the end of handshake()");

	return refs;
}
Beispiel #10
0
int transport_update_ref_remote(struct transport* transport,
				struct ref *remote_refs) {
	// On this command, we need to reproduce small parts of other commands,
	// but because we want to avoid the assumption that we are running from
	// a local git repository, we'll not re-use that code.
	struct git_transport_data *data = transport->data;
	int ret = 0;
	if (!data->got_remote_heads) {
		struct ref *tmp_refs;
		connect_setup(transport, 1, 0);
		get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL,
				 NULL, &data->shallow);
		data->got_remote_heads = 1;
	}
	

	// Now we skip into the functionality from send_pack, where
	// we send the new refs to the server. Since this is a lower-level
	// command, we do not do all the checks from
	// set_ref_status_for_push. We also do support all the options
	// that send_pack does
	//
	// TODO: support omitting the old value for existing refs
	struct strbuf req_buf = STRBUF_INIT;
	struct ref *ref;
	int out = data->fd[1];
	for (ref = remote_refs; ref; ref = ref->next) {
	  char *old_hex = sha1_to_hex(ref->old_sha1);
	  char *new_hex = sha1_to_hex(ref->new_sha1);
	  packet_buf_write(&req_buf, "%s %s %s",
			     old_hex, new_hex, ref->name);
	}
	write_or_die(out, req_buf.buf, req_buf.len);
	packet_flush(out);
	strbuf_release(&req_buf);

	// And finally, we skip all the way to write_pack_file
	// This is actually the part that would absolutely depend on
	// having a local git repository.
	//
	// The basic assumption here is that you can only use this
	// command for objects that are already in the remote,
	// otherwise this would be a regular push.
	//
	// The end result is that the pack we need to send is always
	// empty.
	struct sha1file *f;
	unsigned char sha1[20];
	f = sha1fd_throughput(out, "<stdout>", NULL);
	write_pack_header(f, 0);
	sha1close(f, sha1, CSUM_CLOSE);

	// We now finish the connection on the same fashion that
	// git_transport_push does
	close(data->fd[1]);
	close(data->fd[0]);
	ret |= finish_connect(data->conn);
	data->conn = NULL;
	data->got_remote_heads = 0;

	return ret;
}