Class: OKF::Pro::Target
- Inherits:
-
Object
- Object
- OKF::Pro::Target
- Defined in:
- lib/okf/pro/target.rb
Overview
The bundle root plus the edited path made relative to it.
.for returns nil whenever a check cannot apply — no bundle under the
working directory, a path outside it, not markdown, or behind a dot,
which is the same boundary okf itself walks. A file at the repository
root is outside now: README.md and CLAUDE.md are documentation and
instructions, not concepts, and no conformance rule reaches them.
Nil is a real answer here and not a failure: a check that does not apply
has nothing to say, and saying nothing is different from passing something
it could not read. The checks distinguish the two.
Instance Attribute Summary collapse
-
#rel ⇒ Object
readonly
Returns the value of attribute rel.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Class Method Summary collapse
- .for(event) ⇒ Object
-
.relative(path, root) ⇒ Object
Relative to the bundle root, or nil when the path is outside it.
Instance Method Summary collapse
- #basename ⇒ Object
-
#bundle ⇒ Object
Read once per process.
- #exist?(name) ⇒ Boolean
- #id ⇒ Object
-
#initialize(root, rel) ⇒ Target
constructor
A new instance of Target.
-
#read(name) ⇒ Object
A Target holds its root, so every read through it is contained: a
board.mdthat is a symlink out of the bundle is not this bundle's board, and the gates must not read it as one.
Constructor Details
Instance Attribute Details
#rel ⇒ Object (readonly)
Returns the value of attribute rel.
16 17 18 |
# File 'lib/okf/pro/target.rb', line 16 def rel @rel end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
16 17 18 |
# File 'lib/okf/pro/target.rb', line 16 def root @root end |
Class Method Details
.for(event) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/okf/pro/target.rb', line 18 def self.for(event) # The file's own ancestry decides which bundle governs it — alone. # There used to be a cwd fallback here, and it was a fence bypass: # containing() would refuse a file inside a nested repository, and # resolve(cwd) — which neither walks nor fences — would re-adopt it # through the physical-prefix check below whenever the session sat # in a root-layout bundle. A file genuinely inside a bundle is # found by its own walk — the walk's classifier accepts a # versioned index or any core file beside a bare one, so even a # mid-bootstrap bundle governs its files; only an index.md truly # alone is ambiguous with a directory index, and the walk refuses # to guess. The fallback could only ever add adoptions the walk # had refused. root = BundleRoot.containing(event.file_path) return nil if root.nil? rel = relative(event.file_path, root) return nil if rel.nil? || !rel.end_with?(".md") return nil if rel.split("/").any? { |seg| seg.start_with?(".") } new(root, rel) end |
.relative(path, root) ⇒ Object
Relative to the bundle root, or nil when the path is outside it. Made
relative before the dot test on purpose: an absolute path can pass
through /Users/someone/.local/... and have nothing dot-prefixed about
the file itself.
45 46 47 48 49 50 |
# File 'lib/okf/pro/target.rb', line 45 def self.relative(path, root) return nil if path.to_s.empty? full = File.(path) full.start_with?("#{root}/") ? full[(root.size + 1)..-1] : nil end |
Instance Method Details
#basename ⇒ Object
68 69 70 |
# File 'lib/okf/pro/target.rb', line 68 def basename File.basename(rel) end |
#bundle ⇒ Object
Read once per process. Three PostToolUse checks want the same bundle,
and the read is the expensive part — it is the whole reason they arrive
as one post-edit invocation rather than three.
60 61 62 |
# File 'lib/okf/pro/target.rb', line 60 def bundle @bundle ||= ::OKF::Bundle::Reader.read(root) end |
#exist?(name) ⇒ Boolean
86 87 88 |
# File 'lib/okf/pro/target.rb', line 86 def exist?(name) File.exist?(File.join(root, name)) end |
#id ⇒ Object
64 65 66 |
# File 'lib/okf/pro/target.rb', line 64 def id rel.sub(/\.md\z/, "") end |
#read(name) ⇒ Object
A Target holds its root, so every read through it is contained: a
board.md that is a symlink out of the bundle is not this bundle's
board, and the gates must not read it as one.
Raises rather than rescuing. A caller asking a Target to read a named
core file has already established the file exists (exist? above), so
a Path::Error here is a real containment failure — and the dispatch
rescue in CLI.run turns any exception into a refusal, which is the
correct answer to "something outside the bundle is pretending to be
inside it".
82 83 84 |
# File 'lib/okf/pro/target.rb', line 82 def read(name) Pro.read_contained(root, File.join(root, name)) end |