Skip to content

Commit 1965ff7

Browse files
smoofragitster
authored andcommitted
add --porcelain option to git-push
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] Signed-off-by: Larry D'Anna <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4f2b15c commit 1965ff7

File tree

4 files changed

+58
-32
lines changed

4 files changed

+58
-32
lines changed

Documentation/git-push.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ nor in any Push line of the corresponding remotes file---see below).
8585
--dry-run::
8686
Do everything except actually send the updates.
8787

88+
--porcelain::
89+
Produce machine-readable output. The output status line for each ref
90+
will be tab-separated and sent to stdout instead of stderr. The full
91+
symbolic names of the refs will be given.
92+
8893
--tags::
8994
All refs under `$GIT_DIR/refs/tags` are pushed, in
9095
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:
148153
<flag> <summary> <from> -> <to> (<reason>)
149154
-------------------------------
150155

156+
If --porcelain is used, then each line of the output is of the form:
157+
158+
-------------------------------
159+
<flag> \t <from>:<to> \t <summary> (<reason>)
160+
-------------------------------
161+
151162
flag::
152163
A single character indicating the status of the ref. This is
153164
blank for a successfully pushed ref, `!` for a ref that was

builtin-push.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include "parse-options.h"
1111

1212
static const char * const push_usage[] = {
13-
"git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
13+
"git push [--all | --mirror] [--dry-run] [--porcelain] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
1414
NULL,
1515
};
1616

@@ -200,6 +200,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
200200
(TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
201201
OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
202202
OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
203+
OPT_BIT( 0, "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
203204
OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
204205
OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
205206
OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),

transport.c

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -719,35 +719,46 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref, int verb
719719

720720
#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
721721

722-
static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
722+
static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain)
723723
{
724-
fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
725-
if (from)
726-
fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
727-
else
728-
fputs(prettify_refname(to->name), stderr);
729-
if (msg) {
730-
fputs(" (", stderr);
731-
fputs(msg, stderr);
732-
fputc(')', stderr);
724+
if (porcelain) {
725+
if (from)
726+
fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to->name);
727+
else
728+
fprintf(stdout, "%c\t:%s\t", flag, to->name);
729+
if (msg)
730+
fprintf(stdout, "%s (%s)\n", summary, msg);
731+
else
732+
fprintf(stdout, "%s\n", summary);
733+
} else {
734+
fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
735+
if (from)
736+
fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
737+
else
738+
fputs(prettify_refname(to->name), stderr);
739+
if (msg) {
740+
fputs(" (", stderr);
741+
fputs(msg, stderr);
742+
fputc(')', stderr);
743+
}
744+
fputc('\n', stderr);
733745
}
734-
fputc('\n', stderr);
735746
}
736747

737748
static const char *status_abbrev(unsigned char sha1[20])
738749
{
739750
return find_unique_abbrev(sha1, DEFAULT_ABBREV);
740751
}
741752

742-
static void print_ok_ref_status(struct ref *ref)
753+
static void print_ok_ref_status(struct ref *ref, int porcelain)
743754
{
744755
if (ref->deletion)
745-
print_ref_status('-', "[deleted]", ref, NULL, NULL);
756+
print_ref_status('-', "[deleted]", ref, NULL, NULL, porcelain);
746757
else if (is_null_sha1(ref->old_sha1))
747758
print_ref_status('*',
748759
(!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
749-
"[new branch]"),
750-
ref, ref->peer_ref, NULL);
760+
"[new branch]"),
761+
ref, ref->peer_ref, NULL, porcelain);
751762
else {
752763
char quickref[84];
753764
char type;
@@ -765,69 +776,70 @@ static void print_ok_ref_status(struct ref *ref)
765776
}
766777
strcat(quickref, status_abbrev(ref->new_sha1));
767778

768-
print_ref_status(type, quickref, ref, ref->peer_ref, msg);
779+
print_ref_status(type, quickref, ref, ref->peer_ref, msg, porcelain);
769780
}
770781
}
771782

