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>
This commit is contained in:
parent
4f2b15ce88
commit
1965ff744a
@ -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
|
||||||
|
@ -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"),
|
||||||
|
75
transport.c
75
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)
|
#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 (porcelain) {
|
||||||
if (from)
|
if (from)
|
||||||
fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
|
fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to->name);
|
||||||
else
|
else
|
||||||
fputs(prettify_refname(to->name), stderr);
|
fprintf(stdout, "%c\t:%s\t", flag, to->name);
|
||||||
if (msg) {
|
if (msg)
|
||||||
fputs(" (", stderr);
|
fprintf(stdout, "%s (%s)\n", summary, msg);
|
||||||
fputs(msg, stderr);
|
else
|
||||||
fputc(')', stderr);
|
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])
|
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;
|
||||||
|
@ -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 *);
|
||||||
|
Loading…
Reference in New Issue
Block a user