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.



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

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



145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/listen/directory_record.rb', line 145

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



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

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

#filtered?(path) ⇒ Boolean

Returns whether a path should be filtered or not.

Parameters:

  • path (String)

    the path to test.

Returns:

  • (Boolean)


119
120
121
122
123
124
125
# File 'lib/listen/directory_record.rb', line 119

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

#ignored?(path) ⇒ Boolean

Returns whether a path should be ignored or not.

Parameters:

  • path (String)

    the path to test.

Returns:

  • (Boolean)


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

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



164
165
166
167
# File 'lib/listen/directory_record.rb', line 164

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