Ejemplo n.º 1
0
int cmd_upload_archive(int argc, const char **argv, const char *prefix)
{
	const char *sent_argv[MAX_ARGS];
	struct child_process cld = { sent_argv };
	cld.out = cld.err = -1;
	cld.git_cmd = 1;

	if (argc != 2)
		usage(upload_archive_usage);

	if (!enter_repo(argv[1], 0))
		die("'%s' does not appear to be a git repository", argv[1]);

	prepare_argv(sent_argv, argv);
	if (start_command(&cld)) {
		int err = errno;
		packet_write(1, "NACK fork failed on the remote side\n");
		die("upload-archive: %s", strerror(err));
	}

	/* parent - read from child, multiplex and send out to fd#1 */
	packet_write(1, "ACK\n");
	packet_flush(1);

	while (1) {
		struct pollfd pfd[2];
		int status;

		pfd[0].fd = cld.out;
		pfd[0].events = POLLIN;
		pfd[1].fd = cld.err;
		pfd[1].events = POLLIN;
		if (poll(pfd, 2, -1) < 0) {
			if (errno != EINTR) {
				error("poll failed resuming: %s",
				      strerror(errno));
				sleep(1);
			}
			continue;
		}
		if (pfd[1].revents & POLLIN)
			/* Status stream ready */
			if (process_input(pfd[1].fd, 2))
				continue;
		if (pfd[0].revents & POLLIN)
			/* Data stream ready */
			if (process_input(pfd[0].fd, 1))
				continue;

		if (waitpid(cld.pid, &status, 0) < 0)
			error_clnt("%s", lostchild);
		else if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
			error_clnt("%s", deadchild);
		packet_flush(1);
		break;
	}
	return 0;
}
Ejemplo n.º 2
0
static struct ref *do_fetch_pack(int fd[2],
		const struct ref *orig_ref,
		int nr_match,
		char **match,
		char **pack_lockfile)
{
	struct ref *ref = copy_ref_list(orig_ref);
	unsigned char sha1[20];

	if (is_repository_shallow() && !server_supports("shallow"))
		die("Server does not support shallow clients");
	if (server_supports("multi_ack_detailed")) {
		if (args.verbose)
			fprintf(stderr, "Server supports multi_ack_detailed\n");
		multi_ack = 2;
	}
	else if (server_supports("multi_ack")) {
		if (args.verbose)
			fprintf(stderr, "Server supports multi_ack\n");
		multi_ack = 1;
	}
	if (server_supports("side-band-64k")) {
		if (args.verbose)
			fprintf(stderr, "Server supports side-band-64k\n");
		use_sideband = 2;
	}
	else if (server_supports("side-band")) {
		if (args.verbose)
			fprintf(stderr, "Server supports side-band\n");
		use_sideband = 1;
	}
	if (server_supports("ofs-delta")) {
		if (args.verbose)
			fprintf(stderr, "Server supports ofs-delta\n");
	} else
		prefer_ofs_delta = 0;
	if (everything_local(&ref, nr_match, match)) {
		packet_flush(fd[1]);
		goto all_done;
	}
	if (find_common(fd, sha1, ref) < 0)
		if (!args.keep_pack)
			/* When cloning, it is not unusual to have
			 * no common commit.
			 */
			warning("no common commits");

	if (args.stateless_rpc)
		packet_flush(fd[1]);
	if (get_pack(fd, pack_lockfile))
		die("git fetch-pack: fetch failed.");

 all_done:
	return ref;
}
Ejemplo n.º 3
0
int cmd_upload_archive(int argc, const char **argv, const char *prefix)
{
	struct child_process writer = { argv };

	/*
	 * Set up sideband subprocess.
	 *
	 * We (parent) monitor and read from child, sending its fd#1 and fd#2
	 * multiplexed out to our fd#1.  If the child dies, we tell the other
	 * end over channel #3.
	 */
	argv[0] = "upload-archive--writer";
	writer.out = writer.err = -1;
	writer.git_cmd = 1;
	if (start_command(&writer)) {
		int err = errno;
		packet_write(1, "NACK unable to spawn subprocess\n");
		die("upload-archive: %s", strerror(err));
	}

	packet_write(1, "ACK\n");
	packet_flush(1);

	while (1) {
		struct pollfd pfd[2];

		pfd[0].fd = writer.out;
		pfd[0].events = POLLIN;
		pfd[1].fd = writer.err;
		pfd[1].events = POLLIN;
		if (poll(pfd, 2, -1) < 0) {
			if (errno != EINTR) {
				error("poll failed resuming: %s",
				      strerror(errno));
				sleep(1);
			}
			continue;
		}
		if (pfd[1].revents & POLLIN)
			/* Status stream ready */
			if (process_input(pfd[1].fd, 2))
				continue;
		if (pfd[0].revents & POLLIN)
			/* Data stream ready */
			if (process_input(pfd[0].fd, 1))
				continue;

		if (finish_command(&writer))
			error_clnt("%s", deadchild);
		packet_flush(1);
		break;
	}
	return 0;
}
Ejemplo n.º 4
0
struct ref *fetch_pack(struct fetch_pack_args *args,
		       int fd[], struct child_process *conn,
		       const struct ref *ref,
		       const char *dest,
		       struct ref **sought, int nr_sought,
		       struct sha1_array *shallow,
		       char **pack_lockfile)
{
	struct ref *ref_cpy;
	struct shallow_info si;

	fetch_pack_setup();
	if (nr_sought)
		nr_sought = remove_duplicates_in_refs(sought, nr_sought);

	if (!ref) {
		packet_flush(fd[1]);
		die("no matching remote head");
	}
	prepare_shallow_info(&si, shallow);
	ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
				&si, pack_lockfile);
	reprepare_packed_git();
	update_shallow(args, sought, nr_sought, &si);
	clear_shallow_info(&si);
	return ref_cpy;
}
Ejemplo n.º 5
0
static void upload_pack(void)
{
	struct string_list symref = STRING_LIST_INIT_DUP;

	head_ref_namespaced(find_symref, &symref);

	if (advertise_refs || !stateless_rpc) {
		reset_timeout();
		head_ref_namespaced(send_ref, &symref);
		for_each_namespaced_ref(send_ref, &symref);
		advertise_shallow_grafts(1);
		packet_flush(1);
	} else {
		head_ref_namespaced(mark_our_ref, NULL);
		for_each_namespaced_ref(mark_our_ref, NULL);
	}
	string_list_clear(&symref, 1);
	if (advertise_refs)
		return;

	receive_needs();
	if (want_obj.nr) {
		get_common_commits();
		create_pack_file();
	}
}
Ejemplo n.º 6
0
void upload_pack(struct upload_pack_options *options)
{
	struct string_list symref = STRING_LIST_INIT_DUP;

	stateless_rpc = options->stateless_rpc;
	timeout = options->timeout;
	daemon_mode = options->daemon_mode;

	git_config(upload_pack_config, NULL);

	head_ref_namespaced(find_symref, &symref);

	if (options->advertise_refs || !stateless_rpc) {
		reset_timeout();
		head_ref_namespaced(send_ref, &symref);
		for_each_namespaced_ref(send_ref, &symref);
		advertise_shallow_grafts(1);
		packet_flush(1);
	} else {
		head_ref_namespaced(check_ref, NULL);
		for_each_namespaced_ref(check_ref, NULL);
	}
	string_list_clear(&symref, 1);
	if (options->advertise_refs)
		return;

	receive_needs();
	if (want_obj.nr) {
		get_common_commits();
		create_pack_file();
	}
}
Ejemplo n.º 7
0
static void deepen(int depth, int deepen_relative,
		   struct object_array *shallows)
{
	if (depth == INFINITE_DEPTH && !is_repository_shallow()) {
		int i;

		for (i = 0; i < shallows->nr; i++) {
			struct object *object = shallows->objects[i].item;
			object->flags |= NOT_SHALLOW;
		}
	} else if (deepen_relative) {
		struct object_array reachable_shallows = OBJECT_ARRAY_INIT;
		struct commit_list *result;

		get_reachable_list(shallows, &reachable_shallows);
		result = get_shallow_commits(&reachable_shallows,
					     depth + 1,
					     SHALLOW, NOT_SHALLOW);
		send_shallow(result);
		free_commit_list(result);
		object_array_clear(&reachable_shallows);
	} else {
		struct commit_list *result;

		result = get_shallow_commits(&want_obj, depth,
					     SHALLOW, NOT_SHALLOW);
		send_shallow(result);
		free_commit_list(result);
	}

