Skip to content

Commit

Permalink
Extract file finding into separate helper class
Browse files Browse the repository at this point in the history
Extract file finding/filtering logic into a helper class so it can be
more-easily tested.

In the process, this adds support for linting files without a `.haml`
extension, though files without `.haml` will still be ignored when only
a directory is given.

Change-Id: Ie34745374f0453a55efc03dddd1e2c0abccf5925
Reviewed-on: http://gerrit.causes.com/46309
Tested-by: jenkins <[email protected]>
Reviewed-by: Shane da Silva <[email protected]>
  • Loading branch information
sds committed Feb 9, 2015
1 parent 9df12f7 commit 6dd36da
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 42 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## master (unreleased)

* Fix non-visible line number on light-colored terminal backgrounds
* Allow files without `.haml` extension to be linted when explicitly specified

## 0.11.0

Expand Down
1 change: 1 addition & 0 deletions lib/haml_lint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require 'haml_lint/logger'
require 'haml_lint/reporter'
require 'haml_lint/report'
require 'haml_lint/file_finder'
require 'haml_lint/runner'
require 'haml_lint/utils'
require 'haml_lint/version'
Expand Down
69 changes: 69 additions & 0 deletions lib/haml_lint/file_finder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
require 'find'

module HamlLint
# Finds HAML files that should be linted given a specified list of paths, glob
# patterns, and configuration.
class FileFinder
# List of extensions of files to include under a directory when a directory
# is specified instead of a file.
VALID_EXTENSIONS = %w[.haml]

# @param config [HamlLint::Configuration]
def initialize(config)
@config = config
end

# Return list of files to lint given the specified set of paths and glob
# patterns.
# @param patterns [Array<String>]
# @param excluded_patterns [Array<String>]
# @raise [HamlLint::Exceptions::InvalidFilePath]
# @return [Array<String>] list of actual files
def find(patterns, excluded_patterns)
extract_files_from(patterns).reject do |file|
excluded_patterns.any? do |exclusion_glob|
::File.fnmatch?(exclusion_glob, file,
::File::FNM_PATHNAME | # Wildcards don't match path separators
::File::FNM_DOTMATCH) # `*` wildcard matches dotfiles
end
end
end

private

def extract_files_from(patterns) # rubocop:disable MethodLength
files = []

patterns.each do |pattern|
if File.file?(pattern)
files << pattern
else
begin
::Find.find(pattern) do |file|
files << file if haml_file?(file)
end
rescue ::Errno::ENOENT
# File didn't exist; it might be a file glob pattern
matches = ::Dir.glob(pattern)
if matches.any?
files += matches
else
# One of the paths specified does not exist; raise a more
# descriptive exception so we know which one
raise HamlLint::Exceptions::InvalidFilePath,
"File path '#{pattern}' does not exist"
end
end
end
end

files.uniq
end

def haml_file?(file)
return false unless ::FileTest.file?(file)

VALID_EXTENSIONS.include?(::File.extname(file))
end
end
end
13 changes: 4 additions & 9 deletions lib/haml_lint/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Runner
# @return [HamlLint::Report] a summary of all lints found
def run(options = {})
config = load_applicable_config(options)
files = extract_applicable_files(options)
files = extract_applicable_files(options, config)
linters = extract_enabled_linters(config, options)

raise HamlLint::Exceptions::NoLintersError, 'No linters specified' if linters.empty?
Expand Down Expand Up @@ -63,16 +63,11 @@ def find_lints(file, linters, config)
@lints << Lint.new(nil, file, ex.line, ex.to_s, :error)
end

def extract_applicable_files(options)
def extract_applicable_files(options, config)
included_patterns = options[:files]
excluded_files = options.fetch(:excluded_files, [])

