diff options
Diffstat (limited to 'transport.c')
-rw-r--r-- | transport.c | 109 |
1 files changed, 79 insertions, 30 deletions
diff --git a/transport.c b/transport.c index 51814b5da3..9932f402df 100644 --- a/transport.c +++ b/transport.c @@ -11,6 +11,7 @@ #include "branch.h" #include "url.h" #include "submodule.h" +#include "string-list.h" /* rsync support */ @@ -163,7 +164,7 @@ static void set_upstreams(struct transport *transport, struct ref *refs, /* Follow symbolic refs (mainly for HEAD). */ localname = ref->peer_ref->name; remotename = ref->name; - tmp = resolve_ref(localname, sha, 1, &flag); + tmp = resolve_ref_unsafe(localname, sha, 1, &flag); if (tmp && flag & REF_ISSYMREF && !prefixcmp(tmp, "refs/heads/")) localname = tmp; @@ -215,7 +216,7 @@ static struct ref *get_refs_via_rsync(struct transport *transport, int for_push) rsync.argv = args; rsync.stdout_to_stderr = 1; args[0] = "rsync"; - args[1] = (transport->verbose > 0) ? "-rv" : "-r"; + args[1] = (transport->verbose > 1) ? "-rv" : "-r"; args[2] = buf.buf; args[3] = temp_dir.buf; args[4] = NULL; @@ -268,7 +269,7 @@ static int fetch_objs_via_rsync(struct transport *transport, rsync.argv = args; rsync.stdout_to_stderr = 1; args[0] = "rsync"; - args[1] = (transport->verbose > 0) ? "-rv" : "-r"; + args[1] = (transport->verbose > 1) ? "-rv" : "-r"; args[2] = "--ignore-existing"; args[3] = "--exclude"; args[4] = "info"; @@ -351,7 +352,7 @@ static int rsync_transport_push(struct transport *transport, args[i++] = "-a"; if (flags & TRANSPORT_PUSH_DRY_RUN) args[i++] = "--dry-run"; - if (transport->verbose > 0) + if (transport->verbose > 1) args[i++] = "-v"; args[i++] = "--ignore-existing"; args[i++] = "--exclude"; @@ -474,8 +475,12 @@ static int set_git_option(struct git_transport_options *opts, } else if (!strcmp(name, TRANS_OPT_DEPTH)) { if (!value) opts->depth = 0; - else - opts->depth = atoi(value); + else { + char *end; + opts->depth = strtol(value, &end, 0); + if (*end) + die("transport: invalid depth option '%s'", value); + } return 0; } return 1; @@ -502,7 +507,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus struct ref *refs; connect_setup(transport, for_push, 0); - get_remote_heads(data->fd[0], &refs, 0, NULL, + get_remote_heads(data->fd[0], &refs, for_push ? REF_NORMAL : 0, &data->extra_have); data->got_remote_heads = 1; @@ -513,8 +518,7 @@ static int fetch_refs_via_pack(struct transport *transport, 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; @@ -527,23 +531,23 @@ static int fetch_refs_via_pack(struct transport *transport, args.lock_pack = 1; args.use_thin_pack = data->options.thin; args.include_tag = data->options.followtags; - args.verbose = (transport->verbose > 0); + args.verbose = (transport->verbose > 1); args.quiet = (transport->verbose < 0); args.no_progress = !transport->progress; 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); - get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL); + get_remote_heads(data->fd[0], &refs_tmp, 0, NULL); data->got_remote_heads = 1; } 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)) @@ -553,10 +557,7 @@ static int fetch_refs_via_pack(struct transport *transport, 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); } @@ -717,6 +718,10 @@ void transport_print_push_status(const char *dest, struct ref *refs, { struct ref *ref; int n = 0; + unsigned char head_sha1[20]; + char *head; + + head = resolve_refdup("HEAD", head_sha1, 1, NULL); if (verbose) { for (ref = refs; ref; ref = ref->next) @@ -734,8 +739,13 @@ void transport_print_push_status(const char *dest, struct ref *refs, ref->status != REF_STATUS_UPTODATE && ref->status != REF_STATUS_OK) n += print_one_push_status(ref, dest, n, porcelain); - if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD) - *nonfastforward = 1; + if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD && + *nonfastforward != NON_FF_HEAD) { + if (!strcmp(head, ref->name)) + *nonfastforward = NON_FF_HEAD; + else + *nonfastforward = NON_FF_OTHER; + } } } @@ -772,8 +782,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re struct ref *tmp_refs; connect_setup(transport, 1, 0); - get_remote_heads(data->fd[0], &tmp_refs, 0, NULL, REF_NORMAL, - NULL); + get_remote_heads(data->fd[0], &tmp_refs, REF_NORMAL, NULL); data->got_remote_heads = 1; } @@ -981,7 +990,7 @@ int transport_set_option(struct transport *transport, void transport_set_verbosity(struct transport *transport, int verbosity, int force_progress) { - if (verbosity >= 2) + if (verbosity >= 1) transport->verbose = verbosity <= 3 ? verbosity : 3; if (verbosity < 0) transport->verbose = -1; @@ -990,11 +999,34 @@ void transport_set_verbosity(struct transport *transport, int verbosity, * Rules used to determine whether to report progress (processing aborts * when a rule is satisfied): * - * 1. Report progress, if force_progress is 1 (ie. --progress). - * 2. Don't report progress, if verbosity < 0 (ie. -q/--quiet ). - * 3. Report progress if isatty(2) is 1. + * . Report progress, if force_progress is 1 (ie. --progress). + * . Don't report progress, if force_progress is 0 (ie. --no-progress). + * . Don't report progress, if verbosity < 0 (ie. -q/--quiet ). + * . Report progress if isatty(2) is 1. **/ - transport->progress = force_progress || (verbosity >= 0 && isatty(2)); + if (force_progress >= 0) + transport->progress = !!force_progress; + else + 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, @@ -1025,6 +1057,8 @@ int transport_push(struct transport *transport, match_flags |= MATCH_REFS_ALL; if (flags & TRANSPORT_PUSH_MIRROR) match_flags |= MATCH_REFS_MIRROR; + if (flags & TRANSPORT_PUSH_PRUNE) + match_flags |= MATCH_REFS_PRUNE; if (match_push_refs(local_refs, &remote_refs, refspec_nr, refspec, match_flags)) { @@ -1035,12 +1069,27 @@ int transport_push(struct transport *transport, 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) && + !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) && - check_submodule_needs_pushing(ref->new_sha1,transport->remote->name)) - die("There are unpushed submodules, aborting."); + 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); @@ -1145,7 +1194,7 @@ int transport_disconnect(struct transport *transport) } /* - * 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) |