	send_unshallow(shallows);
	packet_flush(1);
}
Ejemplo n.º 8
0
static void get_info_refs(char *arg)
{
	const char *service_name = get_parameter("service");
	struct strbuf buf = STRBUF_INIT;

	hdr_nocache();

	if (service_name) {
		const char *argv[] = {NULL /* service name */,
			"--stateless-rpc", "--advertise-refs",
			".", NULL};
		struct rpc_service *svc = select_service(service_name);

		strbuf_addf(&buf, "application/x-git-%s-advertisement",
			svc->name);
		hdr_str(content_type, buf.buf);
		end_headers();

		packet_write(1, "# service=git-%s\n", svc->name);
		packet_flush(1);

		argv[0] = svc->name;
		run_service(argv);

	} else {
		select_getanyfile();
		for_each_namespaced_ref(show_text_ref, &buf);
		send_strbuf("text/plain", &buf);
	}
	strbuf_release(&buf);
}
Ejemplo n.º 9
0
struct ref *fetch_pack(struct fetch_pack_args *args,
		       int fd[], struct child_process *conn,
		       const struct ref *ref,
		       const char *dest,
		       struct ref **sought, int nr_sought,
		       char **pack_lockfile)
{
	struct ref *ref_cpy;

	fetch_pack_setup();
	if (nr_sought)
		nr_sought = remove_duplicates_in_refs(sought, nr_sought);

	if (!ref) {
		packet_flush(fd[1]);
		die("no matching remote head");
	}
	ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, pack_lockfile);

	if (args->depth > 0 && alternate_shallow_file) {
		if (*alternate_shallow_file == '\0') { /* --unshallow */
			unlink_or_warn(git_path("shallow"));
			rollback_lock_file(&shallow_lock);
		} else
			commit_lock_file(&shallow_lock);
	}

	reprepare_packed_git();
	return ref_cpy;
}
Ejemplo n.º 10
0
struct ref *fetch_pack(struct fetch_pack_args *my_args,
		       int fd[], struct child_process *conn,
		       const struct ref *ref,
		const char *dest,
		int nr_heads,
		char **heads,
		char **pack_lockfile)
{
	struct stat st;
	struct ref *ref_cpy;

	fetch_pack_setup();
	if (&args != my_args)
		memcpy(&args, my_args, sizeof(args));
	if (args.depth > 0) {
		if (stat(git_path("shallow"), &st))
			st.st_mtime = 0;
	}

	if (heads && nr_heads)
		nr_heads = remove_duplicates(nr_heads, heads);
	if (!ref) {
		packet_flush(fd[1]);
		die("no matching remote head");
	}
	ref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);

	if (args.depth > 0) {
		struct cache_time mtime;
		struct strbuf sb = STRBUF_INIT;
		char *shallow = git_path("shallow");
		int fd;

		mtime.sec = st.st_mtime;
		mtime.nsec = ST_MTIME_NSEC(st);
		if (stat(shallow, &st)) {
			if (mtime.sec)
				die("shallow file was removed during fetch");
		} else if (st.st_mtime != mtime.sec
#ifdef USE_NSEC
				|| ST_MTIME_NSEC(st) != mtime.nsec
#endif
			  )
			die("shallow file was changed during fetch");

		fd = hold_lock_file_for_update(&lock, shallow,
					       LOCK_DIE_ON_ERROR);
		if (!write_shallow_commits(&sb, 0)
		 || write_in_full(fd, sb.buf, sb.len) != sb.len) {
			unlink_or_warn(shallow);
			rollback_lock_file(&lock);
		} else {
			commit_lock_file(&lock);
		}
		strbuf_release(&sb);
	}

	reprepare_packed_git();
	return ref_cpy;
}
Ejemplo n.º 11
0
static void send_request(int fd, struct strbuf *buf)
{
	if (args.stateless_rpc) {
		send_sideband(fd, -1, buf->buf, buf->len, LARGE_PACKET_MAX);
		packet_flush(fd);
	} else
		safe_write(fd, buf->buf, buf->len);
}
Ejemplo n.º 12
0
int cmd_receive_pack(int argc, const char **argv, const char *prefix)
{
	int i;
	char *dir = NULL;

	argv++;
	for (i = 1; i < argc; i++) {
		const char *arg = *argv++;

		if (*arg == '-') {
			/* Do flag handling here */
			usage(receive_pack_usage);
		}
		if (dir)
			usage(receive_pack_usage);
		dir = xstrdup(arg);
	}
	if (!dir)
		usage(receive_pack_usage);

	setup_path();

	if (!enter_repo(dir, 0))
		die("'%s': unable to chdir or not a git archive", dir);

	if (is_repository_shallow())
		die("attempt to push into a shallow repository");

	git_config(receive_pack_config, NULL);

	if (0 <= transfer_unpack_limit)
		unpack_limit = transfer_unpack_limit;
	else if (0 <= receive_unpack_limit)
		unpack_limit = receive_unpack_limit;

	add_alternate_refs();
	write_head_info();
	clear_extra_refs();

	/* EOF */
	packet_flush(1);

	read_head_info();
	if (commands) {
		const char *unpack_status = NULL;

		if (!delete_only(commands))
			unpack_status = unpack();
		execute_commands(unpack_status);
		if (pack_lockfile)
			unlink(pack_lockfile);
		if (report_status)
			report(unpack_status);
		run_receive_hook(post_receive_hook);
		run_update_post_hook(commands);
	}
	return 0;
}
Ejemplo n.º 13
0
struct ref *fetch_pack(struct fetch_pack_args *my_args,
		       int fd[], struct child_process *conn,
		       const struct ref *ref,
		const char *dest,
		int nr_heads,
		char **heads,
		char **pack_lockfile)
{
	struct stat st;
	struct ref *ref_cpy;

	fetch_pack_setup();
	memcpy(&args, my_args, sizeof(args));
	if (args.depth > 0) {
		if (stat(git_path("shallow"), &st))
			st.st_mtime = 0;
	}

	if (heads && nr_heads)
		nr_heads = remove_duplicates(nr_heads, heads);
	if (!ref) {
		packet_flush(fd[1]);
		die("no matching remote head");
	}
	ref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);

	if (args.depth > 0) {
		struct cache_time mtime;
		char *shallow = git_path("shallow");
		int fd;

		mtime.sec = st.st_mtime;
#ifdef USE_NSEC
		mtime.usec = st.st_mtim.usec;
#endif
		if (stat(shallow, &st)) {
			if (mtime.sec)
				die("shallow file was removed during fetch");
		} else if (st.st_mtime != mtime.sec
#ifdef USE_NSEC
				|| st.st_mtim.usec != mtime.usec
#endif
			  )
			die("shallow file was changed during fetch");

		fd = hold_lock_file_for_update(&lock, shallow, 1);
		if (!write_shallow_commits(fd, 0)) {
			unlink(shallow);
			rollback_lock_file(&lock);
		} else {
			commit_lock_file(&lock);
		}
	}

	reprepare_packed_git();
	return ref_cpy;
}
Ejemplo n.º 14
0
static void send_request(struct fetch_pack_args *args,
			 int fd, struct strbuf *buf)
{
	if (args->stateless_rpc) {
		send_sideband(fd, -1, buf->buf, buf->len, LARGE_PACKET_MAX);
		packet_flush(fd);
	} else
		write_or_die(fd, buf->buf, buf->len);
}
Ejemplo n.º 15
0
static void deepen_by_rev_list(int ac, const char **av,
			       struct object_array *shallows)
{
	struct commit_list *result;

