git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: durham@fb.com, mitrandir@fb.com,
	"Junio C Hamano" <gitster@pobox.com>,
	"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 3/2] dir.c: fix dir re-inclusion rules with "NODIR" and "MUSTBEDIR"
Date: Thu, 17 Mar 2016 19:54:14 +0700	[thread overview]
Message-ID: <1458219254-16343-1-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1458218744-15810-2-git-send-email-pclouds@gmail.com>

For NODIR case, the patterns look like this

    *          # exclude dir, dir/file1 and dir/file2..
    !dir       # ..except that dir and everything inside is re-included..
    dir/file2  # ..except (again!) that dir/file2 is excluded
               # ..which means dir/file1 stays included

When we stay at topdir and test "dir", everything is hunky dory, current
code returns "re-include dir" as expected. When we stay in "dir" and
examine "dir/file1", however, match_basename() checks if the base name
component, which is "file1", matches "dir" from the second rule.

This is wrong. We contradict ourselves because earlier we decided to
re-include dir/file1 (from the second rule) when we were at toplevel.
Because the second rule is ignored, we hit the first one and return
"excluded" even though "dir/file1" should be re-included.

In the MUSTBEDIR case, the patterns look like this

    *          # exclude dir, dir/file1 and dir/file2..
    !dir/      #  ..except that dir and everything inside is re-included..
    dir/file2  # ..except (again!) that dir/file2 is excluded
               # ..which means dir/file1 stays included

Again, we're ok at the toplevel, then we enter "dir" and test
"dir/file1". The MUSTBEDIR code tests if the _full_ path (ie. "dir/file1")
is a directory. We want it to test the "dir" part from "dir/file1"
instead.

In both cases, the second decision on "dir/file1" is wrong and
contradicts with the first one on "dir". This is a perfect use case for
"sticky path list" added earlier to solve a different (but quite
similar) problem. So, when we have the right decision the first time, we
mark the path sticky to override the coming wrong decision.

The reason to do this, instead of actually fixing the code to make the
right second decision in the first place, is because it's soooooo
complicated. There are many combinations to take care of, many
optimizations involved to keep the cost on normal/common case (and
what's being described here is NOT normal) down to minimum. On top of
that, exclude code is already complicated as it is. It's best to not
turn the code upside down. Not until this approach is proved
insufficient.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 This is NOT for 2.8.0! Posted here to give you some context on the
 problem mentioned in the first patch.

 If you actually read the link in 1/2, you'll notice this patch is
 completely different. "soooooo complicated" is not an exaggeration. I
 found some problem with that old patch, which ended up with a
 combination explosion of cases I would have to cover separately,
 essentially the same thing I encountered in my first try before that
 patch. I finally admitted I could not fit all that in my brain
 anymore.

 dir.c                              |  5 ++++
 t/t3007-ls-files-other-negative.sh | 51 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/dir.c b/dir.c
index 2028094..a704e8a 100644
--- a/dir.c
+++ b/dir.c
@@ -1090,6 +1090,11 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
 					 x->pattern, x->srcpos);
 			return NULL;
 		}
