sass 3.3.0.alpha.136 → 3.3.0.alpha.138

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/REVISION +1 -1
  2. data/VERSION +1 -1
  3. data/VERSION_DATE +1 -1
  4. data/lib/sass/plugin/compiler.rb +1 -17
  5. metadata +22 -47
  6. data/vendor/listen/CHANGELOG.md +0 -221
  7. data/vendor/listen/CONTRIBUTING.md +0 -38
  8. data/vendor/listen/Gemfile +0 -30
  9. data/vendor/listen/Guardfile +0 -8
  10. data/vendor/listen/LICENSE +0 -20
  11. data/vendor/listen/README.md +0 -315
  12. data/vendor/listen/Rakefile +0 -47
  13. data/vendor/listen/Vagrantfile +0 -96
  14. data/vendor/listen/lib/listen.rb +0 -40
  15. data/vendor/listen/lib/listen/adapter.rb +0 -214
  16. data/vendor/listen/lib/listen/adapters/bsd.rb +0 -112
  17. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -85
  18. data/vendor/listen/lib/listen/adapters/linux.rb +0 -113
  19. data/vendor/listen/lib/listen/adapters/polling.rb +0 -67
  20. data/vendor/listen/lib/listen/adapters/windows.rb +0 -87
  21. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  22. data/vendor/listen/lib/listen/directory_record.rb +0 -371
  23. data/vendor/listen/lib/listen/listener.rb +0 -225
  24. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  25. data/vendor/listen/lib/listen/turnstile.rb +0 -28
  26. data/vendor/listen/lib/listen/version.rb +0 -3
  27. data/vendor/listen/listen.gemspec +0 -22
  28. data/vendor/listen/spec/listen/adapter_spec.rb +0 -183
  29. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
  30. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -37
  31. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -47
  32. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  33. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -30
  34. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  35. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1225
  36. data/vendor/listen/spec/listen/listener_spec.rb +0 -169
  37. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
  38. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  39. data/vendor/listen/spec/listen_spec.rb +0 -73
  40. data/vendor/listen/spec/spec_helper.rb +0 -21
  41. data/vendor/listen/spec/support/adapter_helper.rb +0 -629
  42. data/vendor/listen/spec/support/directory_record_helper.rb +0 -55
  43. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  44. data/vendor/listen/spec/support/listeners_helper.rb +0 -156
  45. data/vendor/listen/spec/support/platform_helper.rb +0 -15
