All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5] Add an explicit GIT_DIR to the list of excludes
@ 2014-06-04 20:15 Pasha Bolokhov
  2014-06-08 10:17 ` Duy Nguyen
  0 siblings, 1 reply; 10+ messages in thread
From: Pasha Bolokhov @ 2014-06-04 20:15 UTC (permalink / raw)
  To: pclouds; +Cc: jrnieder, jnareb, git, Pasha Bolokhov

When an explicit '--git-dir' option points to a directory inside
the work tree, git treats it as if it were any other directory.
In particular, 'git status' lists it as untracked, while 'git add -A'
stages the metadata directory entirely

Add GIT_DIR to the list of excludes in a dedicated function
add_git_dir_exclude(), while checking that GIT_DIR is not just '.git'
or its basename is not '.git', in which cases it would be ignored
by default, and that GIT_DIR is inside GIT_WORK_TREE. Function
add_git_dir_exclude() is invoked at the beginning of
dir.c:setup_standard_excludes()

Although an analogous comparison of any given path against '.git'
is done in treat_path(), this does not seem to be the right place
to compare against GIT_DIR. Instead, the excludes provide an
effective mechanism of ignoring a file/directory, and adding GIT_DIR
as an exclude is equivalent to putting it into '.gitignore'. Function
setup_standard_excludes() was chosen because that is the place where
the excludes are initialized by the commands that are concerned about
excludes

Signed-off-by: Pasha Bolokhov <pasha.bolokhov@gmail.com>
---
basename() is not needed anymore, as we are excluding a "full" path GIT_DIR
but relative to GIT_WORK_TREE. Now, a full path ensures that nothing
else gets excluded (i.e. files with the same basename), and this behaviour
is checked in tests

Docs (git-grep, git-ls-files, gitignore) will be updated in the
subsequent version, wanted to check right now if you agree with code.
Docs kind of depend on what we decide about the code

 Documentation/technical/api-directory-listing.txt |   4 +-
 dir.c                                             |  33 ++++
 t/t2205-add-gitdir.sh                             | 187 ++++++++++++++++++++++
 3 files changed, 222 insertions(+), 2 deletions(-)
 create mode 100755 t/t2205-add-gitdir.sh

diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt
index 7f8e78d..fd4a178 100644
--- a/Documentation/technical/api-directory-listing.txt
+++ b/Documentation/technical/api-directory-listing.txt
@@ -90,8 +90,8 @@ marked. If you to exclude files, make sure you have loaded index first.
   `add_exclude()`.
 
 * To add patterns from a file (e.g. `.git/info/exclude`), call
-  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  A
-  short-hand function `setup_standard_excludes()` can be used to set
+  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  The
+  short-hand function `setup_standard_excludes()` must be used to set
   up the standard set of exclude settings.
 
 * Set options described in the Data Structure section above.
diff --git a/dir.c b/dir.c
index eb6f581..300ce1c 100644
--- a/dir.c
+++ b/dir.c
@@ -1604,11 +1604,44 @@ int remove_dir_recursively(struct strbuf *path, int flag)
 	return remove_dir_recurse(path, flag, NULL);
 }
 
+static void add_git_dir_exclude(struct dir_struct *dir)
+{
+	const char *r_git, *gitdir = get_git_dir();
+	char *n_git;
+	int len;
+
+	r_git = real_path(absolute_path(gitdir));
+	n_git = xmalloc(strlen(r_git) + 1 + 1);
+	normalize_path_copy(n_git, r_git);
+	len = strlen(n_git);
+
+	/* only add it if GIT_DIR does not end with '.git' or '/.git' */
+	if (len < 4 || strcmp(n_git + len - 4, ".git") ||
+	    (len > 4 && n_git[len - 5] != '/')) {
+		const char *worktree = get_git_work_tree();
+
+		if (!worktree ||
+		    dir_inside_of(n_git, worktree) >= 0) {
+			struct exclude_list *el = add_exclude_list(dir, EXC_CMDL,
+							"GIT_DIR setup");
+			char *reldir = worktree ? n_git + strlen(worktree) : n_git;
+
+			/* append a trailing slash to exclude directories only */
+			n_git[len] = '/';
+			n_git[len + 1] = '\0';
+			add_exclude(reldir, "", 0, el, 0);
+		}
+	}
+	free(n_git);
+}
+
 void setup_standard_excludes(struct dir_struct *dir)
 {
 	const char *path;
 	char *xdg_path;
 
+	add_git_dir_exclude(dir);
+
 	dir->exclude_per_dir = ".gitignore";
 	path = git_path("info/exclude");
 	if (!excludes_file) {
diff --git a/t/t2205-add-gitdir.sh b/t/t2205-add-gitdir.sh
new file mode 100755
index 0000000..721970e
--- /dev/null
+++ b/t/t2205-add-gitdir.sh
@@ -0,0 +1,187 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Pasha Bolokhov
+#
+
+test_description='alternative repository path specified by --git-dir is ignored by add and status'
+
+. ./test-lib.sh
+
+#
+# Create a tree:
+#
+#	repo-inside/  repo-outside/
+#
+#
+# repo-inside:
+# 	a  b  c  d  dir1/ dir2/ [meta/]
+#
+# repo-inside/dir1:
+# 	e  f  g  h  meta/  ssubdir/
+#
+# repo-inside/dir1/meta:
+# 	aa
+#
+# repo-inside/dir1/ssubdir:
+# 	meta/
+#
+# repo-inside/dir1/ssubdir/meta:
+# 	aaa
+#
+# repo-inside/dir2:
+#	meta
+#
+#
+#
+# repo-outside:
+#	external/  tree/
+#
+# repo-outside/external:
+#	[meta/]
+#
+# repo-outside/tree:
+#	n  o  p  q  meta/  sub/
+#
+# repo-outside/tree/meta:
+#	bb
+#
+# repo-outside/tree/sub:
+#	meta/
+#
+# repo-outside/tree/sub/meta:
+#	bbb
+#
+#
+# (both of the above [meta/] denote the actual repositories)
+#
+
+#
+# First set of tests (in "repo-inside/"):
+# ---------------------------------------
+#
+# Name the repository "meta" and see whether or not "git status" includes or
+# ignores directories named "meta". Directory "meta" at the top level of
+# "repo-inside/"is the repository and appears upon the first "git init"
+#
+#
+# Second set of tests (in "repo-outside/"):
+# -----------------------------------------
+#
+# Put the work tree into "tree/" and repository into "external/meta"
+# (the latter directory appears upon the corresponding "git init").
+# The work tree again contains directories named "meta", but those ones are
+# tested not to be ignored now
+#
+
+test_expect_success "setup" '
+	mkdir repo-inside/ &&
+	(
+		cd repo-inside/ &&
+		for f in a b c d
+		do
+			echo "DATA" >"$f" || exit 1
+		done &&
+		mkdir dir1 dir1/meta &&
+		mkdir dir1/ssubdir dir1/ssubdir/meta &&
+		for f in e f g h
+		do
+			echo "MORE DATA" >"dir1/$f" || exit 1
+		done &&
+		echo "EVEN more Data" >dir1/meta/aa &&
+		echo "Data and BAIT" >dir1/ssubdir/meta/aaa &&
+		mkdir dir2
+		echo "Not a Metadata File" >dir2/meta
+		git --git-dir=meta init
+	) &&
+	mkdir repo-outside/ repo-outside/external repo-outside/tree &&
+	(
+		cd repo-outside/tree &&
+		for f in n o p q
+		do
+			echo "Literal Data" >"$f" || exit 1
+		done &&
+		mkdir meta sub sub/meta &&
+		echo "Sample data" >meta/bb &&
+		echo "Stream of data" >sub/meta/bbb &&
+		git --git-dir=../external/meta init
+	)
+'
+
+
+#
+# The first set of tests (the repository is inside the work tree)
+#
+test_expect_success "'git status' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		git --git-dir=meta --work-tree=. status --porcelain --untracked=all |
+			grep meta | sort >status.actual.2 &&
+		cat >status.expect.2 <<-\EOF &&
+		?? dir1/meta/aa
+		?? dir1/ssubdir/meta/aaa
+		?? dir2/meta
+		EOF
+		test_cmp status.actual.2 status.expect.2
+	)
+'
+
+test_expect_success "'git add -A' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		git --git-dir=meta --work-tree=. add -A &&
+		git --git-dir=meta --work-tree=. status --porcelain | grep meta | sort >status.actual.3 &&
+		cat >status.expect.3 <<-\EOF &&
+		A  dir1/meta/aa
+		A  dir1/ssubdir/meta/aaa
+		A  dir2/meta
+		EOF
+		test_cmp status.actual.3 status.expect.3
+	)
+'
+
+test_expect_success "'git grep --exclude-standard' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		test_might_fail git --git-dir=meta \
+			grep --no-index --exclude-standard BAIT >grep.actual.4 &&
+		cat >grep.expect.4 <<-\EOF &&
+		dir1/ssubdir/meta/aaa:Data and BAIT
+		EOF
+		test_cmp grep.actual.4 grep.expect.4
+	)
+'
+
+#
+# The second set of tests (the repository is outside of the work tree)
+#
+test_expect_success "'git status' acknowledges directories 'meta' \
+if repo is not within work tree" '
+	test_might_fail rm -rf meta/ &&
+	(
+		cd repo-outside/tree &&
+		git --git-dir=../external/meta init &&
+		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all |
+			grep meta | sort >status.actual.5 &&
+		cat >status.expect.5 <<-\EOF &&
+		?? meta/bb
+		?? sub/meta/bbb
+		EOF
+		test_cmp status.actual.5 status.expect.5
+	)
+'
+
+test_expect_success "'git add -A' adds 'meta' if the repo is outside the work tree" '
+	(
+		cd repo-outside/tree &&
+		git --git-dir=../external/meta --work-tree=. add -A &&
+		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all |
+			grep meta | sort >status.actual.6 &&
+		cat >status.expect.6 <<-\EOF &&
+		A  meta/bb
+		A  sub/meta/bbb
+		EOF
+		test_cmp status.actual.6 status.expect.6
+	)
+'
+
+test_done
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v5] Add an explicit GIT_DIR to the list of excludes
  2014-06-04 20:15 [PATCH v5] Add an explicit GIT_DIR to the list of excludes Pasha Bolokhov
@ 2014-06-08 10:17 ` Duy Nguyen
  2014-06-10  3:18   ` Pasha Bolokhov
  0 siblings, 1 reply; 10+ messages in thread
From: Duy Nguyen @ 2014-06-08 10:17 UTC (permalink / raw)
  To: Pasha Bolokhov; +Cc: Jonathan Nieder, Jakub Narębski, Git Mailing List

On Thu, Jun 5, 2014 at 3:15 AM, Pasha Bolokhov <pasha.bolokhov@gmail.com> wrote:
> +       /* only add it if GIT_DIR does not end with '.git' or '/.git' */
> +       if (len < 4 || strcmp(n_git + len - 4, ".git") ||
> +           (len > 4 && n_git[len - 5] != '/')) {

Hmm.. should we exclude "foobar.git" as well?
-- 
Duy

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v5] Add an explicit GIT_DIR to the list of excludes
  2014-06-08 10:17 ` Duy Nguyen
