From: Phillip Wood <phillip.wood123@gmail.com>
To: Git Mailing List <git@vger.kernel.org>, Duy Nguyen <pclouds@gmail.com>
Cc: Junio C Hamano <gitster@pobox.com>,
Phillip Wood <phillip.wood@dunelm.org.uk>
Subject: [PATCH 2/2] read-tree: add --exclude-standard
Date: Wed, 1 May 2019 11:14:03 +0100 [thread overview]
Message-ID: <20190501101403.20294-3-phillip.wood123@gmail.com> (raw)
In-Reply-To: <20190501101403.20294-1-phillip.wood123@gmail.com>
From: Phillip Wood <phillip.wood@dunelm.org.uk>
Currently there is no way to get read-tree to respect
.git/info/exclude or core.excludesFile so scripts using `read-tree -u`
have subtly different behavior to porcelain commands like checkout
even when they use --exclude-per-directory. This new option is copied
from ls-tree's --exclude-standard option to setup the standard
excludes. The new option is also used to fix a known submodule test
failure.
Note that KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED is still
used by t7112-reset-submodule.sh as it is not removed (apparently
reset does not call setup_standard_excludes()).
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
Documentation/git-read-tree.txt | 9 +++++-
builtin/read-tree.c | 55 ++++++++++++++++++++++++++++++---
t/t1005-read-tree-reset.sh | 36 ++++++++++++++++++---
t/t1013-read-tree-submodule.sh | 3 +-
4 files changed, 90 insertions(+), 13 deletions(-)
diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt
index 67864c6bbc..a2b8b73a99 100644
--- a/Documentation/git-read-tree.txt
+++ b/Documentation/git-read-tree.txt
@@ -107,7 +107,14 @@ OPTIONS
running `make clean` to remove the generated file. This
option tells the command to read per-directory exclude
file (usually '.gitignore') and allows such an untracked
- but explicitly ignored file to be overwritten.
+ but explicitly ignored file to be overwritten. Incompatible
+ with `--exclude-standard`.
+
+--exclude-standard::
+ When updating the worktree use the standard Git exclusions:
+ .git/info/exclude, .gitignore in each directory, and the user's global
+ exclusion file when deciding if it is safe to overwrite a file.
+ Incompatible with `--exclude-per-directory`.
--index-output=<file>::
Instead of writing the results out to `$GIT_INDEX_FILE`,
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 23735adde9..5df493c4a7 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -50,6 +50,40 @@ static int index_output_cb(const struct option *opt, const char *arg,
return 0;
}
+enum exclude_type {
+ EXCLUDE_NONE,
+ EXCLUDE_PER_DIRECTORY,
+ EXCLUDE_STANDARD
+} exclude_opt = EXCLUDE_NONE;
+
+static int exclude_error(enum exclude_type exclude)
+{
+ if (exclude == exclude_opt)
+ return error("more than one --exclude-per-directory given");
+ else
+ return error("cannot combine --exclude-per-directory and "
+ "--exclude-standard");
+}
+
+static int option_parse_exclude_standard(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct unpack_trees_options *opts;
+
+ BUG_ON_OPT_NEG(unset);
+ BUG_ON_OPT_ARG(arg);
+
+ if (exclude_opt == EXCLUDE_PER_DIRECTORY)
+ return exclude_error(EXCLUDE_STANDARD);
+
+ opts = (struct unpack_trees_options *)opt->value;
+ opts->dir = xcalloc(1, sizeof(*opts->dir));
+ setup_standard_excludes(opts->dir);
+ exclude_opt = EXCLUDE_STANDARD;
+
+ return 0;
+}
+
static int exclude_per_directory_cb(const struct option *opt, const char *arg,
int unset)
{
@@ -61,12 +95,13 @@ static int exclude_per_directory_cb(const struct option *opt, const char *arg,
opts = (struct unpack_trees_options *)opt->value;
if (opts->dir)
- die("more than one --exclude-per-directory given.");
+ return exclude_error(EXCLUDE_PER_DIRECTORY);
dir = xcalloc(1, sizeof(*opts->dir));
dir->flags |= DIR_SHOW_IGNORED;
dir->exclude_per_dir = arg;
opts->dir = dir;
+ exclude_opt = EXCLUDE_PER_DIRECTORY;
/* We do not need to nor want to do read-directory
* here; we are merely interested in reusing the
* per directory ignore stack mechanism.
@@ -147,6 +182,10 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
N_("gitignore"),
N_("allow explicitly ignored files to be overwritten"),
PARSE_OPT_NONEG, exclude_per_directory_cb },
+ { OPTION_CALLBACK, 0, "exclude-standard", &opts, NULL,
+ N_("add the standard git exclusions"),
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+ option_parse_exclude_standard },
OPT_BOOL('i', NULL, &opts.index_only,
N_("don't check the working tree after merging")),
OPT__DRY_RUN(&opts.dry_run, N_("don't update the index or the work tree")),
@@ -219,10 +258,16 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
opts.reset = UNPACK_RESET_PROTECT_UNTRACKED;
}
if ((opts.dir && !opts.update))
- die("--exclude-per-directory is meaningless unless -u");
- if (opts.dir && opts.reset == UNPACK_RESET_OVERWRITE_UNTRACKED)
- warning("--exclude-per-directory without --preserve-untracked "
- "has no effect");
+ die("%s requires -u", exclude_opt == EXCLUDE_STANDARD ?
+ "--exclude-standard" :" --exclude-per-directory");
+ if (opts.dir && opts.reset == UNPACK_RESET_OVERWRITE_UNTRACKED) {
+ if (exclude_opt == EXCLUDE_STANDARD)
+ die("--reset with --exclude-standard requires "
+ "--protect-untracked");
+ else
+ warning("--exclude-per-directory without "
+ "--preserve-untracked has no effect");
+ }
if (opts.merge && !opts.index_only)
setup_work_tree();
diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh
index 6c9dd6805b..2e2a6a0c69 100755
--- a/t/t1005-read-tree-reset.sh
+++ b/t/t1005-read-tree-reset.sh
@@ -30,6 +30,20 @@ test_expect_success '--protect-untracked option sanity checks' '
read_tree_u_must_fail -m -u --no-protect-untracked
'
+test_expect_success 'exclude option sanity checks' '
+ read_tree_u_must_fail --reset -u --exclude-standard HEAD &&
+ read_tree_u_must_fail --reset --protect-untracked --exclude-standard &&
+ read_tree_u_must_fail --reset -u --protect-untracked \
+ --exclude-standard \
+ --exclude-per-directory=.gitignore HEAD &&
+ read_tree_u_must_fail --reset -u --protect-untracked \
+ --exclude-per-directory=gitignore \
+ --exclude-per-directory=.gitignore HEAD &&
+ read_tree_u_must_fail --reset --exclude-per-directory=.gitignore HEAD &&
+ read_tree_u_must_succeed --reset -u --exclude-per-directory=.gitignore \
+ HEAD
+'
+
test_expect_success 'reset should reset worktree' '
echo changed >df &&
read_tree_u_must_succeed -u --reset HEAD^ &&
@@ -53,12 +67,24 @@ test_expect_success 'reset --protect-untracked protects untracked directory' '
test_cmp expected-err actual-err
'
-test_expect_success 'reset --protect-untracked resets' '
- rm -rf new &&
+test_expect_success 'reset --protect-untracked --exclude-standard overwrites ignored path' '
+ test_when_finished "rm .git/info/exclude" &&
+ echo missing >.git/info/exclude &&
+ read_tree_u_must_fail -u --reset --protect-untracked \
+ --exclude-standard HEAD &&
+ echo new >.git/info/exclude &&
echo changed >df/file &&
- read_tree_u_must_succeed -u --reset --protect-untracked HEAD &&
- git ls-files >actual-two &&
- test_cmp expect-two actual-two
+ read_tree_u_must_succeed -u --reset --protect-untracked \
+ --exclude-standard HEAD &&
+ git ls-files >actual &&
+ test_cmp expect-two actual
+'
+
+test_expect_success 'reset --protect-untracked resets' '
+ echo changed >df &&
+ read_tree_u_must_succeed -u --reset --protect-untracked HEAD^ &&
+ git ls-files >actual &&
+ test_cmp expect actual
'
test_expect_success 'reset should remove remnants from a failed merge' '
diff --git a/t/t1013-read-tree-submodule.sh b/t/t1013-read-tree-submodule.sh
index 91a6fafcb4..728280d40d 100755
--- a/t/t1013-read-tree-submodule.sh
+++ b/t/t1013-read-tree-submodule.sh
@@ -6,9 +6,8 @@ test_description='read-tree can handle submodules'
. "$TEST_DIRECTORY"/lib-submodule-update.sh
KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
-KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1
-test_submodule_switch_recursing_with_args "read-tree -u -m"
+test_submodule_switch_recursing_with_args "read-tree -u -m --exclude-standard"
test_submodule_forced_switch_recursing_with_args "read-tree -u --reset"
--
2.21.0
next prev parent reply other threads:[~2019-05-01 10:14 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-01 10:14 [PATCH 0/2] read-tree: improve untracked file support Phillip Wood
2019-05-01 10:14 ` [PATCH 1/2] read-tree --reset: add --protect-untracked Phillip Wood
2019-05-01 10:18 ` Duy Nguyen
2019-05-01 10:32 ` Duy Nguyen
2019-05-02 10:38 ` Duy Nguyen
2019-05-03 15:20 ` Phillip Wood
2019-05-01 10:14 ` Phillip Wood [this message]
2019-05-01 10:31 ` [PATCH 0/2] read-tree: improve untracked file support Duy Nguyen
2019-05-01 14:58 ` Phillip Wood
2019-05-02 10:53 ` Duy Nguyen
2019-05-07 10:01 ` Phillip Wood
2019-05-07 11:02 ` Duy Nguyen
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
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190501101403.20294-3-phillip.wood123@gmail.com \
--to=phillip.wood123@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=pclouds@gmail.com \
--cc=phillip.wood@dunelm.org.uk \
/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.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).