@matheusbsbs / matheus-bagliano / commits / 64fcef2daa
Fork 0

Move push matching and reporting logic into transport.c

For native-protocol pushes (and other protocols as they are converted to the new method), this moves the refspec match, tracking update, and report message out of send-pack() and into transport_push(), where it can be shared completely with other protocols. This also makes fetch and push more similar in terms of what code is in what file. Signed-off-by: Daniel Barkalow <barkalow@iabervon.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Daniel Barkalow committed Mar 8, 2009 at 21:06 UTC 64fcef2daa03f6093b480142c6ab2a4173b0b43e
4 files changed +343 -92
builtin-send-pack.c
+74 -69
@@ -11,7 +11,6 @@ static const char send_pack_usage[] =
11 " --all and explicit <ref> specification are mutually exclusive.";
12
13 static struct send_pack_args args = {
14 - /* .receivepack = */ "git-receive-pack",
14 };
15
16 static int feed_object(const unsigned char *sha1, int fd, int negative)
@@ -31,7 +30,7 @@ static int feed_object(const unsigned char *sha1, int fd, int negative)
30 /*
31 * Make a pack stream and spit it out into file descriptor fd
32 */
34 -static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra)
33 +static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args)
34 {
35 /*
36 * The child becomes pack-objects --revs; we feed
@@ -49,7 +48,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
48 struct child_process po;
49 int i;
50
52 - if (args.use_thin_pack)
51 + if (args->use_thin_pack)
52 argv[4] = "--thin";
53 memset(&po, 0, sizeof(po));
54 po.argv = argv;
@@ -83,8 +82,6 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
82 return 0;
83 }
84
86 -static struct ref *remote_refs, **remote_tail;
87 -
85 static int receive_status(int in, struct ref *refs)
86 {
87 struct ref *hint;
@@ -300,27 +297,19 @@ static int refs_pushed(struct ref *ref)
297 return 0;
298 }
299
303 -static int do_send_pack(int in, int out, struct remote *remote, const char *dest, int nr_refspec, const char **refspec)
300 +int send_pack(struct send_pack_args *args,
301 + int fd[], struct child_process *conn,
302 + struct ref *remote_refs,
303 + struct extra_have_objects *extra_have)
304 {
305 - struct ref *ref, *local_refs;
305 + int in = fd[0];
306 + int out = fd[1];
307 + struct ref *ref;
308 int new_refs;
309 int ask_for_status_report = 0;
310 int allow_deleting_refs = 0;
311 int expect_status_report = 0;
310 - int flags = MATCH_REFS_NONE;
312 int ret;
312 - struct extra_have_objects extra_have;
313 -
314 - memset(&extra_have, 0, sizeof(extra_have));
315 - if (args.send_all)
316 - flags |= MATCH_REFS_ALL;
317 - if (args.send_mirror)
318 - flags |= MATCH_REFS_MIRROR;
319 -
320 - /* No funny business with the matcher */
321 - remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL,
322 - &extra_have);
323 - local_refs = get_local_heads();
313
314 /* Does the other end support the reporting? */
315 if (server_supports("report-status"))
@@ -328,19 +317,9 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
317 if (server_supports("delete-refs"))
318 allow_deleting_refs = 1;
319
331 - /* match them up */
332 - if (!remote_tail)
333 - remote_tail = &remote_refs;
334 - if (match_refs(local_refs, remote_refs, &remote_tail,
335 - nr_refspec, refspec, flags)) {
336 - close(out);
337 - return -1;
338 - }
339 -
320 if (!remote_refs) {
321 fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
322 "Perhaps you should specify a branch such as 'master'.\n");
343 - close(out);
323 return 0;
324 }
325
@@ -352,7 +331,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
331
332 if (ref->peer_ref)
333 hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
355 - else if (!args.send_mirror)
334 + else if (!args->send_mirror)
335 continue;
336
337 ref->deletion = is_null_sha1(ref->new_sha1);
@@ -391,7 +370,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
370 (!has_sha1_file(ref->old_sha1)
371 || !ref_newer(ref->new_sha1, ref->old_sha1));
372
394 - if (ref->nonfastforward && !ref->force && !args.force_update) {
373 + if (ref->nonfastforward && !ref->force && !args->force_update) {
374 ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
375 continue;
376 }
@@ -399,7 +378,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
378 if (!ref->deletion)
379 new_refs++;
380
402 - if (!args.dry_run) {
381 + if (!args->dry_run) {
382 char *old_hex = sha1_to_hex(ref->old_sha1);
383 char *new_hex = sha1_to_hex(ref->new_sha1);
384
@@ -420,27 +399,19 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
399 }
400
401 packet_flush(out);
423 - if (new_refs && !args.dry_run) {
424 - if (pack_objects(out, remote_refs, &extra_have) < 0)
402 + if (new_refs && !args->dry_run) {
403 + if (pack_objects(out, remote_refs, extra_have, args) < 0) {
404 + for (ref = remote_refs; ref; ref = ref->next)
405 + ref->status = REF_STATUS_NONE;
406 return -1;
407 + }
408 }
427 - else
428 - close(out);
409
410 if (expect_status_report)
411 ret = receive_status(in, remote_refs);
412 else
413 ret = 0;
414
435 - print_push_status(dest, remote_refs);
436 -
437 - if (!args.dry_run && remote) {
438 - for (ref = remote_refs; ref; ref = ref->next)
439 - update_tracking_ref(remote, ref);
440 - }
441 -
442 - if (!refs_pushed(remote_refs))
443 - fprintf(stderr, "Everything up-to-date\n");
415 if (ret < 0)
416 return ret;
417 for (ref = remote_refs; ref; ref = ref->next) {
@@ -489,11 +460,19 @@ static void verify_remote_names(int nr_heads, const char **heads)
460
461 int cmd_send_pack(int argc, const char **argv, const char *prefix)
462 {
492 - int i, nr_heads = 0;
493 - const char **heads = NULL;
463 + int i, nr_refspecs = 0;
464 + const char **refspecs = NULL;
465 const char *remote_name = NULL;
466 struct remote *remote = NULL;
467 const char *dest = NULL;
468 + int fd[2];
469 + struct child_process *conn;
470 + struct extra_have_objects extra_have;
471 + struct ref *remote_refs, **remote_tail, *local_refs;
472 + int ret;
473 + int send_all = 0;
474 + const char *receivepack = "git-receive-pack";
475 + int flags;
476
477 argv++;
478 for (i = 1; i < argc; i++, argv++) {
@@ -501,11 +480,11 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
480
481 if (*arg == '-') {
482 if (!prefixcmp(arg, "--receive-pack=")) {
504 - args.receivepack = arg + 15;
483 + receivepack = arg + 15;
484 continue;
485 }
486 if (!prefixcmp(arg, "--exec=")) {
508 - args.receivepack = arg + 7;
487 + receivepack = arg + 7;
488 continue;
489 }
490 if (!prefixcmp(arg, "--remote=")) {
@@ -513,7 +492,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
492 continue;
493 }
494 if (!strcmp(arg, "--all")) {
516 - args.send_all = 1;
495 + send_all = 1;
496 continue;
497 }
498 if (!strcmp(arg, "--dry-run")) {
@@ -542,8 +521,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
521 dest = arg;
522 continue;
523 }
545 - heads = (const char **) argv;
546 - nr_heads = argc - i;
524 + refspecs = (const char **) argv;
525 + nr_refspecs = argc - i;
526 break;
527 }
528 if (!dest)
@@ -552,8 +531,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
531 * --all and --mirror are incompatible; neither makes sense
532 * with any refspecs.
533 */
555 - if ((heads && (args.send_all || args.send_mirror)) ||
556 - (args.send_all && args.send_mirror))
534 + if ((refspecs && (send_all || args.send_mirror)) ||
535 + (send_all && args.send_mirror))
536 usage(send_pack_usage);
537
538 if (remote_name) {
@@ -564,24 +543,50 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
543 }
544 }
545
567 - return send_pack(&args, dest, remote, nr_heads, heads);
568 -}
546 + conn = git_connect(fd, dest, receivepack, args.verbose ? CONNECT_VERBOSE : 0);
547
570 -int send_pack(struct send_pack_args *my_args,
571 - const char *dest, struct remote *remote,
572 - int nr_heads, const char **heads)
573 -{
574 - int fd[2], ret;
575 - struct child_process *conn;
548 + memset(&extra_have, 0, sizeof(extra_have));
549 +
550 + get_remote_heads(fd[0], &remote_refs, 0, NULL, REF_NORMAL,
551 + &extra_have);
552 +
553 + verify_remote_names(nr_refspecs, refspecs);
554 +
555 + local_refs = get_local_heads();
556
577 - memcpy(&args, my_args, sizeof(args));
557 + flags = MATCH_REFS_NONE;
558 +
559 + if (send_all)
560 + flags |= MATCH_REFS_ALL;
561 + if (args.send_mirror)
562 + flags |= MATCH_REFS_MIRROR;
563 +
564 + /* match them up */
565 + remote_tail = &remote_refs;
566 + while (*remote_tail)
567 + remote_tail = &((*remote_tail)->next);
568 + if (match_refs(local_refs, remote_refs, &remote_tail,
569 + nr_refspecs, refspecs, flags)) {
570 + return -1;
571 + }
572
579 - verify_remote_names(nr_heads, heads);
573 + ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
574
581 - conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
582 - ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
575 + close(fd[1]);
576 close(fd[0]);
584 - /* do_send_pack always closes fd[1] */
577 +
578 ret |= finish_connect(conn);
586 - return !!ret;
579 +
580 + print_push_status(dest, remote_refs);
581 +
582 + if (!args.dry_run && remote) {
583 + struct ref *ref;
584 + for (ref = remote_refs; ref; ref = ref->next)
585 + update_tracking_ref(remote, ref);
586 + }
587 +
588 + if (!ret && !refs_pushed(remote_refs))
589 + fprintf(stderr, "Everything up-to-date\n");
590 +
591 + return ret;
592 }
send-pack.h
+2 -4
@@ -2,9 +2,7 @@
2 #define SEND_PACK_H
3
4 struct send_pack_args {
5 - const char *receivepack;
5 unsigned verbose:1,
7 - send_all:1,
6 send_mirror:1,
7 force_update:1,
8 use_thin_pack:1,
@@ -12,7 +10,7 @@ struct send_pack_args {
10 };
11
12 int send_pack(struct send_pack_args *args,
15 - const char *dest, struct remote *remote,
16 - int nr_heads, const char **heads);
13 + int fd[], struct child_process *conn,
14 + struct ref *remote_refs, struct extra_have_objects *extra_have);
15
16 #endif
transport.c
+265 -18
@@ -138,7 +138,7 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)
138 }
139 }
140
141 -static struct ref *get_refs_via_rsync(struct transport *transport)
141 +static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
142 {
143 struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
144 struct ref dummy, *tail = &dummy;
@@ -146,6 +146,9 @@ static struct ref *get_refs_via_rsync(struct transport *transport)
146 const char *args[5];
147 int temp_dir_len;
148
149 + if (for_push)
150 + return NULL;
151 +
152 /* copy the refs to the temporary directory */
153
154 strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
@@ -422,7 +425,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
425 return !!err;
426 }
427
425 -static struct ref *get_refs_via_curl(struct transport *transport)
428 +static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
429 {
430 struct strbuf buffer = STRBUF_INIT;
431 char *data, *start, *mid;
@@ -439,6 +442,9 @@ static struct ref *get_refs_via_curl(struct transport *transport)
442
443 struct walker *walker;
444
445 + if (for_push)
446 + return NULL;
447 +
448 if (!transport->data)
449 transport->data = get_http_walker(transport->url,
450 transport->remote);
@@ -525,12 +531,15 @@ struct bundle_transport_data {
531 struct bundle_header header;
532 };
533
528 -static struct ref *get_refs_from_bundle(struct transport *transport)
534 +static struct ref *get_refs_from_bundle(struct transport *transport, int for_push)
535 {
536 struct bundle_transport_data *data = transport->data;
537 struct ref *result = NULL;
538 int i;
539
540 + if (for_push)
541 + return NULL;
542 +
543 if (data->fd > 0)
544 close(data->fd);
545 data->fd = read_bundle_header(transport->url, &data->header);
@@ -571,6 +580,7 @@ struct git_transport_data {
580 int fd[2];
581 const char *uploadpack;
582 const char *receivepack;
583 + struct extra_have_objects extra_have;
584 };
585
586 static int set_git_option(struct transport *connection,
@@ -602,20 +612,23 @@ static int set_git_option(struct transport *connection,
612 return 1;
613 }
614
605 -static int connect_setup(struct transport *transport)
615 +static int connect_setup(struct transport *transport, int for_push, int verbose)
616 {
617 struct git_transport_data *data = transport->data;
608 - data->conn = git_connect(data->fd, transport->url, data->uploadpack, 0);
618 + data->conn = git_connect(data->fd, transport->url,
619 + for_push ? data->receivepack : data->uploadpack,
620 + verbose ? CONNECT_VERBOSE : 0);
621 return 0;
622 }
623
612 -static struct ref *get_refs_via_connect(struct transport *transport)
624 +static struct ref *get_refs_via_connect(struct transport *transport, int for_push)
625 {
626 struct git_transport_data *data = transport->data;
627 struct ref *refs;
628
617 - connect_setup(transport);
618 - get_remote_heads(data->fd[0], &refs, 0, NULL, 0, NULL);
629 + connect_setup(transport, for_push, 0);
630 + get_remote_heads(data->fd[0], &refs, 0, NULL,
631 + for_push ? REF_NORMAL : 0, &data->extra_have);
632
633 return refs;
634 }
@@ -647,7 +660,7 @@ static int fetch_refs_via_pack(struct transport *transport,
660 origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
661
662 if (!data->conn) {
650 - connect_setup(transport);
663 + connect_setup(transport, 0, 0);
664 get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
665 }
666
@@ -670,20 +683,216 @@ static int fetch_refs_via_pack(struct transport *transport,
683 return (refs ? 0 : -1);
684 }
685
673 -static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
686 +static int refs_pushed(struct ref *ref)
687 +{
688 + for (; ref; ref = ref->next) {
689 + switch(ref->status) {
690 + case REF_STATUS_NONE:
691 + case REF_STATUS_UPTODATE:
692 + break;
693 + default:
694 + return 1;
695 + }
696 + }
697 + return 0;
698 +}
699 +
700 +static void update_tracking_ref(struct remote *remote, struct ref *ref, int verbose)
701 +{
702 + struct refspec rs;
703 +
704 + if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
705 + return;
706 +
707 + rs.src = ref->name;
708 + rs.dst = NULL;
709 +
710 + if (!remote_find_tracking(remote, &rs)) {
711 + if (verbose)
712 + fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
713 + if (ref->deletion) {
714 + delete_ref(rs.dst, NULL, 0);
715 + } else
716 + update_ref("update by push", rs.dst,
717 + ref->new_sha1, NULL, 0, 0);
718 + free(rs.dst);
719 + }
720 +}
721 +
722 +#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
723 +
724 +static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
725 +{
726 + fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
727 + if (from)
728 + fprintf(stderr, "%s -> %s", prettify_ref(from), prettify_ref(to));
729 + else
730 + fputs(prettify_ref(to), stderr);
731 + if (msg) {
732 + fputs(" (", stderr);
733 + fputs(msg, stderr);
734 + fputc(')', stderr);
735 + }
736 + fputc('\n', stderr);
737 +}
738 +
739 +static const char *status_abbrev(unsigned char sha1[20])
740 +{
741 + return find_unique_abbrev(sha1, DEFAULT_ABBREV);
742 +}
743 +
744 +static void print_ok_ref_status(struct ref *ref)
745 +{
746 + if (ref->deletion)
747 + print_ref_status('-', "[deleted]", ref, NULL, NULL);
748 + else if (is_null_sha1(ref->old_sha1))
749 + print_ref_status('*',
750 + (!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
751 + "[new branch]"),
752 + ref, ref->peer_ref, NULL);
753 + else {
754 + char quickref[84];
755 + char type;
756 + const char *msg;
757 +
758 + strcpy(quickref, status_abbrev(ref->old_sha1));
759 + if (ref->nonfastforward) {
760 + strcat(quickref, "...");
761 + type = '+';
762 + msg = "forced update";
763 + } else {
764 + strcat(quickref, "..");
765 + type = ' ';
766 + msg = NULL;
767 + }
768 + strcat(quickref, status_abbrev(ref->new_sha1));
769 +
770 + print_ref_status(type, quickref, ref, ref->peer_ref, msg);
771 + }
772 +}
773 +
774 +static int print_one_push_status(struct ref *ref, const char *dest, int count)
775 +{
776 + if (!count)
777 + fprintf(stderr, "To %s\n", dest);
778 +
779 + switch(ref->status) {
780 + case REF_STATUS_NONE:
781 + print_ref_status('X', "[no match]", ref, NULL, NULL);
782 + break;
783 + case REF_STATUS_REJECT_NODELETE:
784 + print_ref_status('!', "[rejected]", ref, NULL,
785 + "remote does not support deleting refs");
786 + break;
787 + case REF_STATUS_UPTODATE:
788 + print_ref_status('=', "[up to date]", ref,
789 + ref->peer_ref, NULL);
790 + break;
791 + case REF_STATUS_REJECT_NONFASTFORWARD:
792 + print_ref_status('!', "[rejected]", ref, ref->peer_ref,
793 + "non-fast forward");
794 + break;
795 + case REF_STATUS_REMOTE_REJECT:
796 + print_ref_status('!', "[remote rejected]", ref,
797 + ref->deletion ? NULL : ref->peer_ref,
798 + ref->remote_status);
799 + break;
800 + case REF_STATUS_EXPECTING_REPORT:
801 + print_ref_status('!', "[remote failure]", ref,
802 + ref->deletion ? NULL : ref->peer_ref,
803 + "remote failed to report status");
804 + break;
805 + case REF_STATUS_OK:
806 + print_ok_ref_status(ref);
807 + break;
808 + }
809 +
810 + return 1;
811 +}
812 +
813 +static void print_push_status(const char *dest, struct ref *refs, int verbose)
814 +{
815 + struct ref *ref;
816 + int n = 0;
817 +
818 + if (verbose) {
819 + for (ref = refs; ref; ref = ref->next)
820 + if (ref->status == REF_STATUS_UPTODATE)
821 + n += print_one_push_status(ref, dest, n);
822 + }
823 +
824 + for (ref = refs; ref; ref = ref->next)
825 + if (ref->status == REF_STATUS_OK)
826 + n += print_one_push_status(ref, dest, n);
827 +
828 + for (ref = refs; ref; ref = ref->next) {
829 + if (ref->status != REF_STATUS_NONE &&
830 + ref->status != REF_STATUS_UPTODATE &&
831 + ref->status != REF_STATUS_OK)
832 + n += print_one_push_status(ref, dest, n);
833 + }
834 +}
835 +
836 +static void verify_remote_names(int nr_heads, const char **heads)
837 +{
838 + int i;
839 +
840 + for (i = 0; i < nr_heads; i++) {
841 + const char *local = heads[i];
842 + const char *remote = strrchr(heads[i], ':');
843 +
844 + if (*local == '+')
845 + local++;
846 +
847 + /* A matching refspec is okay. */
848 + if (remote == local && remote[1] == '\0')
849 + continue;
850 +
851 + remote = remote ? (remote + 1) : local;
852 + switch (check_ref_format(remote)) {
853 + case 0: /* ok */
854 + case CHECK_REF_FORMAT_ONELEVEL:
855 + /* ok but a single level -- that is fine for
856 + * a match pattern.
857 + */
858 + case CHECK_REF_FORMAT_WILDCARD:
859 + /* ok but ends with a pattern-match character */
860 + continue;
861 + }
862 + die("remote part of refspec is not a valid name in %s",
863 + heads[i]);
864 + }
865 +}
866 +
867 +static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
868 {
869 struct git_transport_data *data = transport->data;
870 struct send_pack_args args;
871 + int ret;
872 +
873 + if (!data->conn) {
874 + struct ref *tmp_refs;
875 + connect_setup(transport, 1, 0);
876 +
877 + get_remote_heads(data->fd[0], &tmp_refs, 0, NULL, REF_NORMAL,
878 + NULL);
879 + }
880
678 - args.receivepack = data->receivepack;
679 - args.send_all = !!(flags & TRANSPORT_PUSH_ALL);
881 args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
882 args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
883 args.use_thin_pack = data->thin;
884 args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
885 args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
886
686 - return send_pack(&args, transport->url, transport->remote, refspec_nr, refspec);
887 + ret = send_pack(&args, data->fd, data->conn, remote_refs,
888 + &data->extra_have);
889 +
890 + close(data->fd[1]);
891 + close(data->fd[0]);
892 + ret |= finish_connect(data->conn);
893 + data->conn = NULL;
894 +
895 + return ret;
896 }
897
898 static int disconnect_git(struct transport *transport)
@@ -753,7 +962,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
962 ret->set_option = set_git_option;
963 ret->get_refs_list = get_refs_via_connect;
964 ret->fetch = fetch_refs_via_pack;
756 - ret->push = git_transport_push;
965 + ret->push_refs = git_transport_push;
966 ret->disconnect = disconnect_git;
967
968 data->thin = 1;
@@ -780,15 +989,53 @@ int transport_set_option(struct transport *transport,
989 int transport_push(struct transport *transport,
990 int refspec_nr, const char **refspec, int flags)
991 {
783 - if (!transport->push)
784 - return 1;
785 - return transport->push(transport, refspec_nr, refspec, flags);
992 + verify_remote_names(refspec_nr, refspec);
993 +
994 + if (transport->push)
995 + return transport->push(transport, refspec_nr, refspec, flags);
996 + if (transport->push_refs) {
997 + struct ref *remote_refs =
998 + transport->get_refs_list(transport, 1);
999 + struct ref **remote_tail;
1000 + struct ref *local_refs = get_local_heads();
1001 + int match_flags = MATCH_REFS_NONE;
1002 + int verbose = flags & TRANSPORT_PUSH_VERBOSE;
1003 + int ret;
1004 +
1005 + if (flags & TRANSPORT_PUSH_ALL)
1006 + match_flags |= MATCH_REFS_ALL;
1007 + if (flags & TRANSPORT_PUSH_MIRROR)
1008 + match_flags |= MATCH_REFS_MIRROR;
1009 +
1010 + remote_tail = &remote_refs;
1011 + while (*remote_tail)
1012 + remote_tail = &((*remote_tail)->next);
1013 + if (match_refs(local_refs, remote_refs, &remote_tail,
1014 + refspec_nr, refspec, match_flags)) {
1015 + return -1;
1016 + }
1017 +
1018 + ret = transport->push_refs(transport, remote_refs, flags);
1019 +
1020 + print_push_status(transport->url, remote_refs, verbose);
1021 +
1022 + if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
1023 + struct ref *ref;
1024 + for (ref = remote_refs; ref; ref = ref->next)
1025 + update_tracking_ref(transport->remote, ref, verbose);
1026 + }
1027 +
1028 + if (!ret && !refs_pushed(remote_refs))
1029 + fprintf(stderr, "Everything up-to-date\n");
1030 + return ret;
1031 + }
1032 + return 1;
1033 }
1034
1035 const struct ref *transport_get_remote_refs(struct transport *transport)
1036 {
1037 if (!transport->remote_refs)
791 - transport->remote_refs = transport->get_refs_list(transport);
1038 + transport->remote_refs = transport->get_refs_list(transport, 0);
1039 return transport->remote_refs;
1040 }
1041
transport.h
+2 -1
@@ -18,8 +18,9 @@ struct transport {
18 int (*set_option)(struct transport *connection, const char *name,
19 const char *value);
20
21 - struct ref *(*get_refs_list)(struct transport *transport);
21 + struct ref *(*get_refs_list)(struct transport *transport, int for_push);
22 int (*fetch)(struct transport *transport, int refs_nr, const struct ref **refs);
23 + int (*push_refs)(struct transport *transport, struct ref *refs, int flags);
24 int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
25
26 int (*disconnect)(struct transport *connection);