@ 2014-06-10  3:18   ` Pasha Bolokhov
  2014-06-11 10:48     ` Duy Nguyen
  0 siblings, 1 reply; 10+ messages in thread
From: Pasha Bolokhov @ 2014-06-10  3:18 UTC (permalink / raw)
  To: Duy Nguyen; +Cc: Jonathan Nieder, Jakub Narębski, Git Mailing List

> On Thu, Jun 5, 2014 at 3:15 AM, Pasha Bolokhov <pasha.bolokhov@gmail.com> wrote:
>> +       /* only add it if GIT_DIR does not end with '.git' or '/.git' */
>> +       if (len < 4 || strcmp(n_git + len - 4, ".git") ||
>> +           (len > 4 && n_git[len - 5] != '/')) {
>
> Hmm.. should we exclude "foobar.git" as well?

    Why wouldn't we? Everything that has basename ".git" is hard-wired
to be excluded, but everything else, including "foobar.git" should be
added to the excludes manually... How is it better than just "foobar"?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v5] Add an explicit GIT_DIR to the list of excludes
  2014-06-10  3:18   ` Pasha Bolokhov
@ 2014-06-11 10:48     ` Duy Nguyen
  2014-06-11 23:28       ` [PATCH v6] " Pasha Bolokhov
  0 siblings, 1 reply; 10+ messages in thread
From: Duy Nguyen @ 2014-06-11 10:48 UTC (permalink / raw)
  To: Pasha Bolokhov; +Cc: Jonathan Nieder, Jakub Narębski, Git Mailing List

On Tue, Jun 10, 2014 at 10:18 AM, Pasha Bolokhov
<pasha.bolokhov@gmail.com> wrote:
>> On Thu, Jun 5, 2014 at 3:15 AM, Pasha Bolokhov <pasha.bolokhov@gmail.com> wrote:
>>> +       /* only add it if GIT_DIR does not end with '.git' or '/.git' */
>>> +       if (len < 4 || strcmp(n_git + len - 4, ".git") ||
>>> +           (len > 4 && n_git[len - 5] != '/')) {
>>
>> Hmm.. should we exclude "foobar.git" as well?
>
>     Why wouldn't we? Everything that has basename ".git" is hard-wired
> to be excluded, but everything else, including "foobar.git" should be
> added to the excludes manually... How is it better than just "foobar"?

Yes everything except ".git" should be excluded. And you do exactly
that. I misread the code (probably better to write "if (!(<basename is
".git>))", maybe)
-- 
Duy

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v6] Add an explicit GIT_DIR to the list of excludes
  2014-06-11 10:48     ` Duy Nguyen
