diff mbox series

[v3,2/4] receive-pack: refactor report for proc-receive

Message ID 20200313122318.78000-3-zhiyou.jx@alibaba-inc.com (mailing list archive)
State New, archived
Headers show
Series [v3,1/4] receive-pack: add new proc-receive hook | expand

Commit Message

Jiang Xin March 13, 2020, 12:23 p.m. UTC
The "proc-receive" may update one or more references, and will send its
result one by one in pkt-line format.  Each line of the result has four
fields and one optional message field, as "<old-oid> <new-oid> <ref>
<status> [<message>]".  See the following example:

    # OK, run this command successfully.
    PKT-LINE(old-oid new-oid ref ok)

    # NO, I reject it.
    PKT-LINE(old-oid new-oid ref ng reason)

    # OK, but use an alternate reference.
    PKT-LINE(old-oid new-oid ref ok ref:alt-ref)

    # It will fallthrough to receive-pack to execute.
    PKT-LINE(old-oid new-oid ref ft)

The first three fields have the same foramt as a command.

The forth field has a two-letter status code.  Available status code:

* ok: The command runs successfully.  If the optional message has a
  prefix "ref:", the hook has created/updated an alternate reference
  instead.

* ng: Fail to run the command. Error message is in the optional message
  field.

* ft: Will fallthrough to receive-pack to execute.

Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
---
 builtin/receive-pack.c | 21 ++++++++++++++++-----
 transport.c            | 33 ++++++++++++++++++++++++---------
 2 files changed, 40 insertions(+), 14 deletions(-)
diff mbox series

Patch

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 8cda2b9cf7..23f1ae3795 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -311,6 +311,7 @@  static void write_head_info(void)
 struct command {
 	struct command *next;
 	const char *error_string;
+	const char *extra_string;
 	unsigned int skip_update:1,
 		     did_not_exist:1,
 		     have_special_ref:1;
@@ -868,7 +869,12 @@  static int read_proc_receive_result(struct packet_reader *reader,
 			else
 				cmd->error_string = "failed";
 			code = 1;
-		} else if (strcmp("ok", status)) {
+		} else if (!strcmp("ok", status)) {
+			cmd->extra_string = xstrdup_or_null(msg);
+		} else if (!strcmp("ft", status)) {
+			/* Unset "have_special_ref" field, will execute by "receive-pack" */
+			cmd->have_special_ref = 0;
+		} else {
 			rp_warning("unknown proc-receive status '%s' for '%s'",
 				   status, reader->line);
 			cmd->error_string = "bad status";
@@ -2133,12 +2139,17 @@  static void report(struct command *commands, const char *unpack_status)
 	packet_buf_write(&buf, "unpack %s\n",
 			 unpack_status ? unpack_status : "ok");
 	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (!cmd->error_string)
-			packet_buf_write(&buf, "ok %s\n",
-					 cmd->ref_name);
-		else
+		if (!cmd->error_string) {
+			if (!cmd->extra_string)
+				packet_buf_write(&buf, "ok %s\n",
+						 cmd->ref_name);
+			else
+				packet_buf_write(&buf, "ok %s%c%s\n",
+						 cmd->ref_name, ' ', cmd->extra_string);
+		} else {
 			packet_buf_write(&buf, "ng %s %s\n",
 					 cmd->ref_name, cmd->error_string);
+		}
 	}
 	packet_buf_flush(&buf);
 
diff --git a/transport.c b/transport.c
index 1fdc7dac1a..a4f2a5cc6f 100644
--- a/transport.c
+++ b/transport.c
@@ -463,11 +463,17 @@  static void print_ref_status(char flag, const char *summary,
 			     struct ref *to, struct ref *from, const char *msg,
 			     int porcelain, int summary_width)
 {
+	char *to_name = to->name;
+
+	if (to->remote_status) {
+		if (!strncmp("ref:", to->remote_status, 4))
+			to_name = to->remote_status + 4;
+	}
 	if (porcelain) {
 		if (from)
-			fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to->name);
+			fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to_name);
 		else
-			fprintf(stdout, "%c\t:%s\t", flag, to->name);
+			fprintf(stdout, "%c\t:%s\t", flag, to_name);
 		if (msg)
 			fprintf(stdout, "%s (%s)\n", summary, msg);
 		else
@@ -481,9 +487,9 @@  static void print_ref_status(char flag, const char *summary,
 		fprintf(stderr, " %s%c %-*s%s ", red, flag, summary_width,
 			summary, reset);
 		if (from)
-			fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
+			fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to_name));
 		else
-			fputs(prettify_refname(to->name), stderr);
+			fputs(prettify_refname(to_name), stderr);
 		if (msg) {
 			fputs(" (", stderr);
 			fputs(msg, stderr);
@@ -498,12 +504,21 @@  static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_widt
 	if (ref->deletion)
 		print_ref_status('-', "[deleted]", ref, NULL, NULL,
 				 porcelain, summary_width);
-	else if (is_null_oid(&ref->old_oid))
+	else if (is_null_oid(&ref->old_oid)) {
+		char *refname, *summary;
+		if (ref->remote_status && !strncmp(ref->remote_status, "ref:", 4))
+			refname = ref->remote_status + 4;
+		else
+			refname = ref->name;
+		if (starts_with(refname, "refs/tags/"))
+		       summary = "[new tag]";
+		else if (starts_with(refname, "refs/heads/"))
+		       summary = "[new branch]";
+		else
+		       summary = "[new reference]";
 		print_ref_status('*',
-			(starts_with(ref->name, "refs/tags/") ? "[new tag]" :
-			"[new branch]"),
-			ref, ref->peer_ref, NULL, porcelain, summary_width);
-	else {
+			summary, ref, ref->peer_ref, NULL, porcelain, summary_width);
+	} else {
 		struct strbuf quickref = STRBUF_INIT;
 		char type;
 		const char *msg;