pub struct WorkspaceSet { /* private fields */ }Expand description
An install’s many named workspaces: linked groups (multi-repo graphs) and
standalone singletons (one-repo graphs), keyed by name in stable order (ADR-0008
multi-workspace). The outer layer over Workspace: it selects which
workspace a command operates on, then hands back that Workspace to resolve
projects within it. Built from normalised config (WorkspaceSet::from_resolved)
so the serve/links selection logic is shared.
Implementations§
Source§impl WorkspaceSet
impl WorkspaceSet
Sourcepub fn from_workspaces<I>(entries: I) -> Self
pub fn from_workspaces<I>(entries: I) -> Self
Assemble a set from pre-built named workspaces — the shared core of
WorkspaceSet::from_resolved and the test constructor. With exactly one
entry, that workspace is the default (a bare selection resolves to it).
Sourcepub fn from_single(
name: impl Into<String>,
workspace: Arc<Workspace>,
linked: bool,
) -> Self
pub fn from_single( name: impl Into<String>, workspace: Arc<Workspace>, linked: bool, ) -> Self
Wrap an already-built Workspace (shared via Arc) as a one-entry set
under name, with linked recording whether that workspace is a
cross-linked multi-repo group. Used where a single Workspace is served as
the whole set — e.g. roteiro serve merges the read-only graph API over the
one workspace it already holds for its model tools and MCP router, so the
API’s flat routes resolve to it as the sole (default) workspace. The store
handles are shared, never re-opened.
Sourcepub fn from_resolved(
resolved: Vec<ResolvedWorkspace>,
) -> Result<Self, WorkspaceError>
pub fn from_resolved( resolved: Vec<ResolvedWorkspace>, ) -> Result<Self, WorkspaceError>
Build a set from normalised config groups: each group’s roots/repos are
discovered into member repo paths and opened as Workspaces. A linked
group becomes one multi-repo graph. A standalone (linked = false) group
becomes one single-repo graph per member repo — the invariant that a
standalone workspace is exactly one repo is upheld here, by splitting, so a
hand-built group can never collapse several repos into one unlinked multi-repo
graph (the config normaliser already emits standalone as per-repo singletons,
so in practice each such group has exactly one repo and the split is a no-op).
On a split, the extra members take a -2/-3 suffix off the group name. A
group that resolves to no repos is skipped, so a stale root never aborts
the whole set.
§Errors
WorkspaceError::Discover if a group’s root cannot be read, or
WorkspaceError::Git if an explicit repo path is not inside a git repo.
Sourcepub fn plan_reload(
&self,
resolved: Vec<ResolvedWorkspace>,
) -> Result<SetReloadPlan, WorkspaceError>
pub fn plan_reload( &self, resolved: Vec<ResolvedWorkspace>, ) -> Result<SetReloadPlan, WorkspaceError>
Re-discover resolved into the set a reload would install, without
touching the live set. All of the reload’s I/O (root scans, git
discovery) happens here; WorkspaceSet::apply_reload is then a swap.
A workspace whose name and linkage survive the reload keeps its very
Arc<Workspace> — so its open stores stay warm and any handle already
shared out (workspace_handles, a scoped tool registry) keeps pointing at
the live workspace — and receives a planned ReloadPlan for its own
project registry, which retains warm connections per
Workspace::apply_reload. A workspace that is new, gone, or has flipped
between linked and standalone is rebuilt or dropped, because in those
cases the name no longer denotes the same thing.
Planning reads the current entries; concurrent reloads must be serialised by the caller (the SIGHUP handler holds one lock for the whole reload), or the later plan simply wins.
§Errors
Sourcepub fn apply_reload(
&self,
plan: SetReloadPlan,
) -> Result<Vec<String>, WorkspaceError>
pub fn apply_reload( &self, plan: SetReloadPlan, ) -> Result<Vec<String>, WorkspaceError>
Install a SetReloadPlan, returning the new workspace names in stable
order. Does no I/O: each retained workspace’s planned registry is swapped
in, then the entry map is replaced under one write lock.
§Errors
WorkspaceError::Poisoned if a lock was poisoned.
Sourcepub fn reload_from_resolved(
&self,
resolved: Vec<ResolvedWorkspace>,
) -> Result<Vec<String>, WorkspaceError>
pub fn reload_from_resolved( &self, resolved: Vec<ResolvedWorkspace>, ) -> Result<Vec<String>, WorkspaceError>
Re-discover resolved and install it — WorkspaceSet::plan_reload
followed by WorkspaceSet::apply_reload. Use the halves separately when
another registry must be swapped in the same breath.
§Errors
Sourcepub fn workspace_handles(&self) -> Vec<(String, Arc<Workspace>)>
pub fn workspace_handles(&self) -> Vec<(String, Arc<Workspace>)>
Each configured workspace as a (name, shared handle) pair, in stable name
order. The Arc<Workspace> is the very handle the set holds, so a caller can
build a per-workspace view — e.g. a tool registry confined to one
workspace’s projects — over the same lazily-opened stores, never re-opening
them. Used by serve to scope the workspace-level Ask to the selected
workspace (ADR-0008), mirroring how WorkspaceSet::select scopes the
read-only /v1/graph/workspaces/{ws}/… routes.
Sourcepub fn linked(&self, name: &str) -> Option<bool>
pub fn linked(&self, name: &str) -> Option<bool>
Whether workspace name is linked (Some(true)), standalone
(Some(false)), or unknown (None).
Sourcepub fn select(
&self,
name: Option<&str>,
) -> Result<Arc<Workspace>, WorkspaceError>
pub fn select( &self, name: Option<&str>, ) -> Result<Arc<Workspace>, WorkspaceError>
Select a workspace by name, or the default when name is None.
Hands back the shared Arc rather than a borrow, because the set is
reloadable: a caller that held a reference into the entry map would pin it
against the swap. The handle stays valid across a reload — a retained
workspace is reloaded in place, so a caller reading through it sees the
new project set rather than a detached snapshot.
§Errors
WorkspaceError::UnknownWorkspace if named but absent,
WorkspaceError::AmbiguousWorkspace if omitted with several configured,
or WorkspaceError::Empty if none are configured.
Sourcepub fn select_name(&self, name: Option<&str>) -> Result<String, WorkspaceError>
pub fn select_name(&self, name: Option<&str>) -> Result<String, WorkspaceError>
The name of the workspace WorkspaceSet::select resolves for name:
the given name when present (and valid), else the sole/default workspace’s
name. Same resolution and errors as select, but returns the concrete name
— so a caller (e.g. the /follow endpoint) can report which workspace it
actually resolved in, even on a flat route where the default was implicit.
§Errors
Sourcepub fn containing(&self, cwd_repo_db: &Path) -> Option<String>
pub fn containing(&self, cwd_repo_db: &Path) -> Option<String>
The name of the workspace whose member repos include the repo whose graph is
cwd_repo_db (<repo>/.git/roteiro/graph.db), or None if no workspace
contains it. Used to default --workspace-name to the workspace the current
directory belongs to.