@ 2014-06-11 23:28       ` Pasha Bolokhov
  2014-06-12  6:19         ` Johannes Sixt
  0 siblings, 1 reply; 10+ messages in thread
From: Pasha Bolokhov @ 2014-06-11 23:28 UTC (permalink / raw)
  To: pclouds; +Cc: jrnieder, jnareb, git, Pasha Bolokhov

When an explicit '--git-dir' option points to a directory inside
the work tree, git treats it as if it were any other directory.
In particular, 'git status' lists it as untracked, while 'git add -A'
stages the metadata directory entirely

Add GIT_DIR to the list of excludes in a dedicated function
add_git_dir_exclude(), while checking that GIT_DIR is not just '.git'
or its basename is not '.git', in which cases it would be ignored
by default, and that GIT_DIR is inside GIT_WORK_TREE. Function
add_git_dir_exclude() is invoked at the beginning of
dir.c:setup_standard_excludes()

Although an analogous comparison of any given path against '.git'
is done in treat_path(), this does not seem to be the right place
to compare against GIT_DIR. Instead, the excludes provide an
effective mechanism of ignoring a file/directory, and adding GIT_DIR
as an exclude is equivalent to putting it into '.gitignore'. Function
setup_standard_excludes() was chosen because that is the place where
the excludes are initialized by the commands that are concerned about
excludes

Signed-off-by: Pasha Bolokhov <pasha.bolokhov@gmail.com>
---
Negate the 'basename(GIT_DIR) != ".git"' check for better readability
in add_git_dir_exclude()

 Documentation/technical/api-directory-listing.txt |   4 +-
 dir.c                                             |  33 ++++
 t/t2205-add-gitdir.sh                             | 187 ++++++++++++++++++++++
 3 files changed, 222 insertions(+), 2 deletions(-)
 create mode 100755 t/t2205-add-gitdir.sh

diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt
index 7f8e78d..fd4a178 100644
--- a/Documentation/technical/api-directory-listing.txt
+++ b/Documentation/technical/api-directory-listing.txt
@@ -90,8 +90,8 @@ marked. If you to exclude files, make sure you have loaded index first.
   `add_exclude()`.
 
 * To add patterns from a file (e.g. `.git/info/exclude`), call
-  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  A
-  short-hand function `setup_standard_excludes()` can be used to set
+  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  The
+  short-hand function `setup_standard_excludes()` must be used to set
   up the standard set of exclude settings.
 
 * Set options described in the Data Structure section above.
diff --git a/dir.c b/dir.c
index 797805d..3f57e34 100644
--- a/dir.c
+++ b/dir.c
@@ -1608,11 +1608,44 @@ int remove_dir_recursively(struct strbuf *path, int flag)
 	return remove_dir_recurse(path, flag, NULL);
 }
 
