Class: Textus::Store::Sentinel

Inherits:
Object
  • Object
show all
Defined in:
lib/textus/store/sentinel.rb

Overview

Value object for sentinel files written by Infra::Publisher and inspected by Doctor::Check::Sentinels. Owns the JSON shape (target, sha256, mode) and the on-disk path layout (<store_root>/sentinels/ <target-rel-to-repo>.textus-managed.json). Target/source are repo-relative when the published file is under the repo root, absolute otherwise.

Constant Summary collapse

SUFFIX =
".textus-managed.json".freeze
DIR =
"sentinels".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target:, source:, sha256:, mode:) ⇒ Sentinel

Returns a new instance of Sentinel.



67
68
69
70
71
72
# File 'lib/textus/store/sentinel.rb', line 67

def initialize(target:, source:, sha256:, mode:)
  @target = target
  @source = source
  @sha256 = sha256
  @mode = mode
end

Instance Attribute Details

#modeObject (readonly)

Returns the value of attribute mode.



16
17
18
# File 'lib/textus/store/sentinel.rb', line 16

def mode
  @mode
end

#sha256Object (readonly)

Returns the value of attribute sha256.



16
17
18
# File 'lib/textus/store/sentinel.rb', line 16

def sha256
  @sha256
end

#sourceObject (readonly)

Returns the value of attribute source.



16
17
18
# File 'lib/textus/store/sentinel.rb', line 16

def source
  @source
end

#targetObject (readonly)

Returns the value of attribute target.



16
17
18
# File 'lib/textus/store/sentinel.rb', line 16

def target
  @target
end

Class Method Details

.absolutize(path, repo_root) ⇒ Object



60
61
62
63
64
65
# File 'lib/textus/store/sentinel.rb', line 60

def self.absolutize(path, repo_root)
  return path if path.nil?
  return path if File.absolute_path?(path)

  File.expand_path(path, repo_root)
end

.load(path, repo_root) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/textus/store/sentinel.rb', line 30

def self.load(path, repo_root)
  raw = JSON.parse(File.read(path))
  new(
    target: absolutize(raw["target"], repo_root),
    source: absolutize(raw["source"], repo_root),
    sha256: raw["sha256"],
    mode: raw["mode"],
  )
rescue JSON::ParserError, Errno::ENOENT
  nil
end

.rel_or_abs(path, repo_root) ⇒ Object



48
49
50
# File 'lib/textus/store/sentinel.rb', line 48

def self.rel_or_abs(path, repo_root)
  relative_to(path, repo_root) || File.expand_path(path)
end

.relative_to(path, repo_root) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/textus/store/sentinel.rb', line 52

def self.relative_to(path, repo_root)
  path = File.expand_path(path)
  base = File.expand_path(repo_root)
  return nil unless path.start_with?(base + File::SEPARATOR)

  path[(base.length + 1)..]
end

.sentinel_path(target, store_root) ⇒ Object



42
43
44
45
46
# File 'lib/textus/store/sentinel.rb', line 42

def self.sentinel_path(target, store_root)
  repo_root = File.dirname(store_root)
  rel = relative_to(target, repo_root) || File.basename(target)
  File.join(store_root, DIR, rel + SUFFIX)
end

.write!(target:, source:, store_root:) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
# File 'lib/textus/store/sentinel.rb', line 18

def self.write!(target:, source:, store_root:)
  path = sentinel_path(target, store_root)
  FileUtils.mkdir_p(File.dirname(path))
  repo_root = File.dirname(store_root)
  File.write(path, JSON.generate(
                     "source" => rel_or_abs(source, repo_root),
                     "target" => rel_or_abs(target, repo_root),
                     "sha256" => Digest::SHA256.hexdigest(File.binread(target)),
                     "mode" => "copy",
                   ))
end

Instance Method Details

#drift?Boolean

Returns:

  • (Boolean)


78
79
80
81
82
83
# File 'lib/textus/store/sentinel.rb', line 78

def drift?
  return false if orphan?
  return false if @sha256.nil?

  Digest::SHA256.hexdigest(File.binread(@target)) != @sha256
end

#orphan?Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/textus/store/sentinel.rb', line 74

def orphan?
  @target.nil? || !File.exist?(@target)
end