Message ID | 4b231e9beb43e4fac6457b9bf86e4c1db39c4238.1679903703.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 24fc2cde6448233dbbe1f6695577a49679ccc98b |
Headers | show |
Series | builtin/sparse-checkout: add check-rules command | expand |
"William Sprent via GitGitGadget" <gitgitgadget@gmail.com> writes: > diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c > index c3738154918..5fdc3d9aab5 100644 > --- a/builtin/sparse-checkout.c > +++ b/builtin/sparse-checkout.c > @@ -57,6 +57,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix) > char *sparse_filename; > int res; > > + setup_work_tree(); > if (!core_apply_sparse_checkout) > die(_("this worktree is not sparse")); > ... > @@ -898,6 +903,7 @@ static int sparse_checkout_disable(int argc, const char **argv, > * forcibly return to a dense checkout regardless of initial state. > */ > > + setup_work_tree(); > argc = parse_options(argc, argv, prefix, > builtin_sparse_checkout_disable_options, > builtin_sparse_checkout_disable_usage, 0); I am throwing this out not as "we must tackle this ugliness before this patch can proceed" but as "this is ugly, I wish somebody can figure it out in a cleaner way", so do not take this as a blocking comment or objection, but more as something to think about improving if possible as a bonus point. It really is a shame that we have a nice "dispatch" table at the beginning of the single caller: int cmd_sparse_checkout(int argc, const char **argv, const char *prefix) { parse_opt_subcommand_fn *fn = NULL; struct option builtin_sparse_checkout_options[] = { OPT_SUBCOMMAND("list", &fn, sparse_checkout_list), OPT_SUBCOMMAND("init", &fn, sparse_checkout_init), OPT_SUBCOMMAND("set", &fn, sparse_checkout_set), OPT_SUBCOMMAND("add", &fn, sparse_checkout_add), OPT_SUBCOMMAND("reapply", &fn, sparse_checkout_reapply), OPT_SUBCOMMAND("disable", &fn, sparse_checkout_disable), OPT_END(), }; yet we have to sprinkle setup_work_tree() to all of these functions' implementation. If we were able to describe which selected ones do not need the setup call, we could let the parse-options API to look up the function and then before calling "fn" we could make the setup call. That would allow us to maintain the subcommands much nicely. Thanks.
On Mon, Mar 27, 2023 at 10:51:04AM -0700, Junio C Hamano wrote: > "William Sprent via GitGitGadget" <gitgitgadget@gmail.com> writes: > > > diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c > > index c3738154918..5fdc3d9aab5 100644 > > --- a/builtin/sparse-checkout.c > > +++ b/builtin/sparse-checkout.c > > @@ -57,6 +57,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix) > > char *sparse_filename; > > int res; > > > > + setup_work_tree(); > > if (!core_apply_sparse_checkout) > > die(_("this worktree is not sparse")); > > ... > > @@ -898,6 +903,7 @@ static int sparse_checkout_disable(int argc, const char **argv, > > * forcibly return to a dense checkout regardless of initial state. > > */ > > > > + setup_work_tree(); > > argc = parse_options(argc, argv, prefix, > > builtin_sparse_checkout_disable_options, > > builtin_sparse_checkout_disable_usage, 0); > > I am throwing this out not as "we must tackle this ugliness before > this patch can proceed" but as "this is ugly, I wish somebody can > figure it out in a cleaner way", so do not take this as a blocking > comment or objection, but more as something to think about improving > if possible as a bonus point. > > It really is a shame that we have a nice "dispatch" table at the > beginning of the single caller: > > int cmd_sparse_checkout(int argc, const char **argv, const char *prefix) > { > parse_opt_subcommand_fn *fn = NULL; > struct option builtin_sparse_checkout_options[] = { > OPT_SUBCOMMAND("list", &fn, sparse_checkout_list), > OPT_SUBCOMMAND("init", &fn, sparse_checkout_init), > OPT_SUBCOMMAND("set", &fn, sparse_checkout_set), > OPT_SUBCOMMAND("add", &fn, sparse_checkout_add), > OPT_SUBCOMMAND("reapply", &fn, sparse_checkout_reapply), > OPT_SUBCOMMAND("disable", &fn, sparse_checkout_disable), > OPT_END(), > }; > > yet we have to sprinkle setup_work_tree() to all of these functions' > implementation. If we were able to describe which selected ones do > not need the setup call, we could let the parse-options API to look > up the function and then before calling "fn" we could make the setup > call. That would allow us to maintain the subcommands much nicely. It's easy enough to do in this particular case: there is an OPT_SUBCOMMAND_F() variant which takes an additional flags parameter, so we could add a PARSE_OPT_SETUP_WORK_TREE flag, check it in e.g. parse_subcommand(), and act accordingly if it's set. However, this wouldn't work when the command has a default operation mode and is invoked without any subcommands. And I'm not sure about doing this in parse-options, because it's about, well, parsing options, not about doing fancy setup stuff.
SZEDER Gábor <szeder.dev@gmail.com> writes: >> struct option builtin_sparse_checkout_options[] = { >> OPT_SUBCOMMAND("list", &fn, sparse_checkout_list), >> OPT_SUBCOMMAND("init", &fn, sparse_checkout_init), >> OPT_SUBCOMMAND("set", &fn, sparse_checkout_set), >> OPT_SUBCOMMAND("add", &fn, sparse_checkout_add), >> OPT_SUBCOMMAND("reapply", &fn, sparse_checkout_reapply), >> OPT_SUBCOMMAND("disable", &fn, sparse_checkout_disable), >> OPT_END(), >> }; >> >> yet we have to sprinkle setup_work_tree() to all of these functions' >> implementation. If we were able to describe which selected ones do >> not need the setup call, we could let the parse-options API to look >> up the function and then before calling "fn" we could make the setup >> call. That would allow us to maintain the subcommands much nicely. > > It's easy enough to do in this particular case: there is an > OPT_SUBCOMMAND_F() variant which takes an additional flags parameter, > so we could add a PARSE_OPT_SETUP_WORK_TREE flag, check it in e.g. > parse_subcommand(), and act accordingly if it's set. > > However, this wouldn't work when the command has a default operation > mode and is invoked without any subcommands. And I'm not sure about > doing this in parse-options, because it's about, well, parsing > options, not about doing fancy setup stuff. Yes, exactly. What I was imagining was more along the lines of parse_opt_subcommand_fn *fn = NULL; parse_opt_subcommand_fn *fn_with_setup = NULL; options[] = { OPT_SUBCOMMAND("list", &fn_with_setup, sparse_checkout_list), ... OPT_SUBCOMMAND("check-rules", &fn, sparse_check_rules), }; parse_options(...); if (fn_with_setup) { setup_worktree(); fn = fn_with_setup; } fn(...); But of course as a "safety" measure, one options[] array can all point at the same "fn" variable or parse_options() becomes unhappy, so the above does not work out of the box.
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index c3738154918..5fdc3d9aab5 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -57,6 +57,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix) char *sparse_filename; int res; + setup_work_tree(); if (!core_apply_sparse_checkout) die(_("this worktree is not sparse")); @@ -448,6 +449,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix) OPT_END(), }; + setup_work_tree(); repo_read_index(the_repository); init_opts.cone_mode = -1; @@ -760,6 +762,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix) OPT_END(), }; + setup_work_tree(); if (!core_apply_sparse_checkout) die(_("no sparse-checkout to add to")); @@ -806,6 +809,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix) OPT_END(), }; + setup_work_tree(); repo_read_index(the_repository); set_opts.cone_mode = -1; @@ -855,6 +859,7 @@ static int sparse_checkout_reapply(int argc, const char **argv, OPT_END(), }; + setup_work_tree(); if (!core_apply_sparse_checkout) die(_("must be in a sparse-checkout to reapply sparsity patterns")); @@ -898,6 +903,7 @@ static int sparse_checkout_disable(int argc, const char **argv, * forcibly return to a dense checkout regardless of initial state. */ + setup_work_tree(); argc = parse_options(argc, argv, prefix, builtin_sparse_checkout_disable_options, builtin_sparse_checkout_disable_usage, 0); diff --git a/git.c b/git.c index 6171fd6769d..5adc835cf10 100644 --- a/git.c +++ b/git.c @@ -583,7 +583,7 @@ static struct cmd_struct commands[] = { { "show-branch", cmd_show_branch, RUN_SETUP }, { "show-index", cmd_show_index, RUN_SETUP_GENTLY }, { "show-ref", cmd_show_ref, RUN_SETUP }, - { "sparse-checkout", cmd_sparse_checkout, RUN_SETUP | NEED_WORK_TREE }, + { "sparse-checkout", cmd_sparse_checkout, RUN_SETUP }, { "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE }, { "stash", cmd_stash, RUN_SETUP | NEED_WORK_TREE }, { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE }, diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh index 627267be153..7216267aec7 100755 --- a/t/t1091-sparse-checkout-builtin.sh +++ b/t/t1091-sparse-checkout-builtin.sh @@ -882,4 +882,37 @@ test_expect_success 'by default, non-cone mode will warn on individual files' ' grep "pass a leading slash before paths.*if you want a single file" warning ' +test_expect_success 'setup bare repo' ' + git clone --bare "file://$(pwd)/repo" bare +' +test_expect_success 'list fails outside work tree' ' + test_must_fail git -C bare sparse-checkout list 2>err && + test_i18ngrep "this operation must be run in a work tree" err +' + +test_expect_success 'add fails outside work tree' ' + test_must_fail git -C bare sparse-checkout add deeper 2>err && + test_i18ngrep "this operation must be run in a work tree" err +' + +test_expect_success 'set fails outside work tree' ' + test_must_fail git -C bare sparse-checkout set deeper 2>err && + test_i18ngrep "this operation must be run in a work tree" err +' + +test_expect_success 'init fails outside work tree' ' + test_must_fail git -C bare sparse-checkout init 2>err && + test_i18ngrep "this operation must be run in a work tree" err +' + +test_expect_success 'reapply fails outside work tree' ' + test_must_fail git -C bare sparse-checkout reapply 2>err && + test_i18ngrep "this operation must be run in a work tree" err +' + +test_expect_success 'disable fails outside work tree' ' + test_must_fail git -C bare sparse-checkout disable 2>err && + test_i18ngrep "this operation must be run in a work tree" err +' + test_done