+static void add_git_dir_exclude(struct dir_struct *dir)
+{
+	const char *r_git, *gitdir = get_git_dir();
+	char *n_git;
+	int len;
+
+	r_git = real_path(absolute_path(gitdir));
+	n_git = xmalloc(strlen(r_git) + 1 + 1);
+	normalize_path_copy(n_git, r_git);
+	len = strlen(n_git);
+
+	/* only add it if GIT_DIR does not end with '.git' or '/.git' */
+	if (!(len >= 4 && !strcmp(n_git + len - 4, ".git") &&
+	      (len == 4 || n_git[len - 5] == '/'))) {
+		const char *worktree = get_git_work_tree();
+
+		if (!worktree ||
+		    dir_inside_of(n_git, worktree) >= 0) {
+			struct exclude_list *el = add_exclude_list(dir, EXC_CMDL,
+							"GIT_DIR setup");
+			char *reldir = worktree ? n_git + strlen(worktree) : n_git;
+
+			/* append a trailing slash to exclude directories only */
+			n_git[len] = '/';
+			n_git[len + 1] = '\0';
+			add_exclude(reldir, "", 0, el, 0);
+		}
+	}
+	free(n_git);
+}
+
 void setup_standard_excludes(struct dir_struct *dir)
 {
 	const char *path;
 	char *xdg_path;
 
+	add_git_dir_exclude(dir);
+
 	dir->exclude_per_dir = ".gitignore";
 	path = git_path("info/exclude");
 	if (!excludes_file) {
diff --git a/t/t2205-add-gitdir.sh b/t/t2205-add-gitdir.sh
new file mode 100755
index 0000000..721970e
--- /dev/null
+++ b/t/t2205-add-gitdir.sh
@@ -0,0 +1,187 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Pasha Bolokhov
+#
+
+test_description='alternative repository path specified by --git-dir is ignored by add and status'
+
+. ./test-lib.sh
+
+#
+# Create a tree:
+#
+#	repo-inside/  repo-outside/
+#
+#
+# repo-inside:
+# 	a  b  c  d  dir1/ dir2/ [meta/]
+#
+# repo-inside/dir1:
+# 	e  f  g  h  meta/  ssubdir/
+#
+# repo-inside/dir1/meta:
+# 	aa
+#
+# repo-inside/dir1/ssubdir:
+# 	meta/
+#
+# repo-inside/dir1/ssubdir/meta:
+# 	aaa
+#
+# repo-inside/dir2:
+#	meta
+#
+#
+#
+# repo-outside:
+#	external/  tree/
+#
+# repo-outside/external:
+#	[meta/]
+#
+# repo-outside/tree:
+#	n  o  p  q  meta/  sub/
+#
+# repo-outside/tree/meta:
+#	bb
+#
+# repo-outside/tree/sub:
+#	meta/
+#
+# repo-outside/tree/sub/meta:
+#	bbb
+#
+#
+# (both of the above [meta/] denote the actual repositories)
+#
+
+#
+# First set of tests (in "repo-inside/"):
+# ---------------------------------------
+#
+# Name the repository "meta" and see whether or not "git status" includes or
+# ignores directories named "meta". Directory "meta" at the top level of
+# "repo-inside/"is the repository and appears upon the first "git init"
+#
+#
+# Second set of tests (in "repo-outside/"):
+# -----------------------------------------
+#
+# Put the work tree into "tree/" and repository into "external/meta"
+# (the latter directory appears upon the corresponding "git init").
+# The work tree again contains directories named "meta", but those ones are
+# tested not to be ignored now
+#
+
+test_expect_success "setup" '
+	mkdir repo-inside/ &&
+	(
+		cd repo-inside/ &&
+		for f in a b c d
+		do
+			echo "DATA" >"$f" || exit 1
+		done &&
+		mkdir dir1 dir1/meta &&
+		mkdir dir1/ssubdir dir1/ssubdir/meta &&
+		for f in e f g h
+		do
+			echo "MORE DATA" >"dir1/$f" || exit 1
+		done &&
+		echo "EVEN more Data" >dir1/meta/aa &&
+		echo "Data and BAIT" >dir1/ssubdir/meta/aaa &&
+		mkdir dir2
+		echo "Not a Metadata File" >dir2/meta
+		git --git-dir=meta init
+	) &&
+	mkdir repo-outside/ repo-outside/external repo-outside/tree &&
+	(
+		cd repo-outside/tree &&
+		for f in n o p q
+		do
+			echo "Literal Data" >"$f" || exit 1
+		done &&
+		mkdir meta sub sub/meta &&
+		echo "Sample data" >meta/bb &&
+		echo "Stream of data" >sub/meta/bbb &&
+		git --git-dir=../external/meta init
+	)
+'
+
+
+#
+# The first set of tests (the repository is inside the work tree)
+#
+test_expect_success "'git status' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		git --git-dir=meta --work-tree=. status --porcelain --untracked=all |
+			grep meta | sort >status.actual.2 &&
+		cat >status.expect.2 <<-\EOF &&
+		?? dir1/meta/aa
+		?? dir1/ssubdir/meta/aaa
+		?? dir2/meta
+		EOF
+		test_cmp status.actual.2 status.expect.2
+	)
+'
+
+test_expect_success "'git add -A' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		git --git-dir=meta --work-tree=. add -A &&
+		git --git-dir=meta --work-tree=. status --porcelain | grep meta | sort >status.actual.3 &&
+		cat >status.expect.3 <<-\EOF &&
+		A  dir1/meta/aa
+		A  dir1/ssubdir/meta/aaa
+		A  dir2/meta
+		EOF
+		test_cmp status.actual.3 status.expect.3
+	)
+'
+
+test_expect_success "'git grep --exclude-standard' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		test_might_fail git --git-dir=meta \
+			grep --no-index --exclude-standard BAIT >grep.actual.4 &&
+		cat >grep.expect.4 <<-\EOF &&
+		dir1/ssubdir/meta/aaa:Data and BAIT
+		EOF
+		test_cmp grep.actual.4 grep.expect.4
+	)
+'
+
+#
+# The second set of tests (the repository is outside of the work tree)
+#
+test_expect_success "'git status' acknowledges directories 'meta' \
+if repo is not within work tree" '
+	test_might_fail rm -rf meta/ &&
+	(
+		cd repo-outside/tree &&
+		git --git-dir=../external/meta init &&
+		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all |
+			grep meta | sort >status.actual.5 &&
+		cat >status.expect.5 <<-\EOF &&
+		?? meta/bb
+		?? sub/meta/bbb
+		EOF
+		test_cmp status.actual.5 status.expect.5
+	)
+'
+
+test_expect_success "'git add -A' adds 'meta' if the repo is outside the work tree" '
+	(
+		cd repo-outside/tree &&
+		git --git-dir=../external/meta --work-tree=. add -A &&
+		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all |
+			grep meta | sort >status.actual.6 &&
+		cat >status.expect.6 <<-\EOF &&
+		A  meta/bb
+		A  sub/meta/bbb
+		EOF
+		test_cmp status.actual.6 status.expect.6
+	)
+'
+
+test_done
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v6] Add an explicit GIT_DIR to the list of excludes
  2014-06-11 23:28       ` [PATCH v6] " Pasha Bolokhov
@ 2014-06-12  6:19         ` Johannes Sixt
  2014-06-13 16:10           ` Pasha Bolokhov
  2014-06-13 16:32           ` [PATCH v7] " Pasha Bolokhov
  0 siblings, 2 replies; 10+ messages in thread
From: Johannes Sixt @ 2014-06-12  6:19 UTC (permalink / raw)
  To: Pasha Bolokhov; +Cc: pclouds, jrnieder, jnareb, git

Am 12.06.2014 01:28, schrieb Pasha Bolokhov:
> +test_expect_success "setup" '
> +	mkdir repo-inside/ &&
> +	(
> +		cd repo-inside/ &&
> +		for f in a b c d
> +		do
> +			echo "DATA" >"$f" || exit 1
> +		done &&
> +		mkdir dir1 dir1/meta &&
> +		mkdir dir1/ssubdir dir1/ssubdir/meta &&
> +		for f in e f g h
> +		do
> +			echo "MORE DATA" >"dir1/$f" || exit 1
> +		done &&
> +		echo "EVEN more Data" >dir1/meta/aa &&
> +		echo "Data and BAIT" >dir1/ssubdir/meta/aaa &&
> +		mkdir dir2
> +		echo "Not a Metadata File" >dir2/meta

&&-chain broken twice.

We already use 'mkdir -p' elsewhere; you can use it here as well to
contract several mkdir invocations.

> +		git --git-dir=meta init
> +	) &&
> +	mkdir repo-outside/ repo-outside/external repo-outside/tree &&
> +	(
> +		cd repo-outside/tree &&
> +		for f in n o p q
> +		do
> +			echo "Literal Data" >"$f" || exit 1
> +		done &&
> +		mkdir meta sub sub/meta &&
> +		echo "Sample data" >meta/bb &&
> +		echo "Stream of data" >sub/meta/bbb &&
> +		git --git-dir=../external/meta init
> +	)
> +'
> +
> +
> +#
> +# The first set of tests (the repository is inside the work tree)
> +#
> +test_expect_success "'git status' ignores the repository directory" '
> +	(
> +		cd repo-inside &&
> +		git --git-dir=meta --work-tree=. status --porcelain --untracked=all |
> +			grep meta | sort >status.actual.2 &&

Please do not place a git invocation in a pipline such that it is not
the last command; its exist status would be ignored:

		git --git-dir=meta --work-tree=. status --porcelain --untracked=all
>status.actual.2+ &&
		grep meta status.actual.2+ | sort >status.actual.2 &&

There are more cases like this later in the patch.

> +		cat >status.expect.2 <<-\EOF &&
> +		?? dir1/meta/aa
> +		?? dir1/ssubdir/meta/aaa
> +		?? dir2/meta
> +		EOF
> +		test_cmp status.actual.2 status.expect.2

It is customary to call the files 'expect' and 'actual'. Furthermore,
swap the order so that in case of a failure the diff shows how the
actual text was changed from the expected text:

		test_cmp status.expect.2 status.actual.2

> +	)
> +'
> +
> +test_expect_success "'git add -A' ignores the repository directory" '
> +	(
> +		cd repo-inside &&
> +		git --git-dir=meta --work-tree=. add -A &&
> +		git --git-dir=meta --work-tree=. status --porcelain | grep meta | sort >status.actual.3 &&
> +		cat >status.expect.3 <<-\EOF &&
> +		A  dir1/meta/aa
> +		A  dir1/ssubdir/meta/aaa
> +		A  dir2/meta
> +		EOF
> +		test_cmp status.actual.3 status.expect.3
> +	)
> +'
> +
> +test_expect_success "'git grep --exclude-standard' ignores the repository directory" '
> +	(
> +		cd repo-inside &&
> +		test_might_fail git --git-dir=meta \
> +			grep --no-index --exclude-standard BAIT >grep.actual.4 &&
> +		cat >grep.expect.4 <<-\EOF &&
> +		dir1/ssubdir/meta/aaa:Data and BAIT
> +		EOF
> +		test_cmp grep.actual.4 grep.expect.4
> +	)
> +'
> +
> +#
> +# The second set of tests (the repository is outside of the work tree)
> +#
> +test_expect_success "'git status' acknowledges directories 'meta' \
> +if repo is not within work tree" '
> +	test_might_fail rm -rf meta/ &&

