@matheusbsbs / matheus-bagliano / commits / 1965ff744a
Fork 0

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 <larry@elder-gods.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Larry D'Anna committed Jun 22, 2009 at 21:10 UTC 1965ff744a7e4cdefcc467991182b779f3c9d0e8
4 files changed +58 -32
Documentation/git-push.txt
+11
@@ -85,6 +85,11 @@ nor in any Push line of the corresponding remotes file---see below).
85 --dry-run::
86 Do everything except actually send the updates.
87
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 +
93 --tags::
94 All refs under `$GIT_DIR/refs/tags` are pushed, in
95 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:
153 <flag> <summary> <from> -> <to> (<reason>)
154 -------------------------------
155
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 +
162 flag::
163 A single character indicating the status of the ref. This is
164 blank for a successfully pushed ref, `!` for a ref that was
builtin-push.c
+2 -1
@@ -10,7 +10,7 @@
10 #include "parse-options.h"
11
12 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>...]",
14 NULL,
15 };
16
@@ -200,6 +200,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
200 (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
201 OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
202 OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
203 + OPT_BIT( 0, "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
204 OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
205 OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
206 OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
transport.c
+44 -31
@@ -719,19 +719,30 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref, int verb
719
720 #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
721
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)
723 {
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);
745 }
734 - fputc('\n', stderr);
746 }
747
748 static const char *status_abbrev(unsigned char sha1[20])
@@ -739,15 +750,15 @@ static const char *status_abbrev(unsigned char sha1[20])
750 return find_unique_abbrev(sha1, DEFAULT_ABBREV);
751 }
752
742 -static void print_ok_ref_status(struct ref *ref)
753 +static void print_ok_ref_status(struct ref *ref, int porcelain)
754 {
755 if (ref->deletion)
745 - print_ref_status('-', "[deleted]", ref, NULL, NULL);
756 + print_ref_status('-', "[deleted]", ref, NULL, NULL, porcelain);
757 else if (is_null_sha1(ref->old_sha1))
758 print_ref_status('*',
759 (!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);
762 else {
763 char quickref[84];
764 char type;
@@ -765,50 +776,51 @@ static void print_ok_ref_status(struct ref *ref)
776 }
777 strcat(quickref, status_abbrev(ref->new_sha1));
778
768 - print_ref_status(type, quickref, ref, ref->peer_ref, msg);
779 + print_ref_status(type, quickref, ref, ref->peer_ref, msg, porcelain);
780 }
781 }
782
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)
784 {
785 if (!count)
786 fprintf(stderr, "To %s\n", dest);
787
788 switch(ref->status) {
789 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);
791 break;
792 case REF_STATUS_REJECT_NODELETE:
793 print_ref_status('!', "[rejected]", ref, NULL,
783 - "remote does not support deleting refs");
794 + "remote does not support deleting refs", porcelain);
795 break;
796 case REF_STATUS_UPTODATE:
797 print_ref_status('=', "[up to date]", ref,
787 - ref->peer_ref, NULL);
798 + ref->peer_ref, NULL, porcelain);
799 break;
800 case REF_STATUS_REJECT_NONFASTFORWARD:
801 print_ref_status('!', "[rejected]", ref, ref->peer_ref,
791 - "non-fast forward");
802 + "non-fast forward", porcelain);
803 break;
804 case REF_STATUS_REMOTE_REJECT:
805 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);
808 break;
809 case REF_STATUS_EXPECTING_REPORT:
810 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);
813 break;
814 case REF_STATUS_OK:
804 - print_ok_ref_status(ref);
815 + print_ok_ref_status(ref, porcelain);
816 break;
817 }
818
819 return 1;
820 }
821
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)
824 {
825 struct ref *ref;
826 int n = 0;
@@ -816,18 +828,18 @@ static void print_push_status(const char *dest, struct ref *refs, int verbose)
828 if (verbose) {
829 for (ref = refs; ref; ref = ref->next)
830 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);
832 }
833
834 for (ref = refs; ref; ref = ref->next)
835 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);
837
838 for (ref = refs; ref; ref = ref->next) {
839 if (ref->status != REF_STATUS_NONE &&
840 ref->status != REF_STATUS_UPTODATE &&
841 ref->status != REF_STATUS_OK)
830 - n += print_one_push_status(ref, dest, n);
842 + n += print_one_push_status(ref, dest, n, porcelain);
843 }
844 }
845
@@ -997,6 +1009,7 @@ int transport_push(struct transport *transport,
1009 struct ref *local_refs = get_local_heads();
1010 int match_flags = MATCH_REFS_NONE;
1011 int verbose = flags & TRANSPORT_PUSH_VERBOSE;
1012 + int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
1013 int ret;
1014
1015 if (flags & TRANSPORT_PUSH_ALL)
@@ -1011,7 +1024,7 @@ int transport_push(struct transport *transport,
1024
1025 ret = transport->push_refs(transport, remote_refs, flags);
1026
1014 - print_push_status(transport->url, remote_refs, verbose);
1027 + print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);
1028
1029 if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
1030 struct ref *ref;
transport.h
+1
@@ -35,6 +35,7 @@ struct transport {
35 #define TRANSPORT_PUSH_DRY_RUN 4
36 #define TRANSPORT_PUSH_MIRROR 8
37 #define TRANSPORT_PUSH_VERBOSE 16
38 +#define TRANSPORT_PUSH_PORCELAIN 32
39
40 /* Returns a transport suitable for the url */
41 struct transport *transport_get(struct remote *, const char *);