Class: Driskell::Listen::Directory

Inherits:
Object
  • Object
show all
Defined in:
lib/driskell-listen/directory.rb

Overview

TODO: refactor (turn it into a normal object, cache the stat, etc)

Class Method Summary collapse

Class Method Details

.detect_type(full_path) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/driskell-listen/directory.rb', line 78

def self.detect_type(full_path)
  stat = ::File.lstat(full_path.to_s)
  stat.directory? ? :dir : :file
rescue Errno::ENOENT
  # report as dir for scanning
  :dir
end

.process_previous(snapshot, path, previous, options) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/driskell-listen/directory.rb', line 70

def self.process_previous(snapshot, path, previous, options)
  previous.each do |entry, data|
    type = data.key?(:mtime) ? :file : :tree
    rel_path_s = (path + entry).to_s
    snapshot.invalidate(type, rel_path_s, options)
  end
end

.scan(snapshot, rel_path, options) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/driskell-listen/directory.rb', line 6

def self.scan(snapshot, rel_path, options)
  record = snapshot.record

  # Grab previous entries - and dup so we don't tamper with original list
  previous = record.dir_entries(rel_path).dup

  dir = Pathname.new(record.root)
  path = dir + rel_path
  current = Set.new(path.children)

  Driskell::Listen::Logger.debug do
    format('%s: %s(%s): %s -> %s',
           (options[:silence] ? 'Recording' : 'Scanning'),
           rel_path, options.inspect, previous.inspect, current.inspect)
  end

  record.update_dir(rel_path)

  current.each do |item_full_path|
    item_basename = item_full_path.basename.to_s

    # Find old type so we can ensure we invalidate directory contents
    # if we were previously a file, and vice versa
    if previous.key?(item_basename)
      old = previous.delete(item_basename)
      old_type = old.key?(:mtime) ? :file : :dir
    else
      old_type = nil
    end

    item_rel_path = item_full_path.relative_path_from(dir).to_s
    if detect_type(item_full_path) == :dir
      if old_type == :file
        snapshot.invalidate(:file, item_rel_path, options)
      end

      # Only invalidate subdirectories if we're recursing or it is new
      if options[:recurse] || old_type.nil?
        snapshot.invalidate(:tree, item_rel_path, options)
      end
    else
      if old_type == :dir
        snapshot.invalidate(:tree, item_rel_path, options)
      end

      snapshot.invalidate(:file, item_rel_path, options)
    end
  end

  process_previous(snapshot, Pathname.new(rel_path), previous, options)
rescue Errno::ENOENT, Errno::EHOSTDOWN
  record.unset_path(rel_path)
  process_previous(snapshot, Pathname.new(rel_path), previous, options)
rescue Errno::ENOTDIR
  record.unset_path(rel_path)
  process_previous(snapshot, path, previous, options)
  snapshot.invalidate(:file, rel_path, options)
rescue
  Driskell::Listen::Logger.warn do
    format('scan DIED: %s:%s', $ERROR_INFO, $ERROR_POSITION * "\n")
  end
  raise
end