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 =
%w[.rbx .bundle .git .svn log tmp vendor]
DEFAULT_IGNORED_EXTENSIONS =
%w[.DS_Store]
HIGH_PRECISION_SUPPORTED =

Defines the used precision based on the type of mtime returned by the system (whether its in milliseconds or just seconds)

File.mtime(__FILE__).to_f.to_s[-2..-1] != '.0'

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)


52
53
54
55
56
57
58
59
60
61
# File 'lib/listen/directory_record.rb', line 52

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

  @directory          = directory
  @ignoring_patterns  = Set.new
  @filtering_patterns = Set.new
  @sha1_checksums     = Hash.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.



35
36
37
38
39
40
41
42
43
44
45
# File 'lib/listen/directory_record.rb', line 35

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.



152
153
154
155
# File 'lib/listen/directory_record.rb', line 152

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 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



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/listen/directory_record.rb', line 167

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 listener.

Examples:

Filter some files

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

Parameters:

  • regexp (Regexp)

    a pattern for filtering paths



109
110
111
# File 'lib/listen/directory_record.rb', line 109

def filter(*regexps)
  @filtering_patterns.merge(regexps)
end

#filter!(*regexps) ⇒ Object

Replaces filtering patterns in the listener.

Examples:

Filter only these files

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

Parameters:

  • regexp (Regexp)

    a pattern for filtering paths



120
121
122
# File 'lib/listen/directory_record.rb', line 120

def filter!(*regexps)
  @filtering_patterns.replace(regexps)
end

#filtered?(path) ⇒ Boolean

Returns whether a path should be filtered or not.

Parameters:

  • path (String)

    the path to test.

Returns:

  • (Boolean)


141
142
143
144
145
146
147
# File 'lib/listen/directory_record.rb', line 141

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 used in the record to know which paths should be stored.

Returns:

  • (Array<Regexp>)

    the filtering patterns



76
77
78
# File 'lib/listen/directory_record.rb', line 76

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:

  • regexp (Regexp)

    a pattern for ignoring paths



87
88
89
# File 'lib/listen/directory_record.rb', line 87

def ignore(*regexps)
  @ignoring_patterns.merge(regexps)
end

#ignore!(*regexps) ⇒ Object

Replaces ignoring patterns in the record.

Examples:

Ignore only these paths

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

Parameters:

  • regexp (Regexp)

    a pattern for ignoring paths



98
99
100
# File 'lib/listen/directory_record.rb', line 98

def ignore!(*regexps)
  @ignoring_patterns.replace(regexps)
end

#ignored?(path) ⇒ Boolean

Returns whether a path should be ignored or not.

Parameters:

  • path (String)

    the path to test.

Returns:

  • (Boolean)


130
131
132
133
# File 'lib/listen/directory_record.rb', line 130

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

Returns:

  • (Array<Regexp>)

    the ignoring patterns



67
68
69
# File 'lib/listen/directory_record.rb', line 67

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



186
187
188
189
# File 'lib/listen/directory_record.rb', line 186

def relative_to_base(path)
  return nil unless path[@directory]
  path.sub(%r{^#{Regexp.quote(@directory)}#{File::SEPARATOR}?}, '')
end