diff options
Diffstat (limited to 'send-pack.c')
| -rw-r--r-- | send-pack.c | 69 | 
1 files changed, 49 insertions, 20 deletions
diff --git a/send-pack.c b/send-pack.c index 047bd18fde..90f2ac51a7 100644 --- a/send-pack.c +++ b/send-pack.c @@ -36,18 +36,15 @@ int option_parse_push_signed(const struct option *opt,  	die("bad %s argument: %s", opt->long_name, arg);  } -static int feed_object(const unsigned char *sha1, int fd, int negative) +static void feed_object(const unsigned char *sha1, FILE *fh, int negative)  { -	char buf[42]; -  	if (negative && !has_sha1_file(sha1)) -		return 1; +		return; -	memcpy(buf + negative, sha1_to_hex(sha1), 40);  	if (negative) -		buf[0] = '^'; -	buf[40 + negative] = '\n'; -	return write_or_whine(fd, buf, 41 + negative, "send-pack: send refs"); +		putc('^', fh); +	fputs(sha1_to_hex(sha1), fh); +	putc('\n', fh);  }  /* @@ -73,6 +70,7 @@ static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, stru  		NULL,  	};  	struct child_process po = CHILD_PROCESS_INIT; +	FILE *po_in;  	int i;  	i = 4; @@ -97,21 +95,22 @@ static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, stru  	 * We feed the pack-objects we just spawned with revision  	 * parameters by writing to the pipe.  	 */ +	po_in = xfdopen(po.in, "w");  	for (i = 0; i < extra->nr; i++) -		if (!feed_object(extra->sha1[i], po.in, 1)) -			break; +		feed_object(extra->sha1[i], po_in, 1);  	while (refs) { -		if (!is_null_oid(&refs->old_oid) && -		    !feed_object(refs->old_oid.hash, po.in, 1)) -			break; -		if (!is_null_oid(&refs->new_oid) && -		    !feed_object(refs->new_oid.hash, po.in, 0)) -			break; +		if (!is_null_oid(&refs->old_oid)) +			feed_object(refs->old_oid.hash, po_in, 1); +		if (!is_null_oid(&refs->new_oid)) +			feed_object(refs->new_oid.hash, po_in, 0);  		refs = refs->next;  	} -	close(po.in); +	fflush(po_in); +	if (ferror(po_in)) +		die_errno("error writing to pack-objects"); +	fclose(po_in);  	if (args->stateless_rpc) {  		char *buf = xmalloc(LARGE_PACKET_MAX); @@ -261,12 +260,13 @@ static int generate_push_cert(struct strbuf *req_buf,  			      const char *push_cert_nonce)  {  	const struct ref *ref; +	struct string_list_item *item;  	char *signing_key = xstrdup(get_signing_key());  	const char *cp, *np;  	struct strbuf cert = STRBUF_INIT;  	int update_seen = 0; -	strbuf_addf(&cert, "certificate version 0.1\n"); +	strbuf_addstr(&cert, "certificate version 0.1\n");  	strbuf_addf(&cert, "pusher %s ", signing_key);  	datestamp(&cert);  	strbuf_addch(&cert, '\n'); @@ -277,6 +277,9 @@ static int generate_push_cert(struct strbuf *req_buf,  	}  	if (push_cert_nonce[0])  		strbuf_addf(&cert, "nonce %s\n", push_cert_nonce); +	if (args->push_options) +		for_each_string_list_item(item, args->push_options) +			strbuf_addf(&cert, "push-option %s\n", item->string);  	strbuf_addstr(&cert, "\n");  	for (ref = remote_refs; ref; ref = ref->next) { @@ -371,6 +374,8 @@ int send_pack(struct send_pack_args *args,  	int agent_supported = 0;  	int use_atomic = 0;  	int atomic_supported = 0; +	int use_push_options = 0; +	int push_options_supported = 0;  	unsigned cmds_sent = 0;  	int ret;  	struct async demux; @@ -393,6 +398,8 @@ int send_pack(struct send_pack_args *args,  		args->use_thin_pack = 0;  	if (server_supports("atomic"))  		atomic_supported = 1; +	if (server_supports("push-options")) +		push_options_supported = 1;  	if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {  		int len; @@ -419,6 +426,11 @@ int send_pack(struct send_pack_args *args,  	use_atomic = atomic_supported && args->atomic; +	if (args->push_options && !push_options_supported) +		die(_("the receiving end does not support push options")); + +	use_push_options = push_options_supported && args->push_options; +  	if (status_report)  		strbuf_addstr(&cap_buf, " report-status");  	if (use_sideband) @@ -427,6 +439,8 @@ int send_pack(struct send_pack_args *args,  		strbuf_addstr(&cap_buf, " quiet");  	if (use_atomic)  		strbuf_addstr(&cap_buf, " atomic"); +	if (use_push_options) +		strbuf_addstr(&cap_buf, " push-options");  	if (agent_supported)  		strbuf_addf(&cap_buf, " agent=%s", git_user_agent_sanitized()); @@ -513,11 +527,24 @@ int send_pack(struct send_pack_args *args,  	strbuf_release(&req_buf);  	strbuf_release(&cap_buf); +	if (use_push_options) { +		struct string_list_item *item; +		struct strbuf sb = STRBUF_INIT; + +		for_each_string_list_item(item, args->push_options) +			packet_buf_write(&sb, "%s", item->string); + +		write_or_die(out, sb.buf, sb.len); +		packet_flush(out); +		strbuf_release(&sb); +	} +  	if (use_sideband && cmds_sent) {  		memset(&demux, 0, sizeof(demux));  		demux.proc = sideband_demux;  		demux.data = fd;  		demux.out = -1; +		demux.isolate_sigpipe = 1;  		if (start_async(&demux))  			die("send-pack: unable to fork off sideband demultiplexer");  		in = demux.out; @@ -531,8 +558,10 @@ int send_pack(struct send_pack_args *args,  				close(out);  			if (git_connection_is_socket(conn))  				shutdown(fd[0], SHUT_WR); -			if (use_sideband) +			if (use_sideband) { +				close(demux.out);  				finish_async(&demux); +			}  			fd[1] = -1;  			return -1;  		} @@ -551,11 +580,11 @@ int send_pack(struct send_pack_args *args,  		packet_flush(out);  	if (use_sideband && cmds_sent) { +		close(demux.out);  		if (finish_async(&demux)) {  			error("error in sideband demultiplexer");  			ret = -1;  		} -		close(demux.out);  	}  	if (ret < 0)  | 
