builtin / push.con commit Merge branch 'mb/fetch-call-a-non-branch-a-ref' into maint (66bca3f)
   1/*
   2 * "git push"
   3 */
   4#include "cache.h"
   5#include "refs.h"
   6#include "run-command.h"
   7#include "builtin.h"
   8#include "remote.h"
   9#include "transport.h"
  10#include "parse-options.h"
  11#include "submodule.h"
  12
  13static const char * const push_usage[] = {
  14        "git push [<options>] [<repository> [<refspec>...]]",
  15        NULL,
  16};
  17
  18static int thin;
  19static int deleterefs;
  20static const char *receivepack;
  21static int verbosity;
  22static int progress = -1;
  23
  24static const char **refspec;
  25static int refspec_nr;
  26static int refspec_alloc;
  27
  28static void add_refspec(const char *ref)
  29{
  30        refspec_nr++;
  31        ALLOC_GROW(refspec, refspec_nr, refspec_alloc);
  32        refspec[refspec_nr-1] = ref;
  33}
  34
  35static void set_refspecs(const char **refs, int nr)
  36{
  37        int i;
  38        for (i = 0; i < nr; i++) {
  39                const char *ref = refs[i];
  40                if (!strcmp("tag", ref)) {
  41                        char *tag;
  42                        int len;
  43                        if (nr <= ++i)
  44                                die(_("tag shorthand without <tag>"));
  45                        len = strlen(refs[i]) + 11;
  46                        if (deleterefs) {
  47                                tag = xmalloc(len+1);
  48                                strcpy(tag, ":refs/tags/");
  49                        } else {
  50                                tag = xmalloc(len);
  51                                strcpy(tag, "refs/tags/");
  52                        }
  53                        strcat(tag, refs[i]);
  54                        ref = tag;
  55                } else if (deleterefs && !strchr(ref, ':')) {
  56                        char *delref;
  57                        int len = strlen(ref)+1;
  58                        delref = xmalloc(len+1);
  59                        strcpy(delref, ":");
  60                        strcat(delref, ref);
  61                        ref = delref;
  62                } else if (deleterefs)
  63                        die(_("--delete only accepts plain target ref names"));
  64                add_refspec(ref);
  65        }
  66}
  67
  68static int push_url_of_remote(struct remote *remote, const char ***url_p)
  69{
  70        if (remote->pushurl_nr) {
  71                *url_p = remote->pushurl;
  72                return remote->pushurl_nr;
  73        }
  74        *url_p = remote->url;
  75        return remote->url_nr;
  76}
  77
  78static void setup_push_upstream(struct remote *remote)
  79{
  80        struct strbuf refspec = STRBUF_INIT;
  81        struct branch *branch = branch_get(NULL);
  82        if (!branch)
  83                die(_("You are not currently on a branch.\n"
  84                    "To push the history leading to the current (detached HEAD)\n"
  85                    "state now, use\n"
  86                    "\n"
  87                    "    git push %s HEAD:<name-of-remote-branch>\n"),
  88                    remote->name);
  89        if (!branch->merge_nr || !branch->merge || !branch->remote_name)
  90                die(_("The current branch %s has no upstream branch.\n"
  91                    "To push the current branch and set the remote as upstream, use\n"
  92                    "\n"
  93                    "    git push --set-upstream %s %s\n"),
  94                    branch->name,
  95                    remote->name,
  96                    branch->name);
  97        if (branch->merge_nr != 1)
  98                die(_("The current branch %s has multiple upstream branches, "
  99                    "refusing to push."), branch->name);
 100        if (strcmp(branch->remote_name, remote->name))
 101                die(_("You are pushing to remote '%s', which is not the upstream of\n"
 102                      "your current branch '%s', without telling me what to push\n"
 103                      "to update which remote branch."),
 104                    remote->name, branch->name);
 105
 106        strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
 107        add_refspec(refspec.buf);
 108}
 109
 110static void setup_default_push_refspecs(struct remote *remote)
 111{
 112        switch (push_default) {
 113        default:
 114        case PUSH_DEFAULT_MATCHING:
 115                add_refspec(":");
 116                break;
 117
 118        case PUSH_DEFAULT_UPSTREAM:
 119                setup_push_upstream(remote);
 120                break;
 121
 122        case PUSH_DEFAULT_CURRENT:
 123                add_refspec("HEAD");
 124                break;
 125
 126        case PUSH_DEFAULT_NOTHING:
 127                die(_("You didn't specify any refspecs to push, and "
 128                    "push.default is \"nothing\"."));
 129                break;
 130        }
 131}
 132
 133static int push_with_options(struct transport *transport, int flags)
 134{
 135        int err;
 136        int nonfastforward;
 137
 138        transport_set_verbosity(transport, verbosity, progress);
 139
 140        if (receivepack)
 141                transport_set_option(transport,
 142                                     TRANS_OPT_RECEIVEPACK, receivepack);
 143        if (thin)
 144                transport_set_option(transport, TRANS_OPT_THIN, "yes");
 145
 146        if (verbosity > 0)
 147                fprintf(stderr, _("Pushing to %s\n"), transport->url);
 148        err = transport_push(transport, refspec_nr, refspec, flags,
 149                             &nonfastforward);
 150        if (err != 0)
 151                error(_("failed to push some refs to '%s'"), transport->url);
 152
 153        err |= transport_disconnect(transport);
 154
 155        if (!err)
 156                return 0;
 157
 158        if (nonfastforward && advice_push_nonfastforward) {
 159                fprintf(stderr, _("To prevent you from losing history, non-fast-forward updates were rejected\n"
 160                                "Merge the remote changes (e.g. 'git pull') before pushing again.  See the\n"
 161                                "'Note about fast-forwards' section of 'git push --help' for details.\n"));
 162        }
 163
 164        return 1;
 165}
 166
 167static int do_push(const char *repo, int flags)
 168{
 169        int i, errs;
 170        struct remote *remote = remote_get(repo);
 171        const char **url;
 172        int url_nr;
 173
 174        if (!remote) {
 175                if (repo)
 176                        die(_("bad repository '%s'"), repo);
 177                die(_("No configured push destination.\n"
 178                    "Either specify the URL from the command-line or configure a remote repository using\n"
 179                    "\n"
 180                    "    git remote add <name> <url>\n"
 181                    "\n"
 182                    "and then push using the remote name\n"
 183                    "\n"
 184                    "    git push <name>\n"));
 185        }
 186
 187        if (remote->mirror)
 188                flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
 189
 190        if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
 191                if (!strcmp(*refspec, "refs/tags/*"))
 192                        return error(_("--all and --tags are incompatible"));
 193                return error(_("--all can't be combined with refspecs"));
 194        }
 195
 196        if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
 197                if (!strcmp(*refspec, "refs/tags/*"))
 198                        return error(_("--mirror and --tags are incompatible"));
 199                return error(_("--mirror can't be combined with refspecs"));
 200        }
 201
 202        if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
 203                                (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
 204                return error(_("--all and --mirror are incompatible"));
 205        }
 206
 207        if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
 208                if (remote->push_refspec_nr) {
 209                        refspec = remote->push_refspec;
 210                        refspec_nr = remote->push_refspec_nr;
 211                } else if (!(flags & TRANSPORT_PUSH_MIRROR))
 212                        setup_default_push_refspecs(remote);
 213        }
 214        errs = 0;
 215        url_nr = push_url_of_remote(remote, &url);
 216        if (url_nr) {
 217                for (i = 0; i < url_nr; i++) {
 218                        struct transport *transport =
 219                                transport_get(remote, url[i]);
 220                        if (push_with_options(transport, flags))
 221                                errs++;
 222                }
 223        } else {
 224                struct transport *transport =
 225                        transport_get(remote, NULL);
 226
 227                if (push_with_options(transport, flags))
 228                        errs++;
 229        }
 230        return !!errs;
 231}
 232
 233static int option_parse_recurse_submodules(const struct option *opt,
 234                                   const char *arg, int unset)
 235{
 236        int *flags = opt->value;
 237        if (arg) {
 238                if (!strcmp(arg, "check"))
 239                        *flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
 240                else
 241                        die("bad %s argument: %s", opt->long_name, arg);
 242        } else
 243                die("option %s needs an argument (check)", opt->long_name);
 244
 245        return 0;
 246}
 247
 248int cmd_push(int argc, const char **argv, const char *prefix)
 249{
 250        int flags = 0;
 251        int tags = 0;
 252        int rc;
 253        const char *repo = NULL;        /* default repository */
 254        struct option options[] = {
 255                OPT__VERBOSITY(&verbosity),
 256                OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
 257                OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
 258                OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
 259                            (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
 260                OPT_BOOLEAN( 0, "delete", &deleterefs, "delete refs"),
 261                OPT_BOOLEAN( 0 , "tags", &tags, "push tags (can't be used with --all or --mirror)"),
 262                OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
 263                OPT_BIT( 0,  "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
 264                OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
 265                { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check",
 266                        "controls recursive pushing of submodules",
 267                        PARSE_OPT_OPTARG, option_parse_recurse_submodules },
 268                OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
 269                OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
 270                OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
 271                OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status",
 272                        TRANSPORT_PUSH_SET_UPSTREAM),
 273                OPT_BOOL(0, "progress", &progress, "force progress reporting"),
 274                OPT_BIT(0, "prune", &flags, "prune locally removed refs",
 275                        TRANSPORT_PUSH_PRUNE),
 276                OPT_END()
 277        };
 278
 279        packet_trace_identity("push");
 280        git_config(git_default_config, NULL);
 281        argc = parse_options(argc, argv, prefix, options, push_usage, 0);
 282
 283        if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
 284                die(_("--delete is incompatible with --all, --mirror and --tags"));
 285        if (deleterefs && argc < 2)
 286                die(_("--delete doesn't make sense without any refs"));
 287
 288        if (tags)
 289                add_refspec("refs/tags/*");
 290
 291        if (argc > 0) {
 292                repo = argv[0];
 293                set_refspecs(argv + 1, argc - 1);
 294        }
 295
 296        rc = do_push(repo, flags);
 297        if (rc == -1)
 298                usage_with_options(push_usage, options);
 299        else
 300                return rc;
 301}