From: Junio C Hamano Date: Thu, 7 Feb 2013 23:15:08 +0000 (-0800) Subject: Merge branch 'ft/transport-report-segv' into maint X-Git-Tag: v1.8.1.3~4 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/772847341bc6ea73c57f350ae25688eae95c5c23?ds=inline;hp=-c Merge branch 'ft/transport-report-segv' into maint A failure to push due to non-ff while on an unborn branch dereferenced a NULL pointer when showing an error message. * ft/transport-report-segv: push: fix segfault when HEAD points nowhere --- 772847341bc6ea73c57f350ae25688eae95c5c23 diff --combined transport.c index 9932f402df,af442af329..b9306ef645 --- a/transport.c +++ b/transport.c @@@ -11,7 -11,6 +11,7 @@@ #include "branch.h" #include "url.h" #include "submodule.h" +#include "string-list.h" /* rsync support */ @@@ -518,7 -517,8 +518,7 @@@ static int fetch_refs_via_pack(struct t int nr_heads, struct ref **to_fetch) { struct git_transport_data *data = transport->data; - char **heads = xmalloc(nr_heads * sizeof(*heads)); - char **origh = xmalloc(nr_heads * sizeof(*origh)); + struct string_list sought = STRING_LIST_INIT_DUP; const struct ref *refs; char *dest = xstrdup(transport->url); struct fetch_pack_args args; @@@ -537,7 -537,7 +537,7 @@@ args.depth = data->options.depth; for (i = 0; i < nr_heads; i++) - origh[i] = heads[i] = xstrdup(to_fetch[i]->name); + string_list_append(&sought, to_fetch[i]->name); if (!data->got_remote_heads) { connect_setup(transport, 0, 0); @@@ -547,7 -547,7 +547,7 @@@ refs = fetch_pack(&args, data->fd, data->conn, refs_tmp ? refs_tmp : transport->remote_refs, - dest, nr_heads, heads, &transport->pack_lockfile); + dest, &sought, &transport->pack_lockfile); close(data->fd[0]); close(data->fd[1]); if (finish_connect(data->conn)) @@@ -557,7 -557,10 +557,7 @@@ free_refs(refs_tmp); - for (i = 0; i < nr_heads; i++) - free(origh[i]); - free(origh); - free(heads); + string_list_clear(&sought, 0); free(dest); return (refs ? 0 : -1); } @@@ -741,7 -744,7 +741,7 @@@ void transport_print_push_status(const n += print_one_push_status(ref, dest, n, porcelain); if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD && *nonfastforward != NON_FF_HEAD) { - if (!strcmp(head, ref->name)) + if (head != NULL && !strcmp(head, ref->name)) *nonfastforward = NON_FF_HEAD; else *nonfastforward = NON_FF_OTHER; @@@ -1010,25 -1013,6 +1010,25 @@@ void transport_set_verbosity(struct tra transport->progress = verbosity >= 0 && isatty(2); } +static void die_with_unpushed_submodules(struct string_list *needs_pushing) +{ + int i; + + fprintf(stderr, "The following submodule paths contain changes that can\n" + "not be found on any remote:\n"); + for (i = 0; i < needs_pushing->nr; i++) + printf(" %s\n", needs_pushing->items[i].string); + fprintf(stderr, "\nPlease try\n\n" + " git push --recurse-submodules=on-demand\n\n" + "or cd to the path and use\n\n" + " git push\n\n" + "to push them to a remote.\n\n"); + + string_list_clear(needs_pushing, 0); + + die("Aborting."); +} + int transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags, int *nonfastforward) @@@ -1069,27 -1053,12 +1069,27 @@@ flags & TRANSPORT_PUSH_MIRROR, flags & TRANSPORT_PUSH_FORCE); - if ((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) && !is_bare_repository()) { + if ((flags & TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND) && !is_bare_repository()) { struct ref *ref = remote_refs; for (; ref; ref = ref->next) if (!is_null_sha1(ref->new_sha1) && - check_submodule_needs_pushing(ref->new_sha1,transport->remote->name)) - die("There are unpushed submodules, aborting."); + !push_unpushed_submodules(ref->new_sha1, + transport->remote->name)) + die ("Failed to push all needed submodules!"); + } + + if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND | + TRANSPORT_RECURSE_SUBMODULES_CHECK)) && !is_bare_repository()) { + struct ref *ref = remote_refs; + struct string_list needs_pushing; + + memset(&needs_pushing, 0, sizeof(struct string_list)); + needs_pushing.strdup_strings = 1; + for (; ref; ref = ref->next) + if (!is_null_sha1(ref->new_sha1) && + find_unpushed_submodules(ref->new_sha1, + transport->remote->name, &needs_pushing)) + die_with_unpushed_submodules(&needs_pushing); } push_ret = transport->push_refs(transport, remote_refs, flags); @@@ -1194,7 -1163,7 +1194,7 @@@ int transport_disconnect(struct transpo } /* - * Strip username (and password) from an url and return + * Strip username (and password) from a URL and return * it in a newly allocated string. */ char *transport_anonymize_url(const char *url)