builtin-push.con commit git-p4: After submission to p4 always synchronize from p4 again (into refs/remotes). Whether to rebase HEAD or not is still left as question to the end-user. (14594f4)
   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
  10static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
  11
  12static int all, force, thin = 1, verbose;
  13static const char *receivepack;
  14
  15static const char **refspec;
  16static int refspec_nr;
  17
  18static void add_refspec(const char *ref)
  19{
  20        int nr = refspec_nr + 1;
  21        refspec = xrealloc(refspec, nr * sizeof(char *));
  22        refspec[nr-1] = ref;
  23        refspec_nr = nr;
  24}
  25
  26static void set_refspecs(const char **refs, int nr)
  27{
  28        int i;
  29        for (i = 0; i < nr; i++) {
  30                const char *ref = refs[i];
  31                if (!strcmp("tag", ref)) {
  32                        char *tag;
  33                        int len;
  34                        if (nr <= ++i)
  35                                die("tag shorthand without <tag>");
  36                        len = strlen(refs[i]) + 11;
  37                        tag = xmalloc(len);
  38                        strcpy(tag, "refs/tags/");
  39                        strcat(tag, refs[i]);
  40                        ref = tag;
  41                }
  42                add_refspec(ref);
  43        }
  44}
  45
  46static int do_push(const char *repo)
  47{
  48        int i, errs;
  49        int common_argc;
  50        const char **argv;
  51        int argc;
  52        struct remote *remote = remote_get(repo);
  53
  54        if (!remote)
  55                die("bad repository '%s'", repo);
  56
  57        if (remote->receivepack) {
  58                char *rp = xmalloc(strlen(remote->receivepack) + 16);
  59                sprintf(rp, "--receive-pack=%s", remote->receivepack);
  60                receivepack = rp;
  61        }
  62        if (!refspec && !all && remote->push_refspec_nr) {
  63                refspec = remote->push_refspec;
  64                refspec_nr = remote->push_refspec_nr;
  65        }
  66
  67        argv = xmalloc((refspec_nr + 10) * sizeof(char *));
  68        argv[0] = "dummy-send-pack";
  69        argc = 1;
  70        if (all)
  71                argv[argc++] = "--all";
  72        if (force)
  73                argv[argc++] = "--force";
  74        if (receivepack)
  75                argv[argc++] = receivepack;
  76        common_argc = argc;
  77
  78        errs = 0;
  79        for (i = 0; i < remote->uri_nr; i++) {
  80                int err;
  81                int dest_argc = common_argc;
  82                int dest_refspec_nr = refspec_nr;
  83                const char **dest_refspec = refspec;
  84                const char *dest = remote->uri[i];
  85                const char *sender = "send-pack";
  86                if (!prefixcmp(dest, "http://") ||
  87                    !prefixcmp(dest, "https://"))
  88                        sender = "http-push";
  89                else {
  90                        char *rem = xmalloc(strlen(remote->name) + 10);
  91                        sprintf(rem, "--remote=%s", remote->name);
  92                        argv[dest_argc++] = rem;
  93                        if (thin)
  94                                argv[dest_argc++] = "--thin";
  95                }
  96                argv[0] = sender;
  97                argv[dest_argc++] = dest;
  98                while (dest_refspec_nr--)
  99                        argv[dest_argc++] = *dest_refspec++;
 100                argv[dest_argc] = NULL;
 101                if (verbose)
 102                        fprintf(stderr, "Pushing to %s\n", dest);
 103                err = run_command_v_opt(argv, RUN_GIT_CMD);
 104                if (!err)
 105                        continue;
 106
 107                error("failed to push to '%s'", remote->uri[i]);
 108                switch (err) {
 109                case -ERR_RUN_COMMAND_FORK:
 110                        error("unable to fork for %s", sender);
 111                case -ERR_RUN_COMMAND_EXEC:
 112                        error("unable to exec %s", sender);
 113                        break;
 114                case -ERR_RUN_COMMAND_WAITPID:
 115                case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
 116                case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
 117                case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
 118                        error("%s died with strange error", sender);
 119                }
 120                errs++;
 121        }
 122        return !!errs;
 123}
 124
 125int cmd_push(int argc, const char **argv, const char *prefix)
 126{
 127        int i;
 128        const char *repo = NULL;        /* default repository */
 129
 130        for (i = 1; i < argc; i++) {
 131                const char *arg = argv[i];
 132
 133                if (arg[0] != '-') {
 134                        repo = arg;
 135                        i++;
 136                        break;
 137                }
 138                if (!strcmp(arg, "-v")) {
 139                        verbose=1;
 140                        continue;
 141                }
 142                if (!prefixcmp(arg, "--repo=")) {
 143                        repo = arg+7;
 144                        continue;
 145                }
 146                if (!strcmp(arg, "--all")) {
 147                        all = 1;
 148                        continue;
 149                }
 150                if (!strcmp(arg, "--tags")) {
 151                        add_refspec("refs/tags/*");
 152                        continue;
 153                }
 154                if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
 155                        force = 1;
 156                        continue;
 157                }
 158                if (!strcmp(arg, "--thin")) {
 159                        thin = 1;
 160                        continue;
 161                }
 162                if (!strcmp(arg, "--no-thin")) {
 163                        thin = 0;
 164                        continue;
 165                }
 166                if (!prefixcmp(arg, "--receive-pack=")) {
 167                        receivepack = arg;
 168                        continue;
 169                }
 170                if (!prefixcmp(arg, "--exec=")) {
 171                        receivepack = arg;
 172                        continue;
 173                }
 174                usage(push_usage);
 175        }
 176        set_refspecs(argv + i, argc - i);
 177        if (all && refspec)
 178                usage(push_usage);
 179
 180        return do_push(repo);
 181}