e86d3b5d672a945a1a24bfc96ab5e7b451f5d7f5
   1#include "builtin.h"
   2#include "commit.h"
   3#include "refs.h"
   4#include "pkt-line.h"
   5#include "sideband.h"
   6#include "run-command.h"
   7#include "remote.h"
   8#include "connect.h"
   9#include "send-pack.h"
  10#include "quote.h"
  11#include "transport.h"
  12#include "version.h"
  13
  14static const char send_pack_usage[] =
  15"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
  16"  --all and explicit <ref> specification are mutually exclusive.";
  17
  18static struct send_pack_args args;
  19
  20static void print_helper_status(struct ref *ref)
  21{
  22        struct strbuf buf = STRBUF_INIT;
  23
  24        for (; ref; ref = ref->next) {
  25                const char *msg = NULL;
  26                const char *res;
  27
  28                switch(ref->status) {
  29                case REF_STATUS_NONE:
  30                        res = "error";
  31                        msg = "no match";
  32                        break;
  33
  34                case REF_STATUS_OK:
  35                        res = "ok";
  36                        break;
  37
  38                case REF_STATUS_UPTODATE:
  39                        res = "ok";
  40                        msg = "up to date";
  41                        break;
  42
  43                case REF_STATUS_REJECT_NONFASTFORWARD:
  44                        res = "error";
  45                        msg = "non-fast forward";
  46                        break;
  47
  48                case REF_STATUS_REJECT_FETCH_FIRST:
  49                        res = "error";
  50                        msg = "fetch first";
  51                        break;
  52
  53                case REF_STATUS_REJECT_NEEDS_FORCE:
  54                        res = "error";
  55                        msg = "needs force";
  56                        break;
  57
  58                case REF_STATUS_REJECT_ALREADY_EXISTS:
  59                        res = "error";
  60                        msg = "already exists";
  61                        break;
  62
  63                case REF_STATUS_REJECT_NODELETE:
  64                case REF_STATUS_REMOTE_REJECT:
  65                        res = "error";
  66                        break;
  67
  68                case REF_STATUS_EXPECTING_REPORT:
  69                default:
  70                        continue;
  71                }
  72
  73                strbuf_reset(&buf);
  74                strbuf_addf(&buf, "%s %s", res, ref->name);
  75                if (ref->remote_status)
  76                        msg = ref->remote_status;
  77                if (msg) {
  78                        strbuf_addch(&buf, ' ');
  79                        quote_two_c_style(&buf, "", msg, 0);
  80                }
  81                strbuf_addch(&buf, '\n');
  82
  83                write_or_die(1, buf.buf, buf.len);
  84        }
  85        strbuf_release(&buf);
  86}
  87
  88int cmd_send_pack(int argc, const char **argv, const char *prefix)
  89{
  90        int i, nr_refspecs = 0;
  91        const char **refspecs = NULL;
  92        const char *remote_name = NULL;
  93        struct remote *remote = NULL;
  94        const char *dest = NULL;
  95        int fd[2];
  96        struct child_process *conn;
  97        struct extra_have_objects extra_have;
  98        struct ref *remote_refs, *local_refs;
  99        int ret;
 100        int helper_status = 0;
 101        int send_all = 0;
 102        const char *receivepack = "git-receive-pack";
 103        int flags;
 104        unsigned int reject_reasons;
 105        int progress = -1;
 106
 107        argv++;
 108        for (i = 1; i < argc; i++, argv++) {
 109                const char *arg = *argv;
 110
 111                if (*arg == '-') {
 112                        if (!prefixcmp(arg, "--receive-pack=")) {
 113                                receivepack = arg + 15;
 114                                continue;
 115                        }
 116                        if (!prefixcmp(arg, "--exec=")) {
 117                                receivepack = arg + 7;
 118                                continue;
 119                        }
 120                        if (!prefixcmp(arg, "--remote=")) {
 121                                remote_name = arg + 9;
 122                                continue;
 123                        }
 124                        if (!strcmp(arg, "--all")) {
 125                                send_all = 1;
 126                                continue;
 127                        }
 128                        if (!strcmp(arg, "--dry-run")) {
 129                                args.dry_run = 1;
 130                                continue;
 131                        }
 132                        if (!strcmp(arg, "--mirror")) {
 133                                args.send_mirror = 1;
 134                                continue;
 135                        }
 136                        if (!strcmp(arg, "--force")) {
 137                                args.force_update = 1;
 138                                continue;
 139                        }
 140                        if (!strcmp(arg, "--quiet")) {
 141                                args.quiet = 1;
 142                                continue;
 143                        }
 144                        if (!strcmp(arg, "--verbose")) {
 145                                args.verbose = 1;
 146                                continue;
 147                        }
 148                        if (!strcmp(arg, "--progress")) {
 149                                progress = 1;
 150                                continue;
 151                        }
 152                        if (!strcmp(arg, "--no-progress")) {
 153                                progress = 0;
 154                                continue;
 155                        }
 156                        if (!strcmp(arg, "--thin")) {
 157                                args.use_thin_pack = 1;
 158                                continue;
 159                        }
 160                        if (!strcmp(arg, "--stateless-rpc")) {
 161                                args.stateless_rpc = 1;
 162                                continue;
 163                        }
 164                        if (!strcmp(arg, "--helper-status")) {
 165                                helper_status = 1;
 166                                continue;
 167                        }
 168                        usage(send_pack_usage);
 169                }
 170                if (!dest) {
 171                        dest = arg;
 172                        continue;
 173                }
 174                refspecs = (const char **) argv;
 175                nr_refspecs = argc - i;
 176                break;
 177        }
 178        if (!dest)
 179                usage(send_pack_usage);
 180        /*
 181         * --all and --mirror are incompatible; neither makes sense
 182         * with any refspecs.
 183         */
 184        if ((refspecs && (send_all || args.send_mirror)) ||
 185            (send_all && args.send_mirror))
 186                usage(send_pack_usage);
 187
 188        if (remote_name) {
 189                remote = remote_get(remote_name);
 190                if (!remote_has_url(remote, dest)) {
 191                        die("Destination %s is not a uri for %s",
 192                            dest, remote_name);
 193                }
 194        }
 195
 196        if (progress == -1)
 197                progress = !args.quiet && isatty(2);
 198        args.progress = progress;
 199
 200        if (args.stateless_rpc) {
 201                conn = NULL;
 202                fd[0] = 0;
 203                fd[1] = 1;
 204        } else {
 205                conn = git_connect(fd, dest, receivepack,
 206                        args.verbose ? CONNECT_VERBOSE : 0);
 207        }
 208
 209        memset(&extra_have, 0, sizeof(extra_have));
 210
 211        get_remote_heads(fd[0], NULL, 0, &remote_refs, REF_NORMAL, &extra_have);
 212
 213        transport_verify_remote_names(nr_refspecs, refspecs);
 214
 215        local_refs = get_local_heads();
 216
 217        flags = MATCH_REFS_NONE;
 218
 219        if (send_all)
 220                flags |= MATCH_REFS_ALL;
 221        if (args.send_mirror)
 222                flags |= MATCH_REFS_MIRROR;
 223
 224        /* match them up */
 225        if (match_push_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
 226                return -1;
 227
 228        set_ref_status_for_push(remote_refs, args.send_mirror,
 229                args.force_update);
 230
 231        ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
 232
 233        if (helper_status)
 234                print_helper_status(remote_refs);
 235
 236        close(fd[1]);
 237        close(fd[0]);
 238
 239        ret |= finish_connect(conn);
 240
 241        if (!helper_status)
 242                transport_print_push_status(dest, remote_refs, args.verbose, 0, &reject_reasons);
 243
 244        if (!args.dry_run && remote) {
 245                struct ref *ref;
 246                for (ref = remote_refs; ref; ref = ref->next)
 247                        transport_update_tracking_ref(remote, ref, args.verbose);
 248        }
 249
 250        if (!ret && !transport_refs_pushed(remote_refs))
 251                fprintf(stderr, "Everything up-to-date\n");
 252
 253        return ret;
 254}