Module: Esp::ProjectMarker
- Defined in:
- lib/esp/project_marker.rb
Overview
Reads, writes, and discovers the ‘.esp/project.json` marker that identifies a directory as an esp project. Used by:
-
‘esp init` and `Esp::Operations.projects_new` to write the marker.
-
‘Esp::Operations.open_project` to read the marker’s ‘game:` field so the plugin registry knows which Operations module owns this project.
-
The CLI cwd walk-up so ‘esp build` works from anywhere inside a project tree without `–root`.
Marker filename rename (step 23.5 slice 3): the canonical location is now ‘.esp/project.json`. Projects scaffolded by an earlier ESPresso release wrote `.espresso/project.json`; readers accept both, writers only emit the new name. The back-compat lookup goes away when the release that drops it ships (no auto-migration — we don’t silently rewrite a user’s project files).
Constant Summary collapse
- FILENAME =
'project.json'.freeze
- DIRECTORY =
'.esp'.freeze
- LEGACY_DIRECTORY =
'.espresso'.freeze
- WALK_DEPTH_CAP =
Cap the cwd walk-up depth to defend against symlink loops and pathological filesystem layouts. 32 levels is deeper than any sane project tree (and matches git’s own MAX_DEPTH for similar reasons).
32- SCHEMA_VERSION =
1
Class Method Summary collapse
-
.find_in(root) ⇒ Object
The marker path under ‘root`, preferring the new `.esp/` location but accepting a legacy `.espresso/` marker.
-
.find_walking_up(start_dir) ⇒ Object
Walk up from ‘start_dir` looking for a project marker.
-
.path_in(root) ⇒ Object
The canonical write path for a project rooted at ‘root`.
-
.read(root) ⇒ Object
Read + parse the marker at ‘root`.
-
.write(root, name:, game:) ⇒ Object
Write the canonical marker.
Class Method Details
.find_in(root) ⇒ Object
The marker path under ‘root`, preferring the new `.esp/` location but accepting a legacy `.espresso/` marker. Returns nil if neither exists.
42 43 44 45 46 47 48 49 50 |
# File 'lib/esp/project_marker.rb', line 42 def find_in(root) new_path = path_in(root) return new_path if File.exist?(new_path) legacy = File.join(root, LEGACY_DIRECTORY, FILENAME) return legacy if File.exist?(legacy) nil end |
.find_walking_up(start_dir) ⇒ Object
Walk up from ‘start_dir` looking for a project marker. Returns the project root (the directory containing the marker dir), not the marker path. Nil if no marker is found before the filesystem root. Bounded by WALK_DEPTH_CAP so a symlink loop can’t hang us.
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/esp/project_marker.rb', line 85 def find_walking_up(start_dir) current = File.(start_dir) WALK_DEPTH_CAP.times do return current if find_in(current) parent = File.dirname(current) return nil if parent == current # reached filesystem root current = parent end nil end |
.path_in(root) ⇒ Object
The canonical write path for a project rooted at ‘root`.
35 36 37 |
# File 'lib/esp/project_marker.rb', line 35 def path_in(root) File.join(root, DIRECTORY, FILENAME) end |
.read(root) ⇒ Object
Read + parse the marker at ‘root`. Returns nil if no marker exists or the JSON is malformed — callers default to the registry’s default plugin (every pre-22.5 project is Morrowind) rather than surface a sharp edge.
56 57 58 59 60 61 62 63 |
# File 'lib/esp/project_marker.rb', line 56 def read(root) path = find_in(root) return nil unless path JSON.parse(File.read(path)) rescue JSON::ParserError nil end |
.write(root, name:, game:) ⇒ Object
Write the canonical marker. Always emits the new ‘.esp/` location; never touches a legacy `.espresso/` marker the project might already carry. Returns the path written.
68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/esp/project_marker.rb', line 68 def write(root, name:, game:) path = path_in(root) FileUtils.mkdir_p(File.dirname(path)) payload = { 'name' => name, 'schema' => SCHEMA_VERSION, 'game' => game, 'created_at' => Time.now.utc.iso8601 } File.write(path, "#{JSON.pretty_generate(payload)}\n") path end |