Class: Ibex::Watch::SourceSnapshot

Inherits:
Object
  • Object
show all
Defined in:
lib/ibex/watch/source_snapshot.rb,
sig/ibex/watch/source_snapshot.rbs

Overview

Stable metadata and content fingerprints for watched source paths.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(paths) ⇒ SourceSnapshot

Returns a new instance of SourceSnapshot.

RBS:

  • (Array[String] paths) -> void

Parameters:

  • paths (Array[String])


17
18
19
20
21
# File 'lib/ibex/watch/source_snapshot.rb', line 17

def initialize(paths)
  @paths = paths.map { |path| File.expand_path(path) }.uniq.sort.freeze
  @entries = @paths.to_h { |path| [path, fingerprint(path)] }.freeze #: Hash[String, fingerprint]
  freeze
end

Instance Attribute Details

#entriesHash[String, fingerprint] (readonly)

Signature:

  • Hash[String, fingerprint]

Returns:



38
39
40
# File 'lib/ibex/watch/source_snapshot.rb', line 38

def entries
  @entries
end

#pathsArray[String] (readonly)

RBS:

  • type fingerprint_value = Symbol | String | Integer | nil | Hash[Symbol, fingerprint_value]
    type fingerprint = Hash[Symbol, fingerprint_value]

Returns:

  • (Array[String])


14
15
16
# File 'lib/ibex/watch/source_snapshot.rb', line 14

def paths
  @paths
end

Instance Method Details

#==(other) ⇒ Boolean

RBS:

  • (SourceSnapshot other) -> bool

Parameters:

Returns:

  • (Boolean)


24
25
26
# File 'lib/ibex/watch/source_snapshot.rb', line 24

def ==(other)
  @entries == other.__send__(:entries)
end

#add_resolved_target(value, path) ⇒ void

This method returns an undefined value.

RBS:

  • (fingerprint value, String path) -> void

Parameters:



86
87
88
89
90
91
92
93
94
95
# File 'lib/ibex/watch/source_snapshot.rb', line 86

def add_resolved_target(value, path)
  target = File.realpath(path)
  stat = File.stat(target)
  value[:resolved_path] = target
  resolved = stat_signature(stat)
  resolved[:sha256] = Digest::SHA256.file(target).hexdigest if stat.file?
  value[:resolved] = resolved
rescue SystemCallError => e
  value[:resolved] = { kind: :error, error: e.class.name, errno: e.respond_to?(:errno) ? e.errno : nil }
end

#entry(path) ⇒ fingerprint?

RBS:

  • (String path) -> fingerprint?

Parameters:

  • path (String)

Returns:



41
42
43
# File 'lib/ibex/watch/source_snapshot.rb', line 41

def entry(path)
  @entries[path]
end

#file_kind(stat) ⇒ Symbol

RBS:

  • (File::Stat stat) -> Symbol

Parameters:

  • stat (File::Stat)

Returns:

  • (Symbol)


72
73
74
75
76
77
78
# File 'lib/ibex/watch/source_snapshot.rb', line 72

def file_kind(stat)
  return :file if stat.file?
  return :directory if stat.directory?
  return :symlink if stat.symlink?

  :other
end

#fingerprint(path) ⇒ fingerprint

RBS:

  • (String path) -> fingerprint

Parameters:

  • path (String)

Returns:



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/ibex/watch/source_snapshot.rb', line 48

def fingerprint(path)
  stat = File.lstat(path)
  value = stat_signature(stat)
  if stat.symlink?
    value[:readlink] = File.readlink(path)
    add_resolved_target(value, path)
  else
    value[:resolved_path] = File.realpath(path)
    value[:sha256] = Digest::SHA256.file(path).hexdigest if stat.file?
  end
  value
rescue SystemCallError => e
  { kind: :error, error: e.class.name, errno: e.respond_to?(:errno) ? e.errno : nil }
end

#nanoseconds(time) ⇒ Integer

RBS:

  • (Time time) -> Integer

Parameters:

  • time (Time)

Returns:

  • (Integer)


81
82
83
# File 'lib/ibex/watch/source_snapshot.rb', line 81

def nanoseconds(time)
  (time.to_i * 1_000_000_000) + time.nsec
end

#stat_signature(stat) ⇒ fingerprint

RBS:

  • (File::Stat stat) -> fingerprint

Parameters:

  • stat (File::Stat)

Returns:



64
65
66
67
68
69
# File 'lib/ibex/watch/source_snapshot.rb', line 64

def stat_signature(stat)
  {
    kind: file_kind(stat), dev: stat.dev, ino: stat.ino, size: stat.size,
    mtime_ns: nanoseconds(stat.mtime), ctime_ns: nanoseconds(stat.ctime)
  }
end

#unchanged_since?(older) ⇒ Boolean

Every path in this snapshot must have had the same value in the older snapshot.

RBS:

  • (SourceSnapshot older) -> bool

Parameters:

Returns:

  • (Boolean)


30
31
32
33
34
# File 'lib/ibex/watch/source_snapshot.rb', line 30

def unchanged_since?(older)
  @paths.all? do |path|
    older.__send__(:entry, path) == @entries.fetch(path)
  end
end