From: Junio C Hamano Date: Tue, 2 Mar 2010 20:44:09 +0000 (-0800) Subject: Merge branch 'ml/send-pack-transport-refactor' X-Git-Tag: v1.7.1-rc0~113 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/bd282f58ad9c4c0fdc1a9f56889ac7132d889d34?ds=inline;hp=-c Merge branch 'ml/send-pack-transport-refactor' * ml/send-pack-transport-refactor: refactor duplicated code in builtin-send-pack.c and transport.c --- bd282f58ad9c4c0fdc1a9f56889ac7132d889d34 diff --combined builtin-send-pack.c index 2183a47052,cbda3117d8..6019eac918 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@@ -7,6 -7,7 +7,7 @@@ #include "remote.h" #include "send-pack.h" #include "quote.h" + #include "transport.h" static const char send_pack_usage[] = "git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=] [--verbose] [--thin] [:] [...]\n" @@@ -169,156 -170,6 +170,6 @@@ static int receive_status(int in, struc return ret; } - static void update_tracking_ref(struct remote *remote, struct ref *ref) - { - struct refspec rs; - - if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE) - return; - - rs.src = ref->name; - rs.dst = NULL; - - if (!remote_find_tracking(remote, &rs)) { - if (args.verbose) - fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); - if (ref->deletion) { - delete_ref(rs.dst, NULL, 0); - } else - update_ref("update by push", rs.dst, - ref->new_sha1, NULL, 0, 0); - free(rs.dst); - } - } - - #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) - - static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg) - { - fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary); - if (from) - fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name)); - else - fputs(prettify_refname(to->name), stderr); - if (msg) { - fputs(" (", stderr); - fputs(msg, stderr); - fputc(')', stderr); - } - fputc('\n', stderr); - } - - static const char *status_abbrev(unsigned char sha1[20]) - { - return find_unique_abbrev(sha1, DEFAULT_ABBREV); - } - - static void print_ok_ref_status(struct ref *ref) - { - if (ref->deletion) - print_ref_status('-', "[deleted]", ref, NULL, NULL); - else if (is_null_sha1(ref->old_sha1)) - print_ref_status('*', - (!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" : - "[new branch]"), - ref, ref->peer_ref, NULL); - else { - char quickref[84]; - char type; - const char *msg; - - strcpy(quickref, status_abbrev(ref->old_sha1)); - if (ref->nonfastforward) { - strcat(quickref, "..."); - type = '+'; - msg = "forced update"; - } else { - strcat(quickref, ".."); - type = ' '; - msg = NULL; - } - strcat(quickref, status_abbrev(ref->new_sha1)); - - print_ref_status(type, quickref, ref, ref->peer_ref, msg); - } - } - - static int print_one_push_status(struct ref *ref, const char *dest, int count) - { - if (!count) - fprintf(stderr, "To %s\n", dest); - - switch(ref->status) { - case REF_STATUS_NONE: - print_ref_status('X', "[no match]", ref, NULL, NULL); - break; - case REF_STATUS_REJECT_NODELETE: - print_ref_status('!', "[rejected]", ref, NULL, - "remote does not support deleting refs"); - break; - case REF_STATUS_UPTODATE: - print_ref_status('=', "[up to date]", ref, - ref->peer_ref, NULL); - break; - case REF_STATUS_REJECT_NONFASTFORWARD: - print_ref_status('!', "[rejected]", ref, ref->peer_ref, - "non-fast-forward"); - break; - case REF_STATUS_REMOTE_REJECT: - print_ref_status('!', "[remote rejected]", ref, - ref->deletion ? NULL : ref->peer_ref, - ref->remote_status); - break; - case REF_STATUS_EXPECTING_REPORT: - print_ref_status('!', "[remote failure]", ref, - ref->deletion ? NULL : ref->peer_ref, - "remote failed to report status"); - break; - case REF_STATUS_OK: - print_ok_ref_status(ref); - break; - } - - return 1; - } - - static void print_push_status(const char *dest, struct ref *refs) - { - struct ref *ref; - int n = 0; - - if (args.verbose) { - for (ref = refs; ref; ref = ref->next) - if (ref->status == REF_STATUS_UPTODATE) - n += print_one_push_status(ref, dest, n); - } - - for (ref = refs; ref; ref = ref->next) - if (ref->status == REF_STATUS_OK) - n += print_one_push_status(ref, dest, n); - - for (ref = refs; ref; ref = ref->next) { - if (ref->status != REF_STATUS_NONE && - ref->status != REF_STATUS_UPTODATE && - ref->status != REF_STATUS_OK) - n += print_one_push_status(ref, dest, n); - } - } - - static int refs_pushed(struct ref *ref) - { - for (; ref; ref = ref->next) { - switch(ref->status) { - case REF_STATUS_NONE: - case REF_STATUS_UPTODATE: - break; - default: - return 1; - } - } - return 0; - } - static void print_helper_status(struct ref *ref) { struct strbuf buf = STRBUF_INIT; @@@ -372,14 -223,6 +223,14 @@@ strbuf_release(&buf); } +static int sideband_demux(int in, int out, void *data) +{ + int *fd = data; + int ret = recv_sideband("send-pack", fd[0], out); + close(out); + return ret; +} + int send_pack(struct send_pack_args *args, int fd[], struct child_process *conn, struct ref *remote_refs, @@@ -390,22 -233,18 +241,22 @@@ struct strbuf req_buf = STRBUF_INIT; struct ref *ref; int new_refs; - int ask_for_status_report = 0; int allow_deleting_refs = 0; - int expect_status_report = 0; + int status_report = 0; + int use_sideband = 0; + unsigned cmds_sent = 0; int ret; + struct async demux; /* Does the other end support the reporting? */ if (server_supports("report-status")) - ask_for_status_report = 1; + status_report = 1; if (server_supports("delete-refs")) allow_deleting_refs = 1; if (server_supports("ofs-delta")) args->use_ofs_delta = 1; + if (server_supports("side-band-64k")) + use_sideband = 1; if (!remote_refs) { fprintf(stderr, "No refs in common and none specified; doing nothing.\n" @@@ -438,30 -277,28 +289,30 @@@ if (!ref->deletion) new_refs++; - if (!args->dry_run) { + if (args->dry_run) { + ref->status = REF_STATUS_OK; + } else { char *old_hex = sha1_to_hex(ref->old_sha1); char *new_hex = sha1_to_hex(ref->new_sha1); - if (ask_for_status_report) { - packet_buf_write(&req_buf, "%s %s %s%c%s", + if (!cmds_sent && (status_report || use_sideband)) { + packet_buf_write(&req_buf, "%s %s %s%c%s%s", old_hex, new_hex, ref->name, 0, - "report-status"); - ask_for_status_report = 0; - expect_status_report = 1; + status_report ? " report-status" : "", + use_sideband ? " side-band-64k" : ""); } else packet_buf_write(&req_buf, "%s %s %s", old_hex, new_hex, ref->name); + ref->status = status_report ? + REF_STATUS_EXPECTING_REPORT : + REF_STATUS_OK; + cmds_sent++; } - ref->status = expect_status_report ? - REF_STATUS_EXPECTING_REPORT : - REF_STATUS_OK; } if (args->stateless_rpc) { - if (!args->dry_run) { + if (!args->dry_run && cmds_sent) { packet_buf_flush(&req_buf); send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX); } @@@ -471,43 -308,23 +322,43 @@@ } strbuf_release(&req_buf); - if (new_refs && !args->dry_run) { + if (use_sideband && cmds_sent) { + memset(&demux, 0, sizeof(demux)); + demux.proc = sideband_demux; + demux.data = fd; + demux.out = -1; + if (start_async(&demux)) + die("receive-pack: unable to fork off sideband demultiplexer"); + in = demux.out; + } + + if (new_refs && cmds_sent) { if (pack_objects(out, remote_refs, extra_have, args) < 0) { for (ref = remote_refs; ref; ref = ref->next) ref->status = REF_STATUS_NONE; + if (use_sideband) + finish_async(&demux); return -1; } } - if (args->stateless_rpc && !args->dry_run) + if (args->stateless_rpc && cmds_sent) packet_flush(out); - if (expect_status_report) + if (status_report && cmds_sent) ret = receive_status(in, remote_refs); else ret = 0; if (args->stateless_rpc) packet_flush(out); + if (use_sideband && cmds_sent) { + if (finish_async(&demux)) { + error("error in sideband demultiplexer"); + ret = -1; + } + close(demux.out); + } + if (ret < 0) return ret; for (ref = remote_refs; ref; ref = ref->next) { @@@ -523,37 -340,6 +374,6 @@@ return 0; } - static void 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; - switch (check_ref_format(remote)) { - case 0: /* ok */ - case CHECK_REF_FORMAT_ONELEVEL: - /* ok but a single level -- that is fine for - * a match pattern. - */ - case CHECK_REF_FORMAT_WILDCARD: - /* ok but ends with a pattern-match character */ - continue; - } - die("remote part of refspec is not a valid name in %s", - heads[i]); - } - } - int cmd_send_pack(int argc, const char **argv, const char *prefix) { int i, nr_refspecs = 0; @@@ -570,6 -356,7 +390,7 @@@ int send_all = 0; const char *receivepack = "git-receive-pack"; int flags; + int nonfastforward = 0; argv++; for (i = 1; i < argc; i++, argv++) { @@@ -662,7 -449,7 +483,7 @@@ get_remote_heads(fd[0], &remote_refs, 0, NULL, REF_NORMAL, &extra_have); - verify_remote_names(nr_refspecs, refspecs); + transport_verify_remote_names(nr_refspecs, refspecs); local_refs = get_local_heads(); @@@ -691,15 -478,15 +512,15 @@@ ret |= finish_connect(conn); if (!helper_status) - print_push_status(dest, remote_refs); + transport_print_push_status(dest, remote_refs, args.verbose, 0, &nonfastforward); if (!args.dry_run && remote) { struct ref *ref; for (ref = remote_refs; ref; ref = ref->next) - update_tracking_ref(remote, ref); + transport_update_tracking_ref(remote, ref, args.verbose); } - if (!ret && !refs_pushed(remote_refs)) + if (!ret && !transport_refs_pushed(remote_refs)) fprintf(stderr, "Everything up-to-date\n"); return ret; diff --combined transport.c index 08e4fa0354,6d7a1259a6..1a360cfb48 --- a/transport.c +++ b/transport.c @@@ -573,7 -573,7 +573,7 @@@ static int push_had_errors(struct ref * return 0; } - static int refs_pushed(struct ref *ref) + int transport_refs_pushed(struct ref *ref) { for (; ref; ref = ref->next) { switch(ref->status) { @@@ -587,7 -587,7 +587,7 @@@ return 0; } - static void update_tracking_ref(struct remote *remote, struct ref *ref, int verbose) + void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose) { struct refspec rs; @@@ -609,8 -609,6 +609,6 @@@ } } - #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) - static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg, int porcelain) { if (porcelain) { @@@ -623,7 -621,7 +621,7 @@@ else fprintf(stdout, "%s\n", summary); } else { - fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary); + fprintf(stderr, " %c %-*s ", flag, TRANSPORT_SUMMARY_WIDTH, summary); if (from) fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name)); else @@@ -711,8 -709,8 +709,8 @@@ static int print_one_push_status(struc return 1; } - static void print_push_status(const char *dest, struct ref *refs, - int verbose, int porcelain, int * nonfastforward) + void transport_print_push_status(const char *dest, struct ref *refs, + int verbose, int porcelain, int *nonfastforward) { struct ref *ref; int n = 0; @@@ -738,7 -736,7 +736,7 @@@ } } - static void verify_remote_names(int nr_heads, const char **heads) + void transport_verify_remote_names(int nr_heads, const char **heads) { int i; @@@ -918,7 -916,6 +916,7 @@@ struct transport *transport_get(struct if (!remote) die("No remote provided to transport_get()"); + ret->got_remote_refs = 0; ret->remote = remote; helper = remote->foreign_vcs; @@@ -1019,7 -1016,7 +1017,7 @@@ int transport_push(struct transport *tr int *nonfastforward) { *nonfastforward = 0; - verify_remote_names(refspec_nr, refspec); + transport_verify_remote_names(refspec_nr, refspec); if (transport->push) { /* Maybe FIXME. But no important transport uses this case. */ @@@ -1058,7 -1055,7 +1056,7 @@@ ret |= err; if (!quiet || err) - print_push_status(transport->url, remote_refs, + transport_print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain, nonfastforward); @@@ -1068,10 -1065,10 +1066,10 @@@ if (!(flags & TRANSPORT_PUSH_DRY_RUN)) { struct ref *ref; for (ref = remote_refs; ref; ref = ref->next) - update_tracking_ref(transport->remote, ref, verbose); + transport_update_tracking_ref(transport->remote, ref, verbose); } - if (!quiet && !ret && !refs_pushed(remote_refs)) + if (!quiet && !ret && !transport_refs_pushed(remote_refs)) fprintf(stderr, "Everything up-to-date\n"); return ret; } @@@ -1080,10 -1077,8 +1078,10 @@@ const struct ref *transport_get_remote_refs(struct transport *transport) { - if (!transport->remote_refs) + if (!transport->got_remote_refs) { transport->remote_refs = transport->get_refs_list(transport, 0); + transport->got_remote_refs = 1; + } return transport->remote_refs; } diff --combined transport.h index 6dd9ae182f,7a9bb57d99..096f6e9478 --- a/transport.h +++ b/transport.h @@@ -19,12 -19,6 +19,12 @@@ struct transport void *data; const struct ref *remote_refs; + /** + * Indicates whether we already called get_refs_list(); set by + * transport.c::transport_get_remote_refs(). + */ + unsigned got_remote_refs : 1; + /** * Returns 0 if successful, positive if the option is not * recognized or is inapplicable, and negative if the option @@@ -98,6 -92,7 +98,7 @@@ #define TRANSPORT_PUSH_PORCELAIN 32 #define TRANSPORT_PUSH_QUIET 64 #define TRANSPORT_PUSH_SET_UPSTREAM 128 + #define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) /* Returns a transport suitable for the url */ struct transport *transport_get(struct remote *, const char *); @@@ -148,4 -143,14 +149,14 @@@ int transport_connect(struct transport /* Transport methods defined outside transport.c */ int transport_helper_init(struct transport *transport, const char *name); + /* common methods used by transport.c and builtin-send-pack.c */ + void transport_verify_remote_names(int nr_heads, const char **heads); + + void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose); + + int transport_refs_pushed(struct ref *ref); + + void transport_print_push_status(const char *dest, struct ref *refs, + int verbose, int porcelain, int *nonfastforward); + #endif