All of lore.kernel.org
 help / color / mirror / Atom feed
From: Elijah Newren <newren@gmail.com>
To: Thomas Gummerer <t.gummerer@gmail.com>
Cc: "Git Mailing List" <git@vger.kernel.org>,
	"Junio C Hamano" <gitster@pobox.com>,
	"Nguyễn Thái Ngọc" <pclouds@gmail.com>
Subject: Re: [PATCH 5/8] checkout: introduce --{,no-}overlay option
Date: Mon, 10 Dec 2018 10:19:40 -0800	[thread overview]
Message-ID: <CABPp-BEk+7n2wcbjETishqnMBs5DGrTEvD7gahLtEj5bZ2AYvA@mail.gmail.com> (raw)
In-Reply-To: <20181209200449.16342-6-t.gummerer@gmail.com>

On Sun, Dec 9, 2018 at 12:05 PM Thomas Gummerer <t.gummerer@gmail.com> wrote:
>
> Currently 'git checkout' is defined as an overlay operation, which
> means that if in 'git checkout <tree-ish> -- [<pathspec>]' we have an
> entry in the index that matches <pathspec>, but that doesn't exist in
> <tree-ish>, that entry will not be removed from the index or the
> working tree.
>
> Introduce a new --{,no-}overlay option, which allows using 'git
> checkout' in non-overlay mode, thus removing files from the working
> tree if they do not exist in <tree-ish> but match <pathspec>.
>
> Note that 'git checkout -p <tree-ish> -- [<pathspec>]' already works
> this way, so no changes are needed for the patch mode.  We disallow
> 'git checkout --overlay -p' to avoid confusing users who would expect
> to be able to force overlay mode in 'git checkout -p' this way.

Whoa...that's interesting.  To me, that argues even further that the
traditional checkout behavior was wrong all along and the choice of
--overlay vs. --no-overlay in the original implementation was a total
oversight.  I'm really tempted to say that --no-overlay should just be
the default in checkout too...but maybe that's too high a hill to
climb, at least for now.

Making --overlap and -p incompatible is a reasonable first step.  But
you should probably add a comment to the -p option documentation that
it implies --no-overlay.

> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
> ---
>  builtin/checkout.c             | 64 +++++++++++++++++++++++++++-------
>  t/t2025-checkout-no-overlay.sh | 47 +++++++++++++++++++++++++
>  t/t9902-completion.sh          |  1 +
>  3 files changed, 99 insertions(+), 13 deletions(-)
>  create mode 100755 t/t2025-checkout-no-overlay.sh
>
> diff --git a/builtin/checkout.c b/builtin/checkout.c
> index acdafc6e4c..0aef35bbc4 100644
> --- a/builtin/checkout.c
> +++ b/builtin/checkout.c
> @@ -44,6 +44,7 @@ struct checkout_opts {
>         int ignore_skipworktree;
>         int ignore_other_worktrees;
>         int show_progress;
> +       int overlay_mode;
>         /*
>          * If new checkout options are added, skip_merge_working_tree
>          * should be updated accordingly.
> @@ -132,7 +133,8 @@ static int skip_same_name(const struct cache_entry *ce, int pos)
>         return pos;
>  }
>
> -static int check_stage(int stage, const struct cache_entry *ce, int pos)
> +static int check_stage(int stage, const struct cache_entry *ce, int pos,
> +                      int overlay_mode)
>  {
>         while (pos < active_nr &&
>                !strcmp(active_cache[pos]->name, ce->name)) {
> @@ -140,6 +142,8 @@ static int check_stage(int stage, const struct cache_entry *ce, int pos)
>                         return 0;
>                 pos++;
>         }
> +       if (!overlay_mode)
> +               return 0;
>         if (stage == 2)
>                 return error(_("path '%s' does not have our version"), ce->name);
>         else
> @@ -165,7 +169,7 @@ static int check_stages(unsigned stages, const struct cache_entry *ce, int pos)
>  }
>
>  static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
> -                         const struct checkout *state)
> +                         const struct checkout *state, int overlay_mode)
>  {
>         while (pos < active_nr &&
>                !strcmp(active_cache[pos]->name, ce->name)) {
> @@ -173,6 +177,10 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
>                         return checkout_entry(active_cache[pos], state, NULL);
>                 pos++;
>         }
> +       if (!overlay_mode) {
> +               unlink_entry(ce);
> +               return 0;
> +       }
>         if (stage == 2)
>                 return error(_("path '%s' does not have our version"), ce->name);
>         else
> @@ -302,15 +310,29 @@ static int checkout_paths(const struct checkout_opts *opts,
>                 ce->ce_flags &= ~CE_MATCHED;
>                 if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
>                         continue;
> -               if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
> -                       /*
> -                        * "git checkout tree-ish -- path", but this entry
> -                        * is in the original index; it will not be checked
> -                        * out to the working tree and it does not matter
> -                        * if pathspec matched this entry.  We will not do
> -                        * anything to this entry at all.
> -                        */
> -                       continue;
> +               if (opts->source_tree && !(ce->ce_flags & CE_UPDATE)) {
> +                       if (!opts->overlay_mode &&
> +                           ce_path_match(&the_index, ce, &opts->pathspec, ps_matched)) {
> +                               /*
> +                                * "git checkout --no-overlay <tree-ish> -- path",
> +                                * and the path is not in tree-ish, but is in
> +                                * the current index, which means that it should
> +                                * be removed.
> +                                */
> +                               ce->ce_flags |= CE_MATCHED | CE_REMOVE | CE_WT_REMOVE;
> +                               continue;
> +                       } else {
> +                               /*
> +                                * "git checkout tree-ish -- path", but this
> +                                * entry is in the original index; it will not
> +                                * be checked out to the working tree and it
> +                                * does not matter if pathspec matched this
> +                                * entry.  We will not do anything to this entry
> +                                * at all.
> +                                */
> +                               continue;
> +                       }
> +               }
>                 /*
>                  * Either this entry came from the tree-ish we are
>                  * checking the paths out of, or we are checking out
> @@ -348,7 +370,7 @@ static int checkout_paths(const struct checkout_opts *opts,
>                         if (opts->force) {
>                                 warning(_("path '%s' is unmerged"), ce->name);
>                         } else if (opts->writeout_stage) {
> -                               errs |= check_stage(opts->writeout_stage, ce, pos);
> +                               errs |= check_stage(opts->writeout_stage, ce, pos, opts->overlay_mode);
>                         } else if (opts->merge) {
>                                 errs |= check_stages((1<<2) | (1<<3), ce, pos);
>                         } else {
> @@ -375,12 +397,14 @@ static int checkout_paths(const struct checkout_opts *opts,
>                                 continue;
>                         }
>                         if (opts->writeout_stage)
> -                               errs |= checkout_stage(opts->writeout_stage, ce, pos, &state);
> +                               errs |= checkout_stage(opts->writeout_stage, ce, pos, &state, opts->overlay_mode);
>                         else if (opts->merge)
>                                 errs |= checkout_merged(pos, &state);
>                         pos = skip_same_name(ce, pos) - 1;
>                 }
>         }
> +       remove_marked_cache_entries(&the_index, 1);
> +       remove_scheduled_dirs();
>         errs |= finish_delayed_checkout(&state);
>
>         if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
> @@ -542,6 +566,11 @@ static int skip_merge_working_tree(const struct checkout_opts *opts,
>          * opts->show_progress only impacts output so doesn't require a merge
>          */
>
> +       /*
> +        * opts->overlay_mode cannot be used with switching branches so is
> +        * not tested here
> +        */
> +
>         /*
>          * If we aren't creating a new branch any changes or updates will
>          * happen in the existing branch.  Since that could only be updating
> @@ -1178,6 +1207,10 @@ static int checkout_branch(struct checkout_opts *opts,
>                 die(_("'%s' cannot be used with switching branches"),
>                     "--patch");
>
> +       if (!opts->overlay_mode)
> +               die(_("'%s' cannot be used with switching branches"),
> +                   "--no-overlay");
> +
>         if (opts->writeout_stage)
>                 die(_("'%s' cannot be used with switching branches"),
>                     "--ours/--theirs");
> @@ -1266,6 +1299,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
>                             "checkout", "control recursive updating of submodules",
>                             PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
>                 OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
> +               OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode")),
>                 OPT_END(),
>         };
>
> @@ -1274,6 +1308,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
>         opts.overwrite_ignore = 1;
>         opts.prefix = prefix;
>         opts.show_progress = -1;
> +       opts.overlay_mode = -1;
>
>         git_config(git_checkout_config, &opts);
>
> @@ -1297,6 +1332,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
>         if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
>                 die(_("-b, -B and --orphan are mutually exclusive"));
>
> +       if (opts.overlay_mode == 1 && opts.patch_mode)
> +               die(_("-p and --overlay are mutually exclusive"));
> +
>         /*
>          * From here on, new_branch will contain the branch to be checked out,
>          * and new_branch_force and new_orphan_branch will tell us which one of
> diff --git a/t/t2025-checkout-no-overlay.sh b/t/t2025-checkout-no-overlay.sh
> new file mode 100755
> index 0000000000..3575321382
> --- /dev/null
> +++ b/t/t2025-checkout-no-overlay.sh
> @@ -0,0 +1,47 @@
> +#!/bin/sh
> +
> +test_description='checkout --no-overlay <tree-ish> -- <pathspec>'
> +
> +. ./test-lib.sh
> +
> +test_expect_success 'setup' '
> +       git commit --allow-empty -m "initial"
> +'
> +
> +test_expect_success 'checkout --no-overlay deletes files not in <tree>' '
> +       >file &&
> +       mkdir dir &&
> +       >dir/file1 &&
> +       git add file dir/file1 &&
> +       git checkout --no-overlay HEAD -- file &&
> +       test_path_is_missing file &&
> +       test_path_is_file dir/file1
> +'
> +
> +test_expect_success 'checkout --no-overlay removing last file from directory' '
> +       git checkout --no-overlay HEAD -- dir/file1 &&
> +       test_path_is_missing dir
> +'
> +
> +test_expect_success 'checkout -p --overlay is disallowed' '
> +       test_must_fail git checkout -p --overlay HEAD 2>actual &&
> +       test_i18ngrep "fatal: -p and --overlay are mutually exclusive" actual
> +'
> +
> +test_expect_success '--no-overlay --theirs with M/D conflict deletes file' '
> +       test_commit file1 file1 &&
> +       test_commit file2 file2 &&
> +       git rm --cached file1 &&
> +       echo 1234 >file1 &&
> +       F1=$(git rev-parse HEAD:file1) &&
> +       F2=$(git rev-parse HEAD:file2) &&
> +       {
> +               echo "100644 $F1 1      file1" &&
> +               echo "100644 $F2 2      file1"
> +       } | git update-index --index-info &&
> +       test_path_is_file file1 &&
> +       git checkout --theirs --no-overlay -- file1 &&
> +       test_path_is_missing file1
> +'
> +
> +test_done
> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> index 175f83d704..a3fd9a9630 100755
> --- a/t/t9902-completion.sh
> +++ b/t/t9902-completion.sh
> @@ -1436,6 +1436,7 @@ test_expect_success 'double dash "git checkout"' '
>         --progress Z
>         --no-quiet Z
>         --no-... Z
> +       --overlay Z
>         EOF
>  '
>
> --
> 2.20.0.405.gbc1bbc6f85
>

  parent reply	other threads:[~2018-12-10 18:19 UTC|newest]

Thread overview: 115+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-09 20:04 [PATCH 0/8] introduce no-overlay and cached mode in git checkout Thomas Gummerer
2018-12-09 20:04 ` [PATCH 1/8] move worktree tests to t24* Thomas Gummerer
2018-12-10  3:48   ` Junio C Hamano
2018-12-10 15:32   ` Duy Nguyen
2018-12-11 21:50     ` Thomas Gummerer
2018-12-12 13:26       ` Eric Sunshine
2018-12-12 17:07         ` Duy Nguyen
2018-12-09 20:04 ` [PATCH 2/8] entry: factor out unlink_entry function Thomas Gummerer
2018-12-10 15:49   ` Duy Nguyen
2018-12-10 17:23     ` Elijah Newren
2018-12-10 17:27       ` Duy Nguyen
2018-12-11  2:23     ` Junio C Hamano
2018-12-20 13:36     ` Thomas Gummerer
2018-12-09 20:04 ` [PATCH 3/8] entry: support CE_WT_REMOVE flag in checkout_entry Thomas Gummerer
2018-12-10 15:58   ` Duy Nguyen
2018-12-11  2:28     ` Junio C Hamano
2018-12-12  6:16       ` Duy Nguyen
2018-12-12  7:36         ` Junio C Hamano
2018-12-10 17:49   ` Elijah Newren
2018-12-11 22:00     ` Thomas Gummerer
2018-12-09 20:04 ` [PATCH 4/8] read-cache: add invalidate parameter to remove_marked_cache_entries Thomas Gummerer
2018-12-10 16:08   ` Duy Nguyen
2018-12-10 18:09     ` Elijah Newren
2018-12-10 18:19       ` Duy Nguyen
2018-12-10 18:25         ` Elijah Newren
2018-12-10 18:33           ` Duy Nguyen
2018-12-10 18:47             ` Elijah Newren
2018-12-11 21:59       ` Thomas Gummerer
2018-12-11  2:42     ` Junio C Hamano
2018-12-09 20:04 ` [PATCH 5/8] checkout: introduce --{,no-}overlay option Thomas Gummerer
2018-12-10 16:42   ` Duy Nguyen
2018-12-11 22:42     ` Thomas Gummerer
2018-12-10 18:19   ` Elijah Newren [this message]
2018-12-11  3:07     ` Junio C Hamano
2018-12-11  6:04       ` Elijah Newren
2018-12-11 22:07       ` Thomas Gummerer
2018-12-09 20:04 ` [PATCH 6/8] checkout: add --cached option Thomas Gummerer
2018-12-10 16:49   ` Duy Nguyen
2018-12-11  3:13     ` Junio C Hamano
2018-12-11  6:12       ` Elijah Newren
2018-12-11 19:23         ` Duy Nguyen
2019-01-31  5:54           ` Duy Nguyen
2019-01-31 19:05             ` Junio C Hamano
2019-02-01  6:48               ` Duy Nguyen
2019-02-01 17:57                 ` Junio C Hamano
2019-02-02 10:57                   ` Duy Nguyen
2019-02-19  4:20                   ` Duy Nguyen
2019-02-19 14:42                     ` Elijah Newren
2019-02-19 14:57                       ` Duy Nguyen
2019-02-19 19:07                       ` Junio C Hamano
2019-02-19 22:24                         ` Elijah Newren
2019-02-19 22:36                           ` Junio C Hamano
2019-02-19 23:00                             ` Elijah Newren
2019-02-20  1:53                             ` Duy Nguyen
2019-02-19 19:02                     ` Junio C Hamano
2019-02-19 19:10                       ` Junio C Hamano
2019-02-19 22:04                         ` Elijah Newren
2019-02-19 22:29                           ` Junio C Hamano
2019-02-20  2:32                             ` Duy Nguyen
2019-02-20  3:52                           ` Duy Nguyen
2019-02-20  2:19                         ` Duy Nguyen
2019-02-19 22:13                       ` Elijah Newren
2019-02-19 22:33                         ` Junio C Hamano
2018-12-10 18:42   ` Elijah Newren
2018-12-11 22:18     ` Thomas Gummerer
2018-12-09 20:04 ` [PATCH 7/8] checkout: allow ignoring unmatched pathspec Thomas Gummerer
2018-12-10 16:51   ` Duy Nguyen
2018-12-11 22:23     ` Thomas Gummerer
2018-12-10 20:25   ` Elijah Newren
2018-12-11 22:36     ` Thomas Gummerer
2018-12-09 20:04 ` [PATCH 8/8] stash: use git checkout --no-overlay Thomas Gummerer
2018-12-10 20:26   ` Elijah Newren
2018-12-10  3:47 ` [PATCH 0/8] introduce no-overlay and cached mode in git checkout Junio C Hamano
2018-12-20  8:43   ` Thomas Gummerer
2018-12-10 17:06 ` Duy Nguyen
2018-12-10 17:18 ` Elijah Newren
2018-12-10 18:37   ` Duy Nguyen
2018-12-11 22:52   ` Thomas Gummerer
2018-12-12  7:28     ` Junio C Hamano
2018-12-20 13:48 ` [PATCH v2 0/8] introduce no-overlay " Thomas Gummerer
2018-12-20 13:48   ` [PATCH v2 1/8] move worktree tests to t24* Thomas Gummerer
2018-12-20 13:48   ` [PATCH v2 2/8] entry: factor out unlink_entry function Thomas Gummerer
2018-12-20 13:48   ` [PATCH v2 3/8] entry: support CE_WT_REMOVE flag in checkout_entry Thomas Gummerer
2018-12-20 13:48   ` [PATCH v2 4/8] read-cache: add invalidate parameter to remove_marked_cache_entries Thomas Gummerer
2018-12-20 13:48   ` [PATCH v2 5/8] checkout: clarify comment Thomas Gummerer
2018-12-20 13:48   ` [PATCH v2 6/8] checkout: factor out mark_cache_entry_for_checkout function Thomas Gummerer
2018-12-20 13:48   ` [PATCH v2 7/8] checkout: introduce --{,no-}overlay option Thomas Gummerer
2018-12-23  8:05     ` Duy Nguyen
2018-12-23  9:44       ` Eric Sunshine
2019-01-06 18:18         ` Thomas Gummerer
2018-12-20 13:48   ` [PATCH v2 8/8] checkout: introduce checkout.overlayMode config Thomas Gummerer
2019-01-02 23:39     ` Junio C Hamano
2019-01-06 18:32       ` Thomas Gummerer
2019-01-07 17:00         ` Junio C Hamano
2019-01-08 21:52   ` [PATCH v3 0/8] introduce no-overlay mode in git checkout Thomas Gummerer
2019-01-08 21:52     ` [PATCH v3 1/8] move worktree tests to t24* Thomas Gummerer
2019-01-08 21:52     ` [PATCH v3 2/8] entry: factor out unlink_entry function Thomas Gummerer
2019-01-08 21:52     ` [PATCH v3 3/8] entry: support CE_WT_REMOVE flag in checkout_entry Thomas Gummerer
2019-01-08 21:52     ` [PATCH v3 4/8] read-cache: add invalidate parameter to remove_marked_cache_entries Thomas Gummerer
2019-01-08 21:52     ` [PATCH v3 5/8] checkout: clarify comment Thomas Gummerer
2019-01-08 21:52     ` [PATCH v3 6/8] checkout: factor out mark_cache_entry_for_checkout function Thomas Gummerer
2019-01-08 21:52     ` [PATCH v3 7/8] checkout: introduce --{,no-}overlay option Thomas Gummerer
2019-01-22 23:53       ` Jonathan Nieder
2019-01-23 19:05         ` Junio C Hamano
2019-01-23 20:21         ` Thomas Gummerer
2019-01-23 20:47           ` Jonathan Nieder
2019-01-24 22:08             ` Thomas Gummerer
2019-01-23 21:08           ` Junio C Hamano
2019-01-24  1:12             ` Jonathan Nieder
2019-01-24 22:02               ` Thomas Gummerer
2019-01-24 23:02               ` Junio C Hamano
2019-01-25  2:26                 ` Jonathan Nieder
2019-01-25  9:24                   ` Duy Nguyen
2019-02-09 18:54               ` Philip Oakley
2019-01-08 21:52     ` [PATCH v3 8/8] checkout: introduce checkout.overlayMode config Thomas Gummerer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CABPp-BEk+7n2wcbjETishqnMBs5DGrTEvD7gahLtEj5bZ2AYvA@mail.gmail.com \
    --to=newren@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=pclouds@gmail.com \
    --cc=t.gummerer@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.