path_list 0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +125 -0
- data/LICENSE.txt +21 -0
- data/README.md +317 -0
- data/lib/path_list.rb +62 -0
- data/lib/path_list/backports.rb +66 -0
- data/lib/path_list/gitignore_include_rule_builder.rb +95 -0
- data/lib/path_list/gitignore_rule_builder.rb +192 -0
- data/lib/path_list/gitignore_rule_group.rb +31 -0
- data/lib/path_list/gitignore_rule_scanner.rb +85 -0
- data/lib/path_list/global_gitignore.rb +50 -0
- data/lib/path_list/matchers/allow_any_dir.rb +35 -0
- data/lib/path_list/matchers/allow_path_regexp.rb +45 -0
- data/lib/path_list/matchers/ignore_path_regexp.rb +45 -0
- data/lib/path_list/matchers/shebang_regexp.rb +46 -0
- data/lib/path_list/matchers/unmatchable.rb +31 -0
- data/lib/path_list/matchers/within_dir.rb +54 -0
- data/lib/path_list/path_regexp_builder.rb +78 -0
- data/lib/path_list/patterns.rb +33 -0
- data/lib/path_list/relative_candidate.rb +20 -0
- data/lib/path_list/root_candidate.rb +56 -0
- data/lib/path_list/rule_builder.rb +42 -0
- data/lib/path_list/rule_group.rb +42 -0
- data/lib/path_list/rule_groups.rb +59 -0
- data/lib/path_list/version.rb +5 -0
- data/lib/path_list/walkers/file_system.rb +45 -0
- data/lib/path_list/walkers/gitignore_collecting_file_system.rb +47 -0
- metadata +198 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 91d6f384f20b71300e57606743061284dc17782a28cea3526ca68cc27787cc62
|
4
|
+
data.tar.gz: 355fd59a3a051fab5408d1fb3c7533d869c56b2619384dd60cfc6f688f44b6e5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 67ff7ebb50d8a66ac2305f5bf3ba911af59fce623313f4a2868cdee18445bdf3e21a6445ddb3b5ebfcd0c80accedfa2ada5fb017a156b7846367cfd0ca936cda
|
7
|
+
data.tar.gz: 7b558aaa6c071d63122c29238fb1ae9742d21f3c49171762f3eee94d6d5e45d90e6d6b2e7edf2d4afdc67ac8c86d7db19e4e83f5d1b9e76e064416e234c8e2f5
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# v0.16.0
|
2
|
+
- Remove relative: true/false, always return relative paths like git does, its the only way i've ever used this gem
|
3
|
+
- Remove follow_symlinks: true/false. it's inaccuurately named and unnecessary
|
4
|
+
- relative paths to allowed? are expanded relative to the current dir not the PathList.root dir.
|
5
|
+
- each starts at the current directory, or optionally a given directory
|
6
|
+
- rename gem to path_list with everything in the constant PathList. I've renamed the gem because there's going to be a LOT of api changes soon.
|
7
|
+
|
8
|
+
# v0.15.2
|
9
|
+
- Updated methods with multiple `_` arguments to have different names to make sorbet happy
|
10
|
+
|
11
|
+
# v0.15.1
|
12
|
+
- Updated dependencies to allow running on ruby 3.0.0.preview1
|
13
|
+
|
14
|
+
# v0.15.0
|
15
|
+
- fixed a handful of character class edge cases to match git behavior
|
16
|
+
- mostly ranges with - or / as one end of the range
|
17
|
+
- major refactoring of the regexp builder that shouldn't have any behaviour implications but should make development easier (e.g. seeing those unhandled edge cases).
|
18
|
+
- improved speed of repos with many sub-gitignore files
|
19
|
+
- mentioned submodules & sparse checkout in the readme as yet another thing git does that this project doesn't because submodule details are hidden in the git index.
|
20
|
+
|
21
|
+
# v0.14.0
|
22
|
+
- significant performance improvements ~50% faster
|
23
|
+
- add `PathList#to_proc` for no good reason
|
24
|
+
|
25
|
+
# v0.13.0
|
26
|
+
- Attempt to improve documentation structure
|
27
|
+
- Remove `gitignore: true` raising `Errno::ENOENT` if root:/.gitignore didn't exist. I can't think of a use. Now `gitignore: true` is just the default behaviour.
|
28
|
+
- Don't ignore `.git` if `gitignore: false`.
|
29
|
+
|
30
|
+
# v0.12.1
|
31
|
+
- Reads all relevant git config files when finding a global .gitignore
|
32
|
+
|
33
|
+
# v0.12.0
|
34
|
+
- Reads all relevant gitignore files (nested .gitignore files, global .gitignore referred to in .gitconfig, and .git/info/exclude)
|
35
|
+
|
36
|
+
# v0.11.0
|
37
|
+
- major performance improvement (use regexp rather than fnmatch)
|
38
|
+
- optionally pass directory: and content: into allowed? if these are already loaded.
|
39
|
+
|
40
|
+
# v0.10.2
|
41
|
+
- add PathList#=== as an alias for PathList#allowed? so that PathList objects can be used for case statements.
|
42
|
+
- Fix shebangs in non-pwd-root situations
|
43
|
+
|
44
|
+
# v0.10.1
|
45
|
+
- Add option to follow symlinks (turns out i needed it)
|
46
|
+
- performance improvements
|
47
|
+
|
48
|
+
# v0.10.0
|
49
|
+
- patterns with middle slashes are anchored to the root (like the gitignore documentation, now that it more clearly explains)
|
50
|
+
- new shebang pattern (#!:), the previous version was extremely janky.
|
51
|
+
- now you can ignore by shebang pattern
|
52
|
+
- symlinks aren't followed when deciding if a path is a directory or not (this now matches git)
|
53
|
+
- documentation improvements
|
54
|
+
- root can be given as a path relative to PWD
|
55
|
+
- includes with 'a/**/d' now matches a/b/c/d properly
|
56
|
+
|
57
|
+
# v0.9.0
|
58
|
+
- speed improvements, which may break things (Specifically, only using relative paths internally, is about 30% faster (depending on root depth))
|
59
|
+
- using a `ignore_files:` or `include_files:` that are outside the `root: (default $PWD)` will now raise an error.
|
60
|
+
- remove deprecated `gitignore:` a path (e.g. `gitignore: '/path/to/gitignore'`). please use `gitignore: false, ignore_files: '/path/to/gitignore'` instead.
|
61
|
+
|
62
|
+
# v0.8.3
|
63
|
+
- fix `ignore_rules` not matching directories when using `include_shebangs:`
|
64
|
+
|
65
|
+
# v0.8.2
|
66
|
+
- fix `include_rules` not matching filenames with no extension when using `include_shebangs:`
|
67
|
+
|
68
|
+
# v0.8.1
|
69
|
+
- `include_shebangs:` can be given non array value
|
70
|
+
|
71
|
+
# v0.8.0
|
72
|
+
- drop support for ruby 2.3. My plan is to only support supported ruby versions
|
73
|
+
- add coverage to the pipeline. removed some methods, added some tests, and now we have 100% test coverage
|
74
|
+
- deprecate using `gitignore: '/path/to/gitignore'`. please use `gitignore: false, ignore_files: '/path/to/gitignore'` instead.
|
75
|
+
|
76
|
+
# v0.7.0
|
77
|
+
- add `include_shebangs:` which filters by shebangs
|
78
|
+
|
79
|
+
# v0.6.0
|
80
|
+
- nicer argv handling
|
81
|
+
- add `argv_rules:` option, which resolves paths and considers everything that doesn't start with a `*` to start with a `/`
|
82
|
+
- combine the different includes methods and files using AND
|
83
|
+
- slightly more realistic version comparison just in case someone releases ruby 2.10
|
84
|
+
- can be run with --disable-gems
|
85
|
+
- `.allowed?` now more exactly matches `.each`, it returns false for directories and unreadable files.
|
86
|
+
|
87
|
+
# v0.5.2
|
88
|
+
- performance improvements
|
89
|
+
|
90
|
+
# v0.5.1
|
91
|
+
- restore `.allowed?`. now i have tests for it. oops
|
92
|
+
|
93
|
+
# v0.5.0
|
94
|
+
- remove deprecated `:rules` and `:files` arguments
|
95
|
+
- ! is now evaluated in sequence for include_rules
|
96
|
+
- it's a big refactor, sorry if i broke something
|
97
|
+
- some performance improvements
|
98
|
+
|
99
|
+
# v0.4.1
|
100
|
+
- oops i did a regexp wrong
|
101
|
+
|
102
|
+
# v0.4.0
|
103
|
+
- include_rules support
|
104
|
+
- to make room for this, `:rules` and `:files` keyword arguments are deprecated.
|
105
|
+
Please use `:ignore_rules` and `:ignore_files` instead.
|
106
|
+
|
107
|
+
# v0.3.3
|
108
|
+
- some performance improvements. maybe
|
109
|
+
|
110
|
+
# v0.3.2
|
111
|
+
- handle soft links to nowhere
|
112
|
+
|
113
|
+
# v0.3.1
|
114
|
+
- upgrade rubocop version requirement to avoid github security warning
|
115
|
+
|
116
|
+
# v0.3.0
|
117
|
+
- Supports 2.3 - 2.6
|
118
|
+
|
119
|
+
# v0.2.0
|
120
|
+
- Considers rules relative to the location of the gitignore file instead of just relative to PWD
|
121
|
+
- Can override the path to the gitignore file, using `PathList.new(gitignore: path)`
|
122
|
+
- Mention PathList#allowed? in the documentation.
|
123
|
+
|
124
|
+
# v0.1.0
|
125
|
+
Initial Release
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Dana Sherson
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,317 @@
|
|
1
|
+
# PathList
|
2
|
+
|
3
|
+
# This is undergoing a major API redesign and when i'm done it'll be 1.0.0, please pin the exact version 0.whatever number in your gemfile
|
4
|
+
|
5
|
+
[](https://travis-ci.com/robotdana/path_list)
|
6
|
+
[](https://rubygems.org/gems/path_list)
|
7
|
+
|
8
|
+
This started as a way to quickly and natively ruby-ly parse gitignore files and find matching files.
|
9
|
+
It's now gained an equivalent includes file functionality, ARGV awareness, and some shebang matching, while still being extremely fast, to be a one-stop file-list for your linter.
|
10
|
+
|
11
|
+
Filter a directory tree using a .gitignore file. Recognises all of the [gitignore rules](https://www.git-scm.com/docs/gitignore#_pattern_format)
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
PathList.new.sort == `git ls-files`.split("\n").sort
|
15
|
+
```
|
16
|
+
|
17
|
+
## Features
|
18
|
+
|
19
|
+
- Fast (faster than using `` `git ls-files`.split("\n") `` for small repos (because it avoids the overhead of ``` `` ```))
|
20
|
+
- Supports ruby 2.4-3.0.0.preview1 & jruby
|
21
|
+
- supports all [gitignore rule patterns](https://git-scm.com/docs/gitignore#_pattern_format)
|
22
|
+
- doesn't require git to be installed
|
23
|
+
- supports a gitignore-esque "include" patterns. ([`include_rules:`](#include_rules)/[`include_files:`](#include_files))
|
24
|
+
- supports an expansion of include patterns, expanding and anchoring paths ([`argv_rules:`](#argv_rules))
|
25
|
+
- supports [matching by shebang](#shebang_rules) rather than filename for extensionless files: `#!:`
|
26
|
+
- reads .gitignore in all subdirectories
|
27
|
+
- reads .git/info/excludes
|
28
|
+
- reads the global gitignore file mentioned in your git config
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
Add this line to your application's Gemfile:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
gem 'path_list'
|
36
|
+
```
|
37
|
+
|
38
|
+
And then execute:
|
39
|
+
```sh
|
40
|
+
$ bundle
|
41
|
+
```
|
42
|
+
Or install it yourself as:
|
43
|
+
```sh
|
44
|
+
$ gem install path_list
|
45
|
+
```
|
46
|
+
|
47
|
+
## Usage
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
PathList.new.each { |file| puts "#{file} is not ignored by the .gitignore file" }
|
51
|
+
```
|
52
|
+
|
53
|
+
### `#each`, `#map` etc
|
54
|
+
|
55
|
+
This yields paths that are _not_ ignored by the gitignore, i.e. the paths that would be returned by `git ls-files`.
|
56
|
+
|
57
|
+
A PathList instance is an Enumerable and responds to all Enumerable methods:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
PathList.new.to_a
|
61
|
+
PathList.new.map { |file| file.upcase }
|
62
|
+
```
|
63
|
+
|
64
|
+
Like other enumerables, `PathList#each` can return an enumerator:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
PathList.new.each.with_index { |file, index| puts "#{file}#{index}" }
|
68
|
+
```
|
69
|
+
|
70
|
+
**Warning: Do not change directory (e.g. `Dir.chdir`) in the block.**
|
71
|
+
|
72
|
+
### `#allowed?`
|
73
|
+
|
74
|
+
To check if a single path is allowed, use
|
75
|
+
```ruby
|
76
|
+
PathList.new.allowed?('relative/path')
|
77
|
+
PathList.new.allowed?('./relative/path')
|
78
|
+
PathList.new.allowed?('/absolute/path')
|
79
|
+
PathList.new.allowed?('~/home/path')
|
80
|
+
```
|
81
|
+
|
82
|
+
Relative paths will be considered relative to the [`root:`](#root) directory, not the current directory.
|
83
|
+
|
84
|
+
This is aliased as `===` so you can use a PathList instance in case statements.
|
85
|
+
```ruby
|
86
|
+
case my_path
|
87
|
+
when PathList.new
|
88
|
+
puts(my_path)
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
It's recommended to save the PathList instance to a variable to avoid having to read and parse the gitignore file and gitconfig files repeatedly.
|
93
|
+
|
94
|
+
See [Optimising allowed](#optimising_allowed) for ways to make this even faster
|
95
|
+
|
96
|
+
**Note: A file must exist at that path and not be a directory for it to be considered allowed.**
|
97
|
+
Essentially it can be thought of as `` `git ls-files`.include?(path) `` but much faster.
|
98
|
+
This excludes all directories and all possible path names that don't exist.
|
99
|
+
|
100
|
+
### `root:`
|
101
|
+
|
102
|
+
**Default: Dir.pwd ($PWD, the current working directory)**
|
103
|
+
|
104
|
+
This directory is used for:
|
105
|
+
- the location of `.git/core/exclude`
|
106
|
+
- the ancestor of all non-global [automatically loaded `.gitignore` files](#gitignore_false)
|
107
|
+
- the root directory for array rules ([`ignore_rules:`](#ignore_rules), [`include_rules:`](#include_rules), [`argv_rules:`](#argv_rules)) containing `/`
|
108
|
+
- the path that yielded paths are relative to
|
109
|
+
- the ancestor of all paths yielded by [`#each`](#each_map_etc)
|
110
|
+
- the path that [`#allowed?`](#allowed) considers relative paths relative to
|
111
|
+
- the ancestor of all [`include_files:`](#include_files) and [`ignore_files:`](#ignore_files)
|
112
|
+
|
113
|
+
To use a different directory:
|
114
|
+
```ruby
|
115
|
+
PathList.new(root: '/absolute/path/to/root').to_a
|
116
|
+
PathList.new(root: '../relative/path/to/root').to_a
|
117
|
+
```
|
118
|
+
|
119
|
+
A relative root will be found relative to the current working directory when the PathList instance is initialized, and that will be the last time the current working directory is relevant.
|
120
|
+
|
121
|
+
**Note: Changes to the current working directory (e.g. with `Dir.chdir`), after initialising a PathList instance, will _not_ affect the PathList instance. `root:` will always be what it was when the instance was initialized, even as a default value.**
|
122
|
+
|
123
|
+
### `gitignore:`
|
124
|
+
|
125
|
+
**Default: true**
|
126
|
+
|
127
|
+
When `gitignore: true`: the .gitignore file in the [`root:`](#root) directory is loaded, plus any .gitignore files in its subdirectories, the global git ignore file as described in git config, and .git/info/exclude. `.git` directories are also excluded to match the behaviour of `git ls-files`.
|
128
|
+
When `gitignore: false`: no ignore files or git config files are automatically read, and `.git` will not be automatically excluded.
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
PathList.new(gitignore: false).to_a
|
132
|
+
```
|
133
|
+
|
134
|
+
### `ignore_files:`
|
135
|
+
|
136
|
+
**This is a list of files in the gitignore format to parse and match paths against, not a list of files to ignore** If you want an array of files use [`ignore_rules:`](#ignore_rules)
|
137
|
+
|
138
|
+
Additional gitignore-style files, either as a path or an array of paths.
|
139
|
+
|
140
|
+
You can specify other gitignore-style files to ignore as well.
|
141
|
+
Missing files will raise an `Errno::ENOENT` error.
|
142
|
+
|
143
|
+
Relative paths are relative to the [`root:`](#root) directory.
|
144
|
+
Absolute paths also need to be within the [`root:`](#root) directory.
|
145
|
+
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
PathList.new(ignore_files: 'relative/path/to/my/ignore/file').to_a
|
149
|
+
PathList.new(ignore_files: ['/absolute/path/to/my/ignore/file', '/and/another']).to_a
|
150
|
+
```
|
151
|
+
|
152
|
+
Note: the location of the files will affect rules beginning with or containing `/`.
|
153
|
+
|
154
|
+
To avoid raising `Errno::ENOENT` when the file doesn't exist:
|
155
|
+
```ruby
|
156
|
+
PathList.new(ignore_files: ['/ignore/file'].select { |f| File.exist?(f) }).to_a
|
157
|
+
```
|
158
|
+
|
159
|
+
### `ignore_rules:`
|
160
|
+
|
161
|
+
This can be a string, or an array of strings, and multiline strings can be used with one rule per line.
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
PathList.new(ignore_rules: '.DS_Store').to_a
|
165
|
+
PathList.new(ignore_rules: ['.git', '.gitkeep']).to_a
|
166
|
+
PathList.new(ignore_rules: ".git\n.gitkeep").to_a
|
167
|
+
```
|
168
|
+
|
169
|
+
These rules use the [`root:`](#root) argument to resolve rules containing `/`.
|
170
|
+
|
171
|
+
### `include_files:`
|
172
|
+
|
173
|
+
**This is an array of files in the gitignore format to parse and match paths against, not a list of files to include.** If you want an array of files use [`include_rules:`](#include_rules).
|
174
|
+
|
175
|
+
Building on the gitignore format, PathList also accepts rules to include matching paths (rather than ignoring them).
|
176
|
+
A rule matching a directory will include all descendants of that directory.
|
177
|
+
|
178
|
+
These rules can be provided in files either as absolute or relative paths, or an array of paths.
|
179
|
+
Relative paths are relative to the [`root:`](#root) directory.
|
180
|
+
Absolute paths also need to be within the [`root:`](#root) directory.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
PathList.new(include_files: 'my_include_file').to_a
|
184
|
+
PathList.new(include_files: ['/absolute/include/file', './relative/include/file']).to_a
|
185
|
+
```
|
186
|
+
|
187
|
+
Missing files will raise an `Errno::ENOENT` error.
|
188
|
+
|
189
|
+
To avoid raising `Errno::ENOENT` when the file doesn't exist:
|
190
|
+
```ruby
|
191
|
+
PathList.new(include_files: ['include/file'].select { |f| File.exist?(f) }).to_a
|
192
|
+
```
|
193
|
+
|
194
|
+
**Note: All paths checked must not be excluded by any ignore files AND each included by include file separately AND the [`include_rules:`](#include_rules) AND the [`argv_rules:`](#argv_rules). see [Combinations](#combinations) for solutions to using OR.**
|
195
|
+
|
196
|
+
### `include_rules:`
|
197
|
+
|
198
|
+
Building on the gitignore format, PathList also accepts rules to include matching paths (rather than ignoring them).
|
199
|
+
A rule matching a directory will include all descendants of that directory.
|
200
|
+
|
201
|
+
This can be a string, or an array of strings, and multiline strings can be used with one rule per line.
|
202
|
+
```ruby
|
203
|
+
PathList.new(include_rules: %w{my*rule /and/another !rule}, gitignore: false).to_a
|
204
|
+
```
|
205
|
+
|
206
|
+
Rules use the [`root:`](#root) argument to resolve rules containing `/`.
|
207
|
+
|
208
|
+
**Note: All paths checked must not be excluded by any ignore files AND each included by [include file](#include_files) separately AND the `include_rules:` AND the [`argv_rules:`](#argv_rules). see [Combinations](#combinations) for solutions to using OR.**
|
209
|
+
|
210
|
+
### `argv_rules:`
|
211
|
+
This is like [`include_rules:`](#include_rules) with additional features meant for dealing with humans and `ARGV` values.
|
212
|
+
|
213
|
+
It expands rules that are absolute paths, and paths beginning with `~`, `../` and `./` (with and without `!`).
|
214
|
+
This means rules beginning with `/` are absolute. Not relative to [`root:`](#root).
|
215
|
+
|
216
|
+
Additionally it assumes all rules are relative to the [`root:`](#root) directory (after resolving absolute paths) unless they begin with `*` (or `!*`).
|
217
|
+
|
218
|
+
This can be a string, or an array of strings, and multiline strings can be used with one rule per line.
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
PathList.new(argv_rules: ['./a/pasted/path', '/or/a/path/from/stdin', 'an/argument', '*.txt']).to_a
|
222
|
+
```
|
223
|
+
|
224
|
+
**Warning: it will *not* expand e.g. `/../` in the middle of a rule that doesn't begin with any of `~`,`../`,`./`,`/`.**
|
225
|
+
|
226
|
+
**Note: All paths checked must not be excluded by any ignore files AND each included by [include file](#include_files) separately AND the [`include_rules:`](#include_rules) AND the `argv_rules:`. see [Combinations](#combinations) for solutions to using OR.**
|
227
|
+
|
228
|
+
### shebang rules
|
229
|
+
|
230
|
+
Sometimes you need to match files by their shebang/hashbang/etc rather than their path or filename
|
231
|
+
|
232
|
+
Rules beginning with `#!:` will match whole words in the shebang line of extensionless files.
|
233
|
+
e.g.
|
234
|
+
```gitignore
|
235
|
+
#!:ruby
|
236
|
+
```
|
237
|
+
will match shebang lines: `#!/usr/bin/env ruby` or `#!/usr/bin/ruby` or `#!/usr/bin/ruby -w`
|
238
|
+
|
239
|
+
e.g.
|
240
|
+
```gitignore
|
241
|
+
#!:bin/ruby
|
242
|
+
```
|
243
|
+
will match `#!/bin/ruby` or `#!/usr/bin/ruby` or `#!/usr/bin/ruby -w`
|
244
|
+
Only exact substring matches are available, There's no special handling of * or / or etc.
|
245
|
+
|
246
|
+
These rules can be supplied any way regular rules are, whether in a .gitignore file or files mentioned in [`include_files:`](#include_files) or [`ignore_files:`](#ignore_files) or [`include_rules:`](#include_rules) or [`ignore_rules:`](#ignore_rules) or [`argv_rules:`](#argv_rules)
|
247
|
+
```ruby
|
248
|
+
PathList.new(include_rules: ['*.rb', '#!:ruby']).to_a
|
249
|
+
PathList.new(ignore_rules: ['*.sh', '#!:sh', '#!:bash', '#!:zsh']).to_a
|
250
|
+
```
|
251
|
+
|
252
|
+
**Note: git considers rules like this as a comment and will ignore them.**
|
253
|
+
|
254
|
+
## Combinations
|
255
|
+
|
256
|
+
In the simplest case a file must be allowed by each ignore file, each include file, and each array of rules. That is, they are combined using `AND`.
|
257
|
+
|
258
|
+
To combine files using `OR`, that is, a file may be matched by either file it doesn't have to be referred to in both:
|
259
|
+
provide the files as strings to [`include_rules:`](#include_rules) or [`ignore_rules:`](#ignore_rules)
|
260
|
+
```ruby
|
261
|
+
PathList.new(include_rules: [File.read('/my/path'), File.read('/another/path')])).to_a
|
262
|
+
```
|
263
|
+
This does unfortunately lose the file path as the root for rules containing `/`.
|
264
|
+
If that's important, combine the files in the file system and use [`include_files:`](#include_files) or [`ignore_files:`](#ignore_files) as normal.
|
265
|
+
|
266
|
+
To use the additional `ARGV` handling of [`argv_rules:`](#argv_rules) on a file, read the file into the array.
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
PathList.new(argv_rules: ["my/rule", File.read('/my/path')]).to_a
|
270
|
+
```
|
271
|
+
|
272
|
+
This does unfortunately lose the file path as the root `/` and there is no workaround except setting the [`root:`](#root) for the whole PathList instance.
|
273
|
+
|
274
|
+
### optimising #allowed?
|
275
|
+
|
276
|
+
To avoid unnecessary calls to the filesystem, if your code already knows whether or not it's a directory, or if you're checking shebangs and you have already read the content of the file: use
|
277
|
+
```ruby
|
278
|
+
PathList.new.allowed?('relative/path', directory: false, content: "#!/usr/bin/ruby\n\nputs 'ok'\n")
|
279
|
+
```
|
280
|
+
This is not required, and if PathList does have to go to the filesystem for this information it's well optimised to only read what is necessary.
|
281
|
+
|
282
|
+
## Limitations
|
283
|
+
- Doesn't know what to do if you change the current working directory inside the [`PathList#each`](#each_map_etc) block.
|
284
|
+
So don't do that.
|
285
|
+
|
286
|
+
(It does handle changing the current working directory between [`PathList#allowed?`](#allowed) calls)
|
287
|
+
- PathList always matches patterns case-insensitively. (git varies by filesystem).
|
288
|
+
- PathList always outputs paths as literal UTF-8 characters. (git depends on your core.quotepath setting but by default outputs non ascii paths with octal escapes surrounded by quotes).
|
289
|
+
- Because git looks at its own index objects and PathList looks at the file system there may be some differences between PathList and `git ls-files`. To avoid these differences you may want to use the [`git_ls`](https://github.com/robotdana/git_ls) gem instead
|
290
|
+
- Tracked files that were committed before the matching ignore rule was committed will be returned by `git ls-files`, but not by PathList.
|
291
|
+
- Untracked files will be returned by PathList, but not by `git ls-files`
|
292
|
+
- Deleted files whose deletions haven't been committed will be returned by `git ls-files`, but not by PathList
|
293
|
+
- On a case insensitive file system, with files that differ only by case, `git ls-files` will include all case variations, while PathList will only include whichever variation git placed in the file system.
|
294
|
+
- PathList is unaware of submodules and just treats them like regular directories. For example: `git ls-files --recurse-submodules` won't use the parent repo's gitignore on a submodule, while PathList doesn't know it's a submodule and will.
|
295
|
+
- PathList will only return the files actually on the file system when using `git sparse-checkout`.
|
296
|
+
|
297
|
+
## Contributing
|
298
|
+
|
299
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/robotdana/path_list.
|
300
|
+
|
301
|
+
Some tools that may help:
|
302
|
+
|
303
|
+
- `bin/setup`: install development dependencies
|
304
|
+
- `bundle exec rspec`: run all tests
|
305
|
+
- `bundle exec rake`: run all tests and linters
|
306
|
+
- `bin/console`: open a `pry` console with everything required for experimenting
|
307
|
+
- `bin/ls [argv_rules]`: the equivalent of `git ls-files`
|
308
|
+
- `bin/prof/ls [argv_rules]`: ruby-prof report for `bin/ls`
|
309
|
+
- `bin/prof/parse [argv_rules]`: ruby-prof report for parsing root and global gitignore files and any arguments.
|
310
|
+
- `bin/time [argv_rules]`: the average time for 30 runs of `bin/ls`<br>
|
311
|
+
This repo is too small to stress bin/time more than 0.01s, switch to a large repo and find the average time before and after changes.
|
312
|
+
- `bin/compare`: compare the speed and output of PathList and `git ls-files`.
|
313
|
+
(suppressing differences that are because of known [limitations](#limitations))
|
314
|
+
|
315
|
+
## License
|
316
|
+
|
317
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|