Skip to content

Commit

Permalink
Fix #17 - Use regexp pattrens for ignoring paths instead of strings
Browse files Browse the repository at this point in the history
  • Loading branch information
Maher4Ever committed Apr 19, 2012
1 parent 5f86795 commit 2650607
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 48 deletions.
75 changes: 52 additions & 23 deletions lib/listen/directory_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,30 @@ module Listen
class DirectoryRecord
attr_reader :directory, :paths, :sha1_checksums

# Default paths' beginnings that doesn't get stored in the record
DEFAULT_IGNORED_PATHS = %w[.bundle .git .DS_Store log tmp vendor]
DEFAULT_IGNORED_DIRECTORIES = %w[.bundle .git .svn log tmp vendor]

DEFAULT_IGNORED_EXTENSIONS = %w[.DS_Store]

# Class methods
#
class << self

# Creates the ignoring pattrens from the default ignored
# directories and extensions. It memoizes the generated pattrens
# to avoid unnecessary computation.
#
def generate_default_ignoring_pattrens
@@default_ignoring_pattrens ||= Array.new.tap do |default_pattrens|
# Add directories
ignored_directories = DEFAULT_IGNORED_DIRECTORIES.map { |d| Regexp.escape(d) }
default_pattrens << %r{^(?:#{ignored_directories.join('|')})/}

# Add extensions
ignored_extensions = DEFAULT_IGNORED_EXTENSIONS.map { |e| Regexp.escape(e) }
default_pattrens << %r{(?:#{ignored_extensions.join('|')})$}
end
end
end

# Initializes a directory record.
#
Expand All @@ -21,51 +43,53 @@ class DirectoryRecord
def initialize(directory)
raise ArgumentError, "The path '#{directory}' is not a directory!" unless File.directory?(directory)

@directory = directory
@ignored_paths = Set.new(DEFAULT_IGNORED_PATHS)
@filters = Set.new
@sha1_checksums = Hash.new
@directory = directory
@ignoring_pattrens = Set.new

This comment has been minimized.

Copy link
@akerbos

akerbos Apr 19, 2012

Typo: Should be "patterns". Next line and several times in spec, too.

This comment has been minimized.

Copy link
@rymai

rymai Apr 19, 2012

Member

"pattren" everywhere! :P

This comment has been minimized.

Copy link
@Maher4Ever

Maher4Ever Apr 19, 2012

Author Contributor

lol, it is indeed everywhere... I better fix this before anyone else notices :)

@filtering_pattrens = Set.new
@sha1_checksums = Hash.new

@ignoring_pattrens.merge(DirectoryRecord.generate_default_ignoring_pattrens)
end

# Returns the ignored paths in the record
# Returns the ignoring pattrens in the record
#
# @return [Array<String>] the ignored paths
# @return [Array<Regexp>] the ignoring pattrens
#
def ignored_paths
@ignored_paths.to_a
def ignoring_pattrens
@ignoring_pattrens.to_a
end

# Returns the filters used in the record to know
# Returns the filtering pattrens used in the record to know
# which paths should be stored.
#
# @return [Array<String>] the used filters
# @return [Array<Regexp>] the filtering pattrens
#
def filters
@filters.to_a
def filtering_pattrens
@filtering_pattrens.to_a
end

# Adds ignored path to the record.
# Adds ignoring pattrens to the record.
#
# @example Ignore some paths
# ignore ".git", ".svn"
#
# @param [String, Array<String>] paths a path or a list of paths to ignore
# @param [Regexp] regexp a pattren for ignoring paths
#
def ignore(*paths)
@ignored_paths.merge(paths)
def ignore(*regexps)
@ignoring_pattrens.merge(regexps)
end

# Adds file filters to the listener.
# Adds filtering pattrens to the listener.
#
# @example Filter some files
# ignore /\.txt$/, /.*\.zip/
#
# @param [Array<Regexp>] regexps a list of regexps file filters
# @param [Regexp] regexp a pattren for filtering paths
#
# @return [Listen::Listener] the listener itself
#
def filter(*regexps)
@filters.merge(regexps)
@filtering_pattrens.merge(regexps)
end

# Returns whether a path should be ignored or not.
Expand All @@ -75,7 +99,8 @@ def filter(*regexps)
# @return [Boolean]
#
def ignored?(path)
@ignored_paths.any? { |ignored_path| path =~ /#{ignored_path}$/ }
path = relative_to_base(path)
@ignoring_pattrens.any? { |pattren| pattren =~ path }
end

# Returns whether a path should be filtered or not.
Expand All @@ -85,7 +110,11 @@ def ignored?(path)
# @return [Boolean]
#
def filtered?(path)
@filters.empty? || @filters.any? { |filter| path =~ filter }
# When no filtering pattrens are set, ALL files are stored.
return true if @filtering_pattrens.empty?

path = relative_to_base(path)
@filtering_pattrens.any? { |pattren| pattren =~ path }
end

# Finds the paths that should be stored and adds them
Expand Down
8 changes: 4 additions & 4 deletions lib/listen/listener.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,18 @@ def paused?
!!@adapter && @adapter.paused == true
end

# Adds ignored paths to the listener.
# Adds ignoring pattrens to the listener.
#
# @param (see Listen::DirectoryRecord#ignore)
#
# @return [Listen::Listener] the listener
#
def ignore(*paths)
@directory_record.ignore(*paths)
def ignore(*regexps)
@directory_record.ignore(*regexps)
self
end

# Adds file filters to the listener.
# Adds filtering pattrens to the listener.
#
# @param (see Listen::DirectoryRecord#filter)
#
Expand Down
88 changes: 67 additions & 21 deletions spec/listen/directory_record_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,30 @@

subject { described_class.new(base_directory) }

describe '.generate_default_ignoring_pattrens' do
it 'creates regexp pattrens from the default ignored directories and extensions' do
described_class.generate_default_ignoring_pattrens.should include(
%r{^(?:\.bundle|\.git|\.svn|log|tmp|vendor)/},
%r{(?:\.DS_Store)$}
)
end

it 'memoizes the generated results' do
described_class.generate_default_ignoring_pattrens.should equal described_class.generate_default_ignoring_pattrens
end
end

describe '#initialize' do
it 'sets the base directory' do
subject.directory.should eq base_directory
end

it 'sets the default ignored paths' do
subject.ignored_paths.should =~ described_class::DEFAULT_IGNORED_PATHS
it 'sets the default ignoring pattrens' do
subject.ignoring_pattrens.should =~ described_class.generate_default_ignoring_pattrens
end

it 'sets the default filters' do
subject.filters.should eq []
it 'sets the default filtering pattrens' do
subject.filtering_pattrens.should eq []
end

it 'raises an error when the passed path does not exist' do
Expand All @@ -29,39 +42,72 @@

describe '#ignore' do
it 'adds the passed paths to the list of ignoted paths in the record' do
subject.ignore('.old', '.pid')
subject.ignored_paths.should include('.old', '.pid')
subject.ignore(%r{^\.old/}, %r{\.pid$})
subject.ignoring_pattrens.should include(%r{^\.old/}, %r{\.pid$})
end
end

describe '#filter' do
it 'adds the passed regexps to the list of filters that determine the stored paths' do
subject.filter(%r{\.(?:jpe?g|gif|png)}, %r{\.(?:mp3|ogg|a3c)})
subject.filters.should include(%r{\.(?:jpe?g|gif|png)}, %r{\.(?:mp3|ogg|a3c)})
subject.filtering_pattrens.should include(%r{\.(?:jpe?g|gif|png)}, %r{\.(?:mp3|ogg|a3c)})
end
end

describe '#ignored?' do
it 'tests paths relative to the base directory' do
subject.should_receive(:relative_to_base).with('file.txt')
subject.ignored?('file.txt')
end

it 'returns true when the passed path is a default ignored path' do
subject.ignored?('tmp/some_process.pid').should be_true
subject.ignored?('dir/.DS_Store').should be_true
subject.ignored?('.git/config').should be_true
end

it 'returns false when the passed path is not a default ignored path' do
subject.ignored?('nested/tmp/some_process.pid').should be_false
subject.ignored?('nested/.git').should be_false
subject.ignored?('dir/.DS_Store/file').should be_false
subject.ignored?('file.git').should be_false
end

it 'returns true when the passed path is ignored' do
subject.ignore('.pid')
subject.ignored?('/tmp/some_process.pid').should be_true
subject.ignore(%r{\.pid$})
subject.ignored?('dir/some_process.pid').should be_true
end

it 'returns false when the passed path is not ignored' do
subject.ignore('.pid')
subject.ignored?('/tmp/some_file.txt').should be_false
subject.ignore(%r{\.pid$})
subject.ignored?('dir/some_file.txt').should be_false
end
end

describe '#filterd?' do

This comment has been minimized.

Copy link
@akerbos

akerbos Apr 19, 2012

Typo: Should be "filtered"

This comment has been minimized.

Copy link
@rymai

rymai Apr 19, 2012

Member

Thanks @akerbos for spotting typos (it's my hobby too ^^)!

it 'returns true when the passed path is filtered' do
subject.filter(%r{\.(?:jpe?g|gif|png)})
subject.filtered?('/tmp/picture.jpeg').should be_true
context 'when no filtering pattrens are set' do
it 'returns true for any path' do
subject.filtered?('file.txt').should be_true
end
end

it 'returns false when the passed path is not filtered' do
subject.filter(%r{\.(?:jpe?g|gif|png)})
subject.filtered?('/tmp/song.mp3').should be_false
context 'when filtering pattrens are set' do
before { subject.filter(%r{\.(?:jpe?g|gif|png)}) }

it 'tests paths relative to the base directory' do
subject.should_receive(:relative_to_base).with('file.txt')
subject.filtered?('file.txt')
end

it 'returns true when the passed path is filtered' do
subject.filter(%r{\.(?:jpe?g|gif|png)})
subject.filtered?('dir/picture.jpeg').should be_true
end

it 'returns false when the passed path is not filtered' do
subject.filter(%r{\.(?:jpe?g|gif|png)})
subject.filtered?('dir/song.mp3').should be_false
end
end
end

Expand Down Expand Up @@ -89,7 +135,7 @@
touch 'ignored_directory/file.txt'

record = described_class.new(path)
record.ignore 'ignored_directory'
record.ignore %r{^ignored_directory/}
record.build

record.paths[path]['/a_ignored_directory'].should be_nil
Expand All @@ -103,7 +149,7 @@
touch 'ignored_file.rb'

record = described_class.new(path)
record.ignore 'ignored_file.rb'
record.ignore %r{^ignored_file.rb$}
record.build

record.paths[path]['ignored_file.rb'].should be_nil
Expand Down Expand Up @@ -211,7 +257,7 @@
fixtures do |path|
mkdir 'ignored_directory'

modified, added, removed = changes(path, :ignore => 'ignored_directory', :recursive => true) do
modified, added, removed = changes(path, :ignore => %r{^ignored_directory/}, :recursive => true) do
touch 'ignored_directory/new_file.rb'
end

Expand All @@ -225,7 +271,7 @@
fixtures do |path|
mkdir 'ignored_directory'

modified, added, removed = changes(path, :paths => ["#{path}/ignored_directory"], :ignore => 'ignored_directory', :recursive => true) do
modified, added, removed = changes(path, :paths => ["#{path}/ignored_directory"], :ignore => %r{^ignored_directory/}, :recursive => true) do
touch 'ignored_directory/new_file.rb'
end

Expand Down

0 comments on commit 2650607

Please sign in to comment.