pull: pass git-fetch's options to git-fetch
[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
a32975f5
PT
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
1e1ea69f 50static struct option pull_options[] = {
2a747902
PT
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
11b6d178
PT
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
a32975f5
PT
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
1e1ea69f
PT
140 OPT_END()
141};
142
2a747902
PT
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
a32975f5
PT
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
f2c5baa1
PT
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);
2a747902
PT
193
194 /* Shared options */
195 argv_push_verbosity(&args);
196 if (opt_progress)
197 argv_array_push(&args, opt_progress);
198
a32975f5
PT
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
f2c5baa1
PT
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);
2a747902
PT
245
246 /* Shared options */
247 argv_push_verbosity(&args);
248 if (opt_progress)
249 argv_array_push(&args, opt_progress);
250
11b6d178
PT
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
f2c5baa1
PT
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
1e1ea69f
PT
277int cmd_pull(int argc, const char **argv, const char *prefix)
278{
f2c5baa1
PT
279 const char *repo, **refspecs;
280
1e1ea69f
PT
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
f2c5baa1
PT
290 parse_repo_refspecs(argc, argv, &repo, &refspecs);
291
292 if (run_fetch(repo, refspecs))
293 return 1;
294
a32975f5
PT
295 if (opt_dry_run)
296 return 0;
297
f2c5baa1 298 return run_merge();
1e1ea69f 299}