	result = get_shallow_commits_by_rev_list(ac, av, SHALLOW, NOT_SHALLOW);
	send_shallow(result);
	free_commit_list(result);
	send_unshallow(shallows);
	packet_flush(1);
}
Ejemplo n.º 16
0
static void upload_pack(void)
{
	reset_timeout();
	head_ref(send_ref, NULL);
	for_each_ref(send_ref, NULL);
	packet_flush(1);
	receive_needs();
	if (want_obj.nr) {
		get_common_commits();
		create_pack_file();
	}
}
Ejemplo n.º 17
0
/*
 * Serialize the list of changes to the given file.  The goal of this
 * is to just serialize the key fields in wt_status so that a
 * later command can rebuilt it and do the printing.
 *
 * We DO NOT include the contents of wt_status_state NOR
 * current branch info.  This info easily gets stale and
 * is relatively quick for the status consumer to compute
 * as necessary.
 */
void wt_status_serialize_v1(int fd, struct wt_status *s)
{
	struct string_list_item *iter;
	int k;

	/*
	 * version header must be first line.
	 */
	packet_write_fmt(fd, "version 1\n");

	wt_serialize_v1_header(s, fd);

	if (s->change.nr > 0) {
		packet_write_fmt(fd, "changed %d\n", s->change.nr);
		for (k = 0; k < s->change.nr; k++) {
			iter = &(s->change.items[k]);
			wt_serialize_v1_changed(s, fd, iter);
		}
		packet_flush(fd);
	}

	if (s->untracked.nr > 0) {
		packet_write_fmt(fd, "untracked %d\n", s->untracked.nr);
		for (k = 0; k < s->untracked.nr; k++) {
			iter = &(s->untracked.items[k]);
			wt_serialize_v1_untracked(s, fd, iter);
		}
		packet_flush(fd);
	}

	if (s->ignored.nr > 0) {
		packet_write_fmt(fd, "ignored %d\n", s->ignored.nr);
		for (k = 0; k < s->ignored.nr; k++) {
			iter = &(s->ignored.items[k]);
			wt_serialize_v1_ignored(s, fd, iter);
		}
		packet_flush(fd);
	}
}
Ejemplo n.º 18
0
static void write_head_info(void)
{
	struct sha1_array sa = SHA1_ARRAY_INIT;
	for_each_alternate_ref(collect_one_alternate_ref, &sa);
	sha1_array_for_each_unique(&sa, show_one_alternate_sha1, NULL);
	sha1_array_clear(&sa);
	for_each_ref(show_ref_cb, NULL);
	if (!sent_capabilities)
		show_ref("capabilities^{}", null_sha1);

	/* EOF */
	packet_flush(1);
}
Ejemplo n.º 19
0
static int disconnect_git(struct transport *transport)
{
	struct git_transport_data *data = transport->data;
	if (data->conn) {
		packet_flush(data->fd[1]);
		close(data->fd[0]);
		close(data->fd[1]);
		finish_connect(data->conn);
	}

	free(data);
	return 0;
}
Ejemplo n.º 20
0
/*
 * Write V1 header fields.
 */
