checkout: split options[] array in three pieces

This is a preparation step for introducing new commands that do parts of what checkout does. There will be two new commands, one is about switching branches, detaching HEAD... one about checking out paths. These share the a subset of command line options. The rest of command line options are separate. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Mar 29, 2019 at 17:39 UTC 208718227207480b0f58e35e045e36ed36a59205
3 files changed +77 -23
builtin/checkout.c
+59 -23
@@ -1342,15 +1342,31 @@ static int checkout_branch(struct checkout_opts *opts,
1342 return switch_branches(opts, new_branch_info);
1343 }
1344
1345 -int cmd_checkout(int argc, const char **argv, const char *prefix)
1345 +static struct option *add_common_options(struct checkout_opts *opts,
1346 + struct option *prevopts)
1347 {
1347 - struct checkout_opts real_opts;
1348 - struct checkout_opts *opts = &real_opts;
1349 - struct branch_info new_branch_info;
1350 - int dwim_new_local_branch;
1351 - int dwim_remotes_matched = 0;
1348 struct option options[] = {
1349 OPT__QUIET(&opts->quiet, N_("suppress progress reporting")),
1350 + { OPTION_CALLBACK, 0, "recurse-submodules", NULL,
1351 + "checkout", "control recursive updating of submodules",
1352 + PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
1353 + OPT_BOOL(0, "progress", &opts->show_progress, N_("force progress reporting")),
1354 + OPT__FORCE(&opts->force, N_("force checkout (throw away local modifications)"),
1355 + PARSE_OPT_NOCOMPLETE),
1356 + OPT_BOOL('m', "merge", &opts->merge, N_("perform a 3-way merge with the new branch")),
1357 + OPT_STRING(0, "conflict", &opts->conflict_style, N_("style"),
1358 + N_("conflict style (merge or diff3)")),
1359 + OPT_END()
1360 + };
1361 + struct option *newopts = parse_options_concat(prevopts, options);
1362 + free(prevopts);
1363 + return newopts;
1364 +}
1365 +
1366 +static struct option *add_switch_branch_options(struct checkout_opts *opts,
1367 + struct option *prevopts)
1368 +{
1369 + struct option options[] = {
1370 OPT_STRING('b', NULL, &opts->new_branch, N_("branch"),
1371 N_("create and checkout a new branch")),
1372 OPT_STRING('B', NULL, &opts->new_branch_force, N_("branch"),
@@ -1360,34 +1376,49 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
1376 OPT_SET_INT('t', "track", &opts->track, N_("set upstream info for new branch"),
1377 BRANCH_TRACK_EXPLICIT),
1378 OPT_STRING(0, "orphan", &opts->new_orphan_branch, N_("new-branch"), N_("new unparented branch")),
1379 + OPT_BOOL_F(0, "overwrite-ignore", &opts->overwrite_ignore,
1380 + N_("update ignored files (default)"),
1381 + PARSE_OPT_NOCOMPLETE),
1382 + OPT_BOOL(0, "no-guess", &opts->no_dwim_new_local_branch,
1383 + N_("second guess 'git checkout <no-such-branch>'")),
1384 + OPT_BOOL(0, "ignore-other-worktrees", &opts->ignore_other_worktrees,
1385 + N_("do not check if another worktree is holding the given ref")),
1386 + OPT_END()
1387 + };
1388 + struct option *newopts = parse_options_concat(prevopts, options);
1389 + free(prevopts);
1390 + return newopts;
1391 +}
1392 +
1393 +static struct option *add_checkout_path_options(struct checkout_opts *opts,
1394 + struct option *prevopts)
1395 +{
1396 + struct option options[] = {
1397 OPT_SET_INT_F('2', "ours", &opts->writeout_stage,
1398 N_("checkout our version for unmerged files"),
1399 2, PARSE_OPT_NONEG),
1400 OPT_SET_INT_F('3', "theirs", &opts->writeout_stage,
1401 N_("checkout their version for unmerged files"),
1402 3, PARSE_OPT_NONEG),
1369 - OPT__FORCE(&opts->force, N_("force checkout (throw away local modifications)"),
1370 - PARSE_OPT_NOCOMPLETE),
1371 - OPT_BOOL('m', "merge", &opts->merge, N_("perform a 3-way merge with the new branch")),
1372 - OPT_BOOL_F(0, "overwrite-ignore", &opts->overwrite_ignore,
1373 - N_("update ignored files (default)"),
1374 - PARSE_OPT_NOCOMPLETE),
1375 - OPT_STRING(0, "conflict", &opts->conflict_style, N_("style"),
1376 - N_("conflict style (merge or diff3)")),
1403 OPT_BOOL('p', "patch", &opts->patch_mode, N_("select hunks interactively")),
1404 OPT_BOOL(0, "ignore-skip-worktree-bits", &opts->ignore_skipworktree,
1405 N_("do not limit pathspecs to sparse entries only")),
1380 - OPT_BOOL(0, "no-guess", &opts->no_dwim_new_local_branch,
1381 - N_("do not second guess 'git checkout <no-such-branch>'")),
1382 - OPT_BOOL(0, "ignore-other-worktrees", &opts->ignore_other_worktrees,
1383 - N_("do not check if another worktree is holding the given ref")),
1384 - { OPTION_CALLBACK, 0, "recurse-submodules", NULL,
1385 - "checkout", "control recursive updating of submodules",
1386 - PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
1387 - OPT_BOOL(0, "progress", &opts->show_progress, N_("force progress reporting")),
1406 OPT_BOOL(0, "overlay", &opts->overlay_mode, N_("use overlay mode (default)")),
1389 - OPT_END(),
1407 + OPT_END()
1408 };
1409 + struct option *newopts = parse_options_concat(prevopts, options);
1410 + free(prevopts);
1411 + return newopts;
1412 +}
1413 +
1414 +int cmd_checkout(int argc, const char **argv, const char *prefix)
1415 +{
1416 + struct checkout_opts real_opts;
1417 + struct checkout_opts *opts = &real_opts;
1418 + struct branch_info new_branch_info;
1419 + int dwim_remotes_matched = 0;
1420 + int dwim_new_local_branch;
1421 + struct option *options = NULL;
1422
1423 memset(opts, 0, sizeof(*opts));
1424 memset(&new_branch_info, 0, sizeof(new_branch_info));
@@ -1401,6 +1432,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
1432
1433 opts->track = BRANCH_TRACK_UNSPECIFIED;
1434
1435 + options = parse_options_dup(options);
1436 + options = add_common_options(opts, options);
1437 + options = add_switch_branch_options(opts, options);
1438 + options = add_checkout_path_options(opts, options);
1439 +
1440 argc = parse_options(argc, argv, prefix, options, checkout_usage,
1441 PARSE_OPT_KEEP_DASHDASH);
1442
parse-options-cb.c
+17
@@ -122,6 +122,23 @@ int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
122 return 0;
123 }
124
125 +struct option *parse_options_dup(const struct option *o)
126 +{
127 + struct option *opts;
128 + int nr = 0;
129 +
130 + while (o && o->type != OPTION_END) {
131 + nr++;
132 + o++;
133 + }
134 +
135 + ALLOC_ARRAY(opts, nr + 1);
136 + memcpy(opts, o - nr, sizeof(*o) * nr);
137 + memset(opts + nr, 0, sizeof(*opts));
138 + opts[nr].type = OPTION_END;
139 + return opts;
140 +}
141 +
142 struct option *parse_options_concat(struct option *a, struct option *b)
143 {
144 struct option *ret;
parse-options.h
+1
@@ -257,6 +257,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
257
258 int parse_options_end(struct parse_opt_ctx_t *ctx);
259
260 +struct option *parse_options_dup(const struct option *a);
261 struct option *parse_options_concat(struct option *a, struct option *b);
262
263 /*----- some often used options -----*/