pull: pass git-merge's options to git-merge
[git/git.git] / builtin / pull.c
CommitLineData
1e1ea69f
PT
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"
f2c5baa1 12#include "run-command.h"
1e1ea69f
PT
13
14static const char * const pull_usage[] = {
f2c5baa1 15 N_("git pull [options] [<repository> [<refspec>...]]"),
1e1ea69f
PT
16 NULL
17};
18
2a747902
PT
19/* Shared options */
20static int opt_verbosity;
21static char *opt_progress;
22
11b6d178
PT
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
1e1ea69f 35static struct option pull_options[] = {
2a747902
PT
36 /* Shared options */
37 OPT__VERBOSITY(&opt_verbosity),
38 OPT_PASSTHRU(0, "progress", &opt_progress, NULL,
39 N_("force progress reporting"),
40 PARSE_OPT_NOARG),
41
11b6d178
PT
42 /* Options passed to git-merge */
43 OPT_GROUP(N_("Options related to merging")),
44 OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL,
45 N_("do not show a diffstat at the end of the merge"),
46 PARSE_OPT_NOARG | PARSE_OPT_NONEG),
47 OPT_PASSTHRU(0, "stat", &opt_diffstat, NULL,
48 N_("show a diffstat at the end of the merge"),
49 PARSE_OPT_NOARG),
50 OPT_PASSTHRU(0, "summary", &opt_diffstat, NULL,
51 N_("(synonym to --stat)"),
52 PARSE_OPT_NOARG | PARSE_OPT_HIDDEN),
53 OPT_PASSTHRU(0, "log", &opt_log, N_("n"),
54 N_("add (at most <n>) entries from shortlog to merge commit message"),
55 PARSE_OPT_OPTARG),
56 OPT_PASSTHRU(0, "squash", &opt_squash, NULL,
57 N_("create a single commit instead of doing a merge"),
58 PARSE_OPT_NOARG),
59 OPT_PASSTHRU(0, "commit", &opt_commit, NULL,
60 N_("perform a commit if the merge succeeds (default)"),
61 PARSE_OPT_NOARG),
62 OPT_PASSTHRU(0, "edit", &opt_edit, NULL,
63 N_("edit message before committing"),
64 PARSE_OPT_NOARG),
65 OPT_PASSTHRU(0, "ff", &opt_ff, NULL,
66 N_("allow fast-forward"),
67 PARSE_OPT_NOARG),
68 OPT_PASSTHRU(0, "ff-only", &opt_ff, NULL,
69 N_("abort if fast-forward is not possible"),
70 PARSE_OPT_NOARG | PARSE_OPT_NONEG),
71 OPT_PASSTHRU(0, "verify-signatures", &opt_verify_signatures, NULL,
72 N_("verify that the named commit has a valid GPG signature"),
73 PARSE_OPT_NOARG),
74 OPT_PASSTHRU_ARGV('s', "strategy", &opt_strategies, N_("strategy"),
75 N_("merge strategy to use"),
76 0),
77 OPT_PASSTHRU_ARGV('X', "strategy-option", &opt_strategy_opts,
78 N_("option=value"),
79 N_("option for selected merge strategy"),
80 0),
81 OPT_PASSTHRU('S', "gpg-sign", &opt_gpg_sign, N_("key-id"),
82 N_("GPG sign commit"),
83 PARSE_OPT_OPTARG),
84
1e1ea69f
PT
85 OPT_END()
86};
87
2a747902
PT
88/**
89 * Pushes "-q" or "-v" switches into arr to match the opt_verbosity level.
90 */
91static void argv_push_verbosity(struct argv_array *arr)
92{
93 int verbosity;
94
95 for (verbosity = opt_verbosity; verbosity > 0; verbosity--)
96 argv_array_push(arr, "-v");
97
98 for (verbosity = opt_verbosity; verbosity < 0; verbosity++)
99 argv_array_push(arr, "-q");
100}
101
f2c5baa1
PT
102/**
103 * Parses argv into [<repo> [<refspecs>...]], returning their values in `repo`
104 * as a string and `refspecs` as a null-terminated array of strings. If `repo`
105 * is not provided in argv, it is set to NULL.
106 */
107static void parse_repo_refspecs(int argc, const char **argv, const char **repo,
108 const char ***refspecs)
109{
110 if (argc > 0) {
111 *repo = *argv++;
112 argc--;
113 } else
114 *repo = NULL;
115 *refspecs = argv;
116}
117
118/**
119 * Runs git-fetch, returning its exit status. `repo` and `refspecs` are the
120 * repository and refspecs to fetch, or NULL if they are not provided.
121 */
122static int run_fetch(const char *repo, const char **refspecs)
123{
124 struct argv_array args = ARGV_ARRAY_INIT;
125 int ret;
126
127 argv_array_pushl(&args, "fetch", "--update-head-ok", NULL);
2a747902
PT
128
129 /* Shared options */
130 argv_push_verbosity(&args);
131 if (opt_progress)
132 argv_array_push(&args, opt_progress);
133
f2c5baa1
PT
134 if (repo) {
135 argv_array_push(&args, repo);
136 argv_array_pushv(&args, refspecs);
137 } else if (*refspecs)
138 die("BUG: refspecs without repo?");
139 ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
140 argv_array_clear(&args);
141 return ret;
142}
143
144/**
145 * Runs git-merge, returning its exit status.
146 */
147static int run_merge(void)
148{
149 int ret;
150 struct argv_array args = ARGV_ARRAY_INIT;
151
152 argv_array_pushl(&args, "merge", NULL);
2a747902
PT
153
154 /* Shared options */
155 argv_push_verbosity(&args);
156 if (opt_progress)
157 argv_array_push(&args, opt_progress);
158
11b6d178
PT
159 /* Options passed to git-merge */
160 if (opt_diffstat)
161 argv_array_push(&args, opt_diffstat);
162 if (opt_log)
163 argv_array_push(&args, opt_log);
164 if (opt_squash)
165 argv_array_push(&args, opt_squash);
166 if (opt_commit)
167 argv_array_push(&args, opt_commit);
168 if (opt_edit)
169 argv_array_push(&args, opt_edit);
170 if (opt_ff)
171 argv_array_push(&args, opt_ff);
172 if (opt_verify_signatures)
173 argv_array_push(&args, opt_verify_signatures);
174 argv_array_pushv(&args, opt_strategies.argv);
175 argv_array_pushv(&args, opt_strategy_opts.argv);
176 if (opt_gpg_sign)
177 argv_array_push(&args, opt_gpg_sign);
178
f2c5baa1
PT
179 argv_array_push(&args, "FETCH_HEAD");
180 ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
181 argv_array_clear(&args);
182 return ret;
183}
184
1e1ea69f
PT
185int cmd_pull(int argc, const char **argv, const char *prefix)
186{
f2c5baa1
PT
187 const char *repo, **refspecs;
188
1e1ea69f
PT
189 if (!getenv("_GIT_USE_BUILTIN_PULL")) {
190 const char *path = mkpath("%s/git-pull", git_exec_path());
191
192 if (sane_execvp(path, (char **)argv) < 0)
193 die_errno("could not exec %s", path);
194 }
195
196 argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
197
f2c5baa1
PT
198 parse_repo_refspecs(argc, argv, &repo, &refspecs);
199
200 if (run_fetch(repo, refspecs))
201 return 1;
202
203 return run_merge();
1e1ea69f 204}