Class: Listen::DirectoryRecord

Inherits:
Object
  • Object
show all
Defined in:
lib/listen/directory_record.rb

Overview

The directory record stores information about a directory and keeps track of changes to the structure of its childs.

Defined Under Namespace

Classes: MetaData

Constant Summary collapse

DEFAULT_IGNORED_DIRECTORIES =

The default list of directories that get ignored by the listener.

%w[.rbx .bundle .git .svn log tmp vendor]
DEFAULT_IGNORED_EXTENSIONS =

The default list of files that get ignored by the listener.

%w[.DS_Store]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(directory) ⇒ DirectoryRecord

Initializes a directory record.

Parameters:

  • [String] (Hash)

    a customizable set of options

Raises:

  • (ArgumentError)


58
59
60
61
62
63
64
65
# File 'lib/listen/directory_record.rb', line 58

def initialize(directory)
  raise ArgumentError, "The path '#{directory}' is not a directory!" unless File.directory?(directory)

  @directory, @sha1_checksums = directory, Hash.new
  @ignoring_patterns, @filtering_patterns = Set.new, Set.new

  @ignoring_patterns.merge(DirectoryRecord.generate_default_ignoring_patterns)
end

Instance Attribute Details

#directoryObject (readonly)

Returns the value of attribute directory.



12
13
14
# File 'lib/listen/directory_record.rb', line 12

def directory
  @directory
end

#pathsObject (readonly)

Returns the value of attribute paths.



12
13
14
# File 'lib/listen/directory_record.rb', line 12

def paths
  @paths
end

#sha1_checksumsObject (readonly)

Returns the value of attribute sha1_checksums.



12
13
14
# File 'lib/listen/directory_record.rb', line 12

def sha1_checksums
  @sha1_checksums
end

Class Method Details

.generate_default_ignoring_patternsObject

Creates the ignoring patterns from the default ignored directories and extensions. It memoizes the generated patterns to avoid unnecessary computation.



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/listen/directory_record.rb', line 41

def generate_default_ignoring_patterns
  @@default_ignoring_patterns ||= Array.new.tap do |default_patterns|
    # Add directories
    ignored_directories = DEFAULT_IGNORED_DIRECTORIES.map { |d| Regexp.escape(d) }
    default_patterns << %r{^(?:#{ignored_directories.join('|')})/}

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

Instance Method Details

#buildObject

Finds the paths that should be stored and adds them to the paths’ hash.



157
158
159
160
# File 'lib/listen/directory_record.rb', line 157

def build
  @paths = Hash.new { |h, k| h[k] = Hash.new }
  important_paths { |path| insert_path(path) }
end

#fetch_changes(directories, options = {}) ⇒ Hash<Array>

Detects changes in the passed directories, updates the record with the new changes and returns the changes.

Parameters:

  • directories (Array)

    the list of directories to scan for changes

  • options (Hash) (defaults to: {})

Options Hash (options):

  • recursive (Boolean)

    scan all sub-directories recursively

  • relative_paths (Boolean)

    whether or not to use relative paths for changes

Returns:

  • (Hash<Array>)

    the changes



172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/listen/directory_record.rb', line 172

def fetch_changes(directories, options = {})
  @changes    = { :modified => [], :added => [], :removed => [] }
  directories = directories.sort_by { |el| el.length }.reverse # diff sub-dir first

  directories.each do |directory|
    next unless directory[@directory] # Path is or inside directory

    detect_modifications_and_removals(directory, options)
    detect_additions(directory, options)
  end

  @changes
end

#filter(*regexps) ⇒ Object

Adds filtering patterns to the record.

Examples:

Filter some files

filter /\.txt$/, /.*\.zip/

Parameters:

  • regexps (Regexp)

    a list of patterns for filtering files



114
115
116
# File 'lib/listen/directory_record.rb', line 114

def filter(*regexps)
  @filtering_patterns.merge(regexps).reject! { |r| r.nil? }
end

#filter!(*regexps) ⇒ Object

Replaces filtering patterns in the record.

Examples:

Filter only these files

filter! /\.txt$/, /.*\.zip/

Parameters:

  • regexps (Regexp)

    a list of patterns for filtering files



125
126
127
# File 'lib/listen/directory_record.rb', line 125

def filter!(*regexps)
  @filtering_patterns.replace(regexps).reject! { |r| r.nil? }
end

#filtered?(path) ⇒ Boolean

Returns whether a path should be filtered or not.

Parameters:

  • path (String)

    the path to test

Returns:

  • (Boolean)


146
147
148
149
150
151
152
# File 'lib/listen/directory_record.rb', line 146

def filtered?(path)
  # When no filtering patterns are set, ALL files are stored.
  return true if @filtering_patterns.empty?

  path = relative_to_base(path)
  @filtering_patterns.any? { |pattern| pattern =~ path }
end

#filtering_patternsArray<Regexp>

Returns the filtering patterns in the record to know which paths should be stored.

Returns:

  • (Array<Regexp>)

    the filtering patterns



81
82
83
# File 'lib/listen/directory_record.rb', line 81

def filtering_patterns
  @filtering_patterns.to_a
end

#ignore(*regexps) ⇒ Object

Adds ignoring patterns to the record.

Examples:

Ignore some paths

ignore %r{^ignored/path/}, /man/

Parameters:

  • regexps (Regexp)

    a list of patterns for ignoring paths



92
93
94
# File 'lib/listen/directory_record.rb', line 92

def ignore(*regexps)
  @ignoring_patterns.merge(regexps).reject! { |r| r.nil? }
end

#ignore!(*regexps) ⇒ Object

Replaces ignoring patterns in the record.

Examples:

Ignore only these paths

ignore! %r{^ignored/path/}, /man/

Parameters:

  • regexps (Regexp)

    a list of patterns for ignoring paths



103
104
105
# File 'lib/listen/directory_record.rb', line 103

def ignore!(*regexps)
  @ignoring_patterns.replace(regexps).reject! { |r| r.nil? }
end

#ignored?(path) ⇒ Boolean

Returns whether a path should be ignored or not.

Parameters:

  • path (String)

    the path to test

Returns:

  • (Boolean)


135
136
137
138
# File 'lib/listen/directory_record.rb', line 135

def ignored?(path)
  path = relative_to_base(path)
  @ignoring_patterns.any? { |pattern| pattern =~ path }
end

#ignoring_patternsArray<Regexp>

Returns the ignoring patterns in the record to know which paths should be ignored.

Returns:

  • (Array<Regexp>)

    the ignoring patterns



72
73
74
# File 'lib/listen/directory_record.rb', line 72

def ignoring_patterns
  @ignoring_patterns.to_a
end

#relative_to_base(path) ⇒ String

Converts an absolute path to a path that’s relative to the base directory.

Parameters:

  • path (String)

    the path to convert

Returns:

  • (String)

    the relative path



192
193
194
195
196
197
# File 'lib/listen/directory_record.rb', line 192

def relative_to_base(path)
  return nil unless path[directory]

  path = path.force_encoding("BINARY") if path.respond_to?(:force_encoding)
  path.sub(%r{^#{Regexp.quote(directory)}#{File::SEPARATOR}?}, '')
end