772-
static int print_one_push_status(struct ref *ref, const char *dest, int count)
783+
static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain)
773784
{
774785
if (!count)
775786
fprintf(stderr, "To %s\n", dest);
776787

777788
switch(ref->status) {
778789
case REF_STATUS_NONE:
779-
print_ref_status('X', "[no match]", ref, NULL, NULL);
790+
print_ref_status('X', "[no match]", ref, NULL, NULL, porcelain);
780791
break;
781792
case REF_STATUS_REJECT_NODELETE:
782793
print_ref_status('!', "[rejected]", ref, NULL,
783-
"remote does not support deleting refs");
794+
"remote does not support deleting refs", porcelain);
784795
break;
785796
case REF_STATUS_UPTODATE:
786797
print_ref_status('=', "[up to date]", ref,
787-
ref->peer_ref, NULL);
798+
ref->peer_ref, NULL, porcelain);
788799
break;
789800
case REF_STATUS_REJECT_NONFASTFORWARD:
790801
print_ref_status('!', "[rejected]", ref, ref->peer_ref,
791-
"non-fast forward");
802+
"non-fast forward", porcelain);
792803
break;
793804
case REF_STATUS_REMOTE_REJECT:
794805
print_ref_status('!', "[remote rejected]", ref,
795-
ref->deletion ? NULL : ref->peer_ref,
796-
ref->remote_status);
806+
ref->deletion ? NULL : ref->peer_ref,
807+
ref->remote_status, porcelain);
797808
break;
798809
case REF_STATUS_EXPECTING_REPORT:
799810
print_ref_status('!', "[remote failure]", ref,
800-
ref->deletion ? NULL : ref->peer_ref,
801-
"remote failed to report status");
811+
ref->deletion ? NULL : ref->peer_ref,
812+
"remote failed to report status", porcelain);
802813
break;
803814
case REF_STATUS_OK:
804-
print_ok_ref_status(ref);
815+
print_ok_ref_status(ref, porcelain);
805816
break;
806817
}
807818

808819
return 1;
809820
}
810821

811-
static void print_push_status(const char *dest, struct ref *refs, int verbose)
822+
static void print_push_status(const char *dest, struct ref *refs,
823+
int verbose, int porcelain)
812824
{
813825
struct ref *ref;
814826
int n = 0;
815827

816828
if (verbose) {
817829
for (ref = refs; ref; ref = ref->next)
818830
if (ref->status == REF_STATUS_UPTODATE)
819-
n += print_one_push_status(ref, dest, n);
831+
n += print_one_push_status(ref, dest, n, porcelain);
820832
}
821833

822834
for (ref = refs; ref; ref = ref->next)
823835
if (ref->status == REF_STATUS_OK)
824-
n += print_one_push_status(ref, dest, n);
836+
n += print_one_push_status(ref, dest, n, porcelain);
825837

826838
for (ref = refs; ref; ref = ref->next) {
827839
if (ref->status != REF_STATUS_NONE &&
828840
ref->status != REF_STATUS_UPTODATE &&
829841
ref->status != REF_STATUS_OK)
830-
n += print_one_push_status(ref, dest, n);
842+
n += print_one_push_status(ref, dest, n, porcelain);
831843
}
832844
}
833845

@@ -997,6 +1009,7 @@ int transport_push(struct transport *transport,
9971009
struct ref *local_refs = get_local_heads();
9981010
int match_flags = MATCH_REFS_NONE;
9991011
int verbose = flags & TRANSPORT_PUSH_VERBOSE;
1012+
int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
10001013
int ret;
10011014

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

10121025
ret = transport->push_refs(transport, remote_refs, flags);
10131026

1014-
print_push_status(transport->url, remote_refs, verbose);
1027+
print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);
10151028

10161029
if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
10171030
struct ref *ref;

transport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct transport {
3535
#define TRANSPORT_PUSH_DRY_RUN 4
3636
#define TRANSPORT_PUSH_MIRROR 8
3737
#define TRANSPORT_PUSH_VERBOSE 16
38+
#define TRANSPORT_PUSH_PORCELAIN 32
3839

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

0 commit comments

Comments
 (0)