f35649cc3891c841fba4c48f89dfe2172a1a53f9
   1/*
   2 * Builtin "git pull"
   3 *
   4 * Based on git-pull.sh by Junio C Hamano
   5 *
   6 * Fetch one or more remote refs and merge it/them into the current HEAD.
   7 */
   8#include "cache.h"
   9#include "builtin.h"
  10#include "parse-options.h"
  11#include "exec_cmd.h"
  12#include "run-command.h"
  13
  14static const char * const pull_usage[] = {
  15        N_("git pull [options] [<repository> [<refspec>...]]"),
  16        NULL
  17};
  18
  19/* Shared options */
  20static int opt_verbosity;
  21static char *opt_progress;
  22
  23/* Options passed to git-merge */
  24static char *opt_diffstat;
  25static char *opt_log;
  26static char *opt_squash;
  27static char *opt_commit;
  28static char *opt_edit;
  29static char *opt_ff;
  30static char *opt_verify_signatures;
  31static struct argv_array opt_strategies = ARGV_ARRAY_INIT;
  32static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT;
  33static char *opt_gpg_sign;
  34
  35/* Options passed to git-fetch */
  36static char *opt_all;
  37static char *opt_append;
  38static char *opt_upload_pack;
  39static int opt_force;
  40static char *opt_tags;
  41static char *opt_prune;
  42static char *opt_recurse_submodules;
  43static int opt_dry_run;
  44static char *opt_keep;
  45static char *opt_depth;
  46static char *opt_unshallow;
  47static char *opt_update_shallow;
  48static char *opt_refmap;
  49
  50static struct option pull_options[] = {
  51        /* Shared options */
  52        OPT__VERBOSITY(&opt_verbosity),
  53        OPT_PASSTHRU(0, "progress", &opt_progress, NULL,
  54                N_("force progress reporting"),
  55                PARSE_OPT_NOARG),
  56
  57        /* Options passed to git-merge */
  58        OPT_GROUP(N_("Options related to merging")),
  59        OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL,
  60                N_("do not show a diffstat at the end of the merge"),
  61                PARSE_OPT_NOARG | PARSE_OPT_NONEG),
  62        OPT_PASSTHRU(0, "stat", &opt_diffstat, NULL,
  63                N_("show a diffstat at the end of the merge"),
  64                PARSE_OPT_NOARG),
  65        OPT_PASSTHRU(0, "summary", &opt_diffstat, NULL,
  66                N_("(synonym to --stat)"),
  67                PARSE_OPT_NOARG | PARSE_OPT_HIDDEN),
  68        OPT_PASSTHRU(0, "log", &opt_log, N_("n"),
  69                N_("add (at most <n>) entries from shortlog to merge commit message"),
  70                PARSE_OPT_OPTARG),
  71        OPT_PASSTHRU(0, "squash", &opt_squash, NULL,
  72                N_("create a single commit instead of doing a merge"),
  73                PARSE_OPT_NOARG),
  74        OPT_PASSTHRU(0, "commit", &opt_commit, NULL,
  75                N_("perform a commit if the merge succeeds (default)"),
  76                PARSE_OPT_NOARG),
  77        OPT_PASSTHRU(0, "edit", &opt_edit, NULL,
  78                N_("edit message before committing"),
  79                PARSE_OPT_NOARG),
  80        OPT_PASSTHRU(0, "ff", &opt_ff, NULL,
  81                N_("allow fast-forward"),
  82                PARSE_OPT_NOARG),
  83        OPT_PASSTHRU(0, "ff-only", &opt_ff, NULL,
  84                N_("abort if fast-forward is not possible"),
  85                PARSE_OPT_NOARG | PARSE_OPT_NONEG),
  86        OPT_PASSTHRU(0, "verify-signatures", &opt_verify_signatures, NULL,
  87                N_("verify that the named commit has a valid GPG signature"),
  88                PARSE_OPT_NOARG),
  89        OPT_PASSTHRU_ARGV('s', "strategy", &opt_strategies, N_("strategy"),
  90                N_("merge strategy to use"),
  91                0),
  92        OPT_PASSTHRU_ARGV('X', "strategy-option", &opt_strategy_opts,
  93                N_("option=value"),
  94                N_("option for selected merge strategy"),
  95                0),
  96        OPT_PASSTHRU('S', "gpg-sign", &opt_gpg_sign, N_("key-id"),
  97                N_("GPG sign commit"),
  98                PARSE_OPT_OPTARG),
  99
 100        /* Options passed to git-fetch */
 101        OPT_GROUP(N_("Options related to fetching")),
 102        OPT_PASSTHRU(0, "all", &opt_all, NULL,
 103                N_("fetch from all remotes"),
 104                PARSE_OPT_NOARG),
 105        OPT_PASSTHRU('a', "append", &opt_append, NULL,
 106                N_("append to .git/FETCH_HEAD instead of overwriting"),
 107                PARSE_OPT_NOARG),
 108        OPT_PASSTHRU(0, "upload-pack", &opt_upload_pack, N_("path"),
 109                N_("path to upload pack on remote end"),
 110                0),
 111        OPT__FORCE(&opt_force, N_("force overwrite of local branch")),
 112        OPT_PASSTHRU('t', "tags", &opt_tags, NULL,
 113                N_("fetch all tags and associated objects"),
 114                PARSE_OPT_NOARG),
 115        OPT_PASSTHRU('p', "prune", &opt_prune, NULL,
 116                N_("prune remote-tracking branches no longer on remote"),
 117                PARSE_OPT_NOARG),
 118        OPT_PASSTHRU(0, "recurse-submodules", &opt_recurse_submodules,
 119                N_("on-demand"),
 120                N_("control recursive fetching of submodules"),
 121                PARSE_OPT_OPTARG),
 122        OPT_BOOL(0, "dry-run", &opt_dry_run,
 123                N_("dry run")),
 124        OPT_PASSTHRU('k', "keep", &opt_keep, NULL,
 125                N_("keep downloaded pack"),
 126                PARSE_OPT_NOARG),
 127        OPT_PASSTHRU(0, "depth", &opt_depth, N_("depth"),
 128                N_("deepen history of shallow clone"),
 129                0),
 130        OPT_PASSTHRU(0, "unshallow", &opt_unshallow, NULL,
 131                N_("convert to a complete repository"),
 132                PARSE_OPT_NONEG | PARSE_OPT_NOARG),
 133        OPT_PASSTHRU(0, "update-shallow", &opt_update_shallow, NULL,
 134                N_("accept refs that update .git/shallow"),
 135                PARSE_OPT_NOARG),
 136        OPT_PASSTHRU(0, "refmap", &opt_refmap, N_("refmap"),
 137                N_("specify fetch refmap"),
 138                PARSE_OPT_NONEG),
 139
 140        OPT_END()
 141};
 142
 143/**
 144 * Pushes "-q" or "-v" switches into arr to match the opt_verbosity level.
 145 */
 146static void argv_push_verbosity(struct argv_array *arr)
 147{
 148        int verbosity;
 149
 150        for (verbosity = opt_verbosity; verbosity > 0; verbosity--)
 151                argv_array_push(arr, "-v");
 152
 153        for (verbosity = opt_verbosity; verbosity < 0; verbosity++)
 154                argv_array_push(arr, "-q");
 155}
 156
 157/**
 158 * Pushes "-f" switches into arr to match the opt_force level.
 159 */
 160static void argv_push_force(struct argv_array *arr)
 161{
 162        int force = opt_force;
 163        while (force-- > 0)
 164                argv_array_push(arr, "-f");
 165}
 166
 167/**
 168 * Parses argv into [<repo> [<refspecs>...]], returning their values in `repo`
 169 * as a string and `refspecs` as a null-terminated array of strings. If `repo`
 170 * is not provided in argv, it is set to NULL.
 171 */
 172static void parse_repo_refspecs(int argc, const char **argv, const char **repo,
 173                const char ***refspecs)
 174{
 175        if (argc > 0) {
 176                *repo = *argv++;
 177                argc--;
 178        } else
 179                *repo = NULL;
 180        *refspecs = argv;
 181}
 182
 183/**
 184 * Runs git-fetch, returning its exit status. `repo` and `refspecs` are the
 185 * repository and refspecs to fetch, or NULL if they are not provided.
 186 */
 187static int run_fetch(const char *repo, const char **refspecs)
 188{
 189        struct argv_array args = ARGV_ARRAY_INIT;
 190        int ret;
 191
 192        argv_array_pushl(&args, "fetch", "--update-head-ok", NULL);
 193
 194        /* Shared options */
 195        argv_push_verbosity(&args);
 196        if (opt_progress)
 197                argv_array_push(&args, opt_progress);
 198
 199        /* Options passed to git-fetch */
 200        if (opt_all)
 201                argv_array_push(&args, opt_all);
 202        if (opt_append)
 203                argv_array_push(&args, opt_append);
 204        if (opt_upload_pack)
 205                argv_array_push(&args, opt_upload_pack);
 206        argv_push_force(&args);
 207        if (opt_tags)
 208                argv_array_push(&args, opt_tags);
 209        if (opt_prune)
 210                argv_array_push(&args, opt_prune);
 211        if (opt_recurse_submodules)
 212                argv_array_push(&args, opt_recurse_submodules);
 213        if (opt_dry_run)
 214                argv_array_push(&args, "--dry-run");
 215        if (opt_keep)
 216                argv_array_push(&args, opt_keep);
 217        if (opt_depth)
 218                argv_array_push(&args, opt_depth);
 219        if (opt_unshallow)
 220                argv_array_push(&args, opt_unshallow);
 221        if (opt_update_shallow)
 222                argv_array_push(&args, opt_update_shallow);
 223        if (opt_refmap)
 224                argv_array_push(&args, opt_refmap);
 225
 226        if (repo) {
 227                argv_array_push(&args, repo);
 228                argv_array_pushv(&args, refspecs);
 229        } else if (*refspecs)
 230                die("BUG: refspecs without repo?");
 231        ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
 232        argv_array_clear(&args);
 233        return ret;
 234}
 235
 236/**
 237 * Runs git-merge, returning its exit status.
 238 */
 239static int run_merge(void)
 240{
 241        int ret;
 242        struct argv_array args = ARGV_ARRAY_INIT;
 243
 244        argv_array_pushl(&args, "merge", NULL);
 245
 246        /* Shared options */
 247        argv_push_verbosity(&args);
 248        if (opt_progress)
 249                argv_array_push(&args, opt_progress);
 250
 251        /* Options passed to git-merge */
 252        if (opt_diffstat)
 253                argv_array_push(&args, opt_diffstat);
 254        if (opt_log)
 255                argv_array_push(&args, opt_log);
 256        if (opt_squash)
 257                argv_array_push(&args, opt_squash);
 258        if (opt_commit)
 259                argv_array_push(&args, opt_commit);
 260        if (opt_edit)
 261                argv_array_push(&args, opt_edit);
 262        if (opt_ff)
 263                argv_array_push(&args, opt_ff);
 264        if (opt_verify_signatures)
 265                argv_array_push(&args, opt_verify_signatures);
 266        argv_array_pushv(&args, opt_strategies.argv);
 267        argv_array_pushv(&args, opt_strategy_opts.argv);
 268        if (opt_gpg_sign)
 269                argv_array_push(&args, opt_gpg_sign);
 270
 271        argv_array_push(&args, "FETCH_HEAD");
 272        ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
 273        argv_array_clear(&args);
 274        return ret;
 275}
 276
 277int cmd_pull(int argc, const char **argv, const char *prefix)
 278{
 279        const char *repo, **refspecs;
 280
 281        if (!getenv("_GIT_USE_BUILTIN_PULL")) {
 282                const char *path = mkpath("%s/git-pull", git_exec_path());
 283
 284                if (sane_execvp(path, (char **)argv) < 0)
 285                        die_errno("could not exec %s", path);
 286        }
 287
 288        argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
 289
 290        parse_repo_refspecs(argc, argv, &repo, &refspecs);
 291
 292        if (run_fetch(repo, refspecs))
 293                return 1;
 294
 295        if (opt_dry_run)
 296                return 0;
 297
 298        return run_merge();
 299}