diff options
Diffstat (limited to 'transport.c')
-rw-r--r-- | transport.c | 181 |
1 files changed, 135 insertions, 46 deletions
diff --git a/transport.c b/transport.c index b41386eccb..47da955e4f 100644 --- a/transport.c +++ b/transport.c @@ -127,7 +127,7 @@ struct bundle_transport_data { static struct ref *get_refs_from_bundle(struct transport *transport, int for_push, - const struct argv_array *ref_prefixes) + const struct strvec *ref_prefixes) { struct bundle_transport_data *data = transport->data; struct ref *result = NULL; @@ -232,9 +232,6 @@ static int set_git_option(struct git_transport_options *opts, } else if (!strcmp(name, TRANS_OPT_FROM_PROMISOR)) { opts->from_promisor = !!value; return 0; - } else if (!strcmp(name, TRANS_OPT_NO_DEPENDENTS)) { - opts->no_dependents = !!value; - return 0; } else if (!strcmp(name, TRANS_OPT_LIST_OBJECTS_FILTER)) { list_objects_filter_die_if_populated(&opts->filter_options); parse_list_objects_filter(&opts->filter_options, value); @@ -283,7 +280,7 @@ static void die_if_server_options(struct transport *transport) * remote refs. */ static struct ref *handshake(struct transport *transport, int for_push, - const struct argv_array *ref_prefixes, + const struct strvec *ref_prefixes, int must_list_refs) { struct git_transport_data *data = transport->data; @@ -327,7 +324,7 @@ static struct ref *handshake(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) + const struct strvec *ref_prefixes) { return handshake(transport, for_push, ref_prefixes, 1); } @@ -359,7 +356,6 @@ static int fetch_refs_via_pack(struct transport *transport, args.cloning = transport->cloning; args.update_shallow = data->options.update_shallow; args.from_promisor = data->options.from_promisor; - args.no_dependents = data->options.no_dependents; args.filter_options = data->options.filter_options; args.stateless_rpc = transport->stateless_rpc; args.server_options = transport->server_options; @@ -436,37 +432,67 @@ int transport_refs_pushed(struct ref *ref) return 0; } -void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose) +static void update_one_tracking_ref(struct remote *remote, char *refname, + struct object_id *new_oid, int deletion, + int verbose) { struct refspec_item rs; - if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE) - return; - - rs.src = ref->name; + memset(&rs, 0, sizeof(rs)); + rs.src = refname; rs.dst = NULL; if (!remote_find_tracking(remote, &rs)) { if (verbose) fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); - if (ref->deletion) { + if (deletion) delete_ref(NULL, rs.dst, NULL, 0); - } else - update_ref("update by push", rs.dst, &ref->new_oid, + else + update_ref("update by push", rs.dst, new_oid, NULL, 0, 0); free(rs.dst); } } +void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose) +{ + char *refname; + struct object_id *new_oid; + struct ref_push_report *report; + + if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE) + return; + + report = ref->report; + if (!report) + update_one_tracking_ref(remote, ref->name, &ref->new_oid, + ref->deletion, verbose); + else + for (; report; report = report->next) { + refname = report->ref_name ? (char *)report->ref_name : ref->name; + new_oid = report->new_oid ? report->new_oid : &ref->new_oid; + update_one_tracking_ref(remote, refname, new_oid, + is_null_oid(new_oid), verbose); + } +} + static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, + struct ref_push_report *report, int porcelain, int summary_width) { + const char *to_name; + + if (report && report->ref_name) + to_name = report->ref_name; + else + to_name = to->name; + if (porcelain) { if (from) - fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to->name); + fprintf(stdout, "%c\t%s:%s\t", flag, from->name, to_name); else - fprintf(stdout, "%c\t:%s\t", flag, to->name); + fprintf(stdout, "%c\t:%s\t", flag, to_name); if (msg) fprintf(stdout, "%s (%s)\n", summary, msg); else @@ -480,9 +506,11 @@ static void print_ref_status(char flag, const char *summary, 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)); + fprintf(stderr, "%s -> %s", + prettify_refname(from->name), + prettify_refname(to_name)); else - fputs(prettify_refname(to->name), stderr); + fputs(prettify_refname(to_name), stderr); if (msg) { fputs(" (", stderr); fputs(msg, stderr); @@ -492,24 +520,52 @@ static void print_ref_status(char flag, const char *summary, } } -static void print_ok_ref_status(struct ref *ref, int porcelain, int summary_width) +static void print_ok_ref_status(struct ref *ref, + struct ref_push_report *report, + int porcelain, int summary_width) { + struct object_id *old_oid; + struct object_id *new_oid; + const char *ref_name; + int forced_update; + + if (report && report->old_oid) + old_oid = report->old_oid; + else + old_oid = &ref->old_oid; + if (report && report->new_oid) + new_oid = report->new_oid; + else + new_oid = &ref->new_oid; + if (report && report->forced_update) + forced_update = report->forced_update; + else + forced_update = ref->forced_update; + if (report && report->ref_name) + ref_name = report->ref_name; + else + ref_name = ref->name; + if (ref->deletion) print_ref_status('-', "[deleted]", ref, NULL, NULL, - porcelain, summary_width); - else if (is_null_oid(&ref->old_oid)) + report, porcelain, summary_width); + else if (is_null_oid(old_oid)) print_ref_status('*', - (starts_with(ref->name, "refs/tags/") ? "[new tag]" : - "[new branch]"), - ref, ref->peer_ref, NULL, porcelain, summary_width); + (starts_with(ref_name, "refs/tags/") + ? "[new tag]" + : (starts_with(ref_name, "refs/heads/") + ? "[new branch]" + : "[new reference]")), + ref, ref->peer_ref, NULL, + report, porcelain, summary_width); else { struct strbuf quickref = STRBUF_INIT; char type; const char *msg; - strbuf_add_unique_abbrev(&quickref, &ref->old_oid, + strbuf_add_unique_abbrev(&quickref, old_oid, DEFAULT_ABBREV); - if (ref->forced_update) { + if (forced_update) { strbuf_addstr(&quickref, "..."); type = '+'; msg = "forced update"; @@ -518,16 +574,17 @@ 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, + strbuf_add_unique_abbrev(&quickref, new_oid, DEFAULT_ABBREV); print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg, - porcelain, summary_width); + report, porcelain, summary_width); strbuf_release(&quickref); } } -static int print_one_push_status(struct ref *ref, const char *dest, int count, +static int print_one_push_report(struct ref *ref, const char *dest, int count, + struct ref_push_report *report, int porcelain, int summary_width) { if (!count) { @@ -539,65 +596,94 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, switch(ref->status) { case REF_STATUS_NONE: print_ref_status('X', "[no match]", ref, NULL, NULL, - porcelain, summary_width); + report, porcelain, summary_width); break; case REF_STATUS_REJECT_NODELETE: print_ref_status('!', "[rejected]", ref, NULL, "remote does not support deleting refs", - porcelain, summary_width); + report, porcelain, summary_width); break; case REF_STATUS_UPTODATE: print_ref_status('=', "[up to date]", ref, - ref->peer_ref, NULL, porcelain, summary_width); + ref->peer_ref, NULL, + report, porcelain, summary_width); break; case REF_STATUS_REJECT_NONFASTFORWARD: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "non-fast-forward", porcelain, summary_width); + "non-fast-forward", + report, porcelain, summary_width); break; case REF_STATUS_REJECT_ALREADY_EXISTS: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "already exists", porcelain, summary_width); + "already exists", + report, porcelain, summary_width); break; case REF_STATUS_REJECT_FETCH_FIRST: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "fetch first", porcelain, summary_width); + "fetch first", + report, porcelain, summary_width); break; case REF_STATUS_REJECT_NEEDS_FORCE: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "needs force", porcelain, summary_width); + "needs force", + report, porcelain, summary_width); break; case REF_STATUS_REJECT_STALE: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "stale info", porcelain, summary_width); + "stale info", + report, porcelain, summary_width); + break; + case REF_STATUS_REJECT_REMOTE_UPDATED: + print_ref_status('!', "[rejected]", ref, ref->peer_ref, + "remote ref updated since checkout", + report, porcelain, summary_width); break; case REF_STATUS_REJECT_SHALLOW: print_ref_status('!', "[rejected]", ref, ref->peer_ref, "new shallow roots not allowed", - porcelain, summary_width); + report, porcelain, summary_width); break; case REF_STATUS_REMOTE_REJECT: print_ref_status('!', "[remote rejected]", ref, ref->deletion ? NULL : ref->peer_ref, - ref->remote_status, porcelain, summary_width); + ref->remote_status, + report, porcelain, summary_width); break; case REF_STATUS_EXPECTING_REPORT: print_ref_status('!', "[remote failure]", ref, ref->deletion ? NULL : ref->peer_ref, "remote failed to report status", - porcelain, summary_width); + report, porcelain, summary_width); break; case REF_STATUS_ATOMIC_PUSH_FAILED: print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "atomic push failed", porcelain, summary_width); + "atomic push failed", + report, porcelain, summary_width); break; case REF_STATUS_OK: - print_ok_ref_status(ref, porcelain, summary_width); + print_ok_ref_status(ref, report, porcelain, summary_width); break; } return 1; } +static int print_one_push_status(struct ref *ref, const char *dest, int count, + int porcelain, int summary_width) +{ + struct ref_push_report *report; + int n = 0; + + if (!ref->report) + return print_one_push_report(ref, dest, count, + NULL, porcelain, summary_width); + + for (report = ref->report; report; report = report->next) + print_one_push_report(ref, dest, count + n++, + report, porcelain, summary_width); + return n; +} + static int measure_abbrev(const struct object_id *oid, int sofar) { char hex[GIT_MAX_HEXSZ + 1]; @@ -662,6 +748,8 @@ void transport_print_push_status(const char *dest, struct ref *refs, *reject_reasons |= REJECT_FETCH_FIRST; } else if (ref->status == REF_STATUS_REJECT_NEEDS_FORCE) { *reject_reasons |= REJECT_NEEDS_FORCE; + } else if (ref->status == REF_STATUS_REJECT_REMOTE_UPDATED) { + *reject_reasons |= REJECT_REF_NEEDS_UPDATE; } } free(head); @@ -1104,6 +1192,7 @@ static int run_pre_push_hook(struct transport *transport, if (!r->peer_ref) continue; if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue; if (r->status == REF_STATUS_REJECT_STALE) continue; + if (r->status == REF_STATUS_REJECT_REMOTE_UPDATED) continue; if (r->status == REF_STATUS_UPTODATE) continue; strbuf_reset(&buf); @@ -1153,7 +1242,7 @@ int transport_push(struct repository *r, 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; + struct strvec ref_prefixes = STRVEC_INIT; if (check_push_refs(local_refs, rs) < 0) return -1; @@ -1165,7 +1254,7 @@ int transport_push(struct repository *r, &ref_prefixes); trace2_region_leave("transport_push", "get_refs_list", r); - argv_array_clear(&ref_prefixes); + strvec_clear(&ref_prefixes); if (flags & TRANSPORT_PUSH_ALL) match_flags |= MATCH_REFS_ALL; @@ -1281,7 +1370,7 @@ int transport_push(struct repository *r, } const struct ref *transport_get_remote_refs(struct transport *transport, - const struct argv_array *ref_prefixes) + const struct strvec *ref_prefixes) { if (!transport->got_remote_refs) { transport->remote_refs = |