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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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