Module: Esp::ActiveProject

Defined in:
lib/esp/active_project.rb

Overview

Process-scoped state for “which project is the user currently working in” (step 23). Swapped in by ESPresso’s POST /open-project; helpers that need a working-tree root (vcs_root for diff/approve/reject today; more later) consult this before falling back to Esp::ROOT.

Step 22.5 slice 2: also tracks the project’s game id (‘mw` today, future `ob`/`sr`) so the plugin registry knows which Operations module owns each op for the current request. Missing game on a project read defaults to `mw` for backward compat (every pre-rename project is Morrowind).

Stored module-globally rather than per-request because the WEBrick backend is single-tenant per-instance (one ESPresso ↔ one esp serve), so a global is the right shape; the mutex guards against the thread-per-request model racing a concurrent set + read.

Class Method Summary collapse

Class Method Details

.clear!Object



43
44
45
46
47
48
# File 'lib/esp/active_project.rb', line 43

def clear!
  @mutex.synchronize do
    @root = nil
    @game = nil
  end
end

.gameObject



26
27
28
# File 'lib/esp/active_project.rb', line 26

def game
  @mutex.synchronize { @game }
end

.resolve(params = {}) ⇒ Object

Same precedence as root_for, but with Esp::ROOT as a final fallback. This is what every op that needs a root should call — diff/approve/ reject already do (via Esp::Operations#vcs_root); slice 1 of step 23.5 routes the game ops (build, lint, scaffold, …) through it too so ESPresso’s “open project” actually moves where they operate.



66
67
68
# File 'lib/esp/active_project.rb', line 66

def resolve(params = {})
  root_for(params) || Esp::ROOT
end

.rootObject



22
23
24
# File 'lib/esp/active_project.rb', line 22

def root
  @mutex.synchronize { @root }
end

.root_for(params) ⇒ Object

Resolve a root for a request: explicit ‘root:` param wins (preserves the diff-panel pattern of “operate on a specific tree even if a project is open”), then the active project, then nil — the caller decides whether to fall back to Esp::ROOT or error.



54
55
56
57
58
59
# File 'lib/esp/active_project.rb', line 54

def root_for(params)
  explicit = params.is_a?(Hash) ? params['root'] : nil
  return explicit unless explicit.nil? || explicit.to_s.empty?

  root
end

.set(path, game: nil) ⇒ Object

Store a project root + game id. Returns the normalized path so callers don’t have to expand again. No directory check here —Operations.open_project validates before calling (separation: this module is pure state).



34
35
36
37
38
39
40
41
# File 'lib/esp/active_project.rb', line 34

def set(path, game: nil)
  normalized = File.expand_path(path.to_s)
  @mutex.synchronize do
    @root = normalized
    @game = game
  end
  normalized
end