builtin-push.con commit Merge branch 'maint' (d633f70)
   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
  11static const char push_usage[] = "git-push [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
  12
  13static int thin, verbose;
  14static const char *receivepack;
  15
  16static const char **refspec;
  17static int refspec_nr;
  18
  19static void add_refspec(const char *ref)
  20{
  21        int nr = refspec_nr + 1;
  22        refspec = xrealloc(refspec, nr * sizeof(char *));
  23        refspec[nr-1] = ref;
  24        refspec_nr = nr;
  25}
  26
  27static void set_refspecs(const char **refs, int nr)
  28{
  29        int i;
  30        for (i = 0; i < nr; i++) {
  31                const char *ref = refs[i];
  32                if (!strcmp("tag", ref)) {
  33                        char *tag;
  34                        int len;
  35                        if (nr <= ++i)
  36                                die("tag shorthand without <tag>");
  37                        len = strlen(refs[i]) + 11;
  38                        tag = xmalloc(len);
  39                        strcpy(tag, "refs/tags/");
  40                        strcat(tag, refs[i]);
  41                        ref = tag;
  42                }
  43                add_refspec(ref);
  44        }
  45}
  46
  47static int do_push(const char *repo, int flags)
  48{
  49        int i, errs;
  50        struct remote *remote = remote_get(repo);
  51
  52        if (!remote)
  53                die("bad repository '%s'", repo);
  54
  55        if (!refspec
  56                && !(flags & TRANSPORT_PUSH_ALL)
  57                && remote->push_refspec_nr) {
  58                refspec = remote->push_refspec;
  59                refspec_nr = remote->push_refspec_nr;
  60        }
  61        errs = 0;
  62        for (i = 0; i < remote->url_nr; i++) {
  63                struct transport *transport =
  64                        transport_get(remote, remote->url[i]);
  65                int err;
  66                if (receivepack)
  67                        transport_set_option(transport,
  68                                             TRANS_OPT_RECEIVEPACK, receivepack);
  69                if (thin)
  70                        transport_set_option(transport, TRANS_OPT_THIN, "yes");
  71
  72                if (verbose)
  73                        fprintf(stderr, "Pushing to %s\n", remote->url[i]);
  74                err = transport_push(transport, refspec_nr, refspec, flags);
  75                err |= transport_disconnect(transport);
  76
  77                if (!err)
  78                        continue;
  79
  80                error("failed to push to '%s'", remote->url[i]);
  81                errs++;
  82        }
  83        return !!errs;
  84}
  85
  86int cmd_push(int argc, const char **argv, const char *prefix)
  87{
  88        int i;
  89        int flags = 0;
  90        const char *repo = NULL;        /* default repository */
  91
  92        for (i = 1; i < argc; i++) {
  93                const char *arg = argv[i];
  94
  95                if (arg[0] != '-') {
  96                        repo = arg;
  97                        i++;
  98                        break;
  99                }
 100                if (!strcmp(arg, "-v")) {
 101                        verbose=1;
 102                        continue;
 103                }
 104                if (!prefixcmp(arg, "--repo=")) {
 105                        repo = arg+7;
 106                        continue;
 107                }
 108                if (!strcmp(arg, "--all")) {
 109                        flags |= TRANSPORT_PUSH_ALL;
 110                        continue;
 111                }
 112                if (!strcmp(arg, "--dry-run")) {
 113                        flags |= TRANSPORT_PUSH_DRY_RUN;
 114                        continue;
 115                }
 116                if (!strcmp(arg, "--tags")) {
 117                        add_refspec("refs/tags/*");
 118                        continue;
 119                }
 120                if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
 121                        flags |= TRANSPORT_PUSH_FORCE;
 122                        continue;
 123                }
 124                if (!strcmp(arg, "--thin")) {
 125                        thin = 1;
 126                        continue;
 127                }
 128                if (!strcmp(arg, "--no-thin")) {
 129                        thin = 0;
 130                        continue;
 131                }
 132                if (!prefixcmp(arg, "--receive-pack=")) {
 133                        receivepack = arg + 15;
 134                        continue;
 135                }
 136                if (!prefixcmp(arg, "--exec=")) {
 137                        receivepack = arg + 7;
 138                        continue;
 139                }
 140                usage(push_usage);
 141        }
 142        set_refspecs(argv + i, argc - i);
 143        if ((flags & TRANSPORT_PUSH_ALL) && refspec)
 144                usage(push_usage);
 145
 146        return do_push(repo, flags);
 147}