builtin / push.con commit pickaxe: use textconv for -S counting (ef90ab6)
   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;
  27static int default_matching_used;
  28
  29static void add_refspec(const char *ref)
  30{
  31        refspec_nr++;
  32        ALLOC_GROW(refspec, refspec_nr, refspec_alloc);
  33        refspec[refspec_nr-1] = ref;
  34}
  35
  36static void set_refspecs(const char **refs, int nr)
  37{
  38        int i;
  39        for (i = 0; i < nr; i++) {
  40                const char *ref = refs[i];
  41                if (!strcmp("tag", ref)) {
  42                        char *tag;
  43                        int len;
  44                        if (nr <= ++i)
  45                                die(_("tag shorthand without <tag>"));
  46                        len = strlen(refs[i]) + 11;
  47                        if (deleterefs) {
  48                                tag = xmalloc(len+1);
  49                                strcpy(tag, ":refs/tags/");
  50                        } else {
  51                                tag = xmalloc(len);
  52                                strcpy(tag, "refs/tags/");
  53                        }
  54                        strcat(tag, refs[i]);
  55                        ref = tag;
  56                } else if (deleterefs && !strchr(ref, ':')) {
  57                        char *delref;
  58                        int len = strlen(ref)+1;
  59                        delref = xmalloc(len+1);
  60                        strcpy(delref, ":");
  61                        strcat(delref, ref);
  62                        ref = delref;
  63                } else if (deleterefs)
  64                        die(_("--delete only accepts plain target ref names"));
  65                add_refspec(ref);
  66        }
  67}
  68
  69static int push_url_of_remote(struct remote *remote, const char ***url_p)
  70{
  71        if (remote->pushurl_nr) {
  72                *url_p = remote->pushurl;
  73                return remote->pushurl_nr;
  74        }
  75        *url_p = remote->url;
  76        return remote->url_nr;
  77}
  78
  79static NORETURN int die_push_simple(struct branch *branch, struct remote *remote) {
  80        /*
  81         * There's no point in using shorten_unambiguous_ref here,
  82         * as the ambiguity would be on the remote side, not what
  83         * we have locally. Plus, this is supposed to be the simple
  84         * mode. If the user is doing something crazy like setting
  85         * upstream to a non-branch, we should probably be showing
  86         * them the big ugly fully qualified ref.
  87         */
  88        const char *advice_maybe = "";
  89        const char *short_upstream =
  90                skip_prefix(branch->merge[0]->src, "refs/heads/");
  91
  92        if (!short_upstream)
  93                short_upstream = branch->merge[0]->src;
  94        /*
  95         * Don't show advice for people who explicitely set
  96         * push.default.
  97         */
  98        if (push_default == PUSH_DEFAULT_UNSPECIFIED)
  99                advice_maybe = _("\n"
 100                                 "To choose either option permanently, "
 101                                 "see push.default in 'git help config'.");
 102        die(_("The upstream branch of your current branch does not match\n"
 103              "the name of your current branch.  To push to the upstream branch\n"
 104              "on the remote, use\n"
 105              "\n"
 106              "    git push %s HEAD:%s\n"
 107              "\n"
 108              "To push to the branch of the same name on the remote, use\n"
 109              "\n"
 110              "    git push %s %s\n"
 111              "%s"),
 112            remote->name, short_upstream,
 113            remote->name, branch->name, advice_maybe);
 114}
 115
 116static void setup_push_upstream(struct remote *remote, int simple)
 117{
 118        struct strbuf refspec = STRBUF_INIT;
 119        struct branch *branch = branch_get(NULL);
 120        if (!branch)
 121                die(_("You are not currently on a branch.\n"
 122                    "To push the history leading to the current (detached HEAD)\n"
 123                    "state now, use\n"
 124                    "\n"
 125                    "    git push %s HEAD:<name-of-remote-branch>\n"),
 126                    remote->name);
 127        if (!branch->merge_nr || !branch->merge || !branch->remote_name)
 128                die(_("The current branch %s has no upstream branch.\n"
 129                    "To push the current branch and set the remote as upstream, use\n"
 130                    "\n"
 131                    "    git push --set-upstream %s %s\n"),
 132                    branch->name,
 133                    remote->name,
 134                    branch->name);
 135        if (branch->merge_nr != 1)
 136                die(_("The current branch %s has multiple upstream branches, "
 137                    "refusing to push."), branch->name);
 138        if (strcmp(branch->remote_name, remote->name))
 139                die(_("You are pushing to remote '%s', which is not the upstream of\n"
 140                      "your current branch '%s', without telling me what to push\n"
 141                      "to update which remote branch."),
 142                    remote->name, branch->name);
 143        if (simple && strcmp(branch->refname, branch->merge[0]->src))
 144                die_push_simple(branch, remote);
 145
 146        strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
 147        add_refspec(refspec.buf);
 148}
 149
 150static void setup_default_push_refspecs(struct remote *remote)
 151{
 152        switch (push_default) {
 153        default:
 154        case PUSH_DEFAULT_UNSPECIFIED:
 155                default_matching_used = 1;
 156                /* fallthru */
 157        case PUSH_DEFAULT_MATCHING:
 158                add_refspec(":");
 159                break;
 160
 161        case PUSH_DEFAULT_SIMPLE:
 162                setup_push_upstream(remote, 1);
 163                break;
 164
 165        case PUSH_DEFAULT_UPSTREAM:
 166                setup_push_upstream(remote, 0);
 167                break;
 168
 169        case PUSH_DEFAULT_CURRENT:
 170                add_refspec("HEAD");
 171                break;
 172
 173        case PUSH_DEFAULT_NOTHING:
 174                die(_("You didn't specify any refspecs to push, and "
 175                    "push.default is \"nothing\"."));
 176                break;
 177        }
 178}
 179
 180static const char message_advice_pull_before_push[] =
 181        N_("Updates were rejected because the tip of your current branch is behind\n"
 182           "its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
 183           "before pushing again.\n"
 184           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 185
 186static const char message_advice_use_upstream[] =
 187        N_("Updates were rejected because a pushed branch tip is behind its remote\n"
 188           "counterpart. If you did not intend to push that branch, you may want to\n"
 189           "specify branches to push or set the 'push.default' configuration\n"
 190           "variable to 'current' or 'upstream' to push only the current branch.");
 191
 192static const char message_advice_checkout_pull_push[] =
 193        N_("Updates were rejected because a pushed branch tip is behind its remote\n"
 194           "counterpart. Check out this branch and merge the remote changes\n"
 195           "(e.g. 'git pull') before pushing again.\n"
 196           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 197
 198static void advise_pull_before_push(void)
 199{
 200        if (!advice_push_non_ff_current || !advice_push_nonfastforward)
 201                return;
 202        advise(_(message_advice_pull_before_push));
 203}
 204
 205static void advise_use_upstream(void)
 206{
 207        if (!advice_push_non_ff_default || !advice_push_nonfastforward)
 208                return;
 209        advise(_(message_advice_use_upstream));
 210}
 211
 212static void advise_checkout_pull_push(void)
 213{
 214        if (!advice_push_non_ff_matching || !advice_push_nonfastforward)
 215                return;
 216        advise(_(message_advice_checkout_pull_push));
 217}
 218
 219static int push_with_options(struct transport *transport, int flags)
 220{
 221        int err;
 222        int nonfastforward;
 223
 224        transport_set_verbosity(transport, verbosity, progress);
 225
 226        if (receivepack)
 227                transport_set_option(transport,
 228                                     TRANS_OPT_RECEIVEPACK, receivepack);
 229        if (thin)
 230                transport_set_option(transport, TRANS_OPT_THIN, "yes");
 231
 232        if (verbosity > 0)
 233                fprintf(stderr, _("Pushing to %s\n"), transport->url);
 234        err = transport_push(transport, refspec_nr, refspec, flags,
 235                             &nonfastforward);
 236        if (err != 0)
 237                error(_("failed to push some refs to '%s'"), transport->url);
 238
 239        err |= transport_disconnect(transport);
 240        if (!err)
 241                return 0;
 242
 243        switch (nonfastforward) {
 244        default:
 245                break;
 246        case NON_FF_HEAD:
 247                advise_pull_before_push();
 248                break;
 249        case NON_FF_OTHER:
 250                if (default_matching_used)
 251                        advise_use_upstream();
 252                else
 253                        advise_checkout_pull_push();
 254                break;
 255        }
 256
 257        return 1;
 258}
 259
 260static int do_push(const char *repo, int flags)
 261{
 262        int i, errs;
 263        struct remote *remote = remote_get(repo);
 264        const char **url;
 265        int url_nr;
 266
 267        if (!remote) {
 268                if (repo)
 269                        die(_("bad repository '%s'"), repo);
 270                die(_("No configured push destination.\n"
 271                    "Either specify the URL from the command-line or configure a remote repository using\n"
 272                    "\n"
 273                    "    git remote add <name> <url>\n"
 274                    "\n"
 275                    "and then push using the remote name\n"
 276                    "\n"
 277                    "    git push <name>\n"));
 278        }
 279
 280        if (remote->mirror)
 281                flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
 282
 283        if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
 284                if (!strcmp(*refspec, "refs/tags/*"))
 285                        return error(_("--all and --tags are incompatible"));
 286                return error(_("--all can't be combined with refspecs"));
 287        }
 288
 289        if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
 290                if (!strcmp(*refspec, "refs/tags/*"))
 291                        return error(_("--mirror and --tags are incompatible"));
 292                return error(_("--mirror can't be combined with refspecs"));
 293        }
 294
 295        if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
 296                                (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
 297                return error(_("--all and --mirror are incompatible"));
 298        }
 299
 300        if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
 301                if (remote->push_refspec_nr) {
 302                        refspec = remote->push_refspec;
 303                        refspec_nr = remote->push_refspec_nr;
 304                } else if (!(flags & TRANSPORT_PUSH_MIRROR))
 305                        setup_default_push_refspecs(remote);
 306        }
 307        errs = 0;
 308        url_nr = push_url_of_remote(remote, &url);
 309        if (url_nr) {
 310                for (i = 0; i < url_nr; i++) {
 311                        struct transport *transport =
 312                                transport_get(remote, url[i]);
 313                        if (push_with_options(transport, flags))
 314                                errs++;
 315                }
 316        } else {
 317                struct transport *transport =
 318                        transport_get(remote, NULL);
 319
 320                if (push_with_options(transport, flags))
 321                        errs++;
 322        }
 323        return !!errs;
 324}
 325
 326static int option_parse_recurse_submodules(const struct option *opt,
 327                                   const char *arg, int unset)
 328{
 329        int *flags = opt->value;
 330
 331        if (*flags & (TRANSPORT_RECURSE_SUBMODULES_CHECK |
 332                      TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND))
 333                die("%s can only be used once.", opt->long_name);
 334
 335        if (arg) {
 336                if (!strcmp(arg, "check"))
 337                        *flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
 338                else if (!strcmp(arg, "on-demand"))
 339                        *flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND;
 340                else
 341                        die("bad %s argument: %s", opt->long_name, arg);
 342        } else
 343                die("option %s needs an argument (check|on-demand)",
 344                                opt->long_name);
 345
 346        return 0;
 347}
 348
 349int cmd_push(int argc, const char **argv, const char *prefix)
 350{
 351        int flags = 0;
 352        int tags = 0;
 353        int rc;
 354        const char *repo = NULL;        /* default repository */
 355        struct option options[] = {
 356                OPT__VERBOSITY(&verbosity),
 357                OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
 358                OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
 359                OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
 360                            (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
 361                OPT_BOOLEAN( 0, "delete", &deleterefs, "delete refs"),
 362                OPT_BOOLEAN( 0 , "tags", &tags, "push tags (can't be used with --all or --mirror)"),
 363                OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
 364                OPT_BIT( 0,  "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
 365                OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
 366                { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check",
 367                        "controls recursive pushing of submodules",
 368                        PARSE_OPT_OPTARG, option_parse_recurse_submodules },
 369                OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
 370                OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
 371                OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
 372                OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status",
 373                        TRANSPORT_PUSH_SET_UPSTREAM),
 374                OPT_BOOL(0, "progress", &progress, "force progress reporting"),
 375                OPT_BIT(0, "prune", &flags, "prune locally removed refs",
 376                        TRANSPORT_PUSH_PRUNE),
 377                OPT_END()
 378        };
 379
 380        packet_trace_identity("push");
 381        git_config(git_default_config, NULL);
 382        argc = parse_options(argc, argv, prefix, options, push_usage, 0);
 383
 384        if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
 385                die(_("--delete is incompatible with --all, --mirror and --tags"));
 386        if (deleterefs && argc < 2)
 387                die(_("--delete doesn't make sense without any refs"));
 388
 389        if (tags)
 390                add_refspec("refs/tags/*");
 391
 392        if (argc > 0) {
 393                repo = argv[0];
 394                set_refspecs(argv + 1, argc - 1);
 395        }
 396
 397        rc = do_push(repo, flags);
 398        if (rc == -1)
 399                usage_with_options(push_usage, options);
 400        else
 401                return rc;
 402}