Utils.extract_files_from(options[:files]).reject do |file|
excluded_files.any? do |exclusion_glob|
File.fnmatch?(exclusion_glob, file,
File::FNM_PATHNAME | # Wildcards don't match path separators
File::FNM_DOTMATCH) # `*` wildcard matches dotfiles
end
end
HamlLint::FileFinder.new(config).find(included_patterns, excluded_files)
end
end
end
33 changes: 0 additions & 33 deletions lib/haml_lint/utils.rb
Original file line number Diff line number Diff line change
@@ -1,35 +1,8 @@
require 'find'

module HamlLint
# A miscellaneous set of utility functions.
module Utils
module_function

def extract_files_from(list)
files = []

list.each do |file|
begin
Find.find(file) do |f|
files << f if haml_file?(f)
end
rescue Errno::ENOENT
# File didn't exist; it might be a file glob pattern
matches = Dir.glob(file)
if matches.any?
files += matches
else
# One of the paths specified does not exist; raise a more
# descriptive exception so we know which one
raise HamlLint::Exceptions::InvalidFilePath,
"File path '#{file}' does not exist"
end
end
end

files.uniq
end

# Yields interpolated values within a block of filter text.
def extract_interpolated_values(filter_text)
Haml::Util.handle_interpolation(filter_text.dump) do |scan|
Expand Down Expand Up @@ -81,11 +54,5 @@ def count_consecutive(items, offset, satisfies)
count += 1 while (offset + count < items.count) && satisfies[items[offset + count]]
count
end

def haml_file?(file)
return false unless FileTest.file?(file)

File.extname(file) == '.haml'
end
end
end
101 changes: 101 additions & 0 deletions spec/haml_lint/file_finder_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
require 'spec_helper'

describe HamlLint::FileFinder do
let(:config) { double }
let(:excluded_patterns) { [] }

subject { described_class.new(config) }

describe '#find' do
include_context 'isolated environment'

subject { super().find(patterns, excluded_patterns) }

context 'when no patterns are given' do
let(:patterns) { [] }

context 'and there are no HAML files under the current directory' do
it { should == [] }
end

context 'and there are HAML files under the current directory' do
before do
`touch blah.haml`
`mkdir -p more`
`touch more/more.haml`
end

it { should == [] }
end
end

context 'when files without a valid extension are given' do
let(:patterns) { ['test.txt'] }

context 'and those files exist' do
before do
`touch test.txt`
end

it { should == ['test.txt'] }
end

context 'and those files do not exist' do
it 'raises an error' do
expect { subject }.to raise_error HamlLint::Exceptions::InvalidFilePath
end
end
end

context 'when directories are given' do
let(:patterns) { ['some-dir'] }

context 'and those directories exist' do
before do
`mkdir -p some-dir`
end

context 'and they contain HAML files' do
before do
`touch some-dir/test.haml`
end

it { should == ['some-dir/test.haml'] }
end

context 'and they contain more directories with files with recognized extensions' do
before do
`mkdir -p some-dir/more-dir`
`touch some-dir/more-dir/test.haml`
end

it { should == ['some-dir/more-dir/test.haml'] }
end

context 'and they contain files with some other extension' do
before do
`touch some-dir/test.txt`
end

it { should == [] }
end
end

context 'and those directories do not exist' do
it 'raises an error' do
expect { subject }.to raise_error HamlLint::Exceptions::InvalidFilePath
end
end
end

context 'when the same file is specified multiple times' do
let(:patterns) { ['test.haml'] * 3 }

before do
`touch test.haml`
end

it { should == ['test.haml'] }
end
end
end
25 changes: 25 additions & 0 deletions spec/support/isolated_environment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require 'fileutils'
require 'tmpdir'

shared_context 'isolated environment' do
around do |example|
Dir.mktmpdir do |tmpdir|
original_home = ENV['HOME']

begin
virtual_home = File.expand_path(File.join(tmpdir, 'home'))
Dir.mkdir(virtual_home)
ENV['HOME'] = virtual_home

working_dir = File.join(tmpdir, 'work')
Dir.mkdir(working_dir)

Dir.chdir(working_dir) do
example.run
end
ensure
ENV['HOME'] = original_home
end
end
end
end

0 comments on commit 6dd36da

Please sign in to comment.