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