globby 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +1 -1
- data/README.md +28 -5
- data/lib/globby.rb +43 -44
- data/lib/globby/glob.rb +89 -0
- data/spec/gitignore_spec.rb +100 -0
- data/spec/globby_spec.rb +48 -120
- metadata +6 -4
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,15 +1,23 @@
|
|
1
1
|
# globby
|
2
2
|
|
3
|
-
globby is a [
|
3
|
+
globby is a [`.gitignore`](http://www.kernel.org/pub/software/scm/git/docs/gitignore.html)-compatible
|
4
|
+
file globber for ruby.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Put `gem 'globby'` in your Gemfile.
|
4
9
|
|
5
10
|
## Usage
|
6
11
|
|
7
|
-
Globby.
|
12
|
+
Globby.select(rules) # all files matched by the rules
|
13
|
+
Globby.reject(rules) # all other files
|
8
14
|
|
9
15
|
### An example:
|
10
16
|
|
11
17
|
> rules = File.read('.gitignore').split(/\n/)
|
12
|
-
|
18
|
+
-> ["Gemfile.lock", "doc", "*.gem"]
|
19
|
+
|
20
|
+
> pp Globby.select(rules)
|
13
21
|
["Gemfile.lock",
|
14
22
|
"doc/Foreigner.html",
|
15
23
|
"doc/Foreigner/Adapter.html",
|
@@ -26,9 +34,24 @@ globby is a [.gitignore](http://www.kernel.org/pub/software/scm/git/docs/gitigno
|
|
26
34
|
with those files.
|
27
35
|
* You're writing a library/tool that will have its own list of ignored/tracked
|
28
36
|
files. My use case is for an I18n library that extracts strings from ruby
|
29
|
-
files... I need to provide users a nice configurable way to
|
37
|
+
files... I need to provide users a nice configurable way to blacklist given
|
30
38
|
files/directories/patterns.
|
31
39
|
|
40
|
+
## Compatibility Notes
|
41
|
+
|
42
|
+
globby is compatible with `.gitignore` rules; it respects negated patterns, and
|
43
|
+
ignores comments or empty patterns. That said, it supports some things that may
|
44
|
+
or may not work in your version of git. These platform-dependent `.gitignore`
|
45
|
+
behaviors are platform independent in globby and can always be used:
|
46
|
+
|
47
|
+
* Recursive wildcards à la ant/zsh/ruby. `**` matches directories recursively.
|
48
|
+
* [glob(7)](https://www.kernel.org/doc/man-pages/online/pages/man7/glob.7.html)-style
|
49
|
+
bracket expressions, i.e. character classes, ranges, complementation, named
|
50
|
+
character classes, collating symbols and equivalence class expressions. Note
|
51
|
+
that the syntax for some of these is slightly different than what you would
|
52
|
+
find in regular expressions. Refer to [the documentation](https://www.kernel.org/doc/man-pages/online/pages/man7/glob.7.html)
|
53
|
+
for more info.
|
54
|
+
|
32
55
|
## License
|
33
56
|
|
34
|
-
Copyright (c)
|
57
|
+
Copyright (c) 2013 Jon Jensen, released under the MIT license
|
data/lib/globby.rb
CHANGED
@@ -1,54 +1,53 @@
|
|
1
1
|
require 'set'
|
2
|
+
require '../globby/lib/globby/glob'
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
result.subtract matches_for(pattern[1..-1])
|
13
|
-
else
|
14
|
-
result.merge matches_for(pattern)
|
4
|
+
module Globby
|
5
|
+
class << self
|
6
|
+
def select(patterns, source = get_files_and_dirs, result = {:files => Set.new, :dirs => Set.new})
|
7
|
+
evaluate_patterns(patterns, source, result)
|
8
|
+
|
9
|
+
if result[:dirs] && result[:dirs].size > 0
|
10
|
+
# now go merge/subtract files under directories
|
11
|
+
dir_patterns = result[:dirs].map{ |dir| "/#{dir}**" }
|
12
|
+
evaluate_patterns(dir_patterns, {:files => source[:files]}, result)
|
15
13
|
end
|
16
|
-
end
|
17
|
-
result.to_a.sort
|
18
|
-
end
|
19
|
-
|
20
|
-
def matches_for(pattern)
|
21
|
-
return [] unless pattern = normalize(pattern)
|
22
|
-
expects_dir = pattern.sub!(/\/\z/, '')
|
23
14
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
15
|
+
result[:files].to_a.sort
|
16
|
+
end
|
17
|
+
|
18
|
+
def reject(patterns = [])
|
19
|
+
source = get_files_and_dirs
|
20
|
+
(source[:files] - select(patterns, source)).sort
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def evaluate_patterns(patterns, source, result)
|
26
|
+
patterns.each do |pattern|
|
27
|
+
next unless pattern =~ /\A[^#]/
|
28
|
+
evaluate_pattern pattern, source, result
|
32
29
|
end
|
33
30
|
end
|
34
|
-
result
|
35
|
-
end
|
36
31
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
32
|
+
def evaluate_pattern(pattern, source, result)
|
33
|
+
glob = Globby::Glob.new(pattern)
|
34
|
+
method, candidates = glob.inverse? ?
|
35
|
+
[:subtract, result] :
|
36
|
+
[:merge, source]
|
37
|
+
|
38
|
+
dir_matches = glob.match(candidates[:dirs])
|
39
|
+
file_matches = []
|
40
|
+
file_matches = glob.match(candidates[:files]) unless glob.directory? || glob.exact_match? && !dir_matches.empty?
|
41
|
+
result[:dirs].send method, dir_matches unless dir_matches.empty?
|
42
|
+
result[:files].send method, file_matches unless file_matches.empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_files_and_dirs
|
46
|
+
files, dirs = Dir.glob('**/*', File::FNM_DOTMATCH).
|
47
|
+
reject { |f| f =~ /(\A|\/)\.\.?\z/ }.
|
48
|
+
partition { |f| File.file?(f) || File.symlink?(f) }
|
49
|
+
dirs.map!{ |d| d + "/" }
|
50
|
+
{:files => files, :dirs => dirs}
|
46
51
|
end
|
47
|
-
end
|
48
|
-
|
49
|
-
protected
|
50
|
-
|
51
|
-
def directory?(pattern)
|
52
|
-
File.directory?(pattern) && !File.symlink?(pattern)
|
53
52
|
end
|
54
53
|
end
|
data/lib/globby/glob.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
module Globby
|
2
|
+
class Glob
|
3
|
+
def initialize(pattern)
|
4
|
+
@inverse = pattern.sub!(/\A!/, '')
|
5
|
+
# remove meaningless wildcards
|
6
|
+
@pattern = pattern.
|
7
|
+
sub(/\A\/?(\*\*\/)+/, '').
|
8
|
+
sub(/(\/\*\*)+\/\*\z/, '/**')
|
9
|
+
end
|
10
|
+
|
11
|
+
def match(files)
|
12
|
+
return [] unless files
|
13
|
+
files.grep(to_regexp)
|
14
|
+
end
|
15
|
+
|
16
|
+
def inverse?
|
17
|
+
@inverse
|
18
|
+
end
|
19
|
+
|
20
|
+
def directory?
|
21
|
+
@pattern =~ /\/\z/
|
22
|
+
end
|
23
|
+
|
24
|
+
def exact_match?
|
25
|
+
@pattern =~ /\A\// && @pattern !~ /[\*\?]/
|
26
|
+
end
|
27
|
+
|
28
|
+
# see https://www.kernel.org/doc/man-pages/online/pages/man7/glob.7.html
|
29
|
+
GLOB_BRACKET_EXPR = /
|
30
|
+
\[ # brackets
|
31
|
+
!? # (maybe) negation
|
32
|
+
\]? # (maybe) right bracket
|
33
|
+
(?: # one or more:
|
34
|
+
\[[^\/\]]+\] # named character class, collating symbol or equivalence class
|
35
|
+
| [^\/\]] # non-right bracket character (could be part of a range)
|
36
|
+
)+
|
37
|
+
\]/x
|
38
|
+
GLOB_ESCAPED_CHAR = /\\./
|
39
|
+
GLOB_RECURSIVE_WILDCARD = /\/\*\*(?:\/|\z)/
|
40
|
+
GLOB_WILDCARD = /[\?\*]/
|
41
|
+
|
42
|
+
GLOB_TOKENIZER = /(
|
43
|
+
#{GLOB_BRACKET_EXPR} |
|
44
|
+
#{GLOB_ESCAPED_CHAR} |
|
45
|
+
#{GLOB_RECURSIVE_WILDCARD}
|
46
|
+
)/x
|
47
|
+
|
48
|
+
def to_regexp
|
49
|
+
parts = @pattern.split(GLOB_TOKENIZER) - [""]
|
50
|
+
|
51
|
+
result = parts.first.sub!(/\A\//, '') ? '\A' : '(\A|/)'
|
52
|
+
parts.each do |part|
|
53
|
+
result << part_to_regexp(part)
|
54
|
+
end
|
55
|
+
if result[-1, 1] == '/'
|
56
|
+
result << '\z'
|
57
|
+
elsif result[-2, 2] == '.*'
|
58
|
+
result.slice!(-2, 2)
|
59
|
+
else
|
60
|
+
result << '\/?\z'
|
61
|
+
end
|
62
|
+
Regexp.new result
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def part_to_regexp(part)
|
68
|
+
case part
|
69
|
+
when GLOB_BRACKET_EXPR
|
70
|
+
# fix negation and escape right bracket
|
71
|
+
part.sub(/\A\[!/, '[^').sub(/\A(\[\^?)\]/, '\1\]')
|
72
|
+
when GLOB_ESCAPED_CHAR
|
73
|
+
part
|
74
|
+
when GLOB_RECURSIVE_WILDCARD
|
75
|
+
part[-1, 1] == '/' ? "/(.+/)?" : "/.*"
|
76
|
+
when GLOB_WILDCARD
|
77
|
+
(part.split(/(#{GLOB_WILDCARD})/) - [""]).inject("") do |result, p|
|
78
|
+
result << case p
|
79
|
+
when '?'; '[^/]'
|
80
|
+
when '*'; '[^/]*'
|
81
|
+
else Regexp.escape(p)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
else # literal path component (maybe with slashes)
|
85
|
+
part
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'globby'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
RSpec.configure { |config| config.mock_framework = :mocha }
|
6
|
+
|
7
|
+
describe Globby do
|
8
|
+
around do |example|
|
9
|
+
gitignore_test { example.run }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".select" do
|
13
|
+
it "should match .gitignore perfectly" do
|
14
|
+
rules = prepare_gitignore
|
15
|
+
Globby.select(rules.split(/\n/)).should == all_files - git_files - untracked
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".reject" do
|
20
|
+
it "should match the inverse of .gitignore, plus .git" do
|
21
|
+
rules = prepare_gitignore
|
22
|
+
Globby.reject(rules.split(/\n/)).should == git_files + untracked
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def gitignore_test
|
27
|
+
Dir.mktmpdir do |dir|
|
28
|
+
Dir.chdir(dir) do
|
29
|
+
prepare_files
|
30
|
+
`git init .`
|
31
|
+
yield
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def prepare_gitignore
|
37
|
+
ignore = <<-IGNORE.gsub(/^ +/, '')
|
38
|
+
# here we go...
|
39
|
+
|
40
|
+
# some dotfiles
|
41
|
+
.hidden
|
42
|
+
|
43
|
+
# html, but just in the root
|
44
|
+
/*.html
|
45
|
+
|
46
|
+
# all rb files anywhere
|
47
|
+
*.rb
|
48
|
+
|
49
|
+
# except rb files immediately under foobar
|
50
|
+
!foobar/*.rb
|
51
|
+
|
52
|
+
# this will match foo/bar but not bar
|
53
|
+
bar/
|
54
|
+
|
55
|
+
# this will match nothing
|
56
|
+
foo*bar/baz.pdf
|
57
|
+
|
58
|
+
# this will match baz/ and foobar/baz/
|
59
|
+
baz
|
60
|
+
IGNORE
|
61
|
+
File.open('.gitignore', 'w'){ |f| f.write ignore }
|
62
|
+
ignore
|
63
|
+
end
|
64
|
+
|
65
|
+
def prepare_files
|
66
|
+
files = <<-FILES.strip.split(/\s+/)
|
67
|
+
.gitignore
|
68
|
+
foo.rb
|
69
|
+
foo.html
|
70
|
+
bar
|
71
|
+
baz/lol.txt
|
72
|
+
foo/.hidden
|
73
|
+
foo/bar.rb
|
74
|
+
foo/bar.html
|
75
|
+
foo/bar/baz.pdf
|
76
|
+
foobar/.hidden
|
77
|
+
foobar/baz.txt
|
78
|
+
foobar/baz.rb
|
79
|
+
foobar/baz/lol.wut
|
80
|
+
FILES
|
81
|
+
files.each do |file|
|
82
|
+
FileUtils.mkdir_p File.dirname(file)
|
83
|
+
FileUtils.touch file
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def untracked
|
88
|
+
`git status -uall`.gsub(/.*#\n|#\s+|^nothing.*/m, '').split(/\n/)
|
89
|
+
end
|
90
|
+
|
91
|
+
def git_files
|
92
|
+
Dir.glob('.git/**/*', File::FNM_DOTMATCH).
|
93
|
+
select{ |f| File.symlink?(f) || File.file?(f) }.sort
|
94
|
+
end
|
95
|
+
|
96
|
+
def all_files
|
97
|
+
Dir.glob('**/*', File::FNM_DOTMATCH).
|
98
|
+
select{ |f| File.symlink?(f) || File.file?(f) }.sort
|
99
|
+
end
|
100
|
+
end
|
data/spec/globby_spec.rb
CHANGED
@@ -1,157 +1,85 @@
|
|
1
1
|
require 'globby'
|
2
|
-
RSpec.configure { |config| config.mock_framework = :mocha }
|
3
2
|
|
4
|
-
|
5
|
-
# readability.
|
6
|
-
#
|
7
|
-
# A line starting with # serves as a comment.
|
8
|
-
#
|
9
|
-
# An optional prefix ! which negates the pattern; any matching file excluded by
|
10
|
-
# a previous pattern will become included again. If a negated pattern matches,
|
11
|
-
# this will override lower precedence patterns sources.
|
12
|
-
#
|
13
|
-
# If the pattern ends with a slash, it is removed for the purpose of the
|
14
|
-
# following description, but it would only find a match with a directory. In
|
15
|
-
# other words, foo/ will match a directory foo and paths underneath it, but
|
16
|
-
# will not match a regular file or a symbolic link foo (this is consistent with
|
17
|
-
# the way how pathspec works in general in git).
|
18
|
-
#
|
19
|
-
# If the pattern does not contain a slash /, git treats it as a shell glob
|
20
|
-
# pattern and checks for a match against the pathname relative to the location
|
21
|
-
# of the .gitignore file (relative to the toplevel of the work tree if not from
|
22
|
-
# a .gitignore file).
|
23
|
-
#
|
24
|
-
# Otherwise, git treats the pattern as a shell glob suitable for consumption by
|
25
|
-
# fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will not
|
26
|
-
# match a / in the pathname. For example, "Documentation/*.html" matches
|
27
|
-
# "Documentation/git.html" but not "Documentation/ppc/ppc.html" or
|
28
|
-
# "tools/perf/Documentation/perf.html".
|
29
|
-
#
|
30
|
-
# A leading slash matches the beginning of the pathname. For example, "/*.c"
|
31
|
-
# matches "cat-file.c" but not "mozilla-sha1/sha1.c".
|
3
|
+
RSpec.configure { |config| config.mock_framework = :mocha }
|
32
4
|
|
33
5
|
describe Globby do
|
34
|
-
describe "
|
35
|
-
|
36
|
-
let(:globby) { Globby.new }
|
37
|
-
|
6
|
+
describe ".select" do
|
38
7
|
context "a blank line" do
|
39
8
|
it "should return nothing" do
|
40
|
-
|
41
|
-
|
9
|
+
files = files("foo")
|
10
|
+
Globby.select([""], files).should == []
|
42
11
|
end
|
43
12
|
end
|
44
13
|
|
45
14
|
context "a comment" do
|
46
15
|
it "should return nothing" do
|
47
|
-
|
48
|
-
|
16
|
+
files = files("foo")
|
17
|
+
Globby.select(["#"], files).should == []
|
49
18
|
end
|
50
19
|
end
|
51
20
|
|
52
21
|
context "a pattern ending in a slash" do
|
53
22
|
it "should return a matching directory's contents" do
|
54
|
-
|
55
|
-
|
56
|
-
globby.matches_for("foo/").should == ['foo/bar']
|
23
|
+
files = files(%w{foo/bar/baz foo/bar/baz2})
|
24
|
+
Globby.select(%w{bar/}, files).should == %w{foo/bar/baz foo/bar/baz2}
|
57
25
|
end
|
58
26
|
|
59
27
|
it "should ignore symlinks and regular files" do
|
60
|
-
|
61
|
-
|
62
|
-
globby.matches_for("foo/").should == []
|
28
|
+
files = files(%w{foo/bar bar/baz})
|
29
|
+
Globby.select(%w{bar/}, files).should == %w{bar/baz}
|
63
30
|
end
|
64
31
|
end
|
65
32
|
|
66
|
-
context "a pattern
|
67
|
-
it "should return
|
68
|
-
|
69
|
-
|
33
|
+
context "a pattern starting in a slash" do
|
34
|
+
it "should return only root glob matches" do
|
35
|
+
files = files(%w{foo/bar bar/foo})
|
36
|
+
Globby.select(%w{/foo}, files).should == %w{foo/bar}
|
70
37
|
end
|
71
38
|
end
|
72
39
|
|
73
|
-
context "a pattern with a
|
74
|
-
it "should return
|
75
|
-
|
76
|
-
|
40
|
+
context "a pattern with a *" do
|
41
|
+
it "should return matching files" do
|
42
|
+
files = files(%w{foo/bar foo/baz})
|
43
|
+
Globby.select(%w{*z}, files).should == %w{foo/baz}
|
77
44
|
end
|
78
|
-
end
|
79
45
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
globby.matches_for("/foo/bar")
|
46
|
+
it "should not glob slashes" do
|
47
|
+
files = files(%w{foo/bar foo/baz})
|
48
|
+
Globby.select(%w{foo*bar}, files).should == []
|
84
49
|
end
|
85
50
|
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe "#matches" do
|
89
|
-
it "should match gitignore perfectly" do
|
90
|
-
require 'tmpdir'
|
91
|
-
require 'fileutils'
|
92
|
-
|
93
|
-
files = <<-FILES.strip.split(/\s+/)
|
94
|
-
.gitignore
|
95
|
-
foo.rb
|
96
|
-
foo.html
|
97
|
-
bar
|
98
|
-
baz/lol.txt
|
99
|
-
foo/.hidden
|
100
|
-
foo/bar.rb
|
101
|
-
foo/bar.html
|
102
|
-
foo/bar/baz.pdf
|
103
|
-
foobar/.hidden
|
104
|
-
foobar/baz.txt
|
105
|
-
foobar/baz.rb
|
106
|
-
foobar/baz/lol.wut
|
107
|
-
FILES
|
108
|
-
|
109
|
-
ignore = <<-IGNORE.gsub(/^ +/, '')
|
110
|
-
# here we go...
|
111
|
-
|
112
|
-
# some dotfiles
|
113
|
-
.hidden
|
114
|
-
|
115
|
-
# html, but just in the root
|
116
|
-
/*.html
|
117
51
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
# this will match foo/bar but not bar
|
125
|
-
bar/
|
126
|
-
|
127
|
-
# this will match nothing
|
128
|
-
foo*bar/baz.pdf
|
129
|
-
|
130
|
-
# this will match baz/ and foobar/baz/
|
131
|
-
baz
|
132
|
-
IGNORE
|
52
|
+
context "a pattern with a ?" do
|
53
|
+
it "should return matching files" do
|
54
|
+
files = files(%w{foo/bar foo/baz})
|
55
|
+
Globby.select(%w{b?z}, files).should == %w{foo/baz}
|
56
|
+
end
|
133
57
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
FileUtils.touch file
|
140
|
-
end
|
58
|
+
it "should not glob slashes" do
|
59
|
+
files = files(%w{foo/bar foo/baz})
|
60
|
+
Globby.select(%w{foo?bar}, files).should == []
|
61
|
+
end
|
62
|
+
end
|
141
63
|
|
142
|
-
|
143
|
-
|
64
|
+
context "a pattern with a **" do
|
65
|
+
it "should match directories recursively" do
|
66
|
+
files = files(%w{foo/bar foo/baz foo/c/bar foo/c/c/bar})
|
67
|
+
Globby.select(%w{foo/**/bar}, files).should == %w{foo/bar foo/c/bar foo/c/c/bar}
|
68
|
+
end
|
69
|
+
end
|
144
70
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
reject{ |f| f =~ /^\.git\// }.
|
150
|
-
select{ |f| File.symlink?(f) || File.file?(f) }
|
151
|
-
|
152
|
-
all_files.sort.should == (untracked + ignored).sort
|
153
|
-
end
|
71
|
+
context "a pattern with bracket expressions" do
|
72
|
+
it "should return matching files" do
|
73
|
+
files = files(%w{boo fob f0o foo/bar poo/baz})
|
74
|
+
Globby.select(%w{[e-g][0-9[:alpha:]][!b]}, files).should == %w{f0o foo/bar}
|
154
75
|
end
|
155
76
|
end
|
156
77
|
end
|
78
|
+
|
79
|
+
def files(files)
|
80
|
+
files = Array(files)
|
81
|
+
files.sort!
|
82
|
+
dirs = files.grep(/\//).map { |file| file.sub(/[^\/]+\z/, '') }.uniq.sort
|
83
|
+
{:files => files, :dirs => dirs}
|
84
|
+
end
|
157
85
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: globby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jon Jensen
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2013-01-
|
18
|
+
date: 2013-01-25 00:00:00 Z
|
19
19
|
dependencies: []
|
20
20
|
|
21
21
|
description: find files using .gitignore-style globs
|
@@ -30,7 +30,9 @@ files:
|
|
30
30
|
- LICENSE.txt
|
31
31
|
- Rakefile
|
32
32
|
- README.md
|
33
|
+
- lib/globby/glob.rb
|
33
34
|
- lib/globby.rb
|
35
|
+
- spec/gitignore_spec.rb
|
34
36
|
- spec/globby_spec.rb
|
35
37
|
homepage: http://github.com/jenseng/globby
|
36
38
|
licenses: []
|