예제 #1
0
파일: fetch-pack.c 프로젝트: hashpling/git
static void add_wants(int no_dependents, const struct ref *wants, struct strbuf *req_buf)
{
	int use_ref_in_want = server_supports_feature("fetch", "ref-in-want", 0);

	for ( ; wants ; wants = wants->next) {
		const struct object_id *remote = &wants->old_oid;
		struct object *o;

		/*
		 * If that object is complete (i.e. it is an ancestor of a
		 * local ref), we tell them we have it but do not have to
		 * tell them about its ancestors, which they already know
		 * about.
		 *
		 * We use lookup_object here because we are only
		 * interested in the case we *know* the object is
		 * reachable and we have already scanned it.
		 *
		 * Do this only if args->no_dependents is false (if it is true,
		 * we cannot trust the object flags).
		 */
		if (!no_dependents &&
		    ((o = lookup_object(the_repository, remote->hash)) != NULL) &&
		    (o->flags & COMPLETE)) {
			continue;
		}

		if (!use_ref_in_want || wants->exact_oid)
			packet_buf_write(req_buf, "want %s\n", oid_to_hex(remote));
		else
			packet_buf_write(req_buf, "want-ref %s\n", wants->name);
	}
}
예제 #2
0
파일: fetch-pack.c 프로젝트: DoWonJin/git
static int send_fetch_request(int fd_out, const struct fetch_pack_args *args,
			      const struct ref *wants, struct oidset *common,
			      int *haves_to_send, int *in_vain)
{
	int ret = 0;
	struct strbuf req_buf = STRBUF_INIT;

	if (server_supports_v2("fetch", 1))
		packet_buf_write(&req_buf, "command=fetch");
	if (server_supports_v2("agent", 0))
		packet_buf_write(&req_buf, "agent=%s", git_user_agent_sanitized());

	packet_buf_delim(&req_buf);
	if (args->use_thin_pack)
		packet_buf_write(&req_buf, "thin-pack");
	if (args->no_progress)
		packet_buf_write(&req_buf, "no-progress");
	if (args->include_tag)
		packet_buf_write(&req_buf, "include-tag");
	if (prefer_ofs_delta)
		packet_buf_write(&req_buf, "ofs-delta");

	/* Add shallow-info and deepen request */
	if (server_supports_feature("fetch", "shallow", 0))
		add_shallow_requests(&req_buf, args);
	else if (is_repository_shallow() || args->deepen)
		die(_("Server does not support shallow requests"));

	/* add wants */
	add_wants(wants, &req_buf);

	/* Add all of the common commits we've found in previous rounds */
	add_common(&req_buf, common);

	/* Add initial haves */
	ret = add_haves(&req_buf, haves_to_send, in_vain);

	/* Send request */
	packet_buf_flush(&req_buf);
	write_or_die(fd_out, req_buf.buf, req_buf.len);

	strbuf_release(&req_buf);
	return ret;
}
예제 #3
0
파일: fetch-pack.c 프로젝트: hashpling/git
static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
			      const struct fetch_pack_args *args,
			      const struct ref *wants, struct oidset *common,
			      int *haves_to_send, int *in_vain)
{
	int ret = 0;
	struct strbuf req_buf = STRBUF_INIT;

	if (server_supports_v2("fetch", 1))
		packet_buf_write(&req_buf, "command=fetch");
	if (server_supports_v2("agent", 0))
		packet_buf_write(&req_buf, "agent=%s", git_user_agent_sanitized());
	if (args->server_options && args->server_options->nr &&
	    server_supports_v2("server-option", 1)) {
		int i;
		for (i = 0; i < args->server_options->nr; i++)
			packet_write_fmt(fd_out, "server-option=%s",
					 args->server_options->items[i].string);
	}

	packet_buf_delim(&req_buf);
	if (args->use_thin_pack)
		packet_buf_write(&req_buf, "thin-pack");
	if (args->no_progress)
		packet_buf_write(&req_buf, "no-progress");
	if (args->include_tag)
		packet_buf_write(&req_buf, "include-tag");
	if (prefer_ofs_delta)
		packet_buf_write(&req_buf, "ofs-delta");

	/* Add shallow-info and deepen request */
	if (server_supports_feature("fetch", "shallow", 0))
		add_shallow_requests(&req_buf, args);
	else if (is_repository_shallow(the_repository) || args->deepen)
		die(_("Server does not support shallow requests"));

	/* Add filter */
	if (server_supports_feature("fetch", "filter", 0) &&
	    args->filter_options.choice) {
		print_verbose(args, _("Server supports filter"));
		packet_buf_write(&req_buf, "filter %s",
				 args->filter_options.filter_spec);
	} else if (args->filter_options.choice) {
		warning("filtering not recognized by server, ignoring");
	}

	/* add wants */
	add_wants(args->no_dependents, wants, &req_buf);

	if (args->no_dependents) {
		packet_buf_write(&req_buf, "done");
		ret = 1;
	} else {
		/* Add all of the common commits we've found in previous rounds */
		add_common(&req_buf, common);

		/* Add initial haves */
		ret = add_haves(negotiator, &req_buf, haves_to_send, in_vain);
	}

	/* Send request */
	packet_buf_flush(&req_buf);
	write_or_die(fd_out, req_buf.buf, req_buf.len);

	strbuf_release(&req_buf);
	return ret;
}
예제 #4
0
파일: fetch-pack.c 프로젝트: mtmiller/git
static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
				    int fd[2],
				    const struct ref *orig_ref,
				    struct ref **sought, int nr_sought,
				    char **pack_lockfile)
{
	struct ref *ref = copy_ref_list(orig_ref);
	enum fetch_state state = FETCH_CHECK_LOCAL;
	struct oidset common = OIDSET_INIT;
	struct packet_reader reader;
	int in_vain = 0;
	int haves_to_send = INITIAL_FLUSH;
	struct fetch_negotiator negotiator;
	fetch_negotiator_init(&negotiator, negotiation_algorithm);
	packet_reader_init(&reader, fd[0], NULL, 0,
			   PACKET_READ_CHOMP_NEWLINE |
			   PACKET_READ_DIE_ON_ERR_PACKET);
	if (git_env_bool("GIT_TEST_SIDEBAND_ALL", 1) &&
	    server_supports_feature("fetch", "sideband-all", 0)) {
		reader.use_sideband = 1;
		reader.me = "fetch-pack";
	}

	while (state != FETCH_DONE) {
		switch (state) {
		case FETCH_CHECK_LOCAL:
			sort_ref_list(&ref, ref_compare_name);
			QSORT(sought, nr_sought, cmp_ref_by_name);

			/* v2 supports these by default */
			allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1;
			use_sideband = 2;
			if (args->depth > 0 || args->deepen_since || args->deepen_not)
				args->deepen = 1;

			/* Filter 'ref' by 'sought' and those that aren't local */
			if (!args->no_dependents) {
				mark_complete_and_common_ref(&negotiator, args, &ref);
				filter_refs(args, &ref, sought, nr_sought);
				if (everything_local(args, &ref))
					state = FETCH_DONE;
				else
					state = FETCH_SEND_REQUEST;

				mark_tips(&negotiator, args->negotiation_tips);
				for_each_cached_alternate(&negotiator,
							  insert_one_alternate_object);
			} else {
				filter_refs(args, &ref, sought, nr_sought);
				state = FETCH_SEND_REQUEST;
			}
			break;
		case FETCH_SEND_REQUEST:
			if (send_fetch_request(&negotiator, fd[1], args, ref,
					       &common,
					       &haves_to_send, &in_vain,
					       reader.use_sideband))
				state = FETCH_GET_PACK;
			else
				state = FETCH_PROCESS_ACKS;
			break;
		case FETCH_PROCESS_ACKS:
			/* Process ACKs/NAKs */
			switch (process_acks(&negotiator, &reader, &common)) {
			case 2:
				state = FETCH_GET_PACK;
				break;
			case 1:
				in_vain = 0;
				/* fallthrough */
			default:
				state = FETCH_SEND_REQUEST;
				break;
			}
			break;
		case FETCH_GET_PACK:
			/* Check for shallow-info section */
			if (process_section_header(&reader, "shallow-info", 1))
				receive_shallow_info(args, &reader);

			if (process_section_header(&reader, "wanted-refs", 1))
				receive_wanted_refs(&reader, sought, nr_sought);

			/* get the pack */
			process_section_header(&reader, "packfile", 0);
			if (get_pack(args, fd, pack_lockfile))
				die(_("git fetch-pack: fetch failed."));

			state = FETCH_DONE;
			break;
		case FETCH_DONE:
			continue;
		}
	}

	negotiator.release(&negotiator);
	oidset_clear(&common);
	return ref;
}