Use packet_reader instead of packet_read_line
By using and sharing a packet_reader while handling a Git pack protocol request, the same reader option is used throughout the code. This makes it easy to set a reader option to the request parsing code. Signed-off-by: Masaya Suzuki <masayasuzuki@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									b21ebb671b
								
							
						
					
					
						commit
						01f9ec64c8
					
				|  | @ -27,10 +27,10 @@ static int run_remote_archiver(int argc, const char **argv, | ||||||
| 			       const char *remote, const char *exec, | 			       const char *remote, const char *exec, | ||||||
| 			       const char *name_hint) | 			       const char *name_hint) | ||||||
| { | { | ||||||
| 	char *buf; |  | ||||||
| 	int fd[2], i, rv; | 	int fd[2], i, rv; | ||||||
| 	struct transport *transport; | 	struct transport *transport; | ||||||
| 	struct remote *_remote; | 	struct remote *_remote; | ||||||
|  | 	struct packet_reader reader; | ||||||
|  |  | ||||||
| 	_remote = remote_get(remote); | 	_remote = remote_get(remote); | ||||||
| 	if (!_remote->url[0]) | 	if (!_remote->url[0]) | ||||||
|  | @ -53,18 +53,19 @@ static int run_remote_archiver(int argc, const char **argv, | ||||||
| 		packet_write_fmt(fd[1], "argument %s\n", argv[i]); | 		packet_write_fmt(fd[1], "argument %s\n", argv[i]); | ||||||
| 	packet_flush(fd[1]); | 	packet_flush(fd[1]); | ||||||
|  |  | ||||||
| 	buf = packet_read_line(fd[0], NULL); | 	packet_reader_init(&reader, fd[0], NULL, 0, PACKET_READ_CHOMP_NEWLINE); | ||||||
| 	if (!buf) |  | ||||||
|  | 	if (packet_reader_read(&reader) != PACKET_READ_NORMAL) | ||||||
| 		die(_("git archive: expected ACK/NAK, got a flush packet")); | 		die(_("git archive: expected ACK/NAK, got a flush packet")); | ||||||
| 	if (strcmp(buf, "ACK")) { | 	if (strcmp(reader.line, "ACK")) { | ||||||
| 		if (starts_with(buf, "NACK ")) | 		if (starts_with(reader.line, "NACK ")) | ||||||
| 			die(_("git archive: NACK %s"), buf + 5); | 			die(_("git archive: NACK %s"), reader.line + 5); | ||||||
| 		if (starts_with(buf, "ERR ")) | 		if (starts_with(reader.line, "ERR ")) | ||||||
| 			die(_("remote error: %s"), buf + 4); | 			die(_("remote error: %s"), reader.line + 4); | ||||||
| 		die(_("git archive: protocol error")); | 		die(_("git archive: protocol error")); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (packet_read_line(fd[0], NULL)) | 	if (packet_reader_read(&reader) != PACKET_READ_FLUSH) | ||||||
| 		die(_("git archive: expected a flush")); | 		die(_("git archive: expected a flush")); | ||||||
|  |  | ||||||
| 	/* Now, start reading from fd[0] and spit it out to stdout */ | 	/* Now, start reading from fd[0] and spit it out to stdout */ | ||||||
|  |  | ||||||
|  | @ -1569,30 +1569,29 @@ static void queue_commands_from_cert(struct command **tail, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static struct command *read_head_info(struct oid_array *shallow) | static struct command *read_head_info(struct packet_reader *reader, | ||||||
|  | 				      struct oid_array *shallow) | ||||||
| { | { | ||||||
| 	struct command *commands = NULL; | 	struct command *commands = NULL; | ||||||
| 	struct command **p = &commands; | 	struct command **p = &commands; | ||||||
| 	for (;;) { | 	for (;;) { | ||||||
| 		char *line; | 		int linelen; | ||||||
| 		int len, linelen; |  | ||||||
|  |  | ||||||
| 		line = packet_read_line(0, &len); | 		if (packet_reader_read(reader) != PACKET_READ_NORMAL) | ||||||
| 		if (!line) |  | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		if (len > 8 && starts_with(line, "shallow ")) { | 		if (reader->pktlen > 8 && starts_with(reader->line, "shallow ")) { | ||||||
| 			struct object_id oid; | 			struct object_id oid; | ||||||
| 			if (get_oid_hex(line + 8, &oid)) | 			if (get_oid_hex(reader->line + 8, &oid)) | ||||||
| 				die("protocol error: expected shallow sha, got '%s'", | 				die("protocol error: expected shallow sha, got '%s'", | ||||||
| 				    line + 8); | 				    reader->line + 8); | ||||||
| 			oid_array_append(shallow, &oid); | 			oid_array_append(shallow, &oid); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		linelen = strlen(line); | 		linelen = strlen(reader->line); | ||||||
| 		if (linelen < len) { | 		if (linelen < reader->pktlen) { | ||||||
| 			const char *feature_list = line + linelen + 1; | 			const char *feature_list = reader->line + linelen + 1; | ||||||
| 			if (parse_feature_request(feature_list, "report-status")) | 			if (parse_feature_request(feature_list, "report-status")) | ||||||
| 				report_status = 1; | 				report_status = 1; | ||||||
| 			if (parse_feature_request(feature_list, "side-band-64k")) | 			if (parse_feature_request(feature_list, "side-band-64k")) | ||||||
|  | @ -1607,28 +1606,32 @@ static struct command *read_head_info(struct oid_array *shallow) | ||||||
| 				use_push_options = 1; | 				use_push_options = 1; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (!strcmp(line, "push-cert")) { | 		if (!strcmp(reader->line, "push-cert")) { | ||||||
| 			int true_flush = 0; | 			int true_flush = 0; | ||||||
| 			char certbuf[1024]; | 			int saved_options = reader->options; | ||||||
|  | 			reader->options &= ~PACKET_READ_CHOMP_NEWLINE; | ||||||
|  |  | ||||||
| 			for (;;) { | 			for (;;) { | ||||||
| 				len = packet_read(0, NULL, NULL, | 				packet_reader_read(reader); | ||||||
| 						  certbuf, sizeof(certbuf), 0); | 				if (reader->status == PACKET_READ_FLUSH) { | ||||||
| 				if (!len) { |  | ||||||
| 					true_flush = 1; | 					true_flush = 1; | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
| 				if (!strcmp(certbuf, "push-cert-end\n")) | 				if (reader->status != PACKET_READ_NORMAL) { | ||||||
|  | 					die("protocol error: got an unexpected packet"); | ||||||
|  | 				} | ||||||
|  | 				if (!strcmp(reader->line, "push-cert-end\n")) | ||||||
| 					break; /* end of cert */ | 					break; /* end of cert */ | ||||||
| 				strbuf_addstr(&push_cert, certbuf); | 				strbuf_addstr(&push_cert, reader->line); | ||||||
| 			} | 			} | ||||||
|  | 			reader->options = saved_options; | ||||||
|  |  | ||||||
| 			if (true_flush) | 			if (true_flush) | ||||||
| 				break; | 				break; | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		p = queue_command(p, line, linelen); | 		p = queue_command(p, reader->line, linelen); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (push_cert.len) | 	if (push_cert.len) | ||||||
|  | @ -1637,18 +1640,14 @@ static struct command *read_head_info(struct oid_array *shallow) | ||||||
| 	return commands; | 	return commands; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void read_push_options(struct string_list *options) | static void read_push_options(struct packet_reader *reader, | ||||||
|  | 			      struct string_list *options) | ||||||
| { | { | ||||||
| 	while (1) { | 	while (1) { | ||||||
| 		char *line; | 		if (packet_reader_read(reader) != PACKET_READ_NORMAL) | ||||||
| 		int len; |  | ||||||
|  |  | ||||||
| 		line = packet_read_line(0, &len); |  | ||||||
|  |  | ||||||
| 		if (!line) |  | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		string_list_append(options, line); | 		string_list_append(options, reader->line); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1924,6 +1923,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) | ||||||
| 	struct oid_array shallow = OID_ARRAY_INIT; | 	struct oid_array shallow = OID_ARRAY_INIT; | ||||||
| 	struct oid_array ref = OID_ARRAY_INIT; | 	struct oid_array ref = OID_ARRAY_INIT; | ||||||
| 	struct shallow_info si; | 	struct shallow_info si; | ||||||
|  | 	struct packet_reader reader; | ||||||
|  |  | ||||||
| 	struct option options[] = { | 	struct option options[] = { | ||||||
| 		OPT__QUIET(&quiet, N_("quiet")), | 		OPT__QUIET(&quiet, N_("quiet")), | ||||||
|  | @ -1986,12 +1986,14 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) | ||||||
| 	if (advertise_refs) | 	if (advertise_refs) | ||||||
| 		return 0; | 		return 0; | ||||||
|  |  | ||||||
| 	if ((commands = read_head_info(&shallow)) != NULL) { | 	packet_reader_init(&reader, 0, NULL, 0, PACKET_READ_CHOMP_NEWLINE); | ||||||
|  |  | ||||||
|  | 	if ((commands = read_head_info(&reader, &shallow)) != NULL) { | ||||||
| 		const char *unpack_status = NULL; | 		const char *unpack_status = NULL; | ||||||
| 		struct string_list push_options = STRING_LIST_INIT_DUP; | 		struct string_list push_options = STRING_LIST_INIT_DUP; | ||||||
|  |  | ||||||
| 		if (use_push_options) | 		if (use_push_options) | ||||||
| 			read_push_options(&push_options); | 			read_push_options(&reader, &push_options); | ||||||
| 		if (!check_cert_push_options(&push_options)) { | 		if (!check_cert_push_options(&push_options)) { | ||||||
| 			struct command *cmd; | 			struct command *cmd; | ||||||
| 			for (cmd = commands; cmd; cmd = cmd->next) | 			for (cmd = commands; cmd; cmd = cmd->next) | ||||||
|  |  | ||||||
							
								
								
									
										61
									
								
								fetch-pack.c
								
								
								
								
							
							
						
						
									
										61
									
								
								fetch-pack.c
								
								
								
								
							|  | @ -135,38 +135,42 @@ enum ack_type { | ||||||
| 	ACK_ready | 	ACK_ready | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static void consume_shallow_list(struct fetch_pack_args *args, int fd) | static void consume_shallow_list(struct fetch_pack_args *args, | ||||||
|  | 				 struct packet_reader *reader) | ||||||
| { | { | ||||||
| 	if (args->stateless_rpc && args->deepen) { | 	if (args->stateless_rpc && args->deepen) { | ||||||
| 		/* If we sent a depth we will get back "duplicate" | 		/* If we sent a depth we will get back "duplicate" | ||||||
| 		 * shallow and unshallow commands every time there | 		 * shallow and unshallow commands every time there | ||||||
| 		 * is a block of have lines exchanged. | 		 * is a block of have lines exchanged. | ||||||
| 		 */ | 		 */ | ||||||
| 		char *line; | 		while (packet_reader_read(reader) == PACKET_READ_NORMAL) { | ||||||
| 		while ((line = packet_read_line(fd, NULL))) { | 			if (starts_with(reader->line, "shallow ")) | ||||||
| 			if (starts_with(line, "shallow ")) |  | ||||||
| 				continue; | 				continue; | ||||||
| 			if (starts_with(line, "unshallow ")) | 			if (starts_with(reader->line, "unshallow ")) | ||||||
| 				continue; | 				continue; | ||||||
| 			die(_("git fetch-pack: expected shallow list")); | 			die(_("git fetch-pack: expected shallow list")); | ||||||
| 		} | 		} | ||||||
|  | 		if (reader->status != PACKET_READ_FLUSH) | ||||||
|  | 			die(_("git fetch-pack: expected a flush packet after shallow list")); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static enum ack_type get_ack(int fd, struct object_id *result_oid) | static enum ack_type get_ack(struct packet_reader *reader, | ||||||
|  | 			     struct object_id *result_oid) | ||||||
| { | { | ||||||
| 	int len; | 	int len; | ||||||
| 	char *line = packet_read_line(fd, &len); |  | ||||||
| 	const char *arg; | 	const char *arg; | ||||||
|  |  | ||||||
| 	if (!line) | 	if (packet_reader_read(reader) != PACKET_READ_NORMAL) | ||||||
| 		die(_("git fetch-pack: expected ACK/NAK, got a flush packet")); | 		die(_("git fetch-pack: expected ACK/NAK, got a flush packet")); | ||||||
| 	if (!strcmp(line, "NAK")) | 	len = reader->pktlen; | ||||||
|  |  | ||||||
|  | 	if (!strcmp(reader->line, "NAK")) | ||||||
| 		return NAK; | 		return NAK; | ||||||
| 	if (skip_prefix(line, "ACK ", &arg)) { | 	if (skip_prefix(reader->line, "ACK ", &arg)) { | ||||||
| 		if (!get_oid_hex(arg, result_oid)) { | 		if (!get_oid_hex(arg, result_oid)) { | ||||||
| 			arg += 40; | 			arg += 40; | ||||||
| 			len -= arg - line; | 			len -= arg - reader->line; | ||||||
| 			if (len < 1) | 			if (len < 1) | ||||||
| 				return ACK; | 				return ACK; | ||||||
| 			if (strstr(arg, "continue")) | 			if (strstr(arg, "continue")) | ||||||
|  | @ -178,9 +182,9 @@ static enum ack_type get_ack(int fd, struct object_id *result_oid) | ||||||
| 			return ACK; | 			return ACK; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (skip_prefix(line, "ERR ", &arg)) | 	if (skip_prefix(reader->line, "ERR ", &arg)) | ||||||
| 		die(_("remote error: %s"), arg); | 		die(_("remote error: %s"), arg); | ||||||
| 	die(_("git fetch-pack: expected ACK/NAK, got '%s'"), line); | 	die(_("git fetch-pack: expected ACK/NAK, got '%s'"), reader->line); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void send_request(struct fetch_pack_args *args, | static void send_request(struct fetch_pack_args *args, | ||||||
|  | @ -248,10 +252,14 @@ static int find_common(struct fetch_negotiator *negotiator, | ||||||
| 	int got_ready = 0; | 	int got_ready = 0; | ||||||
| 	struct strbuf req_buf = STRBUF_INIT; | 	struct strbuf req_buf = STRBUF_INIT; | ||||||
| 	size_t state_len = 0; | 	size_t state_len = 0; | ||||||
|  | 	struct packet_reader reader; | ||||||
|  |  | ||||||
| 	if (args->stateless_rpc && multi_ack == 1) | 	if (args->stateless_rpc && multi_ack == 1) | ||||||
| 		die(_("--stateless-rpc requires multi_ack_detailed")); | 		die(_("--stateless-rpc requires multi_ack_detailed")); | ||||||
|  |  | ||||||
|  | 	packet_reader_init(&reader, fd[0], NULL, 0, | ||||||
|  | 			   PACKET_READ_CHOMP_NEWLINE); | ||||||
|  |  | ||||||
| 	if (!args->no_dependents) { | 	if (!args->no_dependents) { | ||||||
| 		mark_tips(negotiator, args->negotiation_tips); | 		mark_tips(negotiator, args->negotiation_tips); | ||||||
| 		for_each_cached_alternate(negotiator, insert_one_alternate_object); | 		for_each_cached_alternate(negotiator, insert_one_alternate_object); | ||||||
|  | @ -336,31 +344,30 @@ static int find_common(struct fetch_negotiator *negotiator, | ||||||
| 	state_len = req_buf.len; | 	state_len = req_buf.len; | ||||||
|  |  | ||||||
| 	if (args->deepen) { | 	if (args->deepen) { | ||||||
| 		char *line; |  | ||||||
| 		const char *arg; | 		const char *arg; | ||||||
| 		struct object_id oid; | 		struct object_id oid; | ||||||
|  |  | ||||||
| 		send_request(args, fd[1], &req_buf); | 		send_request(args, fd[1], &req_buf); | ||||||
| 		while ((line = packet_read_line(fd[0], NULL))) { | 		while (packet_reader_read(&reader) == PACKET_READ_NORMAL) { | ||||||
| 			if (skip_prefix(line, "shallow ", &arg)) { | 			if (skip_prefix(reader.line, "shallow ", &arg)) { | ||||||
| 				if (get_oid_hex(arg, &oid)) | 				if (get_oid_hex(arg, &oid)) | ||||||
| 					die(_("invalid shallow line: %s"), line); | 					die(_("invalid shallow line: %s"), reader.line); | ||||||
| 				register_shallow(the_repository, &oid); | 				register_shallow(the_repository, &oid); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (skip_prefix(line, "unshallow ", &arg)) { | 			if (skip_prefix(reader.line, "unshallow ", &arg)) { | ||||||
| 				if (get_oid_hex(arg, &oid)) | 				if (get_oid_hex(arg, &oid)) | ||||||
| 					die(_("invalid unshallow line: %s"), line); | 					die(_("invalid unshallow line: %s"), reader.line); | ||||||
| 				if (!lookup_object(the_repository, oid.hash)) | 				if (!lookup_object(the_repository, oid.hash)) | ||||||
| 					die(_("object not found: %s"), line); | 					die(_("object not found: %s"), reader.line); | ||||||
| 				/* make sure that it is parsed as shallow */ | 				/* make sure that it is parsed as shallow */ | ||||||
| 				if (!parse_object(the_repository, &oid)) | 				if (!parse_object(the_repository, &oid)) | ||||||
| 					die(_("error in object: %s"), line); | 					die(_("error in object: %s"), reader.line); | ||||||
| 				if (unregister_shallow(&oid)) | 				if (unregister_shallow(&oid)) | ||||||
| 					die(_("no shallow found: %s"), line); | 					die(_("no shallow found: %s"), reader.line); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			die(_("expected shallow/unshallow, got %s"), line); | 			die(_("expected shallow/unshallow, got %s"), reader.line); | ||||||
| 		} | 		} | ||||||
| 	} else if (!args->stateless_rpc) | 	} else if (!args->stateless_rpc) | ||||||
| 		send_request(args, fd[1], &req_buf); | 		send_request(args, fd[1], &req_buf); | ||||||
|  | @ -397,9 +404,9 @@ static int find_common(struct fetch_negotiator *negotiator, | ||||||
| 			if (!args->stateless_rpc && count == INITIAL_FLUSH) | 			if (!args->stateless_rpc && count == INITIAL_FLUSH) | ||||||
| 				continue; | 				continue; | ||||||
|  |  | ||||||
| 			consume_shallow_list(args, fd[0]); | 			consume_shallow_list(args, &reader); | ||||||
| 			do { | 			do { | ||||||
| 				ack = get_ack(fd[0], result_oid); | 				ack = get_ack(&reader, result_oid); | ||||||
| 				if (ack) | 				if (ack) | ||||||
| 					print_verbose(args, _("got %s %d %s"), "ack", | 					print_verbose(args, _("got %s %d %s"), "ack", | ||||||
| 						      ack, oid_to_hex(result_oid)); | 						      ack, oid_to_hex(result_oid)); | ||||||
|  | @ -469,9 +476,9 @@ done: | ||||||
| 	strbuf_release(&req_buf); | 	strbuf_release(&req_buf); | ||||||
|  |  | ||||||
| 	if (!got_ready || !no_done) | 	if (!got_ready || !no_done) | ||||||
| 		consume_shallow_list(args, fd[0]); | 		consume_shallow_list(args, &reader); | ||||||
| 	while (flushes || multi_ack) { | 	while (flushes || multi_ack) { | ||||||
| 		int ack = get_ack(fd[0], result_oid); | 		int ack = get_ack(&reader, result_oid); | ||||||
| 		if (ack) { | 		if (ack) { | ||||||
| 			print_verbose(args, _("got %s (%d) %s"), "ack", | 			print_verbose(args, _("got %s (%d) %s"), "ack", | ||||||
| 				      ack, oid_to_hex(result_oid)); | 				      ack, oid_to_hex(result_oid)); | ||||||
|  |  | ||||||
|  | @ -409,28 +409,36 @@ static struct discovery *discover_refs(const char *service, int for_push) | ||||||
| 	if (maybe_smart && | 	if (maybe_smart && | ||||||
| 	    (5 <= last->len && last->buf[4] == '#') && | 	    (5 <= last->len && last->buf[4] == '#') && | ||||||
| 	    !strbuf_cmp(&exp, &type)) { | 	    !strbuf_cmp(&exp, &type)) { | ||||||
| 		char *line; | 		struct packet_reader reader; | ||||||
|  | 		packet_reader_init(&reader, -1, last->buf, last->len, | ||||||
|  | 				   PACKET_READ_CHOMP_NEWLINE); | ||||||
|  |  | ||||||
| 		/* | 		/* | ||||||
| 		 * smart HTTP response; validate that the service | 		 * smart HTTP response; validate that the service | ||||||
| 		 * pkt-line matches our request. | 		 * pkt-line matches our request. | ||||||
| 		 */ | 		 */ | ||||||
| 		line = packet_read_line_buf(&last->buf, &last->len, NULL); | 		if (packet_reader_read(&reader) != PACKET_READ_NORMAL) | ||||||
| 		if (!line) |  | ||||||
| 			die("invalid server response; expected service, got flush packet"); | 			die("invalid server response; expected service, got flush packet"); | ||||||
|  |  | ||||||
| 		strbuf_reset(&exp); | 		strbuf_reset(&exp); | ||||||
| 		strbuf_addf(&exp, "# service=%s", service); | 		strbuf_addf(&exp, "# service=%s", service); | ||||||
| 		if (strcmp(line, exp.buf)) | 		if (strcmp(reader.line, exp.buf)) | ||||||
| 			die("invalid server response; got '%s'", line); | 			die("invalid server response; got '%s'", reader.line); | ||||||
| 		strbuf_release(&exp); | 		strbuf_release(&exp); | ||||||
|  |  | ||||||
| 		/* The header can include additional metadata lines, up | 		/* The header can include additional metadata lines, up | ||||||
| 		 * until a packet flush marker.  Ignore these now, but | 		 * until a packet flush marker.  Ignore these now, but | ||||||
| 		 * in the future we might start to scan them. | 		 * in the future we might start to scan them. | ||||||
| 		 */ | 		 */ | ||||||
| 		while (packet_read_line_buf(&last->buf, &last->len, NULL)) | 		for (;;) { | ||||||
| 			; | 			packet_reader_read(&reader); | ||||||
|  | 			if (reader.pktlen <= 0) { | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		last->buf = reader.src_buffer; | ||||||
|  | 		last->len = reader.src_len; | ||||||
|  |  | ||||||
| 		last->proto_git = 1; | 		last->proto_git = 1; | ||||||
| 	} else if (maybe_smart && | 	} else if (maybe_smart && | ||||||
|  |  | ||||||
							
								
								
									
										37
									
								
								send-pack.c
								
								
								
								
							
							
						
						
									
										37
									
								
								send-pack.c
								
								
								
								
							|  | @ -135,38 +135,36 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *extra, struc | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int receive_unpack_status(int in) | static int receive_unpack_status(struct packet_reader *reader) | ||||||
| { | { | ||||||
| 	const char *line = packet_read_line(in, NULL); | 	if (packet_reader_read(reader) != PACKET_READ_NORMAL) | ||||||
| 	if (!line) |  | ||||||
| 		return error(_("unexpected flush packet while reading remote unpack status")); | 		return error(_("unexpected flush packet while reading remote unpack status")); | ||||||
| 	if (!skip_prefix(line, "unpack ", &line)) | 	if (!skip_prefix(reader->line, "unpack ", &reader->line)) | ||||||
| 		return error(_("unable to parse remote unpack status: %s"), line); | 		return error(_("unable to parse remote unpack status: %s"), reader->line); | ||||||
| 	if (strcmp(line, "ok")) | 	if (strcmp(reader->line, "ok")) | ||||||
| 		return error(_("remote unpack failed: %s"), line); | 		return error(_("remote unpack failed: %s"), reader->line); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int receive_status(int in, struct ref *refs) | static int receive_status(struct packet_reader *reader, struct ref *refs) | ||||||
| { | { | ||||||
| 	struct ref *hint; | 	struct ref *hint; | ||||||
| 	int ret; | 	int ret; | ||||||
|  |  | ||||||
| 	hint = NULL; | 	hint = NULL; | ||||||
| 	ret = receive_unpack_status(in); | 	ret = receive_unpack_status(reader); | ||||||
| 	while (1) { | 	while (1) { | ||||||
| 		char *refname; | 		const char *refname; | ||||||
| 		char *msg; | 		char *msg; | ||||||
| 		char *line = packet_read_line(in, NULL); | 		if (packet_reader_read(reader) != PACKET_READ_NORMAL) | ||||||
| 		if (!line) |  | ||||||
| 			break; | 			break; | ||||||
| 		if (!starts_with(line, "ok ") && !starts_with(line, "ng ")) { | 		if (!starts_with(reader->line, "ok ") && !starts_with(reader->line, "ng ")) { | ||||||
| 			error("invalid ref status from remote: %s", line); | 			error("invalid ref status from remote: %s", reader->line); | ||||||
| 			ret = -1; | 			ret = -1; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		refname = line + 3; | 		refname = reader->line + 3; | ||||||
| 		msg = strchr(refname, ' '); | 		msg = strchr(refname, ' '); | ||||||
| 		if (msg) | 		if (msg) | ||||||
| 			*msg++ = '\0'; | 			*msg++ = '\0'; | ||||||
|  | @ -187,7 +185,7 @@ static int receive_status(int in, struct ref *refs) | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (line[0] == 'o' && line[1] == 'k') | 		if (reader->line[0] == 'o' && reader->line[1] == 'k') | ||||||
| 			hint->status = REF_STATUS_OK; | 			hint->status = REF_STATUS_OK; | ||||||
| 		else { | 		else { | ||||||
| 			hint->status = REF_STATUS_REMOTE_REJECT; | 			hint->status = REF_STATUS_REMOTE_REJECT; | ||||||
|  | @ -390,6 +388,7 @@ int send_pack(struct send_pack_args *args, | ||||||
| 	int ret; | 	int ret; | ||||||
| 	struct async demux; | 	struct async demux; | ||||||
| 	const char *push_cert_nonce = NULL; | 	const char *push_cert_nonce = NULL; | ||||||
|  | 	struct packet_reader reader; | ||||||
|  |  | ||||||
| 	/* Does the other end support the reporting? */ | 	/* Does the other end support the reporting? */ | ||||||
| 	if (server_supports("report-status")) | 	if (server_supports("report-status")) | ||||||
|  | @ -559,6 +558,8 @@ int send_pack(struct send_pack_args *args, | ||||||
| 		in = demux.out; | 		in = demux.out; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	packet_reader_init(&reader, in, NULL, 0, PACKET_READ_CHOMP_NEWLINE); | ||||||
|  |  | ||||||
| 	if (need_pack_data && cmds_sent) { | 	if (need_pack_data && cmds_sent) { | ||||||
| 		if (pack_objects(out, remote_refs, extra_have, args) < 0) { | 		if (pack_objects(out, remote_refs, extra_have, args) < 0) { | ||||||
| 			for (ref = remote_refs; ref; ref = ref->next) | 			for (ref = remote_refs; ref; ref = ref->next) | ||||||
|  | @ -573,7 +574,7 @@ int send_pack(struct send_pack_args *args, | ||||||
| 			 * are failing, and just want the error() side effects. | 			 * are failing, and just want the error() side effects. | ||||||
| 			 */ | 			 */ | ||||||
| 			if (status_report) | 			if (status_report) | ||||||
| 				receive_unpack_status(in); | 				receive_unpack_status(&reader); | ||||||
|  |  | ||||||
| 			if (use_sideband) { | 			if (use_sideband) { | ||||||
| 				close(demux.out); | 				close(demux.out); | ||||||
|  | @ -590,7 +591,7 @@ int send_pack(struct send_pack_args *args, | ||||||
| 		packet_flush(out); | 		packet_flush(out); | ||||||
|  |  | ||||||
| 	if (status_report && cmds_sent) | 	if (status_report && cmds_sent) | ||||||
| 		ret = receive_status(in, remote_refs); | 		ret = receive_status(&reader, remote_refs); | ||||||
| 	else | 	else | ||||||
| 		ret = 0; | 		ret = 0; | ||||||
| 	if (args->stateless_rpc) | 	if (args->stateless_rpc) | ||||||
|  |  | ||||||
|  | @ -354,7 +354,8 @@ static int ok_to_give_up(const struct object_array *have_obj, | ||||||
| 					    min_generation); | 					    min_generation); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int get_common_commits(struct object_array *have_obj, | static int get_common_commits(struct packet_reader *reader, | ||||||
|  | 			      struct object_array *have_obj, | ||||||
| 			      struct object_array *want_obj) | 			      struct object_array *want_obj) | ||||||
| { | { | ||||||
| 	struct object_id oid; | 	struct object_id oid; | ||||||
|  | @ -366,12 +367,11 @@ static int get_common_commits(struct object_array *have_obj, | ||||||
| 	save_commit_buffer = 0; | 	save_commit_buffer = 0; | ||||||
|  |  | ||||||
| 	for (;;) { | 	for (;;) { | ||||||
| 		char *line = packet_read_line(0, NULL); |  | ||||||
| 		const char *arg; | 		const char *arg; | ||||||
|  |  | ||||||
| 		reset_timeout(); | 		reset_timeout(); | ||||||
|  |  | ||||||
| 		if (!line) { | 		if (packet_reader_read(reader) != PACKET_READ_NORMAL) { | ||||||
| 			if (multi_ack == 2 && got_common | 			if (multi_ack == 2 && got_common | ||||||
| 			    && !got_other && ok_to_give_up(have_obj, want_obj)) { | 			    && !got_other && ok_to_give_up(have_obj, want_obj)) { | ||||||
| 				sent_ready = 1; | 				sent_ready = 1; | ||||||
|  | @ -390,7 +390,7 @@ static int get_common_commits(struct object_array *have_obj, | ||||||
| 			got_other = 0; | 			got_other = 0; | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		if (skip_prefix(line, "have ", &arg)) { | 		if (skip_prefix(reader->line, "have ", &arg)) { | ||||||
| 			switch (got_oid(arg, &oid, have_obj)) { | 			switch (got_oid(arg, &oid, have_obj)) { | ||||||
| 			case -1: /* they have what we do not */ | 			case -1: /* they have what we do not */ | ||||||
| 				got_other = 1; | 				got_other = 1; | ||||||
|  | @ -416,7 +416,7 @@ static int get_common_commits(struct object_array *have_obj, | ||||||
| 			} | 			} | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		if (!strcmp(line, "done")) { | 		if (!strcmp(reader->line, "done")) { | ||||||
| 			if (have_obj->nr > 0) { | 			if (have_obj->nr > 0) { | ||||||
| 				if (multi_ack) | 				if (multi_ack) | ||||||
| 					packet_write_fmt(1, "ACK %s\n", last_hex); | 					packet_write_fmt(1, "ACK %s\n", last_hex); | ||||||
|  | @ -425,7 +425,7 @@ static int get_common_commits(struct object_array *have_obj, | ||||||
| 			packet_write_fmt(1, "NAK\n"); | 			packet_write_fmt(1, "NAK\n"); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 		die("git upload-pack: expected SHA1 list, got '%s'", line); | 		die("git upload-pack: expected SHA1 list, got '%s'", reader->line); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -826,7 +826,7 @@ static int process_deepen_not(const char *line, struct string_list *deepen_not, | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void receive_needs(struct object_array *want_obj) | static void receive_needs(struct packet_reader *reader, struct object_array *want_obj) | ||||||
| { | { | ||||||
| 	struct object_array shallows = OBJECT_ARRAY_INIT; | 	struct object_array shallows = OBJECT_ARRAY_INIT; | ||||||
| 	struct string_list deepen_not = STRING_LIST_INIT_DUP; | 	struct string_list deepen_not = STRING_LIST_INIT_DUP; | ||||||
|  | @ -840,33 +840,32 @@ static void receive_needs(struct object_array *want_obj) | ||||||
| 		struct object *o; | 		struct object *o; | ||||||
| 		const char *features; | 		const char *features; | ||||||
| 		struct object_id oid_buf; | 		struct object_id oid_buf; | ||||||
| 		char *line = packet_read_line(0, NULL); |  | ||||||
| 		const char *arg; | 		const char *arg; | ||||||
|  |  | ||||||
| 		reset_timeout(); | 		reset_timeout(); | ||||||
| 		if (!line) | 		if (packet_reader_read(reader) != PACKET_READ_NORMAL) | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		if (process_shallow(line, &shallows)) | 		if (process_shallow(reader->line, &shallows)) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (process_deepen(line, &depth)) | 		if (process_deepen(reader->line, &depth)) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (process_deepen_since(line, &deepen_since, &deepen_rev_list)) | 		if (process_deepen_since(reader->line, &deepen_since, &deepen_rev_list)) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (process_deepen_not(line, &deepen_not, &deepen_rev_list)) | 		if (process_deepen_not(reader->line, &deepen_not, &deepen_rev_list)) | ||||||
| 			continue; | 			continue; | ||||||
|  |  | ||||||
| 		if (skip_prefix(line, "filter ", &arg)) { | 		if (skip_prefix(reader->line, "filter ", &arg)) { | ||||||
| 			if (!filter_capability_requested) | 			if (!filter_capability_requested) | ||||||
| 				die("git upload-pack: filtering capability not negotiated"); | 				die("git upload-pack: filtering capability not negotiated"); | ||||||
| 			parse_list_objects_filter(&filter_options, arg); | 			parse_list_objects_filter(&filter_options, arg); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (!skip_prefix(line, "want ", &arg) || | 		if (!skip_prefix(reader->line, "want ", &arg) || | ||||||
| 		    parse_oid_hex(arg, &oid_buf, &features)) | 		    parse_oid_hex(arg, &oid_buf, &features)) | ||||||
| 			die("git upload-pack: protocol error, " | 			die("git upload-pack: protocol error, " | ||||||
| 			    "expected to get object ID, not '%s'", line); | 			    "expected to get object ID, not '%s'", reader->line); | ||||||
|  |  | ||||||
| 		if (parse_feature_request(features, "deepen-relative")) | 		if (parse_feature_request(features, "deepen-relative")) | ||||||
| 			deepen_relative = 1; | 			deepen_relative = 1; | ||||||
|  | @ -1055,6 +1054,7 @@ void upload_pack(struct upload_pack_options *options) | ||||||
| { | { | ||||||
| 	struct string_list symref = STRING_LIST_INIT_DUP; | 	struct string_list symref = STRING_LIST_INIT_DUP; | ||||||
| 	struct object_array want_obj = OBJECT_ARRAY_INIT; | 	struct object_array want_obj = OBJECT_ARRAY_INIT; | ||||||
|  | 	struct packet_reader reader; | ||||||
|  |  | ||||||
| 	stateless_rpc = options->stateless_rpc; | 	stateless_rpc = options->stateless_rpc; | ||||||
| 	timeout = options->timeout; | 	timeout = options->timeout; | ||||||
|  | @ -1078,10 +1078,12 @@ void upload_pack(struct upload_pack_options *options) | ||||||
| 	if (options->advertise_refs) | 	if (options->advertise_refs) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	receive_needs(&want_obj); | 	packet_reader_init(&reader, 0, NULL, 0, PACKET_READ_CHOMP_NEWLINE); | ||||||
|  |  | ||||||
|  | 	receive_needs(&reader, &want_obj); | ||||||
| 	if (want_obj.nr) { | 	if (want_obj.nr) { | ||||||
| 		struct object_array have_obj = OBJECT_ARRAY_INIT; | 		struct object_array have_obj = OBJECT_ARRAY_INIT; | ||||||
| 		get_common_commits(&have_obj, &want_obj); | 		get_common_commits(&reader, &have_obj, &want_obj); | ||||||
| 		create_pack_file(&have_obj, &want_obj); | 		create_pack_file(&have_obj, &want_obj); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Masaya Suzuki
						Masaya Suzuki