Class: OKF::Bundle::Folder
- Inherits:
-
Object
- Object
- OKF::Bundle::Folder
- Defined in:
- lib/okf/bundle/folder.rb
Overview
A bundle on disk — the directory-level handle. Reads a directory into a pure OKF::Bundle once, exposes the analyzers over it, and can materialize an in-memory bundle back to disk. Part of the shell.
folder = OKF::Bundle::Folder.load("docs")
folder.bundle # => OKF::Bundle (pure)
folder.validate; folder.lint; folder.graph
folder.concept("tables/orders") # => OKF::Concept::File (or nil)
# build in memory (the Rails / snapshot-publisher path) and write it out:
OKF::Bundle::Folder.new(bundle: pure_bundle, root: "out/dir").save
Instance Attribute Summary collapse
-
#bundle ⇒ Object
readonly
Returns the value of attribute bundle.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Class Method Summary collapse
-
.label(root) ⇒ Object
The bundle's display label — path arithmetic, no disk.
- .load(dir) ⇒ Object
Instance Method Summary collapse
- #catalog ⇒ Object
-
#concept(id) ⇒ Object
A single-file handle for one concept id (read live from disk), or nil when no concept in the loaded bundle has that id.
-
#concept_source(id) ⇒ Object
The raw markdown bytes for one concept id — read once through the same containment guard as #concept, but without the parse #concept pays for, so a caller that wants the file verbatim (never a re-serialized copy) does one read, not a read plus a discarded frontmatter parse.
- #concepts ⇒ Object
- #directories ⇒ Object
- #directory_index ⇒ Object
- #graph(minimal: false, body: true) ⇒ Object
- #hubs ⇒ Object
-
#initialize(bundle:, root:) ⇒ Folder
constructor
A new instance of Folder.
- #lint(**options) ⇒ Object
-
#log_entries ⇒ Object
Every log.md with its content, root scope first — read live from disk so a just-appended entry shows without a reload; the reserved snapshot is the fallback if the file has since vanished.
- #name ⇒ Object
-
#references ⇒ Object
The §6.3 inventory — this handle's half is the disk: the reader models only markdown, so listing
references/here is how a .py attester or a .sql computation becomes visible at all. - #reload ⇒ Object
-
#save(overwrite: false) ⇒ Object
Materialize the in-memory bundle to disk (Writer validates §11 before publishing, so a malformed bundle is never written).
- #skeleton ⇒ Object
- #stats ⇒ Object
- #tag_groups(by:, entries: nil) ⇒ Object
- #validate ⇒ Object
Constructor Details
Instance Attribute Details
#bundle ⇒ Object (readonly)
Returns the value of attribute bundle.
17 18 19 |
# File 'lib/okf/bundle/folder.rb', line 17 def bundle @bundle end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
17 18 19 |
# File 'lib/okf/bundle/folder.rb', line 17 def root @root end |
Class Method Details
.label(root) ⇒ Object
The bundle's display label — path arithmetic, no disk. It is a class method so a caller that only wants the label (the registry naming an entry) can have it without a Reader.read of every file.
"parent/dir", because a bundle directory's own name is rarely unique
enough to name it by — except when that name is .okf, the conventional
container, and then the parent carries the whole answer on its own. A
registry of eight projects is eight rows reading …/.okf, which is the
one word that tells none of them apart; repo/.okf is read as "repo" by
anyone looking at it anyway.
A directory with no parent to borrow (/.okf) keeps its own name: the
parent is /, which names nothing. That case used to compose into
//.okf.
105 106 107 108 109 110 111 112 113 |
# File 'lib/okf/bundle/folder.rb', line 105 def self.label(root) pathname = Pathname.new(root) parent = pathname.parent.basename.to_s base = pathname.basename.to_s return base if [ "/", "." ].include?(parent) return parent if base == ".okf" "#{parent}/#{base}" end |
Instance Method Details
#catalog ⇒ Object
49 50 51 |
# File 'lib/okf/bundle/folder.rb', line 49 def catalog @bundle.catalog end |
#concept(id) ⇒ Object
A single-file handle for one concept id (read live from disk), or nil when no
concept in the loaded bundle has that id. The id may be a frontmatter id, so
it is resolved to a path through the bundle rather than assumed to be "id.md".
122 123 124 125 |
# File 'lib/okf/bundle/folder.rb', line 122 def concept(id) path = @bundle.paths_by_id[id] or return nil Concept::File.read(root: @root, path: path) end |
#concept_source(id) ⇒ Object
The raw markdown bytes for one concept id — read once through the same containment guard as #concept, but without the parse #concept pays for, so a caller that wants the file verbatim (never a re-serialized copy) does one read, not a read plus a discarded frontmatter parse. nil when no concept has that id; raises Path::Error if the file has become a symlink escaping the root, and the reader's own SystemCallError if it has gone.
133 134 135 136 |
# File 'lib/okf/bundle/folder.rb', line 133 def concept_source(id) path = @bundle.paths_by_id[id] or return nil Concept::File.new(root: @root, path: path).read end |
#concepts ⇒ Object
29 30 31 |
# File 'lib/okf/bundle/folder.rb', line 29 def concepts @bundle.concepts end |
#directories ⇒ Object
57 58 59 |
# File 'lib/okf/bundle/folder.rb', line 57 def directories @bundle.directories end |
#directory_index ⇒ Object
61 62 63 |
# File 'lib/okf/bundle/folder.rb', line 61 def directory_index @bundle.directory_index end |
#graph(minimal: false, body: true) ⇒ Object
41 42 43 |
# File 'lib/okf/bundle/folder.rb', line 41 def graph(minimal: false, body: true) @bundle.graph(minimal: minimal, body: body) end |
#hubs ⇒ Object
53 54 55 |
# File 'lib/okf/bundle/folder.rb', line 53 def hubs @bundle.hubs end |
#lint(**options) ⇒ Object
37 38 39 |
# File 'lib/okf/bundle/folder.rb', line 37 def lint(**) @bundle.lint(**) end |
#log_entries ⇒ Object
Every log.md with its content, root scope first — read live from disk so a
just-appended entry shows without a reload; the reserved snapshot is the
fallback if the file has since vanished. Shared by okf render's bake
(OKF::Render::Graph.payload) and OKF::Server::App's /log endpoint.
85 86 87 88 89 |
# File 'lib/okf/bundle/folder.rb', line 85 def log_entries @bundle.log_files.sort_by { |path| [ path == "log.md" ? 0 : 1, path ] }.map do |path| { path: path, dir: File.dirname(path), content: log_content(path) } end end |
#name ⇒ Object
115 116 117 |
# File 'lib/okf/bundle/folder.rb', line 115 def name self.class.label(@root) end |
#references ⇒ Object
The §6.3 inventory — this handle's half is the disk: the reader models
only markdown, so listing references/ here is how a .py attester or a
.sql computation becomes visible at all. The pure model gets the
manifest and answers the rest (citers, dangling pointers).
77 78 79 |
# File 'lib/okf/bundle/folder.rb', line 77 def references Bundle::References.build(@bundle, files: reference_files) end |
#reload ⇒ Object
151 152 153 154 |
# File 'lib/okf/bundle/folder.rb', line 151 def reload @bundle = Reader.read(@root) self end |
#save(overwrite: false) ⇒ Object
Materialize the in-memory bundle to disk (Writer validates §11 before publishing, so a malformed bundle is never written).
140 141 142 143 144 145 146 147 148 149 |
# File 'lib/okf/bundle/folder.rb', line 140 def save(overwrite: false) Writer.call( bundle_path: @root, concepts: @bundle.concepts, index_files: reserved_hash("index.md"), log_files: reserved_hash("log.md"), overwrite: overwrite ) self end |
#skeleton ⇒ Object
45 46 47 |
# File 'lib/okf/bundle/folder.rb', line 45 def skeleton @bundle.skeleton end |
#stats ⇒ Object
65 66 67 |
# File 'lib/okf/bundle/folder.rb', line 65 def stats @bundle.stats end |
#tag_groups(by:, entries: nil) ⇒ Object
69 70 71 |
# File 'lib/okf/bundle/folder.rb', line 69 def tag_groups(by:, entries: nil) @bundle.tag_groups(by: by, entries: entries) end |
#validate ⇒ Object
33 34 35 |
# File 'lib/okf/bundle/folder.rb', line 33 def validate @bundle.validate end |