How might this fail? Only if permissions are wrong, and then we do want
this to fail.

Moreover, test_*_fail helpers are intended to be used only with git
commands; we don't expect system commands to fail in unexpected ways.

> +	(
> +		cd repo-outside/tree &&
> +		git --git-dir=../external/meta init &&
> +		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all |
> +			grep meta | sort >status.actual.5 &&
> +		cat >status.expect.5 <<-\EOF &&
> +		?? meta/bb
> +		?? sub/meta/bbb
> +		EOF
> +		test_cmp status.actual.5 status.expect.5
> +	)
> +'
> +
> +test_expect_success "'git add -A' adds 'meta' if the repo is outside the work tree" '
> +	(
> +		cd repo-outside/tree &&
> +		git --git-dir=../external/meta --work-tree=. add -A &&
> +		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all |
> +			grep meta | sort >status.actual.6 &&
> +		cat >status.expect.6 <<-\EOF &&
> +		A  meta/bb
> +		A  sub/meta/bbb
> +		EOF
> +		test_cmp status.actual.6 status.expect.6
> +	)
> +'
> +
> +test_done
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6] Add an explicit GIT_DIR to the list of excludes
  2014-06-12  6:19         ` Johannes Sixt
@ 2014-06-13 16:10           ` Pasha Bolokhov
  2014-06-13 16:50             ` Junio C Hamano
  2014-06-13 16:32           ` [PATCH v7] " Pasha Bolokhov
  1 sibling, 1 reply; 10+ messages in thread
From: Pasha Bolokhov @ 2014-06-13 16:10 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Duy Nguyen, Jonathan Nieder, Jakub Narębski, Git Mailing List

>> +             test_cmp status.actual.2 status.expect.2
>
> It is customary to call the files 'expect' and 'actual'. Furthermore,
> swap the order so that in case of a failure the diff shows how the
> actual text was changed from the expected text:
>
>                 test_cmp status.expect.2 status.actual.2

So, is naming the files "status.expect.2" instead of just
"expect"/"actual" ok or not?
Those prefixes "status" etc just help sorting out where the problem
lies that causes the test to fail. But let me know if this is too
"detailed"

>
> Moreover, test_*_fail helpers are intended to be used only with git
> commands; we don't expect system commands to fail in unexpected ways.

Ok, no problem, will change that. The only thing, I saw this in other
tests, so decided to use it too. Those tests use "test_mighf_fail rm"
and "ls" seemingly without invocation of git

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v7] Add an explicit GIT_DIR to the list of excludes
  2014-06-12  6:19         ` Johannes Sixt
  2014-06-13 16:10           ` Pasha Bolokhov
