git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Marc Branchaud <marcnarc@xiplink.com>
To: Larry D'Anna <larry@elder-gods.org>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] add --porcelain option to git-push
Date: Tue, 23 Jun 2009 11:07:08 -0400	[thread overview]
Message-ID: <4A40EF9C.7000706@xiplink.com> (raw)
In-Reply-To: <20090623011001.GA15352@cthulhu>

Shouldn't this option be named "--plumbing" since it's making 'git push' act like plumbing?  Actually, neither name seems intuitively descriptive to me...

Why not teach 'git push' to change its output format if it's writing to a pipe?

		M.


Larry D'Anna wrote:
> If --porcelain is used git-push will produce machine-readable output.  The
> output status line for each ref will be tab-separated and sent to stdout instead
> of stderr.  The full symbolic names of the refs will be given.  For example
> 
> $ git push --dry-run --porcelain master :foobar 2>/dev/null \
>   | perl -pe 's/\t/ TAB /g'
> 
> = TAB refs/heads/master:refs/heads/master TAB [up to date]
> - TAB :refs/heads/foobar TAB [deleted]
> ---
>  Documentation/git-push.txt |   11 ++++++
>  builtin-push.c             |    3 +-
>  transport.c                |   75 +++++++++++++++++++++++++------------------
>  transport.h                |    1 +
>  4 files changed, 58 insertions(+), 32 deletions(-)
> 
> diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
> index fd53c49..2653388 100644
> --- a/Documentation/git-push.txt
> +++ b/Documentation/git-push.txt
> @@ -85,6 +85,11 @@ nor in any Push line of the corresponding remotes file---see below).
>  --dry-run::
>  	Do everything except actually send the updates.
>  
> +--porcelain::
> +	Produce machine-readable output.  The output status line for each ref
> +	will be tab-separated and sent to stdout instead of stderr.  The full
> +	symbolic names of the refs will be given.
> +
>  --tags::
>  	All refs under `$GIT_DIR/refs/tags` are pushed, in
>  	addition to refspecs explicitly listed on the command
> @@ -148,6 +153,12 @@ representing the status of a single ref. Each line is of the form:
>   <flag> <summary> <from> -> <to> (<reason>)
>  -------------------------------
>  
> +If --porcelain is used, then each line of the output is of the form:
> +
> +-------------------------------
> + <flag> \t <from>:<to> \t <summary> (<reason>)
> +-------------------------------
> +
>  flag::
>  	A single character indicating the status of the ref. This is
>  	blank for a successfully pushed ref, `!` for a ref that was
> diff --git a/builtin-push.c b/builtin-push.c
> index 7be1239..0a0297f 100644
> --- a/builtin-push.c
> +++ b/builtin-push.c
> @@ -10,7 +10,7 @@
>  #include "parse-options.h"
>  
>  static const char * const push_usage[] = {
> -	"git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
> +	"git push [--all | --mirror] [--dry-run] [--porcelain] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
>  	NULL,
>  };
>  
> @@ -200,6 +200,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
>  			    (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
>  		OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
>  		OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
> +		OPT_BIT( 0,  "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
>  		OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
>  		OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
>  		OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
> diff --git a/transport.c b/transport.c
> index 501a77b..b074067 100644
> --- a/transport.c
> +++ b/transport.c
> @@ -719,19 +719,30 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref, int verb
>  
>  #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
>  
> -static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
> +static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain)
>  {
> -	fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
> -	if (from)
> -		fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
> -	else
> -		fputs(prettify_refname(to->name), stderr);
> -	if (msg) {
> -		fputs(" (", stderr);
> -		fputs(msg, stderr);
> -		fputc(')', stderr);
> +	if (porcelain) {
> +		if (from)
> +			fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to->name);
> +		else
> +			fprintf(stdout, "%c\t:%s\t", flag, to->name);
> +		if (msg)
> +			fprintf(stdout, "%s (%s)\n", summary, msg);
> +		else
> +			fprintf(stdout, "%s\n", summary);
> +	} else {
> +		fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
> +		if (from)
> +			fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
> +		else
> +			fputs(prettify_refname(to->name), stderr);
> +		if (msg) {
> +			fputs(" (", stderr);
> +			fputs(msg, stderr);
> +			fputc(')', stderr);
> +		}
> +		fputc('\n', stderr);
>  	}
> -	fputc('\n', stderr);
>  }
>  
>  static const char *status_abbrev(unsigned char sha1[20])
> @@ -739,15 +750,15 @@ static const char *status_abbrev(unsigned char sha1[20])
>  	return find_unique_abbrev(sha1, DEFAULT_ABBREV);
>  }
>  
> -static void print_ok_ref_status(struct ref *ref)
> +static void print_ok_ref_status(struct ref *ref, int porcelain)
>  {
>  	if (ref->deletion)
> -		print_ref_status('-', "[deleted]", ref, NULL, NULL);
> +		print_ref_status('-', "[deleted]", ref, NULL, NULL, porcelain);
>  	else if (is_null_sha1(ref->old_sha1))
>  		print_ref_status('*',
>  			(!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
> -			  "[new branch]"),
> -			ref, ref->peer_ref, NULL);
> +			"[new branch]"),
> +			ref, ref->peer_ref, NULL, porcelain);
>  	else {
>  		char quickref[84];
>  		char type;
> @@ -765,50 +776,51 @@ static void print_ok_ref_status(struct ref *ref)
>  		}
>  		strcat(quickref, status_abbrev(ref->new_sha1));
>  
> -		print_ref_status(type, quickref, ref, ref->peer_ref, msg);
> +		print_ref_status(type, quickref, ref, ref->peer_ref, msg, porcelain);
>  	}
>  }
>  
> -static int print_one_push_status(struct ref *ref, const char *dest, int count)
> +static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain)
>  {
>  	if (!count)
>  		fprintf(stderr, "To %s\n", dest);
>  
>  	switch(ref->status) {
>  	case REF_STATUS_NONE:
> -		print_ref_status('X', "[no match]", ref, NULL, NULL);
> +		print_ref_status('X', "[no match]", ref, NULL, NULL, porcelain);
>  		break;
>  	case REF_STATUS_REJECT_NODELETE:
>  		print_ref_status('!', "[rejected]", ref, NULL,
> -				"remote does not support deleting refs");
> +						 "remote does not support deleting refs", porcelain);
>  		break;
>  	case REF_STATUS_UPTODATE:
>  		print_ref_status('=', "[up to date]", ref,
> -				ref->peer_ref, NULL);
> +						 ref->peer_ref, NULL, porcelain);
>  		break;
>  	case REF_STATUS_REJECT_NONFASTFORWARD:
>  		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
> -				"non-fast forward");
> +						 "non-fast forward", porcelain);
>  		break;
>  	case REF_STATUS_REMOTE_REJECT:
>  		print_ref_status('!', "[remote rejected]", ref,
> -				ref->deletion ? NULL : ref->peer_ref,
> -				ref->remote_status);
> +						 ref->deletion ? NULL : ref->peer_ref,
> +						 ref->remote_status, porcelain);
>  		break;
>  	case REF_STATUS_EXPECTING_REPORT:
>  		print_ref_status('!', "[remote failure]", ref,
> -				ref->deletion ? NULL : ref->peer_ref,
> -				"remote failed to report status");
> +						 ref->deletion ? NULL : ref->peer_ref,
> +						 "remote failed to report status", porcelain);
>  		break;
>  	case REF_STATUS_OK:
> -		print_ok_ref_status(ref);
> +		print_ok_ref_status(ref, porcelain);
>  		break;
>  	}
>  
>  	return 1;
>  }
>  
> -static void print_push_status(const char *dest, struct ref *refs, int verbose)
> +static void print_push_status(const char *dest, struct ref *refs,
> +							  int verbose, int porcelain)
>  {
>  	struct ref *ref;
>  	int n = 0;
> @@ -816,18 +828,18 @@ static void print_push_status(const char *dest, struct ref *refs, int verbose)
>  	if (verbose) {
>  		for (ref = refs; ref; ref = ref->next)
>  			if (ref->status == REF_STATUS_UPTODATE)
> -				n += print_one_push_status(ref, dest, n);
> +				n += print_one_push_status(ref, dest, n, porcelain);
>  	}
>  
>  	for (ref = refs; ref; ref = ref->next)
>  		if (ref->status == REF_STATUS_OK)
> -			n += print_one_push_status(ref, dest, n);
> +			n += print_one_push_status(ref, dest, n, porcelain);
>  
>  	for (ref = refs; ref; ref = ref->next) {
>  		if (ref->status != REF_STATUS_NONE &&
>  		    ref->status != REF_STATUS_UPTODATE &&
>  		    ref->status != REF_STATUS_OK)
> -			n += print_one_push_status(ref, dest, n);
> +			n += print_one_push_status(ref, dest, n, porcelain);
>  	}
>  }
>  
> @@ -997,6 +1009,7 @@ int transport_push(struct transport *transport,
>  		struct ref *local_refs = get_local_heads();
>  		int match_flags = MATCH_REFS_NONE;
>  		int verbose = flags & TRANSPORT_PUSH_VERBOSE;
> +		int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
>  		int ret;
>  
>  		if (flags & TRANSPORT_PUSH_ALL)
> @@ -1011,7 +1024,7 @@ int transport_push(struct transport *transport,
>  
>  		ret = transport->push_refs(transport, remote_refs, flags);
>  
> -		print_push_status(transport->url, remote_refs, verbose);
> +		print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);
>  
>  		if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
>  			struct ref *ref;
> diff --git a/transport.h b/transport.h
> index 27bfc52..51b5397 100644
> --- a/transport.h
> +++ b/transport.h
> @@ -35,6 +35,7 @@ struct transport {
>  #define TRANSPORT_PUSH_DRY_RUN 4
>  #define TRANSPORT_PUSH_MIRROR 8
>  #define TRANSPORT_PUSH_VERBOSE 16
> +#define TRANSPORT_PUSH_PORCELAIN 32
>  
>  /* Returns a transport suitable for the url */
>  struct transport *transport_get(struct remote *, const char *);

  reply	other threads:[~2009-06-23 15:08 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-18 21:28 I'd like to be able to know what git-push will do Larry D'Anna
2009-06-22 21:40 ` Jeff King
2009-06-23  1:10   ` [PATCH] add --porcelain option to git-push Larry D'Anna
2009-06-23 15:07     ` Marc Branchaud [this message]
2009-06-23 15:38       ` [PATCH] add --plumbing " Larry D'Anna
2009-06-23 15:50       ` [PATCH] add --porcelain " Junio C Hamano
2009-06-23 17:09         ` Marc Branchaud
2009-06-23 18:41       ` Markus Heidelberg
2009-06-23 22:38     ` Constantine Plotnikov
2009-06-24  0:26       ` Larry D'Anna
2009-06-25 19:07     ` Junio C Hamano
2009-06-25 19:30       ` Larry D'Anna
2009-06-27  0:23       ` [PATCH] add --summary " Larry D'Anna

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A40EF9C.7000706@xiplink.com \
    --to=marcnarc@xiplink.com \
    --cc=git@vger.kernel.org \
    --cc=larry@elder-gods.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).