static void wt_serialize_v1_header(struct wt_status *s, int fd)
{
	/*
	 * Write select fields from the current index to help
	 * the deserializer recognize a stale data set.
	 */
	packet_write_fmt(fd, "index_mtime %d %d\n",
			 the_index.timestamp.sec,
			 the_index.timestamp.nsec);

	/*
	 * Write data from wt_status to qualify this status report.
	 * That is, if this run specified "-uno", the consumer of
	 * our serialization should know that.
	 */
	packet_write_fmt(fd, "is_initial %d\n", s->is_initial);
	if (s->branch)
		packet_write_fmt(fd, "branch %s\n", s->branch);
	if (s->reference)
		packet_write_fmt(fd, "reference %s\n", s->reference);
	/* pathspec */
	/* verbose */
	/* amend */
	packet_write_fmt(fd, "whence %d\n", s->whence);
	/* nowarn */
	/* use_color */
	/* no_gettext */
	/* display_comment_prefix */
	/* relative_paths */
	/* submodule_summary */
	packet_write_fmt(fd, "show_ignored_mode %d\n", s->show_ignored_mode);
	packet_write_fmt(fd, "show_untracked_files %d\n", s->show_untracked_files);
	if (s->ignore_submodule_arg)
		packet_write_fmt(fd, "ignore_submodule_arg %s\n", s->ignore_submodule_arg);
	/* color_palette */
	/* colopts */
	/* null_termination */
	/* commit_template */
	/* show_branch */
	/* show_stash */
	packet_write_fmt(fd, "hints %d\n", s->hints);
	packet_write_fmt(fd, "detect_rename %d\n", s->detect_rename);
	packet_write_fmt(fd, "rename_score %d\n", s->rename_score);
	packet_write_fmt(fd, "rename_limit %d\n", s->rename_limit);
	/* status_format */
	packet_write_fmt(fd, "sha1_commit %s\n", sha1_to_hex(s->sha1_commit));
	packet_write_fmt(fd, "commitable %d\n", s->commitable);
	packet_write_fmt(fd, "workdir_dirty %d\n", s->workdir_dirty);
	/* prefix */
	packet_flush(fd);
}
Ejemplo n.º 21
0
static int run_remote_archiver(int argc, const char **argv,
			       const char *remote, const char *exec,
			       const char *name_hint)
{
	char buf[LARGE_PACKET_MAX];
	int fd[2], i, len, rv;
	struct transport *transport;
	struct remote *_remote;

	_remote = remote_get(remote);
	if (!_remote->url[0])
		die(_("git archive: Remote with no URL"));
	transport = transport_get(_remote, _remote->url[0]);
	transport_connect(transport, "git-upload-archive", exec, fd);

	/*
	 * Inject a fake --format field at the beginning of the
	 * arguments, with the format inferred from our output
	 * filename. This way explicit --format options can override
	 * it.
	 */
	if (name_hint) {
		const char *format = archive_format_from_filename(name_hint);
		if (format)
			packet_write(fd[1], "argument --format=%s\n", format);
	}
	for (i = 1; i < argc; i++)
		packet_write(fd[1], "argument %s\n", argv[i]);
	packet_flush(fd[1]);

	len = packet_read_line(fd[0], buf, sizeof(buf));
	if (!len)
		die(_("git archive: expected ACK/NAK, got EOF"));
	if (buf[len-1] == '\n')
		buf[--len] = 0;
	if (strcmp(buf, "ACK")) {
		if (len > 5 && !prefixcmp(buf, "NACK "))
			die(_("git archive: NACK %s"), buf + 5);
		die(_("git archive: protocol error"));
	}

	len = packet_read_line(fd[0], buf, sizeof(buf));
	if (len)
		die(_("git archive: expected a flush"));

	/* Now, start reading from fd[0] and spit it out to stdout */
	rv = recv_sideband("archive", fd[0], 1);
	rv |= transport_disconnect(transport);

	return !!rv;
}
Ejemplo n.º 22
0
struct ref *fetch_pack(struct fetch_pack_args *args,
		       int fd[], struct child_process *conn,
		       const struct ref *ref,
		       const char *dest,
		       struct ref **sought, int nr_sought,
		       struct oid_array *shallow,
		       char **pack_lockfile,
		       enum protocol_version version)
{
	struct ref *ref_cpy;
	struct shallow_info si;