@ 2014-06-13 16:32           ` Pasha Bolokhov
  1 sibling, 0 replies; 10+ messages in thread
From: Pasha Bolokhov @ 2014-06-13 16:32 UTC (permalink / raw)
  To: j6t; +Cc: pclouds, jrnieder, jnareb, git, Pasha Bolokhov

When an explicit '--git-dir' option points to a directory inside
the work tree, git treats it as if it were any other directory.
In particular, 'git status' lists it as untracked, while 'git add -A'
stages the metadata directory entirely

Add GIT_DIR to the list of excludes in a dedicated function
add_git_dir_exclude(), while checking that GIT_DIR is not just '.git'
or its basename is not '.git', in which cases it would be ignored
by default, and that GIT_DIR is inside GIT_WORK_TREE. Function
add_git_dir_exclude() is invoked at the beginning of
dir.c:setup_standard_excludes()

Although an analogous comparison of any given path against '.git'
is done in treat_path(), this does not seem to be the right place
to compare against GIT_DIR. Instead, the excludes provide an
effective mechanism of ignoring a file/directory, and adding GIT_DIR
as an exclude is equivalent to putting it into '.gitignore'. Function
setup_standard_excludes() was chosen because that is the place where
the excludes are initialized by the commands that are concerned about
excludes

Signed-off-by: Pasha Bolokhov <pasha.bolokhov@gmail.com>
---
Brush up the test -- make sure 'git' is the last command in pipelines,
compact mkdirs into 'mkdir -p', remove unnecessary 'test_might_fail'

 Documentation/technical/api-directory-listing.txt |   4 +-
 dir.c                                             |  33 ++++
 t/t2205-add-gitdir.sh                             | 187 ++++++++++++++++++++++
 3 files changed, 222 insertions(+), 2 deletions(-)
 create mode 100755 t/t2205-add-gitdir.sh

diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt
index 7f8e78d..fd4a178 100644
--- a/Documentation/technical/api-directory-listing.txt
+++ b/Documentation/technical/api-directory-listing.txt
@@ -90,8 +90,8 @@ marked. If you to exclude files, make sure you have loaded index first.
   `add_exclude()`.
 
 * To add patterns from a file (e.g. `.git/info/exclude`), call
-  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  A
-  short-hand function `setup_standard_excludes()` can be used to set
+  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  The
+  short-hand function `setup_standard_excludes()` must be used to set
   up the standard set of exclude settings.
 
 * Set options described in the Data Structure section above.
diff --git a/dir.c b/dir.c
index 797805d..3f57e34 100644
--- a/dir.c
+++ b/dir.c
@@ -1608,11 +1608,44 @@ int remove_dir_recursively(struct strbuf *path, int flag)
 	return remove_dir_recurse(path, flag, NULL);
 }
 
+static void add_git_dir_exclude(struct dir_struct *dir)
+{
+	const char *r_git, *gitdir = get_git_dir();
+	char *n_git;
+	int len;
+
+	r_git = real_path(absolute_path(gitdir));
+	n_git = xmalloc(strlen(r_git) + 1 + 1);
+	normalize_path_copy(n_git, r_git);
+	len = strlen(n_git);
+
+	/* only add it if GIT_DIR does not end with '.git' or '/.git' */
+	if (!(len >= 4 && !strcmp(n_git + len - 4, ".git") &&
+	      (len == 4 || n_git[len - 5] == '/'))) {
+		const char *worktree = get_git_work_tree();
+
+		if (!worktree ||
+		    dir_inside_of(n_git, worktree) >= 0) {
+			struct exclude_list *el = add_exclude_list(dir, EXC_CMDL,
+							"GIT_DIR setup");
+			char *reldir = worktree ? n_git + strlen(worktree) : n_git;
+
+			/* append a trailing slash to exclude directories only */
+			n_git[len] = '/';
+			n_git[len + 1] = '\0';
+			add_exclude(reldir, "", 0, el, 0);
+		}
+	}
+	free(n_git);
+}
+
 void setup_standard_excludes(struct dir_struct *dir)
 {
 	const char *path;
 	char *xdg_path;
 
+	add_git_dir_exclude(dir);
+
 	dir->exclude_per_dir = ".gitignore";
 	path = git_path("info/exclude");
 	if (!excludes_file) {
diff --git a/t/t2205-add-gitdir.sh b/t/t2205-add-gitdir.sh
new file mode 100755
index 0000000..92b925f
--- /dev/null
+++ b/t/t2205-add-gitdir.sh
@@ -0,0 +1,187 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Pasha Bolokhov
+#
+
+test_description='alternative repository path specified by --git-dir is ignored by add and status'
+
+. ./test-lib.sh
+
+#
+# Create a tree:
+#
+#	repo-inside/  repo-outside/
+#
+#
+# repo-inside:
+# 	a  b  c  d  dir1/ dir2/ [meta/]
+#
+# repo-inside/dir1:
+# 	e  f  g  h  meta/  ssubdir/
+#
+# repo-inside/dir1/meta:
+# 	aa
+#
+# repo-inside/dir1/ssubdir:
+# 	meta/
+#
+# repo-inside/dir1/ssubdir/meta:
+# 	aaa
+#
+# repo-inside/dir2:
+#	meta
+#
+#
+#
+# repo-outside:
+#	external/  tree/
+#
+# repo-outside/external:
+#	[meta/]
+#
+# repo-outside/tree:
+#	n  o  p  q  meta/  sub/
+#
+# repo-outside/tree/meta:
+#	bb
+#
+# repo-outside/tree/sub:
+#	meta/
+#
+# repo-outside/tree/sub/meta:
+#	bbb
+#
+#
+# (both of the above [meta/] denote the actual repositories)
+#
+
+#
+# First set of tests (in "repo-inside/"):
+# ---------------------------------------
+#
+# Name the repository "meta" and see whether or not "git status" includes or
+# ignores directories named "meta". Directory "meta" at the top level of
+# "repo-inside/"is the repository and appears upon the first "git init"
+#
+#
+# Second set of tests (in "repo-outside/"):
+# -----------------------------------------
+#
+# Put the work tree into "tree/" and repository into "external/meta"
+# (the latter directory appears upon the corresponding "git init").
+# The work tree again contains directories named "meta", but those ones are
+# tested not to be ignored now
+#
+
+test_expect_success "setup" '
+	mkdir repo-inside/ &&
+	(
+		cd repo-inside/ &&
+		for f in a b c d
+		do
+			echo "DATA" >"$f" || exit 1
+		done &&
+		mkdir -p dir1/meta dir1/ssubdir/meta &&
+		for f in e f g h
+		do
+			echo "MORE DATA" >"dir1/$f" || exit 1
+		done &&
+		echo "EVEN more Data" >dir1/meta/aa &&
+		echo "Data and BAIT" >dir1/ssubdir/meta/aaa &&
+		mkdir dir2 &&
+		echo "Not a Metadata File" >dir2/meta &&
+		git --git-dir=meta init
+	) &&
+	mkdir repo-outside/ repo-outside/external repo-outside/tree &&
+	(
+		cd repo-outside/tree &&
+		for f in n o p q
+		do
+			echo "Literal Data" >"$f" || exit 1
+		done &&
+		mkdir -p meta sub/meta &&
+		echo "Sample data" >meta/bb &&
+		echo "Stream of data" >sub/meta/bbb &&
+		git --git-dir=../external/meta init
+	)
+'
+
+
+#
+# The first set of tests (the repository is inside the work tree)
+#
+test_expect_success "'git status' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		git --git-dir=meta --work-tree=. status --porcelain --untracked=all >status.actual.2+ &&
+		grep meta status.actual.2+ | sort >status.actual.2 &&
+		cat >status.expect.2 <<-\EOF &&
+		?? dir1/meta/aa
+		?? dir1/ssubdir/meta/aaa
+		?? dir2/meta
+		EOF
+		test_cmp status.expect.2 status.actual.2
+	)
+'
+
+test_expect_success "'git add -A' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		git --git-dir=meta --work-tree=. add -A &&
+		git --git-dir=meta --work-tree=. status --porcelain >status.actual.3+ &&
+		grep meta status.actual.3+ | sort >status.actual.3 &&
+		cat >status.expect.3 <<-\EOF &&
+		A  dir1/meta/aa
+		A  dir1/ssubdir/meta/aaa
+		A  dir2/meta
+		EOF
+		test_cmp status.expect.3 status.actual.3
+	)
+'
+
+test_expect_success "'git grep --exclude-standard' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		test_might_fail git --git-dir=meta \
+			grep --no-index --exclude-standard BAIT >grep.actual.4 &&
+		cat >grep.expect.4 <<-\EOF &&
+		dir1/ssubdir/meta/aaa:Data and BAIT
+		EOF
+		test_cmp grep.expect.4 grep.actual.4
+	)
+'
+
+#
+# The second set of tests (the repository is outside of the work tree)
+#
+test_expect_success "'git status' acknowledges directories 'meta' \
+if repo is not within work tree" '
+	rm -rf meta/ &&
+	(
+		cd repo-outside/tree &&
+		git --git-dir=../external/meta init &&
+		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all >status.actual.5+ &&
+		grep meta status.actual.5+ | sort >status.actual.5 &&
+		cat >status.expect.5 <<-\EOF &&
+		?? meta/bb
+		?? sub/meta/bbb
+		EOF
+		test_cmp status.expect.5 status.actual.5
+	)
+'
+
+test_expect_success "'git add -A' adds 'meta' if the repo is outside the work tree" '
+	(
+		cd repo-outside/tree &&
+		git --git-dir=../external/meta --work-tree=. add -A &&
+		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all >status.actual.6+ &&
+		grep meta status.actual.6+ | sort >status.actual.6 &&
+		cat >status.expect.6 <<-\EOF &&
+		A  meta/bb
+		A  sub/meta/bbb
+		EOF
+		test_cmp status.expect.6 status.actual.6
+	)
+'
+
+test_done
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v6] Add an explicit GIT_DIR to the list of excludes
  2014-06-13 16:10           ` Pasha Bolokhov
