builtin / push.con commit refs.c: extract function search_for_subdir() (f348ac9)
   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 void setup_push_upstream(struct remote *remote)
  80{
  81        struct strbuf refspec = STRBUF_INIT;
  82        struct branch *branch = branch_get(NULL);
  83        if (!branch)
  84                die(_("You are not currently on a branch.\n"
  85                    "To push the history leading to the current (detached HEAD)\n"
  86                    "state now, use\n"
  87                    "\n"
  88                    "    git push %s HEAD:<name-of-remote-branch>\n"),
  89                    remote->name);
  90        if (!branch->merge_nr || !branch->merge || !branch->remote_name)
  91                die(_("The current branch %s has no upstream branch.\n"
  92                    "To push the current branch and set the remote as upstream, use\n"
  93                    "\n"
  94                    "    git push --set-upstream %s %s\n"),
  95                    branch->name,
  96                    remote->name,
  97                    branch->name);
  98        if (branch->merge_nr != 1)
  99                die(_("The current branch %s has multiple upstream branches, "
 100                    "refusing to push."), branch->name);
 101        if (strcmp(branch->remote_name, remote->name))
 102                die(_("You are pushing to remote '%s', which is not the upstream of\n"
 103                      "your current branch '%s', without telling me what to push\n"
 104                      "to update which remote branch."),
 105                    remote->name, branch->name);
 106
 107        strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
 108        add_refspec(refspec.buf);
 109}
 110
 111static void setup_default_push_refspecs(struct remote *remote)
 112{
 113        switch (push_default) {
 114        default:
 115        case PUSH_DEFAULT_UNSPECIFIED:
 116                default_matching_used = 1;
 117                /* fallthru */
 118        case PUSH_DEFAULT_MATCHING:
 119                add_refspec(":");
 120                break;
 121
 122        case PUSH_DEFAULT_UPSTREAM:
 123                setup_push_upstream(remote);
 124                break;
 125
 126        case PUSH_DEFAULT_CURRENT:
 127                add_refspec("HEAD");
 128                break;
 129
 130        case PUSH_DEFAULT_NOTHING:
 131                die(_("You didn't specify any refspecs to push, and "
 132                    "push.default is \"nothing\"."));
 133                break;
 134        }
 135}
 136
 137static const char message_advice_pull_before_push[] =
 138        N_("Updates were rejected because the tip of your current branch is behind\n"
 139           "its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
 140           "before pushing again.\n"
 141           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 142
 143static const char message_advice_use_upstream[] =
 144        N_("Updates were rejected because a pushed branch tip is behind its remote\n"
 145           "counterpart. If you did not intend to push that branch, you may want to\n"
 146           "specify branches to push or set the 'push.default' configuration\n"
 147           "variable to 'current' or 'upstream' to push only the current branch.");
 148
 149static const char message_advice_checkout_pull_push[] =
 150        N_("Updates were rejected because a pushed branch tip is behind its remote\n"
 151           "counterpart. Check out this branch and merge the remote changes\n"
 152           "(e.g. 'git pull') before pushing again.\n"
 153           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 154
 155static void advise_pull_before_push(void)
 156{
 157        if (!advice_push_non_ff_current || !advice_push_nonfastforward)
 158                return;
 159        advise(_(message_advice_pull_before_push));
 160}
 161
 162static void advise_use_upstream(void)
 163{
 164        if (!advice_push_non_ff_default || !advice_push_nonfastforward)
 165                return;
 166        advise(_(message_advice_use_upstream));
 167}
 168
 169static void advise_checkout_pull_push(void)
 170{
 171        if (!advice_push_non_ff_matching || !advice_push_nonfastforward)
 172                return;
 173        advise(_(message_advice_checkout_pull_push));
 174}
 175
 176static int push_with_options(struct transport *transport, int flags)
 177{
 178        int err;
 179        int nonfastforward;
 180
 181        transport_set_verbosity(transport, verbosity, progress);
 182
 183        if (receivepack)
 184                transport_set_option(transport,
 185                                     TRANS_OPT_RECEIVEPACK, receivepack);
 186        if (thin)
 187                transport_set_option(transport, TRANS_OPT_THIN, "yes");
 188
 189        if (verbosity > 0)
 190                fprintf(stderr, _("Pushing to %s\n"), transport->url);
 191        err = transport_push(transport, refspec_nr, refspec, flags,
 192                             &nonfastforward);
 193        if (err != 0)
 194                error(_("failed to push some refs to '%s'"), transport->url);
 195
 196        err |= transport_disconnect(transport);
 197        if (!err)
 198                return 0;
 199
 200        switch (nonfastforward) {
 201        default:
 202                break;
 203        case NON_FF_HEAD:
 204                advise_pull_before_push();
 205                break;
 206        case NON_FF_OTHER:
 207                if (default_matching_used)
 208                        advise_use_upstream();
 209                else
 210                        advise_checkout_pull_push();
 211                break;
 212        }
 213
 214        return 1;
 215}
 216
 217static int do_push(const char *repo, int flags)
 218{
 219        int i, errs;
 220        struct remote *remote = remote_get(repo);
 221        const char **url;
 222        int url_nr;
 223
 224        if (!remote) {
 225                if (repo)
 226                        die(_("bad repository '%s'"), repo);
 227                die(_("No configured push destination.\n"
 228                    "Either specify the URL from the command-line or configure a remote repository using\n"
 229                    "\n"
 230                    "    git remote add <name> <url>\n"
 231                    "\n"
 232                    "and then push using the remote name\n"
 233                    "\n"
 234                    "    git push <name>\n"));
 235        }
 236
 237        if (remote->mirror)
 238                flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
 239
 240        if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
 241                if (!strcmp(*refspec, "refs/tags/*"))
 242                        return error(_("--all and --tags are incompatible"));
 243                return error(_("--all can't be combined with refspecs"));
 244        }
 245
 246        if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
 247                if (!strcmp(*refspec, "refs/tags/*"))
 248                        return error(_("--mirror and --tags are incompatible"));
 249                return error(_("--mirror can't be combined with refspecs"));
 250        }
 251
 252        if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
 253                                (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
 254                return error(_("--all and --mirror are incompatible"));
 255        }
 256
 257        if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
 258                if (remote->push_refspec_nr) {
 259                        refspec = remote->push_refspec;
 260                        refspec_nr = remote->push_refspec_nr;
 261                } else if (!(flags & TRANSPORT_PUSH_MIRROR))
 262                        setup_default_push_refspecs(remote);
 263        }
 264        errs = 0;
 265        url_nr = push_url_of_remote(remote, &url);
 266        if (url_nr) {
 267                for (i = 0; i < url_nr; i++) {
 268                        struct transport *transport =
 269                                transport_get(remote, url[i]);
 270                        if (push_with_options(transport, flags))
 271                                errs++;
 272                }
 273        } else {
 274                struct transport *transport =
 275                        transport_get(remote, NULL);
 276
 277                if (push_with_options(transport, flags))
 278                        errs++;
 279        }
 280        return !!errs;
 281}
 282
 283static int option_parse_recurse_submodules(const struct option *opt,
 284                                   const char *arg, int unset)
 285{
 286        int *flags = opt->value;
 287
 288        if (*flags & (TRANSPORT_RECURSE_SUBMODULES_CHECK |
 289                      TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND))
 290                die("%s can only be used once.", opt->long_name);
 291
 292        if (arg) {
 293                if (!strcmp(arg, "check"))
 294                        *flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
 295                else if (!strcmp(arg, "on-demand"))
 296                        *flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND;
 297                else
 298                        die("bad %s argument: %s", opt->long_name, arg);
 299        } else
 300                die("option %s needs an argument (check|on-demand)",
 301                                opt->long_name);
 302
 303        return 0;
 304}
 305
 306int cmd_push(int argc, const char **argv, const char *prefix)
 307{
 308        int flags = 0;
 309        int tags = 0;
 310        int rc;
 311        const char *repo = NULL;        /* default repository */
 312        struct option options[] = {
 313                OPT__VERBOSITY(&verbosity),
 314                OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
 315                OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
 316                OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
 317                            (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
 318                OPT_BOOLEAN( 0, "delete", &deleterefs, "delete refs"),
 319                OPT_BOOLEAN( 0 , "tags", &tags, "push tags (can't be used with --all or --mirror)"),
 320                OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
 321                OPT_BIT( 0,  "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
 322                OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
 323                { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check",
 324                        "controls recursive pushing of submodules",
 325                        PARSE_OPT_OPTARG, option_parse_recurse_submodules },
 326                OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
 327                OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
 328                OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
 329                OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status",
 330                        TRANSPORT_PUSH_SET_UPSTREAM),
 331                OPT_BOOL(0, "progress", &progress, "force progress reporting"),
 332                OPT_BIT(0, "prune", &flags, "prune locally removed refs",
 333                        TRANSPORT_PUSH_PRUNE),
 334                OPT_END()
 335        };
 336
 337        packet_trace_identity("push");
 338        git_config(git_default_config, NULL);
 339        argc = parse_options(argc, argv, prefix, options, push_usage, 0);
 340
 341        if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
 342                die(_("--delete is incompatible with --all, --mirror and --tags"));
 343        if (deleterefs && argc < 2)
 344                die(_("--delete doesn't make sense without any refs"));
 345
 346        if (tags)
 347                add_refspec("refs/tags/*");
 348
 349        if (argc > 0) {
 350                repo = argv[0];
 351                set_refspecs(argv + 1, argc - 1);
 352        }
 353
 354        rc = do_push(repo, flags);
 355        if (rc == -1)
 356                usage_with_options(push_usage, options);
 357        else
 358                return rc;
 359}