diff options
Diffstat (limited to 'transport.c')
-rw-r--r-- | transport.c | 85 |
1 files changed, 76 insertions, 9 deletions
diff --git a/transport.c b/transport.c index 2673d273ff..bd290fa7d3 100644 --- a/transport.c +++ b/transport.c @@ -518,11 +518,9 @@ static int fetch_refs_via_pack(struct transport *transport, int nr_heads, struct ref **to_fetch) { struct git_transport_data *data = transport->data; - struct string_list sought = STRING_LIST_INIT_DUP; const struct ref *refs; char *dest = xstrdup(transport->url); struct fetch_pack_args args; - int i; struct ref *refs_tmp = NULL; memset(&args, 0, sizeof(args)); @@ -536,9 +534,6 @@ static int fetch_refs_via_pack(struct transport *transport, args.no_progress = !transport->progress; args.depth = data->options.depth; - for (i = 0; i < nr_heads; i++) - 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); @@ -547,7 +542,8 @@ static int fetch_refs_via_pack(struct transport *transport, refs = fetch_pack(&args, data->fd, data->conn, refs_tmp ? refs_tmp : transport->remote_refs, - dest, &sought, &transport->pack_lockfile); + dest, to_fetch, nr_heads, + &transport->pack_lockfile); close(data->fd[0]); close(data->fd[1]); if (finish_connect(data->conn)) @@ -557,7 +553,6 @@ static int fetch_refs_via_pack(struct transport *transport, free_refs(refs_tmp); - string_list_clear(&sought, 0); free(dest); return (refs ? 0 : -1); } @@ -659,7 +654,7 @@ static void print_ok_ref_status(struct ref *ref, int porcelain) const char *msg; strcpy(quickref, status_abbrev(ref->old_sha1)); - if (ref->requires_force) { + if (ref->forced_update) { strcat(quickref, "..."); type = '+'; msg = "forced update"; @@ -699,6 +694,14 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i print_ref_status('!', "[rejected]", ref, ref->peer_ref, "already exists", porcelain); break; + case REF_STATUS_REJECT_FETCH_FIRST: + print_ref_status('!', "[rejected]", ref, ref->peer_ref, + "fetch first", porcelain); + break; + case REF_STATUS_REJECT_NEEDS_FORCE: + print_ref_status('!', "[rejected]", ref, ref->peer_ref, + "needs force", porcelain); + break; case REF_STATUS_REMOTE_REJECT: print_ref_status('!', "[remote rejected]", ref, ref->deletion ? NULL : ref->peer_ref, @@ -744,12 +747,16 @@ void transport_print_push_status(const char *dest, struct ref *refs, ref->status != REF_STATUS_OK) n += print_one_push_status(ref, dest, n, porcelain); if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD) { - if (!strcmp(head, ref->name)) + if (head != NULL && !strcmp(head, ref->name)) *reject_reasons |= REJECT_NON_FF_HEAD; else *reject_reasons |= REJECT_NON_FF_OTHER; } else if (ref->status == REF_STATUS_REJECT_ALREADY_EXISTS) { *reject_reasons |= REJECT_ALREADY_EXISTS; + } else if (ref->status == REF_STATUS_REJECT_FETCH_FIRST) { + *reject_reasons |= REJECT_FETCH_FIRST; + } else if (ref->status == REF_STATUS_REJECT_NEEDS_FORCE) { + *reject_reasons |= REJECT_NEEDS_FORCE; } } } @@ -1034,6 +1041,62 @@ static void die_with_unpushed_submodules(struct string_list *needs_pushing) die("Aborting."); } +static int run_pre_push_hook(struct transport *transport, + struct ref *remote_refs) +{ + int ret = 0, x; + struct ref *r; + struct child_process proc; + struct strbuf buf; + const char *argv[4]; + + if (!(argv[0] = find_hook("pre-push"))) + return 0; + + argv[1] = transport->remote->name; + argv[2] = transport->url; + argv[3] = NULL; + + memset(&proc, 0, sizeof(proc)); + proc.argv = argv; + proc.in = -1; + + if (start_command(&proc)) { + finish_command(&proc); + return -1; + } + + strbuf_init(&buf, 256); + + for (r = remote_refs; r; r = r->next) { + if (!r->peer_ref) continue; + if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue; + if (r->status == REF_STATUS_UPTODATE) continue; + + strbuf_reset(&buf); + strbuf_addf( &buf, "%s %s %s %s\n", + r->peer_ref->name, sha1_to_hex(r->new_sha1), + r->name, sha1_to_hex(r->old_sha1)); + + if (write_in_full(proc.in, buf.buf, buf.len) != buf.len) { + ret = -1; + break; + } + } + + strbuf_release(&buf); + + x = close(proc.in); + if (!ret) + ret = x; + + x = finish_command(&proc); + if (!ret) + ret = x; + + return ret; +} + int transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags, unsigned int *reject_reasons) @@ -1074,6 +1137,10 @@ int transport_push(struct transport *transport, flags & TRANSPORT_PUSH_MIRROR, flags & TRANSPORT_PUSH_FORCE); + if (!(flags & TRANSPORT_PUSH_NO_HOOK)) + if (run_pre_push_hook(transport, remote_refs)) + return -1; + if ((flags & TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND) && !is_bare_repository()) { struct ref *ref = remote_refs; for (; ref; ref = ref->next) |