	fetch_pack_setup();
	if (nr_sought)
		nr_sought = remove_duplicates_in_refs(sought, nr_sought);

	if (!ref) {
		packet_flush(fd[1]);
		die(_("no matching remote head"));
	}
	prepare_shallow_info(&si, shallow);
	if (version == protocol_v2)
		ref_cpy = do_fetch_pack_v2(args, fd, ref, sought, nr_sought,
					   pack_lockfile);
	else
		ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
					&si, pack_lockfile);
	reprepare_packed_git(the_repository);

	if (!args->cloning && args->deepen) {
		struct check_connected_options opt = CHECK_CONNECTED_INIT;
		struct ref *iterator = ref_cpy;
		opt.shallow_file = alternate_shallow_file;
		if (args->deepen)
			opt.is_deepening_fetch = 1;
		if (check_connected(iterate_ref_map, &iterator, &opt)) {
			error(_("remote did not send all necessary objects"));
			free_refs(ref_cpy);
			ref_cpy = NULL;
			rollback_lock_file(&shallow_lock);
			goto cleanup;
		}
		args->connectivity_checked = 1;
	}

	update_shallow(args, sought, nr_sought, &si);
cleanup:
	clear_shallow_info(&si);
	return ref_cpy;
}
Ejemplo n.º 23
0
/*
 * This function places the outgoing packet buffer into an outgoing
 * socket buffer
 */
