Class: Textus::Store::Sentinel
- Inherits:
-
Object
- Object
- Textus::Store::Sentinel
- 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).
Repo-relative target/source on write so example trees can be committed without leaking the author’s absolute filesystem paths. Legacy absolute paths are still accepted on read.
Constant Summary collapse
- SUFFIX =
".textus-managed.json".freeze
- DIR =
"sentinels".freeze
Instance Attribute Summary collapse
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
-
#sha256 ⇒ Object
readonly
Returns the value of attribute sha256.
-
#source ⇒ Object
readonly
Returns the value of attribute source.
-
#target ⇒ Object
readonly
Returns the value of attribute target.
Class Method Summary collapse
- .absolutize(path, repo_root) ⇒ Object
- .legacy_path(target) ⇒ Object
- .load(path, repo_root) ⇒ Object
- .rel_or_abs(path, repo_root) ⇒ Object
- .relative_to(path, repo_root) ⇒ Object
- .sentinel_path(target, store_root) ⇒ Object
- .write!(target:, source:, store_root:) ⇒ Object
Instance Method Summary collapse
- #drift? ⇒ Boolean
-
#initialize(target:, source:, sha256:, mode:) ⇒ Sentinel
constructor
A new instance of Sentinel.
- #orphan? ⇒ Boolean
Constructor Details
#initialize(target:, source:, sha256:, mode:) ⇒ Sentinel
Returns a new instance of Sentinel.
74 75 76 77 78 79 |
# File 'lib/textus/store/sentinel.rb', line 74 def initialize(target:, source:, sha256:, mode:) @target = target @source = source @sha256 = sha256 @mode = mode end |
Instance Attribute Details
#mode ⇒ Object (readonly)
Returns the value of attribute mode.
19 20 21 |
# File 'lib/textus/store/sentinel.rb', line 19 def mode @mode end |
#sha256 ⇒ Object (readonly)
Returns the value of attribute sha256.
19 20 21 |
# File 'lib/textus/store/sentinel.rb', line 19 def sha256 @sha256 end |
#source ⇒ Object (readonly)
Returns the value of attribute source.
19 20 21 |
# File 'lib/textus/store/sentinel.rb', line 19 def source @source end |
#target ⇒ Object (readonly)
Returns the value of attribute target.
19 20 21 |
# File 'lib/textus/store/sentinel.rb', line 19 def target @target end |
Class Method Details
.absolutize(path, repo_root) ⇒ Object
67 68 69 70 71 72 |
# File 'lib/textus/store/sentinel.rb', line 67 def self.absolutize(path, repo_root) return path if path.nil? return path if File.absolute_path?(path) File.(path, repo_root) end |
.legacy_path(target) ⇒ Object
51 52 53 |
# File 'lib/textus/store/sentinel.rb', line 51 def self.legacy_path(target) target + SUFFIX end |
.load(path, repo_root) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/textus/store/sentinel.rb', line 33 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
55 56 57 |
# File 'lib/textus/store/sentinel.rb', line 55 def self.rel_or_abs(path, repo_root) relative_to(path, repo_root) || File.(path) end |
.relative_to(path, repo_root) ⇒ Object
59 60 61 62 63 64 65 |
# File 'lib/textus/store/sentinel.rb', line 59 def self.relative_to(path, repo_root) path = File.(path) base = File.(repo_root) return nil unless path.start_with?(base + File::SEPARATOR) path[(base.length + 1)..] end |
.sentinel_path(target, store_root) ⇒ Object
45 46 47 48 49 |
# File 'lib/textus/store/sentinel.rb', line 45 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
21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/textus/store/sentinel.rb', line 21 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
85 86 87 88 89 90 |
# File 'lib/textus/store/sentinel.rb', line 85 def drift? return false if orphan? return false if @sha256.nil? Digest::SHA256.hexdigest(File.binread(@target)) != @sha256 end |
#orphan? ⇒ Boolean
81 82 83 |
# File 'lib/textus/store/sentinel.rb', line 81 def orphan? @target.nil? || !File.exist?(@target) end |