@ 2014-06-13 16:50             ` Junio C Hamano
  2014-06-14 19:16               ` [PATCH v8] " Pasha Bolokhov
  0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2014-06-13 16:50 UTC (permalink / raw)
  To: Pasha Bolokhov
  Cc: Johannes Sixt, Duy Nguyen, Jonathan Nieder, Jakub Narębski,
	Git Mailing List

Pasha Bolokhov <pasha.bolokhov@gmail.com> writes:

>>> +             test_cmp status.actual.2 status.expect.2
>>
>> It is customary to call the files 'expect' and 'actual'. Furthermore,
>> swap the order so that in case of a failure the diff shows how the
>> actual text was changed from the expected text:
>>
>>                 test_cmp status.expect.2 status.actual.2
>
> So, is naming the files "status.expect.2" instead of just
> "expect"/"actual" ok or not?

Unless there is a compelling reason not to, just use expect/actual,
without "status." or ".<number>".  When debugging, people pass the
"-i" (and often "-v") to the script which would stop at the first
breakage.  If they can inspect the result in "actual", that is far
more pleasant than having to know that it is status.actual.43 they
have to inspect while ignoring clutters in status.actual.{1-42} that
have nothing to do with the breakage they are dealing with.

> Ok, no problem, will change that. The only thing, I saw this in other
> tests, so decided to use it too. Those tests use "test_mighf_fail rm"

"might_fail" and "must_fail" are totally different beasts.
"must_fail" is about controlled failure exit (i.e. no segfaulting
allowed) and we avoid using it on non-git things.

When you run clean-up commands without knowing if there is anythning
to clean-up, e.g. you may or may not have successfully created a
junk file and you want to make sure that file does not exist.  It
happens that "rm junk" has a convenient option "-f" to make it not
barf upon missing "junk", so you can do so with "rm -f junk" instead
of saying "test_might_fail rm junk", but "might_fail" is designed to
be useful for commands that do not have such a convenient option.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v8] Add an explicit GIT_DIR to the list of excludes
  2014-06-13 16:50             ` Junio C Hamano
@ 2014-06-14 19:16               ` Pasha Bolokhov
  0 siblings, 0 replies; 10+ messages in thread
From: Pasha Bolokhov @ 2014-06-14 19:16 UTC (permalink / raw)
  To: gitster; +Cc: j6t, pclouds, jrnieder, jnareb, git, Pasha Bolokhov

When an explicit '--git-dir' option points to a directory inside
the work tree, git treats it as if it were any other directory.
In particular, 'git status' lists it as untracked, while 'git add -A'
stages the metadata directory entirely

Add GIT_DIR to the list of excludes in a dedicated function
add_git_dir_exclude(), while checking that GIT_DIR is not just '.git'
or its basename is not '.git', in which cases it would be ignored
by default, and that GIT_DIR is inside GIT_WORK_TREE. Function
add_git_dir_exclude() is invoked at the beginning of
dir.c:setup_standard_excludes()

Although an analogous comparison of any given path against '.git'
is done in treat_path(), this does not seem to be the right place
to compare against GIT_DIR. Instead, the excludes provide an
effective mechanism of ignoring a file/directory, and adding GIT_DIR
as an exclude is equivalent to putting it into '.gitignore'. Function
setup_standard_excludes() was chosen because that is the place where
the excludes are initialized by the commands that are concerned about
excludes

Signed-off-by: Pasha Bolokhov <pasha.bolokhov@gmail.com>
---
Rename output files in the test into just 'expect' and 'actual'.
Will add documentation on the standard excludes in the later revision.

 Documentation/technical/api-directory-listing.txt |   4 +-
 dir.c                                             |  33 ++++
 t/t2205-add-gitdir.sh                             | 187 ++++++++++++++++++++++
 3 files changed, 222 insertions(+), 2 deletions(-)
 create mode 100755 t/t2205-add-gitdir.sh

diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt
index 7f8e78d..fd4a178 100644
--- a/Documentation/technical/api-directory-listing.txt
+++ b/Documentation/technical/api-directory-listing.txt
@@ -90,8 +90,8 @@ marked. If you to exclude files, make sure you have loaded index first.
   `add_exclude()`.
 
 * To add patterns from a file (e.g. `.git/info/exclude`), call
-  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  A
-  short-hand function `setup_standard_excludes()` can be used to set
+  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  The
+  short-hand function `setup_standard_excludes()` must be used to set
   up the standard set of exclude settings.
 
 * Set options described in the Data Structure section above.
diff --git a/dir.c b/dir.c
index 797805d..3f57e34 100644
--- a/dir.c
+++ b/dir.c
@@ -1608,11 +1608,44 @@ int remove_dir_recursively(struct strbuf *path, int flag)
 	return remove_dir_recurse(path, flag, NULL);
 }
 
