Class: Rulebow::WatchList

Inherits:
Object
  • Object
show all
Defined in:
lib/rulebow/watchlist.rb

Overview

Encapsulates list of file globs to be watched.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ void

Initialize new instance of Ignore.



13
14
15
16
# File 'lib/rulebow/watchlist.rb', line 13

def initialize(options={})
  @accept = options[:accept].to_a.flatten
  @ignore = options[:ignore].to_a.flatten
end

Instance Attribute Details

#rootObject (readonly)

Project’s root directory.



19
20
21
# File 'lib/rulebow/watchlist.rb', line 19

def root
  @root
end

Instance Method Details

#accept(*globs) ⇒ Object



78
79
80
# File 'lib/rulebow/watchlist.rb', line 78

def accept(*globs)
  @accept.concat(globs.flatten)
end

#accept!(*globs) ⇒ Object



83
84
85
# File 'lib/rulebow/watchlist.rb', line 83

def accept!(*globs)
  @accept.replace(globs.flatten)
end

#checksum(file) ⇒ String (private)

Compute the sha1 identifer for a file.

Parameters:

  • file

    path to a file

Returns:

  • (String)

    Returns String SHA1 digest string.



172
173
174
175
176
177
178
179
180
# File 'lib/rulebow/watchlist.rb', line 172

def checksum(file)
  sha = ::Digest::SHA1.new
  File.open(file, 'r') do |fh|
    fh.each_line do |l|
      sha << l
    end
  end
  sha.hexdigest
end

#digest(root = nil) ⇒ Hash

Get a current digest.

Returns:

  • (Hash)

    Returns digest.



100
101
102
103
104
105
106
107
108
# File 'lib/rulebow/watchlist.rb', line 100

def digest(root=nil)
  if root
    Dir.chdir(root) do
      read_digest
    end
  else
    read_digest
  end
end

#filter(files) ⇒ Object

Filter a list of files in accordance with the accept and ignore lists.



24
25
26
# File 'lib/rulebow/watchlist.rb', line 24

def filter(files)
  filter_ignore(filter_accept(files))
end

#filter_accept(files) ⇒ Array<String>

Filter a list of files in accordance with the ignore list.

Parameters:

  • files

    The list of files. [Array<String>]

Returns:

  • (Array<String>)

    Returns



34
35
36
37
38
39
40
41
42
43
# File 'lib/rulebow/watchlist.rb', line 34

def filter_accept(files)
  list = []
  files.each do |file|
    hit = @accept.any? do |pattern|
      match?(pattern, file)
    end
    list << file if hit
  end
  list
end

#filter_ignore(files) ⇒ Array<String>

Filter a list of files in accordance with the ignore list.

Parameters:

  • files

    The list of files. [Array<String>]

Returns:

  • (Array<String>)

    Returns



51
52
53
54
55
56
57
58
59
60
# File 'lib/rulebow/watchlist.rb', line 51

def filter_ignore(files)
  list = []
  files.each do |file|
    hit = @ignore.any? do |pattern|
      match?(pattern, file)
    end
    list << file unless hit
  end
  list
end

#fnmatch?(pattern, file, mode = File::FNM_PATHNAME) ⇒ Boolean (private)

Shortcut to File.fnmatch? method.

Returns:



163
164
165
# File 'lib/rulebow/watchlist.rb', line 163

def fnmatch?(pattern, file, mode=File::FNM_PATHNAME)
  File.fnmatch?(pattern, file, File::FNM_PATHNAME)
end

#ignore(*globs) ⇒ Object



88
89
90
# File 'lib/rulebow/watchlist.rb', line 88

def ignore(*globs)
  @ignore.concat(globs.flatten)
end

#ignore!(*globs) ⇒ Object



93
94
95
# File 'lib/rulebow/watchlist.rb', line 93

def ignore!(*globs)
  @ignore.replace(globs.flatten)
end

#match?(pattern, file) ⇒ Boolean (private)

TODO:

The code is probably not quite right.

TODO:

Handle regular expressions.

Given a pattern and a file, does the file match the pattern? This code is based on the rules used by git’s .gitignore file.

Returns:



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/rulebow/watchlist.rb', line 134

def match?(pattern, file)
  if Regexp === pattern
    return pattern.match(file) ? true : false
  end

  if pattern.start_with?('!')
    return !match?(pattern.sub('!','').strip)
  end

  dir = pattern.end_with?('/')
  pattern = pattern.chomp('/') if dir

  if pattern.start_with?('/')
    fnmatch?(pattern.sub('/',''), file)
  else
    if dir
      fnmatch?(File.join(pattern, '**', '*'), file) ||
      fnmatch?(pattern, file) && File.directory?(file)
    elsif pattern.include?('/')
      fnmatch?(pattern, file)
    else
      fnmatch?(File.join('**',pattern), file)
    end
  end
end

#read_digestObject (private)



112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/rulebow/watchlist.rb', line 112

def read_digest
  dig = {}
  list = filter(Dir.glob('**/*', File::FNM_PATHNAME))
  list.each do |path|
    if File.directory?(path)
      # TODO: how to handle directories as a whole?
    elsif File.exist?(path)
      dig[path] = checksum(path)
    end
  end
  dig
end