@@ -1,113 +0,0 @@
1
- module Listen
2
- module Adapters
3
-
4
- # Listener implementation for Linux `inotify`.
5
- #
6
- class Linux < Adapter
7
- extend DependencyManager
8
-
9
- # Declare the adapter's dependencies
10
- dependency 'rb-inotify', '~> 0.8.8'
11
-
12
- # Watched inotify events
13
- #
14
- # @see http://www.tin.org/bin/man.cgi?section=7&topic=inotify
15
- # @see https://github.com/nex3/rb-inotify/blob/master/lib/rb-inotify/notifier.rb#L99-L177
16
- #
17
- EVENTS = %w[recursive attrib create delete move close_write]
18
-
19
- # The message to show when the limit of inotify watchers is not enough
20
- #
21
- INOTIFY_LIMIT_MESSAGE = <<-EOS.gsub(/^\s*/, '')
22
- Listen error: unable to monitor directories for changes.
23
-
24
- Please head to https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers
25
- for information on how to solve this issue.
26
- EOS
27
-
28
- # Initializes the Adapter. See {Listen::Adapter#initialize} for more info.
29
- #
30
- def initialize(directories, options = {}, &callback)
31
- super
32
- @worker = init_worker
33
- rescue Errno::ENOSPC
34
- abort(INOTIFY_LIMIT_MESSAGE)
35
- end
36
-
37
- # Starts the adapter.
38
- #
39
- # @param [Boolean] blocking whether or not to block the current thread after starting
40
- #
41
- def start(blocking = true)
42
- @mutex.synchronize do
43
- return if @stop == false
44
- super
45
- end
46
-
47
- @worker_thread = Thread.new { @worker.run }
48
- @poll_thread = Thread.new { poll_changed_dirs } if @report_changes
49
-
50
- @worker_thread.join if blocking
51
- end
52
-
53
- # Stops the adapter.
54
- #
55
- def stop
56
- @mutex.synchronize do
57
- return if @stop == true
58
- super
59
- end
60
-
61
- @worker.stop
62
- Thread.kill(@worker_thread) if @worker_thread
63
- @poll_thread.join if @poll_thread
64
- end
65
-
66
- # Checks if the adapter is usable on the current OS.
67
- #
68
- # @return [Boolean] whether usable or not
69
- #
70
- def self.usable?
71
- return false unless RbConfig::CONFIG['target_os'] =~ /linux/i
72
- super
73
- end
74
-
75
- private
76
-
77
- # Initializes a INotify worker and adds a watcher for
78
- # each directory passed to the adapter.
79
- #
80
- # @return [INotify::Notifier] initialized worker
81
- #
82
- def init_worker
83
- callback = lambda do |event|
84
- if @paused || (
85
- # Event on root directory
86
- event.name == ""
87
- ) || (
88
- # INotify reports changes to files inside directories as events
89
- # on the directories themselves too.
90
- #
91
- # @see http://linux.die.net/man/7/inotify
92
- event.flags.include?(:isdir) and event.flags & [:close, :modify] != []
93
- )
94
- # Skip all of these!
95
- next
96
- end
97
-
98
- @mutex.synchronize do
99
- @changed_dirs << File.dirname(event.absolute_name)
100
- end
101
- end
102
-
103
- INotify::Notifier.new.tap do |worker|
104
- @directories.each do |directory|
105
- worker.watch(directory, *EVENTS.map(&:to_sym), &callback)
106
- end
107
- end
108
- end
109
-
110
- end
111
-
112
- end
113
- end
@@ -1,67 +0,0 @@
1
- module Listen
2
- module Adapters
3
-
4
- # The default delay between checking for changes.
5
- DEFAULT_POLLING_LATENCY = 1.0
6
-
7
- # Polling Adapter that works cross-platform and
8
- # has no dependencies. This is the adapter that
9
- # uses the most CPU processing power and has higher
10
- # file IO that the other implementations.
11
- #
12
- class Polling < Adapter
13
- extend DependencyManager
14
-
15
- # Initialize the Adapter. See {Listen::Adapter#initialize} for more info.
16
- #
17
- def initialize(directories, options = {}, &callback)
18
- @latency ||= DEFAULT_POLLING_LATENCY
19
- super
20
- end
21
-
22
- # Start the adapter.
23
- #
24
- # @param [Boolean] blocking whether or not to block the current thread after starting
25
- #
26
- def start(blocking = true)
27
- @mutex.synchronize do
28
- return if @stop == false
29
- super
30
- end
31
-
32
- @poll_thread = Thread.new { poll }
33
- @poll_thread.join if blocking
34
- end
35
-
36
- # Stop the adapter.
37
- #
38
- def stop
39
- @mutex.synchronize do
40
- return if @stop == true
41
- super
42
- end
43
-
44
- @poll_thread.join
45
- end
46
-
47
- private
48
-
49
- # Poll listener directory for file system changes.
50
- #
51
- def poll
52
- until @stop
53
- next if @paused
54
-
55
- start = Time.now.to_f
56
- @callback.call(@directories.dup, :recursive => true)
57
- @turnstile.signal
58
- nap_time = @latency - (Time.now.to_f - start)
59
- sleep(nap_time) if nap_time > 0
60
- end
61
- rescue Interrupt
62
- end
63
-
64
- end
65
-
66
- end
67
- end
@@ -1,87 +0,0 @@
1
- require 'set'
2
-
3
- module Listen
4
- module Adapters
5
-
6
- # Adapter implementation for Windows `wdm`.
7
- #
8
- class Windows < Adapter
9
- extend DependencyManager
10
-
11
- # Declare the adapter's dependencies
12
- dependency 'wdm', '~> 0.0.3'
13
-
14
- # Initializes the Adapter. See {Listen::Adapter#initialize} for more info.
15
- #
16
- def initialize(directories, options = {}, &callback)
17
- super
18
- @worker = init_worker
19
- end
20
-
21
- # Starts the adapter.
22
- #
23
- # @param [Boolean] blocking whether or not to block the current thread after starting
24
- #
25
- def start(blocking = true)
26
- @mutex.synchronize do
27
- return if @stop == false
28
- super
29
- end
30
-
31
- @worker_thread = Thread.new { @worker.run! }
32
-
33
- # Wait for the worker to start. This is needed to avoid a deadlock
34
- # when stopping immediately after starting.
35
- sleep 0.1
36
-
37
- @poll_thread = Thread.new { poll_changed_dirs } if @report_changes
38
-
39
- @worker_thread.join if blocking
40
- end
41
-
42
- # Stops the adapter.
43
- #
44
- def stop
45
- @mutex.synchronize do
46
- return if @stop == true
47
- super
48
- end
49
-
50
- @worker.stop
51
- @worker_thread.join if @worker_thread
52
- @poll_thread.join if @poll_thread
53
- end
54
-
55
- # Checks if the adapter is usable on the current OS.
56
- #
57
- # @return [Boolean] whether usable or not
58
- #
59
- def self.usable?
60
- return false unless RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
61
- super
62
- end
63
-
64
- private
65
-
66
- # Initializes a WDM monitor and adds a watcher for
67
- # each directory passed to the adapter.
68
- #
69
- # @return [WDM::Monitor] initialized worker
70
- #
71
- def init_worker
72
- callback = Proc.new do |change|
73
- next if @paused
74
- @mutex.synchronize do
75
- @changed_dirs << File.dirname(change.path)
76
- end
77
- end
78
-
79
- WDM::Monitor.new.tap do |worker|
80
- @directories.each { |d| worker.watch_recursively(d, &callback) }
81
- end
82
- end
83
-
84
- end
85
-
86
- end
87
- end
@@ -1,126 +0,0 @@
1
- require 'set'
2
-
3
- module Listen
4
-
5
- # The dependency-manager offers a simple DSL which allows
6
- # classes to declare their gem dependencies and load them when
7
- # needed.
8
- # It raises a user-friendly exception when the dependencies
9
- # can't be loaded which has the install command in the message.
10
- #
11
- module DependencyManager
12
-
13
- GEM_LOAD_MESSAGE = <<-EOS.gsub(/^ {6}/, '')
14
- Missing dependency '%s' (version '%s')!
15
- EOS
16
-
17
- GEM_INSTALL_COMMAND = <<-EOS.gsub(/^ {6}/, '')
18
- Please run the following to satisfy the dependency:
19
- gem install --version '%s' %s
20
- EOS
21
-
22
- BUNDLER_DECLARE_GEM = <<-EOS.gsub(/^ {6}/, '')
23
- Please add the following to your Gemfile to satisfy the dependency:
24
- gem '%s', '%s'
25
- EOS
26
-
27
- Dependency = Struct.new(:name, :version)
28
-
29
- # The error raised when a dependency can't be loaded.
30
- class Error < StandardError; end
31
-
32
- # A list of all loaded dependencies in the dependency manager.
33
- @_loaded_dependencies = Set.new
34
-
35
- # class methods
36
- class << self
37
-
38
- # Initializes the extended class.
39
- #
40
- # @param [Class] the class for which some dependencies must be managed
41
- #
42
- def extended(base)
43
- base.class_eval do
44
- @_dependencies = Set.new
45
- end
46
- end
47
-
48
- # Adds a loaded dependency to a list so that it doesn't have
49
- # to be loaded again by another classes.
50
- #
51
- # @param [Dependency] dependency
52
- #
53
- def add_loaded(dependency)
54
- @_loaded_dependencies << dependency
55
- end
56
-
57
- # Returns whether the dependency is alread loaded or not.
58
- #
59
- # @param [Dependency] dependency
60
- # @return [Boolean]
61
- #
62
- def already_loaded?(dependency)
63
- @_loaded_dependencies.include?(dependency)
64
- end
65
-
66
- # Clears the list of loaded dependencies.
67
- #
68
- def clear_loaded
69
- @_loaded_dependencies.clear
70
- end
71
- end
72
-
73
- # Registers a new dependency.
74
- #
75
- # @param [String] name the name of the gem
76
- # @param [String] version the version of the gem
77
- #
78
- def dependency(name, version)
79
- @_dependencies << Dependency.new(name, version)
80
- end
81
-
82
- # Loads the registered dependencies.
83
- #
84
- # @raise DependencyManager::Error if the dependency can't be loaded.
85
- #
86
- def load_depenencies
87
- @_dependencies.each do |dependency|
88
- begin
89
- next if DependencyManager.already_loaded?(dependency)
90
- gem(dependency.name, dependency.version)
91
- require(dependency.name)
92
- DependencyManager.add_loaded(dependency)
93
- @_dependencies.delete(dependency)
94
- rescue Gem::LoadError
95
- args = [dependency.name, dependency.version]
96
- command = if running_under_bundler?
97
- BUNDLER_DECLARE_GEM % args
98
- else
99
- GEM_INSTALL_COMMAND % args.reverse
100
- end
101
- message = GEM_LOAD_MESSAGE % args
102
-
103
- raise Error.new(message + command)
104
- end
105
- end
106
- end
107
-
108
- # Returns whether all the dependencies has been loaded or not.
109
- #
110
- # @return [Boolean]
111
- #
112
- def dependencies_loaded?
113
- @_dependencies.empty?
114
- end
115
-
116
- private
117
-
118
- # Returns whether we are running under bundler or not
119
- #
120
- # @return [Boolean]
121
- #
122
- def running_under_bundler?
123
- !!(File.exists?('Gemfile') && ENV['BUNDLE_GEMFILE'])
124
- end
125
- end
126
- end
@@ -1,371 +0,0 @@
1
- require 'set'
2
- require 'find'
3
- require 'digest/sha1'
4
-
5
- module Listen
6
-
7
- # The directory record stores information about
8
- # a directory and keeps track of changes to
9
- # the structure of its childs.
10
- #
11
- class DirectoryRecord
12
- attr_reader :directory, :paths, :sha1_checksums
13
-
14
- DEFAULT_IGNORED_DIRECTORIES = %w[.rbx .bundle .git .svn log tmp vendor]
15
-
16
- DEFAULT_IGNORED_EXTENSIONS = %w[.DS_Store]
17
-
18
- # Defines the used precision based on the type of mtime returned by the
19
- # system (whether its in milliseconds or just seconds)
20
- #
21
- begin
22
- HIGH_PRECISION_SUPPORTED = File.mtime(__FILE__).to_f.to_s[-2..-1] != '.0'
23
- rescue
24
- HIGH_PRECISION_SUPPORTED = false
25
- end
26
-
27
- # Data structure used to save meta data about a path
28
- #
29
- MetaData = Struct.new(:type, :mtime)
30
-
31
- # Class methods
32
- #
33
- class << self
34
-
35
- # Creates the ignoring patterns from the default ignored
36
- # directories and extensions. It memoizes the generated patterns
37
- # to avoid unnecessary computation.
38
- #
39
- def generate_default_ignoring_patterns
40
- @@default_ignoring_patterns ||= Array.new.tap do |default_patterns|
41
- # Add directories
42
- ignored_directories = DEFAULT_IGNORED_DIRECTORIES.map { |d| Regexp.escape(d) }
43
- default_patterns << %r{^(?:#{ignored_directories.join('|')})/}
44
-
45
- # Add extensions
46
- ignored_extensions = DEFAULT_IGNORED_EXTENSIONS.map { |e| Regexp.escape(e) }
47
- default_patterns << %r{(?:#{ignored_extensions.join('|')})$}
48
- end
49
- end
50
- end
51
-
52
- # Initializes a directory record.
53
- #
54
- # @option [String] directory the directory to keep track of
55
- #
56
- def initialize(directory)
57
- raise ArgumentError, "The path '#{directory}' is not a directory!" unless File.directory?(directory)
58
-
59
- @directory = directory
60
- @ignoring_patterns = Set.new
61
- @filtering_patterns = Set.new
62
- @sha1_checksums = Hash.new
63
-
64
- @ignoring_patterns.merge(DirectoryRecord.generate_default_ignoring_patterns)
65
- end
66
-
67
- # Returns the ignoring patterns in the record
68
- #
69
- # @return [Array<Regexp>] the ignoring patterns
70
- #
71
- def ignoring_patterns
72
- @ignoring_patterns.to_a
73
- end
74
-
75
- # Returns the filtering patterns used in the record to know
76
- # which paths should be stored.
77
- #
78
- # @return [Array<Regexp>] the filtering patterns
79
- #
80
- def filtering_patterns
81
- @filtering_patterns.to_a
82
- end
83
-
84
- # Adds ignoring patterns to the record.
85
- #
86
- # @example Ignore some paths
87
- # ignore %r{^ignored/path/}, /man/
88
- #
89
- # @param [Regexp] regexp a pattern for ignoring paths
90
- #
91
- def ignore(*regexps)
92
- @ignoring_patterns.merge(regexps)
93
- end
94
-
95
- # Replaces ignoring patterns in the record.
96
- #
97
- # @example Ignore only these paths
98
- # ignore! %r{^ignored/path/}, /man/
99
- #
100
- # @param [Regexp] regexp a pattern for ignoring paths
101
- #
102
- def ignore!(*regexps)
103
- @ignoring_patterns.replace(regexps)
104
- end
105
-
106
- # Adds filtering patterns to the listener.
107
- #
108
- # @example Filter some files
109
- # ignore /\.txt$/, /.*\.zip/
110
- #
111
- # @param [Regexp] regexp a pattern for filtering paths
112
- #
113
- def filter(*regexps)
114
- @filtering_patterns.merge(regexps)
115
- end
116
-
117
- # Replaces filtering patterns in the listener.
118
- #
119
- # @example Filter only these files
120
- # ignore /\.txt$/, /.*\.zip/
121
- #
122
- # @param [Regexp] regexp a pattern for filtering paths
123
- #
124
- def filter!(*regexps)
125
- @filtering_patterns.replace(regexps)
126
- end
127
-
128
- # Returns whether a path should be ignored or not.
129
- #
130
- # @param [String] path the path to test.
131
- #
132
- # @return [Boolean]
133
- #
134
- def ignored?(path)
135
- path = relative_to_base(path)
136
- @ignoring_patterns.any? { |pattern| pattern =~ path }
137
- end
138
-
139
- # Returns whether a path should be filtered or not.
140
- #
141
- # @param [String] path the path to test.
142
- #
143
- # @return [Boolean]
144
- #
145
- def filtered?(path)
146
- # When no filtering patterns are set, ALL files are stored.
147
- return true if @filtering_patterns.empty?
148
-
149
- path = relative_to_base(path)
150
- @filtering_patterns.any? { |pattern| pattern =~ path }
151
- end
152
-
153
- # Finds the paths that should be stored and adds them
154
- # to the paths' hash.
155
- #
156
- def build
157
- @paths = Hash.new { |h, k| h[k] = Hash.new }
158
- important_paths { |path| insert_path(path) }
159
- end
160
-
161
- # Detects changes in the passed directories, updates
162
- # the record with the new changes and returns the changes
163
- #
164
- # @param [Array] directories the list of directories scan for changes
165
- # @param [Hash] options
166
- # @option options [Boolean] recursive scan all sub-directories recursively
167
- # @option options [Boolean] relative_paths whether or not to use relative paths for changes
168
- #
169
- # @return [Hash<Array>] the changes
170
- #
171
- def fetch_changes(directories, options = {})
172
- @changes = { :modified => [], :added => [], :removed => [] }
173
- directories = directories.sort_by { |el| el.length }.reverse # diff sub-dir first
174
-
175
- directories.each do |directory|
176
- next unless directory[@directory] # Path is or inside directory
177
- detect_modifications_and_removals(directory, options)
178
- detect_additions(directory, options)
179
- end
180
-
181
- @changes
182
- end
183
-
184
- # Converts an absolute path to a path that's relative to the base directory.
185
- #
186
- # @param [String] path the path to convert
187
- #
188
- # @return [String] the relative path
189
- #
190
- def relative_to_base(path)
191
- return nil unless path[@directory]
192
- path = path.force_encoding("BINARY") if path.respond_to?(:force_encoding)
193
- path.sub(%r{^#{Regexp.quote(@directory)}#{File::SEPARATOR}?}, '')
194
- end
195
-
196
- private
197
-
198
- # Detects modifications and removals recursively in a directory.
199
- #
200
- # @note Modifications detection begins by checking the modification time (mtime)
201
- # of files and then by checking content changes (using SHA1-checksum)
202
- # when the mtime of files is not changed.
203
- #
204
- # @param [String] directory the path to analyze
205
- # @param [Hash] options
206
- # @option options [Boolean] recursive scan all sub-directories recursively
207
- # @option options [Boolean] relative_paths whether or not to use relative paths for changes
208
- #
209
- def detect_modifications_and_removals(directory, options = {})
210
- @paths[directory].each do |basename, meta_data|
211
- path = File.join(directory, basename)
212
-
213
- case meta_data.type
214
- when 'Dir'
215
- if File.directory?(path)
216
- detect_modifications_and_removals(path, options) if options[:recursive]
217
- else
218
- detect_modifications_and_removals(path, { :recursive => true }.merge(options))
219
- @paths[directory].delete(basename)
220
- @paths.delete("#{directory}/#{basename}")
221
- end
222
- when 'File'
223
- if File.exist?(path)
224
- new_mtime = mtime_of(path)
225
-
226
- # First check if we are in the same second (to update checksums)
227
- # before checking the time difference
228
- if (meta_data.mtime.to_i == new_mtime.to_i && content_modified?(path)) || meta_data.mtime < new_mtime
229
- # Update the sha1 checksum of the file
230
- insert_sha1_checksum(path)
231
-
232
- # Update the meta data of the file
233
- meta_data.mtime = new_mtime
234
- @paths[directory][basename] = meta_data
235
-
236
- @changes[:modified] << (options[:relative_paths] ? relative_to_base(path) : path)
237
- end
238
- else
239
- @paths[directory].delete(basename)
240
- @sha1_checksums.delete(path)
241
- @changes[:removed] << (options[:relative_paths] ? relative_to_base(path) : path)
242
- end
243
- end
244
- end
245
- end
246
-
247
- # Detects additions in a directory.
248
- #
249
- # @param [String] directory the path to analyze
250
- # @param [Hash] options
251
- # @option options [Boolean] recursive scan all sub-directories recursively
252
- # @option options [Boolean] relative_paths whether or not to use relative paths for changes
253
- #
254
- def detect_additions(directory, options = {})
255
- # Don't process removed directories
256
- return unless File.exist?(directory)
257
-
258
- Find.find(directory) do |path|
259
- next if path == @directory
260
-
261
- if File.directory?(path)
262
- # Add a trailing slash to directories when checking if a directory is
263
- # ignored to optimize finding them as Find.find doesn't.
264
- if ignored?(path + File::SEPARATOR) || (directory != path && (!options[:recursive] && existing_path?(path)))
265
- Find.prune # Don't look any further into this directory.
266
- else
267
- insert_path(path)
268
- end
269
- elsif !ignored?(path) && filtered?(path) && !existing_path?(path)
270
- if File.file?(path)
271
- @changes[:added] << (options[:relative_paths] ? relative_to_base(path) : path)
272
- insert_path(path)
273
- end
274
- end
275
- end
276
- end
277
-
278
- # Returns whether or not a file's content has been modified by
279
- # comparing the SHA1-checksum to a stored one.
280
- # Ensure that the SHA1-checksum is inserted to the sha1_checksums
281
- # array for later comparaison if false.
282
- #
283
- # @param [String] path the file path
284
- #
285
- def content_modified?(path)
286
- @sha1_checksum = sha1_checksum(path)
287
- if @sha1_checksums[path] == @sha1_checksum || !@sha1_checksums.key?(path)
288
- insert_sha1_checksum(path)
289
- false
290
- else
291
- true
292
- end
293
- end
294
-
295
- # Inserts a SHA1-checksum path in @SHA1-checksums hash.
296
- #
297
- # @param [String] path the SHA1-checksum path to insert in @sha1_checksums.
298
- #
299
- def insert_sha1_checksum(path)
300
- if @sha1_checksum ||= sha1_checksum(path)
301
- @sha1_checksums[path] = @sha1_checksum
302
- @sha1_checksum = nil
303
- end
304
- end
305
-
306
- # Returns the SHA1-checksum for the file path.
307
- #
308
- # @param [String] path the file path
309
- #
310
- def sha1_checksum(path)
311
- Digest::SHA1.file(path).to_s
312
- rescue Errno::EACCES, Errno::ENOENT, Errno::ENXIO, Errno::EOPNOTSUPP
313
- nil
314
- end
315
-
316
- # Traverses the base directory looking for paths that should
317
- # be stored; thus paths that are filters or not ignored.
318
- #
319
- # @yield [path] an important path
320
- #
321
- def important_paths
322
- Find.find(@directory) do |path|
323
- next if path == @directory
324
-
325
- if File.directory?(path)
326
- # Add a trailing slash to directories when checking if a directory is
327
- # ignored to optimize finding them as Find.find doesn't.
328
- if ignored?(path + File::SEPARATOR)
329
- Find.prune # Don't look any further into this directory.
330
- else
331
- yield(path)
332
- end
333
- elsif !ignored?(path) && filtered?(path)
334
- yield(path)
335
- end
336
- end
337
- end
338
-
339
- # Inserts a path with its type (Dir or File) in paths hash.
340
- #
341
- # @param [String] path the path to insert in @paths.
342
- #
343
- def insert_path(path)
344
- meta_data = MetaData.new
345
- meta_data.type = File.directory?(path) ? 'Dir' : 'File'
346
- meta_data.mtime = mtime_of(path) unless meta_data.type == 'Dir' # mtimes of dirs are not used yet
347
- @paths[File.dirname(path)][File.basename(path)] = meta_data
348
- rescue Errno::ENOENT
349
- end
350
-
351
- # Returns whether or not a path exists in the paths hash.
352
- #
353
- # @param [String] path the path to check
354
- #
355
- # @return [Boolean]
356
- #
357
- def existing_path?(path)
358
- @paths[File.dirname(path)][File.basename(path)] != nil
359
- end
360
-
361
- # Returns the modification time of a file based on the precision defined by the system
362
- #
363
- # @param [String] file the file for which the mtime must be returned
364
- #
365
- # @return [Fixnum, Float] the mtime of the file
366
- #
367
- def mtime_of(file)
368
- File.lstat(file).mtime.send(HIGH_PRECISION_SUPPORTED ? :to_f : :to_i)
369
- end
370
- end
371
- end