static int packet_write(SSH_SESSION *session) {
  int rc = SSH_ERROR;

  enter_function();

  ssh_socket_write(session->socket,
      buffer_get(session->out_buffer),
      buffer_get_len(session->out_buffer));

  rc = packet_flush(session, 0);

  leave_function();
  return rc;
}
Ejemplo n.º 24
0
static void report(const char *unpack_status)
{
	struct command *cmd;
	packet_write(1, "unpack %s\n",
		     unpack_status ? unpack_status : "ok");
	for (cmd = commands; cmd; cmd = cmd->next) {
		if (!cmd->error_string)
			packet_write(1, "ok %s\n",
				     cmd->ref_name);
		else
			packet_write(1, "ng %s %s\n",
				     cmd->ref_name, cmd->error_string);
	}
	packet_flush(1);
}
Ejemplo n.º 25
0
static void upload_pack(void)
{
	if (advertise_refs || !stateless_rpc) {
		reset_timeout();
		head_ref(send_ref, NULL);
		for_each_ref(send_ref, NULL);
		packet_flush(1);
	} else {
		head_ref(mark_our_ref, NULL);
		for_each_ref(mark_our_ref, NULL);
	}
	if (advertise_refs)
		return;

	receive_needs();
	if (want_obj.nr) {
		get_common_commits();
		create_pack_file();
	}
}
Ejemplo n.º 26
0
static int run_remote_archiver(int argc, const char **argv,
			       const char *remote, const char *exec)
{
	char buf[LARGE_PACKET_MAX];
	int fd[2], i, len, rv;
	struct transport *transport;
	struct remote *_remote;

	_remote = remote_get(remote);
	if (!_remote->url[0])
		die(_("git archive: Remote with no URL"));
	transport = transport_get(_remote, _remote->url[0]);
	transport_connect(transport, "git-upload-archive", exec, fd);

	for (i = 1; i < argc; i++)
		packet_write(fd[1], "argument %s\n", argv[i]);
	packet_flush(fd[1]);

	len = packet_read_line(fd[0], buf, sizeof(buf));
	if (!len)
		die(_("git archive: expected ACK/NAK, got EOF"));
	if (buf[len-1] == '\n')
		buf[--len] = 0;
	if (strcmp(buf, "ACK")) {
		if (len > 5 && !prefixcmp(buf, "NACK "))
			die(_("git archive: NACK %s"), buf + 5);
		die(_("git archive: protocol error"));
	}

	len = packet_read_line(fd[0], buf, sizeof(buf));
	if (len)
		die(_("git archive: expected a flush"));

	/* Now, start reading from fd[0] and spit it out to stdout */
	rv = recv_sideband("archive", fd[0], 1);
	rv |= transport_disconnect(transport);

	return !!rv;
}
Ejemplo n.º 27
0
static int run_remote_archiver(int argc, const char **argv,
			       const char *remote, const char *exec)
{
	char *url, buf[LARGE_PACKET_MAX];
	int fd[2], i, len, rv;
	struct child_process *conn;

	url = xstrdup(remote);
	conn = git_connect(fd, url, exec, 0);

	for (i = 1; i < argc; i++)
		packet_write(fd[1], "argument %s\n", argv[i]);
	packet_flush(fd[1]);

	len = packet_read_line(fd[0], buf, sizeof(buf));
	if (!len)
		die("git archive: expected ACK/NAK, got EOF");
	if (buf[len-1] == '\n')
		buf[--len] = 0;
	if (strcmp(buf, "ACK")) {
		if (len > 5 && !prefixcmp(buf, "NACK "))
			die("git archive: NACK %s", buf + 5);
		die("git archive: protocol error");
	}

	len = packet_read_line(fd[0], buf, sizeof(buf));
	if (len)
		die("git archive: expected a flush");

	/* Now, start reading from fd[0] and spit it out to stdout */
	rv = recv_sideband("archive", fd[0], 1);
	close(fd[0]);
	close(fd[1]);
	rv |= finish_connect(conn);

	return !!rv;
}
Ejemplo n.º 28
0
static struct ref *do_fetch_pack(struct fetch_pack_args *args,
				 int fd[2],
				 const struct ref *orig_ref,
				 struct ref **sought, int nr_sought,
				 struct shallow_info *si,
				 char **pack_lockfile)
{
	struct ref *ref = copy_ref_list(orig_ref);
	unsigned char sha1[20];
	const char *agent_feature;
	int agent_len;

	sort_ref_list(&ref, ref_compare_name);
	qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name);

	if (is_repository_shallow() && !server_supports("shallow"))
		die("Server does not support shallow clients");
	if (server_supports("multi_ack_detailed")) {
		if (args->verbose)
			fprintf(stderr, "Server supports multi_ack_detailed\n");
		multi_ack = 2;
		if (server_supports("no-done")) {
			if (args->verbose)
				fprintf(stderr, "Server supports no-done\n");
			if (args->stateless_rpc)
				no_done = 1;
		}
	}
	else if (server_supports("multi_ack")) {
		if (args->verbose)
			fprintf(stderr, "Server supports multi_ack\n");
		multi_ack = 1;
	}
	if (server_supports("side-band-64k")) {
		if (args->verbose)
			fprintf(stderr, "Server supports side-band-64k\n");
		use_sideband = 2;
	}
	else if (server_supports("side-band")) {
		if (args->verbose)
			fprintf(stderr, "Server supports side-band\n");
		use_sideband = 1;
	}
	if (server_supports("allow-tip-sha1-in-want")) {
		if (args->verbose)
			fprintf(stderr, "Server supports allow-tip-sha1-in-want\n");
		allow_tip_sha1_in_want = 1;
	}
	if (!server_supports("thin-pack"))
		args->use_thin_pack = 0;
	if (!server_supports("no-progress"))
		args->no_progress = 0;
	if (!server_supports("include-tag"))
		args->include_tag = 0;
	if (server_supports("ofs-delta")) {
		if (args->verbose)
			fprintf(stderr, "Server supports ofs-delta\n");
	} else
		prefer_ofs_delta = 0;

	if ((agent_feature = server_feature_value("agent", &agent_len))) {
		agent_supported = 1;
		if (args->verbose && agent_len)
			fprintf(stderr, "Server version is %.*s\n",
				agent_len, agent_feature);
	}

	if (everything_local(args, &ref, sought, nr_sought)) {
		packet_flush(fd[1]);
		goto all_done;
	}
	if (find_common(args, fd, sha1, ref) < 0)
		if (!args->keep_pack)
			/* When cloning, it is not unusual to have
			 * no common commit.
			 */
			warning("no common commits");

	if (args->stateless_rpc)
		packet_flush(fd[1]);
	if (args->depth > 0)
		setup_alternate_shallow(&shallow_lock, &alternate_shallow_file,
					NULL);
	else if (si->nr_ours || si->nr_theirs)
		alternate_shallow_file = setup_temporary_shallow(si->shallow);
	else
		alternate_shallow_file = NULL;
	if (get_pack(args, fd, pack_lockfile))
		die("git fetch-pack: fetch failed.");

 all_done:
	return ref;
}
Ejemplo n.º 29
0
static int find_common(struct fetch_pack_args *args,
		       int fd[2], unsigned char *result_sha1,
		       struct ref *refs)
{
	int fetching;
	int count = 0, flushes = 0, flush_at = INITIAL_FLUSH, retval;
	const unsigned char *sha1;
	unsigned in_vain = 0;
	int got_continue = 0;
	int got_ready = 0;
	struct strbuf req_buf = STRBUF_INIT;
	size_t state_len = 0;

