Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The pattern in the subdirectory gitignore is not correctly excluded #146

Open
sounisi5011 opened this issue Jun 22, 2020 · 2 comments
Open

Comments

@sounisi5011
Copy link

file structure:

.
├── dir
│   ├── .gitignore
│   ├── bar.log
│   └── subdir
│       └── baz.log
└── foo.log

./dir/.gitignore:

*.log

List of files to be excluded by git:

$ git check-ignore ./foo.log ./dir/bar.log ./dir/subdir/baz.log
./dir/bar.log
./dir/subdir/baz.log

If globby works correctly, only the foo.log file should be output:

const globby = require('globby');

(async () => {
  const paths = await globby(['**/*.log'], { gitignore: true });
  console.log(paths);
  // expected: [ 'foo.log' ]
})();

However, globby@11.0.1 outputs like this:

[ 'foo.log', 'dir/subdir/baz.log' ]

The file dir/subdir/baz.log is not excluded!


When globby@11.0.1 parses the .gitignore in a subdirectory, it adds the path of the parent to the beginning of each rule:

https://github.com/sindresorhus/globby/blob/v11.0.1/gitignore.js#L18-L24

So, internally, globby@11.0.1 has changed the contents of the ./dir/.gitignore file to look like this:

- *.log
+ dir/*.log

Therefore, you can avoid this problem by modifying the contents of the ./dir/.gitignore file as follows:

**/*.log

However, this writing style is redundant. Most projects will probably be written in the *.log style.

I believe this is a bug that should be fixed.

@sounisi5011
Copy link
Author

According to .gitignore spec 2.22.1:

  • The slash / is used as the directory separator. Separators may occur at the beginning, middle or end of the .gitignore search pattern.
  • If there is a separator at the beginning or middle (or both) of the pattern, then the pattern is relative to the directory level of the particular .gitignore file itself. Otherwise the pattern may also match at any level below the .gitignore level.
  • For example, a pattern doc/frotz/ matches doc/frotz directory, but not a/doc/frotz directory; however frotz/ matches frotz and a/frotz that is a directory (all paths are relative from the .gitignore file).

A patch of code that conforms to this specification is as follows:

 const mapGitIgnorePatternTo = base => ignore => {
+	const isSubLevelMatch = /^[^/]+\/?$/.test(ignore);
+
 	if (ignore.startsWith('!')) {
+		if (isSubLevelMatch) {
+			return '!' + path.posix.join(base, '**', ignore.slice(1));
+		}
 		return '!' + path.posix.join(base, ignore.slice(1));
 	}
 
+	if (isSubLevelMatch) {
+		return path.posix.join(base, '**', ignore);
+	}
 	return path.posix.join(base, ignore);
 };

@sounisi5011
Copy link
Author

Is there any progress on this?
It's been a year since I reported this bug, and it still doesn't seem to have been fixed.

globby/gitignore.js

Lines 18 to 24 in c1a3b32

const mapGitIgnorePatternTo = base => ignore => {
if (ignore.startsWith('!')) {
return '!' + path.posix.join(base, ignore.slice(1));
}
return path.posix.join(base, ignore);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant