Merge branch 'ld/push-porcelain-output-format'

* ld/push-porcelain-output-format:
  add --porcelain option to git-push
maint
Junio C Hamano 2009-07-09 01:07:54 -07:00
commit 3125be17d6
4 changed files with 58 additions and 32 deletions

View File

@ -85,6 +85,11 @@ nor in any Push line of the corresponding remotes file---see below).
--dry-run:: --dry-run::
Do everything except actually send the updates. 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:: --tags::
All refs under `$GIT_DIR/refs/tags` are pushed, in All refs under `$GIT_DIR/refs/tags` are pushed, in
addition to refspecs explicitly listed on the command 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>) <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:: flag::
A single character indicating the status of the ref. This is A single character indicating the status of the ref. This is
blank for a successfully pushed ref, `!` for a ref that was blank for a successfully pushed ref, `!` for a ref that was

View File

@ -10,7 +10,7 @@
#include "parse-options.h" #include "parse-options.h"


static const char * const push_usage[] = { 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, NULL,
}; };


@ -200,6 +200,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
(TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
OPT_BOOLEAN( 0 , "tags", &tags, "push tags"), OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN), 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_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"), OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),

View File

@ -719,8 +719,18 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref, int verb


#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) #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)
{ {
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); fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
if (from) 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));
@ -732,6 +742,7 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str
fputc(')', stderr); fputc(')', stderr);
} }
fputc('\n', stderr); fputc('\n', stderr);
}
} }


static const char *status_abbrev(unsigned char sha1[20]) 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); 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) 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)) else if (is_null_sha1(ref->old_sha1))
print_ref_status('*', print_ref_status('*',
(!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" : (!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
"[new branch]"), "[new branch]"),
ref, ref->peer_ref, NULL); ref, ref->peer_ref, NULL, porcelain);
else { else {
char quickref[84]; char quickref[84];
char type; char type;
@ -765,50 +776,51 @@ static void print_ok_ref_status(struct ref *ref)
} }
strcat(quickref, status_abbrev(ref->new_sha1)); 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) if (!count)
fprintf(stderr, "To %s\n", dest); fprintf(stderr, "To %s\n", dest);


switch(ref->status) { switch(ref->status) {
case REF_STATUS_NONE: case REF_STATUS_NONE:
print_ref_status('X', "[no match]", ref, NULL, NULL); print_ref_status('X', "[no match]", ref, NULL, NULL, porcelain);
break; break;
case REF_STATUS_REJECT_NODELETE: case REF_STATUS_REJECT_NODELETE:
print_ref_status('!', "[rejected]", ref, NULL, print_ref_status('!', "[rejected]", ref, NULL,
"remote does not support deleting refs"); "remote does not support deleting refs", porcelain);
break; break;
case REF_STATUS_UPTODATE: case REF_STATUS_UPTODATE:
print_ref_status('=', "[up to date]", ref, print_ref_status('=', "[up to date]", ref,
ref->peer_ref, NULL); ref->peer_ref, NULL, porcelain);
break; break;
case REF_STATUS_REJECT_NONFASTFORWARD: case REF_STATUS_REJECT_NONFASTFORWARD:
print_ref_status('!', "[rejected]", ref, ref->peer_ref, print_ref_status('!', "[rejected]", ref, ref->peer_ref,
"non-fast forward"); "non-fast forward", porcelain);
break; break;
case REF_STATUS_REMOTE_REJECT: case REF_STATUS_REMOTE_REJECT:
print_ref_status('!', "[remote rejected]", ref, print_ref_status('!', "[remote rejected]", ref,
ref->deletion ? NULL : ref->peer_ref, ref->deletion ? NULL : ref->peer_ref,
ref->remote_status); ref->remote_status, porcelain);
break; break;
case REF_STATUS_EXPECTING_REPORT: case REF_STATUS_EXPECTING_REPORT:
print_ref_status('!', "[remote failure]", ref, print_ref_status('!', "[remote failure]", ref,
ref->deletion ? NULL : ref->peer_ref, ref->deletion ? NULL : ref->peer_ref,
"remote failed to report status"); "remote failed to report status", porcelain);
break; break;
case REF_STATUS_OK: case REF_STATUS_OK:
print_ok_ref_status(ref); print_ok_ref_status(ref, porcelain);
break; break;
} }


return 1; 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; struct ref *ref;
int n = 0; int n = 0;
@ -816,18 +828,18 @@ static void print_push_status(const char *dest, struct ref *refs, int verbose)
if (verbose) { if (verbose) {
for (ref = refs; ref; ref = ref->next) for (ref = refs; ref; ref = ref->next)
if (ref->status == REF_STATUS_UPTODATE) 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) for (ref = refs; ref; ref = ref->next)
if (ref->status == REF_STATUS_OK) 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) { for (ref = refs; ref; ref = ref->next) {
if (ref->status != REF_STATUS_NONE && if (ref->status != REF_STATUS_NONE &&
ref->status != REF_STATUS_UPTODATE && ref->status != REF_STATUS_UPTODATE &&
ref->status != REF_STATUS_OK) 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(); struct ref *local_refs = get_local_heads();
int match_flags = MATCH_REFS_NONE; int match_flags = MATCH_REFS_NONE;
int verbose = flags & TRANSPORT_PUSH_VERBOSE; int verbose = flags & TRANSPORT_PUSH_VERBOSE;
int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
int ret; int ret;


if (flags & TRANSPORT_PUSH_ALL) if (flags & TRANSPORT_PUSH_ALL)
@ -1011,7 +1024,7 @@ int transport_push(struct transport *transport,


ret = transport->push_refs(transport, remote_refs, flags); 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)) { if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
struct ref *ref; struct ref *ref;

View File

@ -35,6 +35,7 @@ struct transport {
#define TRANSPORT_PUSH_DRY_RUN 4 #define TRANSPORT_PUSH_DRY_RUN 4
#define TRANSPORT_PUSH_MIRROR 8 #define TRANSPORT_PUSH_MIRROR 8
#define TRANSPORT_PUSH_VERBOSE 16 #define TRANSPORT_PUSH_VERBOSE 16
#define TRANSPORT_PUSH_PORCELAIN 32


/* Returns a transport suitable for the url */ /* Returns a transport suitable for the url */
struct transport *transport_get(struct remote *, const char *); struct transport *transport_get(struct remote *, const char *);