{"thread":{"id":"19906","subject":"(unknown)","startedAt":"2009-06-23T01:07:27Z","lastAt":"2009-06-23T01:07:27Z","messageCount":1,"participants":["Larry D'Anna"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"116796","messageId":"20090623010727.GA13509@cthulhu","threadId":"19906","inReplyTo":null,"subject":"(unknown)","fromName":"Larry D'Anna","fromEmail":"larry@elder-gods.org","sentAt":"2009-06-23T01:07:27Z","receivedAt":"2009-06-23T01:07:27Z","isPatch":false,"sender":{"key":"larry@elder-gods.org","avatar":"https://avatars.githubusercontent.com/u/3013304?v=4"},"body":">From 1efb13a16b86b0e7d4735b583cf8d90bd74728fb Mon Sep 17 00:00:00 2001\nIn-Reply-To: <20090622214032.GC19364@coredump.intra.peff.net>\nReferences: <20090622214032.GC19364@coredump.intra.peff.net>\nFrom: Larry D'Anna <larry@elder-gods.org>\nDate: Mon, 22 Jun 2009 21:02:55 -0400\nSubject: [PATCH] add --porcelain option to git-push\n\nIf --porcelain is used git-push will produce machine-readable output.  The\noutput status line for each ref will be tab-separated and sent to stdout instead\nof stderr.  The full symbolic names of the refs will be given.  For example\n\n$ git push --dry-run --porcelain master :foobar 2>/dev/null \\\n  | perl -pe 's/\\t/ TAB /g'\n\n= TAB refs/heads/master:refs/heads/master TAB [up to date]\n- TAB :refs/heads/foobar TAB [deleted]\n---\n Documentation/git-push.txt |   11 ++++++\n builtin-push.c             |    3 +-\n transport.c                |   75 +++++++++++++++++++++++++------------------\n transport.h                |    1 +\n 4 files changed, 58 insertions(+), 32 deletions(-)\n\ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex fd53c49..2653388 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -85,6 +85,11 @@ nor in any Push line of the corresponding remotes file---see below).\n --dry-run::\n \tDo everything except actually send the updates.\n \n+--porcelain::\n+\tProduce machine-readable output.  The output status line for each ref\n+\twill be tab-separated and sent to stdout instead of stderr.  The full\n+\tsymbolic names of the refs will be given.\n+\n --tags::\n \tAll refs under `$GIT_DIR/refs/tags` are pushed, in\n \taddition to refspecs explicitly listed on the command\n@@ -148,6 +153,12 @@ representing the status of a single ref. Each line is of the form:\n  <flag> <summary> <from> -> <to> (<reason>)\n -------------------------------\n \n+If --porcelain is used, then each line of the output is of the form:\n+\n+-------------------------------\n+ <flag> \\t <from>:<to> \\t <summary> (<reason>)\n+-------------------------------\n+\n flag::\n \tA single character indicating the status of the ref. This is\n \tblank for a successfully pushed ref, `!` for a ref that was\ndiff --git a/builtin-push.c b/builtin-push.c\nindex 7be1239..0a0297f 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -10,7 +10,7 @@\n #include \"parse-options.h\"\n \n static const char * const push_usage[] = {\n-\t\"git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]\",\n+\t\"git push [--all | --mirror] [--dry-run] [--porcelain] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]\",\n \tNULL,\n };\n \n@@ -200,6 +200,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \t\t\t    (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),\n \t\tOPT_BOOLEAN( 0 , \"tags\", &tags, \"push tags\"),\n \t\tOPT_BIT( 0 , \"dry-run\", &flags, \"dry run\", TRANSPORT_PUSH_DRY_RUN),\n+\t\tOPT_BIT( 0,  \"porcelain\", &flags, \"machine-readable output\", TRANSPORT_PUSH_PORCELAIN),\n \t\tOPT_BIT('f', \"force\", &flags, \"force updates\", TRANSPORT_PUSH_FORCE),\n \t\tOPT_BOOLEAN( 0 , \"thin\", &thin, \"use thin pack\"),\n \t\tOPT_STRING( 0 , \"receive-pack\", &receivepack, \"receive-pack\", \"receive pack program\"),\ndiff --git a/transport.c b/transport.c\nindex 501a77b..b074067 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -719,19 +719,30 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref, int verb\n \n #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)\n \n-static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)\n+static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain)\n {\n-\tfprintf(stderr, \" %c %-*s \", flag, SUMMARY_WIDTH, summary);\n-\tif (from)\n-\t\tfprintf(stderr, \"%s -> %s\", prettify_refname(from->name), prettify_refname(to->name));\n-\telse\n-\t\tfputs(prettify_refname(to->name), stderr);\n-\tif (msg) {\n-\t\tfputs(\" (\", stderr);\n-\t\tfputs(msg, stderr);\n-\t\tfputc(')', stderr);\n+\tif (porcelain) {\n+\t\tif (from)\n+\t\t\tfprintf(stdout, \"%c\\t%s:%s\\t\", flag, from->name, to->name);\n+\t\telse\n+\t\t\tfprintf(stdout, \"%c\\t:%s\\t\", flag, to->name);\n+\t\tif (msg)\n+\t\t\tfprintf(stdout, \"%s (%s)\\n\", summary, msg);\n+\t\telse\n+\t\t\tfprintf(stdout, \"%s\\n\", summary);\n+\t} else {\n+\t\tfprintf(stderr, \" %c %-*s \", flag, SUMMARY_WIDTH, summary);\n+\t\tif (from)\n+\t\t\tfprintf(stderr, \"%s -> %s\", prettify_refname(from->name), prettify_refname(to->name));\n+\t\telse\n+\t\t\tfputs(prettify_refname(to->name), stderr);\n+\t\tif (msg) {\n+\t\t\tfputs(\" (\", stderr);\n+\t\t\tfputs(msg, stderr);\n+\t\t\tfputc(')', stderr);\n+\t\t}\n+\t\tfputc('\\n', stderr);\n \t}\n-\tfputc('\\n', stderr);\n }\n \n static const char *status_abbrev(unsigned char sha1[20])\n@@ -739,15 +750,15 @@ static const char *status_abbrev(unsigned char sha1[20])\n \treturn find_unique_abbrev(sha1, DEFAULT_ABBREV);\n }\n \n-static void print_ok_ref_status(struct ref *ref)\n+static void print_ok_ref_status(struct ref *ref, int porcelain)\n {\n \tif (ref->deletion)\n-\t\tprint_ref_status('-', \"[deleted]\", ref, NULL, NULL);\n+\t\tprint_ref_status('-', \"[deleted]\", ref, NULL, NULL, porcelain);\n \telse if (is_null_sha1(ref->old_sha1))\n \t\tprint_ref_status('*',\n \t\t\t(!prefixcmp(ref->name, \"refs/tags/\") ? \"[new tag]\" :\n-\t\t\t  \"[new branch]\"),\n-\t\t\tref, ref->peer_ref, NULL);\n+\t\t\t\"[new branch]\"),\n+\t\t\tref, ref->peer_ref, NULL, porcelain);\n \telse {\n \t\tchar quickref[84];\n \t\tchar type;\n@@ -765,50 +776,51 @@ static void print_ok_ref_status(struct ref *ref)\n \t\t}\n \t\tstrcat(quickref, status_abbrev(ref->new_sha1));\n \n-\t\tprint_ref_status(type, quickref, ref, ref->peer_ref, msg);\n+\t\tprint_ref_status(type, quickref, ref, ref->peer_ref, msg, porcelain);\n \t}\n }\n \n-static int print_one_push_status(struct ref *ref, const char *dest, int count)\n+static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain)\n {\n \tif (!count)\n \t\tfprintf(stderr, \"To %s\\n\", dest);\n \n \tswitch(ref->status) {\n \tcase REF_STATUS_NONE:\n-\t\tprint_ref_status('X', \"[no match]\", ref, NULL, NULL);\n+\t\tprint_ref_status('X', \"[no match]\", ref, NULL, NULL, porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_NODELETE:\n \t\tprint_ref_status('!', \"[rejected]\", ref, NULL,\n-\t\t\t\t\"remote does not support deleting refs\");\n+\t\t\t\t\t\t \"remote does not support deleting refs\", porcelain);\n \t\tbreak;\n \tcase REF_STATUS_UPTODATE:\n \t\tprint_ref_status('=', \"[up to date]\", ref,\n-\t\t\t\tref->peer_ref, NULL);\n+\t\t\t\t\t\t ref->peer_ref, NULL, porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_NONFASTFORWARD:\n \t\tprint_ref_status('!', \"[rejected]\", ref, ref->peer_ref,\n-\t\t\t\t\"non-fast forward\");\n+\t\t\t\t\t\t \"non-fast forward\", porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REMOTE_REJECT:\n \t\tprint_ref_status('!', \"[remote rejected]\", ref,\n-\t\t\t\tref->deletion ? NULL : ref->peer_ref,\n-\t\t\t\tref->remote_status);\n+\t\t\t\t\t\t ref->deletion ? NULL : ref->peer_ref,\n+\t\t\t\t\t\t ref->remote_status, porcelain);\n \t\tbreak;\n \tcase REF_STATUS_EXPECTING_REPORT:\n \t\tprint_ref_status('!', \"[remote failure]\", ref,\n-\t\t\t\tref->deletion ? NULL : ref->peer_ref,\n-\t\t\t\t\"remote failed to report status\");\n+\t\t\t\t\t\t ref->deletion ? NULL : ref->peer_ref,\n+\t\t\t\t\t\t \"remote failed to report status\", porcelain);\n \t\tbreak;\n \tcase REF_STATUS_OK:\n-\t\tprint_ok_ref_status(ref);\n+\t\tprint_ok_ref_status(ref, porcelain);\n \t\tbreak;\n \t}\n \n \treturn 1;\n }\n \n-static void print_push_status(const char *dest, struct ref *refs, int verbose)\n+static void print_push_status(const char *dest, struct ref *refs,\n+\t\t\t\t\t\t\t  int verbose, int porcelain)\n {\n \tstruct ref *ref;\n \tint n = 0;\n@@ -816,18 +828,18 @@ static void print_push_status(const char *dest, struct ref *refs, int verbose)\n \tif (verbose) {\n \t\tfor (ref = refs; ref; ref = ref->next)\n \t\t\tif (ref->status == REF_STATUS_UPTODATE)\n-\t\t\t\tn += print_one_push_status(ref, dest, n);\n+\t\t\t\tn += print_one_push_status(ref, dest, n, porcelain);\n \t}\n \n \tfor (ref = refs; ref; ref = ref->next)\n \t\tif (ref->status == REF_STATUS_OK)\n-\t\t\tn += print_one_push_status(ref, dest, n);\n+\t\t\tn += print_one_push_status(ref, dest, n, porcelain);\n \n \tfor (ref = refs; ref; ref = ref->next) {\n \t\tif (ref->status != REF_STATUS_NONE &&\n \t\t    ref->status != REF_STATUS_UPTODATE &&\n \t\t    ref->status != REF_STATUS_OK)\n-\t\t\tn += print_one_push_status(ref, dest, n);\n+\t\t\tn += print_one_push_status(ref, dest, n, porcelain);\n \t}\n }\n \n@@ -997,6 +1009,7 @@ int transport_push(struct transport *transport,\n \t\tstruct ref *local_refs = get_local_heads();\n \t\tint match_flags = MATCH_REFS_NONE;\n \t\tint verbose = flags & TRANSPORT_PUSH_VERBOSE;\n+\t\tint porcelain = flags & TRANSPORT_PUSH_PORCELAIN;\n \t\tint ret;\n \n \t\tif (flags & TRANSPORT_PUSH_ALL)\n@@ -1011,7 +1024,7 @@ int transport_push(struct transport *transport,\n \n \t\tret = transport->push_refs(transport, remote_refs, flags);\n \n-\t\tprint_push_status(transport->url, remote_refs, verbose);\n+\t\tprint_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);\n \n \t\tif (!(flags & TRANSPORT_PUSH_DRY_RUN)) {\n \t\t\tstruct ref *ref;\ndiff --git a/transport.h b/transport.h\nindex 27bfc52..51b5397 100644\n--- a/transport.h\n+++ b/transport.h\n@@ -35,6 +35,7 @@ struct transport {\n #define TRANSPORT_PUSH_DRY_RUN 4\n #define TRANSPORT_PUSH_MIRROR 8\n #define TRANSPORT_PUSH_VERBOSE 16\n+#define TRANSPORT_PUSH_PORCELAIN 32\n \n /* Returns a transport suitable for the url */\n struct transport *transport_get(struct remote *, const char *);\n-- \n1.6.0.4\n"}]}