+	} else if (exc->flags & EXC_FLAG_NEGATIVE) {
+		if (*dtype == DT_UNKNOWN)
+			*dtype = get_dtype(NULL, pathname, pathlen);
+		if (*dtype == DT_DIR)
+			add_sticky(exc, pathname, pathlen);
 	}
 
 	trace_printf_key(&trace_exclude, "exclude: %.*s vs %s at line %d => %s%s\n",
diff --git a/t/t3007-ls-files-other-negative.sh b/t/t3007-ls-files-other-negative.sh
index 0797b86..c8f39dd 100755
--- a/t/t3007-ls-files-other-negative.sh
+++ b/t/t3007-ls-files-other-negative.sh
@@ -150,4 +150,55 @@ test_expect_success 'match, literal pathname, nested negatives' '
 	test_cmp tmp/expected tmp/actual
 '
 
+test_expect_success 're-include case, NODIR' '
+	git init re-include-nodir &&
+	(
+		cd re-include-nodir &&
+		mkdir dir &&
+		touch dir/file1 dir/file2 &&
+		cat >.gitignore <<-\EOF &&
+		*
+		!dir
+		dir/file2
+		EOF
+		git ls-files -o --exclude-standard >../actual &&
+		echo dir/file1 >../expected &&
+		test_cmp ../expected ../actual
+	)
+'
+
+test_expect_success 're-include case, MUSTBEDIR with NODIR' '
+	git init re-include-mustbedir &&
+	(
+		cd re-include-mustbedir &&
+		mkdir dir &&
+		touch dir/file1 dir/file2 &&
+		cat >.gitignore <<-\EOF &&
+		*
+		!dir/
+		dir/file2
+		EOF
+		git ls-files -o --exclude-standard >../actual &&
+		echo dir/file1 >../expected &&
+		test_cmp ../expected ../actual
+	)
+'
+
+test_expect_success 're-include case, MUSTBEDIR without NODIR' '
+	git init re-include-pathname &&
+	(
+		cd re-include-pathname &&
+		mkdir -p dir1/dir2 &&
+		touch dir1/dir2/file1 dir1/dir2/file2 &&
+		cat >.gitignore <<-\EOF &&
+		*
+		!dir1/dir2/
+		dir1/dir2/file2
+		EOF
+		git ls-files -o --exclude-standard >../actual &&
+		echo dir1/dir2/file1 >../expected &&
+		test_cmp ../expected ../actual
+	)
+'
+
 test_done
-- 
2.8.0.rc0.210.gd302cd2

  reply	other threads:[~2016-03-17 12:54 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-17  0:09 bug: sparse config interpretation incorrectness in 2.8.0-rc2 Durham Goode
2016-03-17  0:56 ` Duy Nguyen
2016-03-17  6:49   ` Durham Goode
2016-03-17  7:51   ` Junio C Hamano
2016-03-17 10:17     ` Duy Nguyen
2016-03-17 13:04       ` Johannes Schindelin
2016-03-17 13:20         ` Duy Nguyen
2016-03-17 13:46           ` Johannes Schindelin
2016-03-17 14:00             ` Duy Nguyen
2016-03-18 15:49               ` Johannes Schindelin
2016-03-17  7:22 ` Junio C Hamano
2016-03-17 17:51   ` Durham Goode
2016-03-17 12:45 ` [PATCH 1/2] dir.c: fix bug in 'nd/exclusion-regression-fix' topic Nguyễn Thái Ngọc Duy
2016-03-17 12:45   ` Nguyễn Thái Ngọc Duy
2016-03-17 12:54     ` Nguyễn Thái Ngọc Duy [this message]
2016-03-17 23:49       ` [PATCH 3/2] dir.c: fix dir re-inclusion rules with "NODIR" and "MUSTBEDIR" Junio C Hamano
2016-03-18  0:15         ` Duy Nguyen
2016-03-18  5:40           ` Junio C Hamano
2016-03-18  5:51             ` Duy Nguyen
2016-03-18  5:58             ` Eric Sunshine
2016-03-18  4:51         ` Durham Goode
2016-03-18  5:40           ` Duy Nguyen
2016-03-18  6:21             ` Durham Goode
2016-03-18  6:28               ` Duy Nguyen
2016-03-18 18:00             ` Junio C Hamano
2016-03-18 18:37               ` Extending this cycle by a week and reverting !reinclusion topic Junio C Hamano
2016-03-19  1:03               ` [PATCH 3/2] dir.c: fix dir re-inclusion rules with "NODIR" and "MUSTBEDIR" Duy Nguyen
2016-03-17 12:45   ` [PATCH 2/2] dir.c: correct "stuck" logging logic Nguyễn Thái Ngọc Duy
2016-03-17 12:45   ` Nguyễn Thái Ngọc Duy
2016-03-18 17:38   ` [PATCH 1/2] dir.c: fix bug in 'nd/exclusion-regression-fix' topic Junio C Hamano

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=1458219254-16343-1-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.com \
    --cc=durham@fb.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=mitrandir@fb.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 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 NNTP newsgroup(s).