	if (args->stateless_rpc && multi_ack == 1)
		die("--stateless-rpc requires multi_ack_detailed");
	if (marked)
		for_each_ref(clear_marks, NULL);
	marked = 1;

	for_each_ref(rev_list_insert_ref, NULL);
	for_each_alternate_ref(insert_one_alternate_ref, NULL);

	fetching = 0;
	for ( ; refs ; refs = refs->next) {
		unsigned char *remote = refs->old_sha1;
		const char *remote_hex;
		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.
		 */
		if (((o = lookup_object(remote)) != NULL) &&
				(o->flags & COMPLETE)) {
			continue;
		}

		remote_hex = sha1_to_hex(remote);
		if (!fetching) {
			struct strbuf c = STRBUF_INIT;
			if (multi_ack == 2)     strbuf_addstr(&c, " multi_ack_detailed");
			if (multi_ack == 1)     strbuf_addstr(&c, " multi_ack");
			if (no_done)            strbuf_addstr(&c, " no-done");
			if (use_sideband == 2)  strbuf_addstr(&c, " side-band-64k");
			if (use_sideband == 1)  strbuf_addstr(&c, " side-band");
			if (args->use_thin_pack) strbuf_addstr(&c, " thin-pack");
			if (args->no_progress)   strbuf_addstr(&c, " no-progress");
			if (args->include_tag)   strbuf_addstr(&c, " include-tag");
			if (prefer_ofs_delta)   strbuf_addstr(&c, " ofs-delta");
			if (agent_supported)    strbuf_addf(&c, " agent=%s",
							    git_user_agent_sanitized());
			packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
			strbuf_release(&c);
		} else
			packet_buf_write(&req_buf, "want %s\n", remote_hex);
		fetching++;
	}

	if (!fetching) {
		strbuf_release(&req_buf);
		packet_flush(fd[1]);
		return 1;
	}

	if (is_repository_shallow())
		write_shallow_commits(&req_buf, 1, NULL);
	if (args->depth > 0)
		packet_buf_write(&req_buf, "deepen %d", args->depth);
	packet_buf_flush(&req_buf);
	state_len = req_buf.len;

	if (args->depth > 0) {
		char *line;
		const char *arg;
		unsigned char sha1[20];

		send_request(args, fd[1], &req_buf);
		while ((line = packet_read_line(fd[0], NULL))) {
			if (skip_prefix(line, "shallow ", &arg)) {
				if (get_sha1_hex(arg, sha1))
					die("invalid shallow line: %s", line);
				register_shallow(sha1);
				continue;
			}
			if (skip_prefix(line, "unshallow ", &arg)) {
				if (get_sha1_hex(arg, sha1))
					die("invalid unshallow line: %s", line);
				if (!lookup_object(sha1))
					die("object not found: %s", line);
				/* make sure that it is parsed as shallow */
				if (!parse_object(sha1))
					die("error in object: %s", line);
				if (unregister_shallow(sha1))
					die("no shallow found: %s", line);
				continue;
			}
			die("expected shallow/unshallow, got %s", line);
		}
	} else if (!args->stateless_rpc)
		send_request(args, fd[1], &req_buf);

	if (!args->stateless_rpc) {
		/* If we aren't using the stateless-rpc interface
		 * we don't need to retain the headers.
		 */
		strbuf_setlen(&req_buf, 0);
		state_len = 0;
	}

