diff options
Diffstat (limited to 'transport.c')
-rw-r--r-- | transport.c | 225 |
1 files changed, 157 insertions, 68 deletions
diff --git a/transport.c b/transport.c index 00d48b5b56..a32da30dee 100644 --- a/transport.c +++ b/transport.c @@ -11,6 +11,7 @@ #include "bundle.h" #include "dir.h" #include "refs.h" +#include "refspec.h" #include "branch.h" #include "url.h" #include "submodule.h" @@ -18,6 +19,58 @@ #include "sha1-array.h" #include "sigchain.h" #include "transport-internal.h" +#include "protocol.h" +#include "object-store.h" +#include "color.h" + +static int transport_use_color = -1; +static char transport_colors[][COLOR_MAXLEN] = { + GIT_COLOR_RESET, + GIT_COLOR_RED /* REJECTED */ +}; + +enum color_transport { + TRANSPORT_COLOR_RESET = 0, + TRANSPORT_COLOR_REJECTED = 1 +}; + +static int transport_color_config(void) +{ + const char *keys[] = { + "color.transport.reset", + "color.transport.rejected" + }, *key = "color.transport"; + char *value; + int i; + static int initialized; + + if (initialized) + return 0; + initialized = 1; + + if (!git_config_get_string(key, &value)) + transport_use_color = git_config_colorbool(key, value); + + if (!want_color_stderr(transport_use_color)) + return 0; + + for (i = 0; i < ARRAY_SIZE(keys); i++) + if (!git_config_get_string(keys[i], &value)) { + if (!value) + return config_error_nonbool(keys[i]); + if (color_parse(value, transport_colors[i]) < 0) + return -1; + } + + return 0; +} + +static const char *transport_get_color(enum color_transport ix) +{ + if (want_color_stderr(transport_use_color)) + return transport_colors[ix]; + return ""; +} static void set_upstreams(struct transport *transport, struct ref *refs, int pretend) @@ -71,7 +124,9 @@ struct bundle_transport_data { struct bundle_header header; }; -static struct ref *get_refs_from_bundle(struct transport *transport, int for_push) +static struct ref *get_refs_from_bundle(struct transport *transport, + int for_push, + const struct argv_array *ref_prefixes) { struct bundle_transport_data *data = transport->data; struct ref *result = NULL; @@ -117,6 +172,7 @@ struct git_transport_data { struct child_process *conn; int fd[2]; unsigned got_remote_heads : 1; + enum protocol_version version; struct oid_array extra_have; struct oid_array shallow; }; @@ -196,16 +252,35 @@ static int connect_setup(struct transport *transport, int for_push) return 0; } -static struct ref *get_refs_via_connect(struct transport *transport, int for_push) +static struct ref *get_refs_via_connect(struct transport *transport, int for_push, + const struct argv_array *ref_prefixes) { struct git_transport_data *data = transport->data; - struct ref *refs; + struct ref *refs = NULL; + struct packet_reader reader; connect_setup(transport, for_push); - get_remote_heads(data->fd[0], NULL, 0, &refs, - for_push ? REF_NORMAL : 0, - &data->extra_have, - &data->shallow); + + packet_reader_init(&reader, data->fd[0], NULL, 0, + PACKET_READ_CHOMP_NEWLINE | + PACKET_READ_GENTLE_ON_EOF); + + data->version = discover_version(&reader); + switch (data->version) { + case protocol_v2: + get_remote_refs(data->fd[1], &reader, &refs, for_push, + ref_prefixes, transport->server_options); + break; + case protocol_v1: + case protocol_v0: + get_remote_heads(&reader, &refs, + for_push ? REF_NORMAL : 0, + &data->extra_have, + &data->shallow); + break; + case protocol_unknown_version: + BUG("unknown protocol version"); + } data->got_remote_heads = 1; return refs; @@ -216,7 +291,7 @@ static int fetch_refs_via_pack(struct transport *transport, { int ret = 0; struct git_transport_data *data = transport->data; - struct ref *refs; + struct ref *refs = NULL; char *dest = xstrdup(transport->url); struct fetch_pack_args args; struct ref *refs_tmp = NULL; @@ -241,18 +316,30 @@ static int fetch_refs_via_pack(struct transport *transport, args.from_promisor = data->options.from_promisor; args.no_dependents = data->options.no_dependents; args.filter_options = data->options.filter_options; - - if (!data->got_remote_heads) { - connect_setup(transport, 0); - get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0, - NULL, &data->shallow); - data->got_remote_heads = 1; + args.stateless_rpc = transport->stateless_rpc; + args.server_options = transport->server_options; + + if (!data->got_remote_heads) + refs_tmp = get_refs_via_connect(transport, 0, NULL); + + switch (data->version) { + case protocol_v2: + refs = fetch_pack(&args, data->fd, data->conn, + refs_tmp ? refs_tmp : transport->remote_refs, + dest, to_fetch, nr_heads, &data->shallow, + &transport->pack_lockfile, data->version); + break; + case protocol_v1: + case protocol_v0: + refs = fetch_pack(&args, data->fd, data->conn, + refs_tmp ? refs_tmp : transport->remote_refs, + dest, to_fetch, nr_heads, &data->shallow, + &transport->pack_lockfile, data->version); + break; + case protocol_unknown_version: + BUG("unknown protocol version"); } - refs = fetch_pack(&args, data->fd, data->conn, - refs_tmp ? refs_tmp : transport->remote_refs, - dest, to_fetch, nr_heads, &data->shallow, - &transport->pack_lockfile); close(data->fd[0]); close(data->fd[1]); if (finish_connect(data->conn)) @@ -304,7 +391,7 @@ int transport_refs_pushed(struct ref *ref) void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose) { - struct refspec rs; + struct refspec_item rs; if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE) return; @@ -338,7 +425,13 @@ static void print_ref_status(char flag, const char *summary, else fprintf(stdout, "%s\n", summary); } else { - fprintf(stderr, " %c %-*s ", flag, summary_width, summary); + const char *red = "", *reset = ""; + if (push_had_errors(to)) { + red = transport_get_color(TRANSPORT_COLOR_REJECTED); + reset = transport_get_color(TRANSPORT_COLOR_RESET); + } + fprintf(stderr, " %s%c %-*s%s ", red, flag, summary_width, + summary, reset); if (from) fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name)); else @@ -367,7 +460,7 @@ static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_widt char type; const char *msg; - strbuf_add_unique_abbrev(&quickref, ref->old_oid.hash, + strbuf_add_unique_abbrev(&quickref, &ref->old_oid, DEFAULT_ABBREV); if (ref->forced_update) { strbuf_addstr(&quickref, "..."); @@ -378,7 +471,7 @@ static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_widt type = ' '; msg = NULL; } - strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, + strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV); print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg, @@ -461,7 +554,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, static int measure_abbrev(const struct object_id *oid, int sofar) { char hex[GIT_MAX_HEXSZ + 1]; - int w = find_unique_abbrev_r(hex, oid->hash, DEFAULT_ABBREV); + int w = find_unique_abbrev_r(hex, oid, DEFAULT_ABBREV); return (w < sofar) ? sofar : w; } @@ -487,6 +580,9 @@ void transport_print_push_status(const char *dest, struct ref *refs, char *head; int summary_width = transport_summary_width(refs); + if (transport_color_config() < 0) + warning(_("could not parse transport.color.* config")); + head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL); if (verbose) { @@ -524,43 +620,17 @@ void transport_print_push_status(const char *dest, struct ref *refs, free(head); } -void transport_verify_remote_names(int nr_heads, const char **heads) -{ - int i; - - for (i = 0; i < nr_heads; i++) { - const char *local = heads[i]; - const char *remote = strrchr(heads[i], ':'); - - if (*local == '+') - local++; - - /* A matching refspec is okay. */ - if (remote == local && remote[1] == '\0') - continue; - - remote = remote ? (remote + 1) : local; - if (check_refname_format(remote, - REFNAME_ALLOW_ONELEVEL|REFNAME_REFSPEC_PATTERN)) - die("remote part of refspec is not a valid name in %s", - heads[i]); - } -} - static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags) { struct git_transport_data *data = transport->data; struct send_pack_args args; - int ret; + int ret = 0; - if (!data->got_remote_heads) { - struct ref *tmp_refs; - connect_setup(transport, 1); + if (transport_color_config() < 0) + return -1; - get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL, - NULL, &data->shallow); - data->got_remote_heads = 1; - } + if (!data->got_remote_heads) + get_refs_via_connect(transport, 1, NULL); memset(&args, 0, sizeof(args)); args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR); @@ -582,8 +652,18 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re else args.push_cert = SEND_PACK_PUSH_CERT_NEVER; - ret = send_pack(&args, data->fd, data->conn, remote_refs, - &data->extra_have); + switch (data->version) { + case protocol_v2: + die("support for protocol v2 not implemented yet"); + break; + case protocol_v1: + case protocol_v0: + ret = send_pack(&args, data->fd, data->conn, remote_refs, + &data->extra_have); + break; + case protocol_unknown_version: + BUG("unknown protocol version"); + } close(data->fd[1]); close(data->fd[0]); @@ -635,7 +715,7 @@ void transport_take_over(struct transport *transport, struct git_transport_data *data; if (!transport->smart_options) - die("BUG: taking over transport requires non-NULL " + BUG("taking over transport requires non-NULL " "smart_options field."); data = xcalloc(1, sizeof(*data)); @@ -760,7 +840,7 @@ int is_transport_allowed(const char *type, int from_user) return from_user; } - die("BUG: invalid protocol_allow_config type"); + BUG("invalid protocol_allow_config type"); } void transport_check_allowed(const char *type) @@ -991,11 +1071,13 @@ static int run_pre_push_hook(struct transport *transport, } int transport_push(struct transport *transport, - int refspec_nr, const char **refspec, int flags, + struct refspec *rs, int flags, unsigned int *reject_reasons) { *reject_reasons = 0; - transport_verify_remote_names(refspec_nr, refspec); + + if (transport_color_config() < 0) + return -1; if (transport->vtable->push_refs) { struct ref *remote_refs; @@ -1006,11 +1088,17 @@ int transport_push(struct transport *transport, int porcelain = flags & TRANSPORT_PUSH_PORCELAIN; int pretend = flags & TRANSPORT_PUSH_DRY_RUN; int push_ret, ret, err; + struct argv_array ref_prefixes = ARGV_ARRAY_INIT; - if (check_push_refs(local_refs, refspec_nr, refspec) < 0) + if (check_push_refs(local_refs, rs) < 0) return -1; - remote_refs = transport->vtable->get_refs_list(transport, 1); + refspec_ref_prefixes(rs, &ref_prefixes); + + remote_refs = transport->vtable->get_refs_list(transport, 1, + &ref_prefixes); + + argv_array_clear(&ref_prefixes); if (flags & TRANSPORT_PUSH_ALL) match_flags |= MATCH_REFS_ALL; @@ -1021,10 +1109,8 @@ int transport_push(struct transport *transport, if (flags & TRANSPORT_PUSH_FOLLOW_TAGS) match_flags |= MATCH_REFS_FOLLOW_TAGS; - if (match_push_refs(local_refs, &remote_refs, - refspec_nr, refspec, match_flags)) { + if (match_push_refs(local_refs, &remote_refs, rs, match_flags)) return -1; - } if (transport->smart_options && transport->smart_options->cas && @@ -1053,7 +1139,7 @@ int transport_push(struct transport *transport, if (!push_unpushed_submodules(&commits, transport->remote, - refspec, refspec_nr, + rs, transport->push_options, pretend)) { oid_array_clear(&commits); @@ -1116,10 +1202,13 @@ int transport_push(struct transport *transport, return 1; } -const struct ref *transport_get_remote_refs(struct transport *transport) +const struct ref *transport_get_remote_refs(struct transport *transport, + const struct argv_array *ref_prefixes) { if (!transport->got_remote_refs) { - transport->remote_refs = transport->vtable->get_refs_list(transport, 0); + transport->remote_refs = + transport->vtable->get_refs_list(transport, 0, + ref_prefixes); transport->got_remote_refs = 1; } |