+static void add_git_dir_exclude(struct dir_struct *dir)
+{
+	const char *r_git, *gitdir = get_git_dir();
+	char *n_git;
+	int len;
+
+	r_git = real_path(absolute_path(gitdir));
+	n_git = xmalloc(strlen(r_git) + 1 + 1);
+	normalize_path_copy(n_git, r_git);
+	len = strlen(n_git);
+
+	/* only add it if GIT_DIR does not end with '.git' or '/.git' */
+	if (!(len >= 4 && !strcmp(n_git + len - 4, ".git") &&
+	      (len == 4 || n_git[len - 5] == '/'))) {
+		const char *worktree = get_git_work_tree();
+
+		if (!worktree ||
+		    dir_inside_of(n_git, worktree) >= 0) {
+			struct exclude_list *el = add_exclude_list(dir, EXC_CMDL,
+							"GIT_DIR setup");
+			char *reldir = worktree ? n_git + strlen(worktree) : n_git;
+
+			/* append a trailing slash to exclude directories only */
+			n_git[len] = '/';
+			n_git[len + 1] = '\0';
+			add_exclude(reldir, "", 0, el, 0);
+		}
+	}
+	free(n_git);
+}
+
 void setup_standard_excludes(struct dir_struct *dir)
 {
 	const char *path;
 	char *xdg_path;
 
+	add_git_dir_exclude(dir);
+
 	dir->exclude_per_dir = ".gitignore";
 	path = git_path("info/exclude");
 	if (!excludes_file) {
diff --git a/t/t2205-add-gitdir.sh b/t/t2205-add-gitdir.sh
new file mode 100755
index 0000000..c48a845
--- /dev/null
+++ b/t/t2205-add-gitdir.sh
@@ -0,0 +1,187 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Pasha Bolokhov
+#
+
+test_description='alternative repository path specified by --git-dir is ignored by add and status'
+
+. ./test-lib.sh
+
+#
+# Create a tree:
+#
+#	repo-inside/  repo-outside/
+#
+#
+# repo-inside:
+# 	a  b  c  d  dir1/ dir2/ [meta/]
+#
+# repo-inside/dir1:
+# 	e  f  g  h  meta/  ssubdir/
+#
+# repo-inside/dir1/meta:
+# 	aa
+#
+# repo-inside/dir1/ssubdir:
+# 	meta/
+#
+# repo-inside/dir1/ssubdir/meta:
+# 	aaa
+#
+# repo-inside/dir2:
+#	meta
+#
+#
+#
+# repo-outside:
+#	external/  tree/
+#
+# repo-outside/external:
+#	[meta/]
+#
+# repo-outside/tree:
+#	n  o  p  q  meta/  sub/
+#
+# repo-outside/tree/meta:
+#	bb
+#
+# repo-outside/tree/sub:
+#	meta/
+#
+# repo-outside/tree/sub/meta:
+#	bbb
+#
+#
+# (both of the above [meta/] denote the actual repositories)
+#
+
+#
+# First set of tests (in "repo-inside/"):
+# ---------------------------------------
+#
+# Name the repository "meta" and see whether or not "git status" includes or
+# ignores directories named "meta". Directory "meta" at the top level of
+# "repo-inside/"is the repository and appears upon the first "git init"
+#
+#
+# Second set of tests (in "repo-outside/"):
+# -----------------------------------------
+#
+# Put the work tree into "tree/" and repository into "external/meta"
+# (the latter directory appears upon the corresponding "git init").
+# The work tree again contains directories named "meta", but those ones are
+# tested not to be ignored now
+#
+
+test_expect_success "setup" '
+	mkdir repo-inside/ &&
+	(
+		cd repo-inside/ &&
+		for f in a b c d
+		do
+			echo "DATA" >"$f" || exit 1
+		done &&
+		mkdir -p dir1/meta dir1/ssubdir/meta &&
+		for f in e f g h
+		do
+			echo "MORE DATA" >"dir1/$f" || exit 1
+		done &&
+		echo "EVEN more Data" >dir1/meta/aa &&
+		echo "Data and BAIT" >dir1/ssubdir/meta/aaa &&
+		mkdir dir2 &&
+		echo "Not a Metadata File" >dir2/meta &&
+		git --git-dir=meta init
+	) &&
+	mkdir repo-outside/ repo-outside/external repo-outside/tree &&
+	(
+		cd repo-outside/tree &&
+		for f in n o p q
+		do
+			echo "Literal Data" >"$f" || exit 1
+		done &&
+		mkdir -p meta sub/meta &&
+		echo "Sample data" >meta/bb &&
+		echo "Stream of data" >sub/meta/bbb &&
+		git --git-dir=../external/meta init
+	)
+'
+
+
+#
+# The first set of tests (the repository is inside the work tree)
+#
+test_expect_success "'git status' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		git --git-dir=meta --work-tree=. status --porcelain --untracked=all >actual+ &&
+		grep meta actual+ | sort >actual &&
+		cat >expect <<-\EOF &&
+		?? dir1/meta/aa
+		?? dir1/ssubdir/meta/aaa
+		?? dir2/meta
+		EOF
+		test_cmp expect actual
+	)
+'
+
+test_expect_success "'git add -A' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		git --git-dir=meta --work-tree=. add -A &&
+		git --git-dir=meta --work-tree=. status --porcelain >actual+ &&
+		grep meta actual+ | sort >actual &&
+		cat >expect <<-\EOF &&
+		A  dir1/meta/aa
+		A  dir1/ssubdir/meta/aaa
+		A  dir2/meta
+		EOF
+		test_cmp expect actual
+	)
+'
+
+test_expect_success "'git grep --exclude-standard' ignores the repository directory" '
+	(
+		cd repo-inside &&
+		test_might_fail git --git-dir=meta \
+			grep --no-index --exclude-standard BAIT >actual &&
+		cat >expect <<-\EOF &&
+		dir1/ssubdir/meta/aaa:Data and BAIT
+		EOF
+		test_cmp expect actual
+	)
+'
+
+#
+# The second set of tests (the repository is outside of the work tree)
+#
+test_expect_success "'git status' acknowledges directories 'meta' \
+if repo is not within work tree" '
+	rm -rf meta/ &&
+	(
+		cd repo-outside/tree &&
+		git --git-dir=../external/meta init &&
+		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all >actual+ &&
+		grep meta actual+ | sort >actual &&
+		cat >expect <<-\EOF &&
+		?? meta/bb
+		?? sub/meta/bbb
+		EOF
+		test_cmp expect actual
+	)
+'
+
+test_expect_success "'git add -A' adds 'meta' if the repo is outside the work tree" '
+	(
+		cd repo-outside/tree &&
+		git --git-dir=../external/meta --work-tree=. add -A &&
+		git --git-dir=../external/meta --work-tree=. status --porcelain --untracked=all >actual+ &&
+		grep meta actual+ | sort >actual &&
+		cat >expect <<-\EOF &&
+		A  meta/bb
+		A  sub/meta/bbb
+		EOF
+		test_cmp expect actual
+	)
+'
+
+test_done
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-06-14 19:17 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-04 20:15 [PATCH v5] Add an explicit GIT_DIR to the list of excludes Pasha Bolokhov
2014-06-08 10:17 ` Duy Nguyen
2014-06-10  3:18   ` Pasha Bolokhov
2014-06-11 10:48     ` Duy Nguyen
2014-06-11 23:28       ` [PATCH v6] " Pasha Bolokhov
2014-06-12  6:19         ` Johannes Sixt
2014-06-13 16:10           ` Pasha Bolokhov
2014-06-13 16:50             ` Junio C Hamano
2014-06-14 19:16               ` [PATCH v8] " Pasha Bolokhov
2014-06-13 16:32           ` [PATCH v7] " Pasha Bolokhov

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.