	flushes = 0;
	retval = -1;
	while ((sha1 = get_rev())) {
		packet_buf_write(&req_buf, "have %s\n", sha1_to_hex(sha1));
		if (args->verbose)
			fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
		in_vain++;
		if (flush_at <= ++count) {
			int ack;

			packet_buf_flush(&req_buf);
			send_request(args, fd[1], &req_buf);
			strbuf_setlen(&req_buf, state_len);
			flushes++;
			flush_at = next_flush(args, count);

			/*
			 * We keep one window "ahead" of the other side, and
			 * will wait for an ACK only on the next one
			 */
			if (!args->stateless_rpc && count == INITIAL_FLUSH)
				continue;

			consume_shallow_list(args, fd[0]);
			do {
				ack = get_ack(fd[0], result_sha1);
				if (args->verbose && ack)
					fprintf(stderr, "got ack %d %s\n", ack,
							sha1_to_hex(result_sha1));
				switch (ack) {
				case ACK:
					flushes = 0;
					multi_ack = 0;
					retval = 0;
					goto done;
				case ACK_common:
				case ACK_ready:
				case ACK_continue: {
					struct commit *commit =
						lookup_commit(result_sha1);
					if (!commit)
						die("invalid commit %s", sha1_to_hex(result_sha1));
					if (args->stateless_rpc
					 && ack == ACK_common
					 && !(commit->object.flags & COMMON)) {
						/* We need to replay the have for this object
						 * on the next RPC request so the peer knows
						 * it is in common with us.
						 */
						const char *hex = sha1_to_hex(result_sha1);
						packet_buf_write(&req_buf, "have %s\n", hex);
						state_len = req_buf.len;
					}
					mark_common(commit, 0, 1);
					retval = 0;
					in_vain = 0;
					got_continue = 1;
					if (ack == ACK_ready) {
						clear_prio_queue(&rev_list);
						got_ready = 1;
					}
					break;
					}
				}
			} while (ack);
			flushes--;
			if (got_continue && MAX_IN_VAIN < in_vain) {
				if (args->verbose)
					fprintf(stderr, "giving up\n");
				break; /* give up */
			}
		}
	}
done:
	if (!got_ready || !no_done) {
		packet_buf_write(&req_buf, "done\n");
		send_request(args, fd[1], &req_buf);
	}
	if (args->verbose)
		fprintf(stderr, "done\n");
	if (retval != 0) {
		multi_ack = 0;
		flushes++;
	}
	strbuf_release(&req_buf);

	if (!got_ready || !no_done)
		consume_shallow_list(args, fd[0]);
	while (flushes || multi_ack) {
		int ack = get_ack(fd[0], result_sha1);
		if (ack) {
			if (args->verbose)
				fprintf(stderr, "got ack (%d) %s\n", ack,
					sha1_to_hex(result_sha1));
			if (ack == ACK)
				return 0;
			multi_ack = 1;
			continue;
		}
		flushes--;
	}
	/* it is no error to fetch into a completely empty repo */
	return count ? retval : 0;
}
Ejemplo n.º 30
0
int send_pack(struct send_pack_args *args,
	      int fd[], struct child_process *conn,
	      struct ref *remote_refs,
	      struct extra_have_objects *extra_have)
{
	int in = fd[0];
	int out = fd[1];
	struct ref *ref;
	int new_refs;
	int ask_for_status_report = 0;
	int allow_deleting_refs = 0;
	int expect_status_report = 0;
	int ret;

	/* Does the other end support the reporting? */
	if (server_supports("report-status"))
		ask_for_status_report = 1;
	if (server_supports("delete-refs"))
		allow_deleting_refs = 1;
	if (server_supports("ofs-delta"))
		args->use_ofs_delta = 1;

	if (!remote_refs) {
		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
			"Perhaps you should specify a branch such as 'master'.\n");
		return 0;
	}

	/*
	 * Finally, tell the other end!
	 */
	new_refs = 0;
	for (ref = remote_refs; ref; ref = ref->next) {

		if (ref->peer_ref)
			hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
		else if (!args->send_mirror)
			continue;

		ref->deletion = is_null_sha1(ref->new_sha1);
		if (ref->deletion && !allow_deleting_refs) {
			ref->status = REF_STATUS_REJECT_NODELETE;
			continue;
		}
		if (!ref->deletion &&
		    !hashcmp(ref->old_sha1, ref->new_sha1)) {
			ref->status = REF_STATUS_UPTODATE;
			continue;
		}

		/* This part determines what can overwrite what.
		 * The rules are:
		 *
		 * (0) you can always use --force or +A:B notation to
		 *     selectively force individual ref pairs.
		 *
		 * (1) if the old thing does not exist, it is OK.
		 *
		 * (2) if you do not have the old thing, you are not allowed
		 *     to overwrite it; you would not know what you are losing
		 *     otherwise.
		 *
		 * (3) if both new and old are commit-ish, and new is a
		 *     descendant of old, it is OK.
		 *
		 * (4) regardless of all of the above, removing :B is
		 *     always allowed.
		 */

		ref->nonfastforward =
		    !ref->deletion &&
		    !is_null_sha1(ref->old_sha1) &&
		    (!has_sha1_file(ref->old_sha1)
		      || !ref_newer(ref->new_sha1, ref->old_sha1));

		if (ref->nonfastforward && !ref->force && !args->force_update) {
			ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
			continue;
		}

		if (!ref->deletion)
			new_refs++;

		if (!args->dry_run) {
			char *old_hex = sha1_to_hex(ref->old_sha1);
			char *new_hex = sha1_to_hex(ref->new_sha1);

			if (ask_for_status_report) {
				packet_write(out, "%s %s %s%c%s",
					old_hex, new_hex, ref->name, 0,
					"report-status");
				ask_for_status_report = 0;
				expect_status_report = 1;
			}
			else
				packet_write(out, "%s %s %s",
					old_hex, new_hex, ref->name);
		}
		ref->status = expect_status_report ?
			REF_STATUS_EXPECTING_REPORT :
			REF_STATUS_OK;
	}

	packet_flush(out);
	if (new_refs && !args->dry_run) {
		if (pack_objects(out, remote_refs, extra_have, args) < 0) {
			for (ref = remote_refs; ref; ref = ref->next)
				ref->status = REF_STATUS_NONE;
			return -1;
		}
	}

	if (expect_status_report)
		ret = receive_status(in, remote_refs);
	else
		ret = 0;

	if (ret < 0)
		return ret;
	for (ref = remote_refs; 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;
}