builtin / send-pack.con commit push: support signing pushes iff the server supports it (3026109)
   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#include "sha1-array.h"
  14#include "gpg-interface.h"
  15#include "gettext.h"
  16
  17static const char * const send_pack_usage[] = {
  18        N_("git send-pack [--all | --mirror] [--dry-run] [--force] "
  19          "[--receive-pack=<git-receive-pack>] [--verbose] [--thin] [--atomic] "
  20          "[<host>:]<directory> [<ref>...]\n"
  21          "  --all and explicit <ref> specification are mutually exclusive."),
  22        NULL,
  23};
  24
  25static struct send_pack_args args;
  26
  27static void print_helper_status(struct ref *ref)
  28{
  29        struct strbuf buf = STRBUF_INIT;
  30
  31        for (; ref; ref = ref->next) {
  32                const char *msg = NULL;
  33                const char *res;
  34
  35                switch(ref->status) {
  36                case REF_STATUS_NONE:
  37                        res = "error";
  38                        msg = "no match";
  39                        break;
  40
  41                case REF_STATUS_OK:
  42                        res = "ok";
  43                        break;
  44
  45                case REF_STATUS_UPTODATE:
  46                        res = "ok";
  47                        msg = "up to date";
  48                        break;
  49
  50                case REF_STATUS_REJECT_NONFASTFORWARD:
  51                        res = "error";
  52                        msg = "non-fast forward";
  53                        break;
  54
  55                case REF_STATUS_REJECT_FETCH_FIRST:
  56                        res = "error";
  57                        msg = "fetch first";
  58                        break;
  59
  60                case REF_STATUS_REJECT_NEEDS_FORCE:
  61                        res = "error";
  62                        msg = "needs force";
  63                        break;
  64
  65                case REF_STATUS_REJECT_STALE:
  66                        res = "error";
  67                        msg = "stale info";
  68                        break;
  69
  70                case REF_STATUS_REJECT_ALREADY_EXISTS:
  71                        res = "error";
  72                        msg = "already exists";
  73                        break;
  74
  75                case REF_STATUS_REJECT_NODELETE:
  76                case REF_STATUS_REMOTE_REJECT:
  77                        res = "error";
  78                        break;
  79
  80                case REF_STATUS_EXPECTING_REPORT:
  81                default:
  82                        continue;
  83                }
  84
  85                strbuf_reset(&buf);
  86                strbuf_addf(&buf, "%s %s", res, ref->name);
  87                if (ref->remote_status)
  88                        msg = ref->remote_status;
  89                if (msg) {
  90                        strbuf_addch(&buf, ' ');
  91                        quote_two_c_style(&buf, "", msg, 0);
  92                }
  93                strbuf_addch(&buf, '\n');
  94
  95                write_or_die(1, buf.buf, buf.len);
  96        }
  97        strbuf_release(&buf);
  98}
  99
 100int cmd_send_pack(int argc, const char **argv, const char *prefix)
 101{
 102        int i, nr_refspecs = 0;
 103        const char **refspecs = NULL;
 104        const char *remote_name = NULL;
 105        struct remote *remote = NULL;
 106        const char *dest = NULL;
 107        int fd[2];
 108        struct child_process *conn;
 109        struct sha1_array extra_have = SHA1_ARRAY_INIT;
 110        struct sha1_array shallow = SHA1_ARRAY_INIT;
 111        struct ref *remote_refs, *local_refs;
 112        int ret;
 113        int helper_status = 0;
 114        int send_all = 0;
 115        int verbose = 0;
 116        const char *receivepack = "git-receive-pack";
 117        unsigned dry_run = 0;
 118        unsigned send_mirror = 0;
 119        unsigned force_update = 0;
 120        unsigned quiet = 0;
 121        int push_cert = 0;
 122        unsigned use_thin_pack = 0;
 123        unsigned atomic = 0;
 124        unsigned stateless_rpc = 0;
 125        int flags;
 126        unsigned int reject_reasons;
 127        int progress = -1;
 128        int from_stdin = 0;
 129        struct push_cas_option cas = {0};
 130
 131        struct option options[] = {
 132                OPT__VERBOSITY(&verbose),
 133                OPT_STRING(0, "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
 134                OPT_STRING(0, "exec", &receivepack, "receive-pack", N_("receive pack program")),
 135                OPT_STRING(0, "remote", &remote_name, "remote", N_("remote name")),
 136                OPT_BOOL(0, "all", &send_all, N_("push all refs")),
 137                OPT_BOOL('n' , "dry-run", &dry_run, N_("dry run")),
 138                OPT_BOOL(0, "mirror", &send_mirror, N_("mirror all refs")),
 139                OPT_BOOL('f', "force", &force_update, N_("force updates")),
 140                { OPTION_CALLBACK,
 141                  0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
 142                  PARSE_OPT_OPTARG, option_parse_push_signed },
 143                OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
 144                OPT_BOOL(0, "thin", &use_thin_pack, N_("use thin pack")),
 145                OPT_BOOL(0, "atomic", &atomic, N_("request atomic transaction on remote side")),
 146                OPT_BOOL(0, "stateless-rpc", &stateless_rpc, N_("use stateless RPC protocol")),
 147                OPT_BOOL(0, "stdin", &from_stdin, N_("read refs from stdin")),
 148                OPT_BOOL(0, "helper-status", &helper_status, N_("print status from remote helper")),
 149                { OPTION_CALLBACK,
 150                  0, CAS_OPT_NAME, &cas, N_("refname>:<expect"),
 151                  N_("require old value of ref to be at this value"),
 152                  PARSE_OPT_OPTARG, parseopt_push_cas_option },
 153                OPT_END()
 154        };
 155
 156        git_config(git_gpg_config, NULL);
 157        argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0);
 158        if (argc > 0) {
 159                dest = argv[0];
 160                refspecs = (const char **)(argv + 1);
 161                nr_refspecs = argc - 1;
 162        }
 163
 164        if (!dest)
 165                usage_with_options(send_pack_usage, options);
 166
 167        args.verbose = verbose;
 168        args.dry_run = dry_run;
 169        args.send_mirror = send_mirror;
 170        args.force_update = force_update;
 171        args.quiet = quiet;
 172        args.push_cert = push_cert;
 173        args.progress = progress;
 174        args.use_thin_pack = use_thin_pack;
 175        args.atomic = atomic;
 176        args.stateless_rpc = stateless_rpc;
 177
 178        if (from_stdin) {
 179                struct argv_array all_refspecs = ARGV_ARRAY_INIT;
 180
 181                for (i = 0; i < nr_refspecs; i++)
 182                        argv_array_push(&all_refspecs, refspecs[i]);
 183
 184                if (args.stateless_rpc) {
 185                        const char *buf;
 186                        while ((buf = packet_read_line(0, NULL)))
 187                                argv_array_push(&all_refspecs, buf);
 188                } else {
 189                        struct strbuf line = STRBUF_INIT;
 190                        while (strbuf_getline(&line, stdin, '\n') != EOF)
 191                                argv_array_push(&all_refspecs, line.buf);
 192                        strbuf_release(&line);
 193                }
 194
 195                refspecs = all_refspecs.argv;
 196                nr_refspecs = all_refspecs.argc;
 197        }
 198
 199        /*
 200         * --all and --mirror are incompatible; neither makes sense
 201         * with any refspecs.
 202         */
 203        if ((refspecs && (send_all || args.send_mirror)) ||
 204            (send_all && args.send_mirror))
 205                usage_with_options(send_pack_usage, options);
 206
 207        if (remote_name) {
 208                remote = remote_get(remote_name);
 209                if (!remote_has_url(remote, dest)) {
 210                        die("Destination %s is not a uri for %s",
 211                            dest, remote_name);
 212                }
 213        }
 214
 215        if (progress == -1)
 216                progress = !args.quiet && isatty(2);
 217        args.progress = progress;
 218
 219        if (args.stateless_rpc) {
 220                conn = NULL;
 221                fd[0] = 0;
 222                fd[1] = 1;
 223        } else {
 224                conn = git_connect(fd, dest, receivepack,
 225                        args.verbose ? CONNECT_VERBOSE : 0);
 226        }
 227
 228        get_remote_heads(fd[0], NULL, 0, &remote_refs, REF_NORMAL,
 229                         &extra_have, &shallow);
 230
 231        transport_verify_remote_names(nr_refspecs, refspecs);
 232
 233        local_refs = get_local_heads();
 234
 235        flags = MATCH_REFS_NONE;
 236
 237        if (send_all)
 238                flags |= MATCH_REFS_ALL;
 239        if (args.send_mirror)
 240                flags |= MATCH_REFS_MIRROR;
 241
 242        /* match them up */
 243        if (match_push_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
 244                return -1;
 245
 246        if (!is_empty_cas(&cas))
 247                apply_push_cas(&cas, remote, remote_refs);
 248
 249        set_ref_status_for_push(remote_refs, args.send_mirror,
 250                args.force_update);
 251
 252        ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
 253
 254        if (helper_status)
 255                print_helper_status(remote_refs);
 256
 257        close(fd[1]);
 258        close(fd[0]);
 259
 260        ret |= finish_connect(conn);
 261
 262        if (!helper_status)
 263                transport_print_push_status(dest, remote_refs, args.verbose, 0, &reject_reasons);
 264
 265        if (!args.dry_run && remote) {
 266                struct ref *ref;
 267                for (ref = remote_refs; ref; ref = ref->next)
 268                        transport_update_tracking_ref(remote, ref, args.verbose);
 269        }
 270
 271        if (!ret && !transport_refs_pushed(remote_refs))
 272                fprintf(stderr, "Everything up-to-date\n");
 273
 274        return ret;
 275}