Class BowirePluginRoot
- Namespace
- Kuestenlogik.Bowire.Plugins
- Assembly
- Kuestenlogik.Bowire.dll
The one answer to "which directories hold the installed plugins" (#549, then #28 Phase D).
public static class BowirePluginRoot
- Inheritance
-
BowirePluginRoot
- Inherited Members
Remarks
BowirePaths (#616) gave every storage question a single resolver, and the plugin directory rides on it — but only for the default. Two things sit on top of that default, and both are why this type exists.
The explicit override (#549). The plugin directory is the one
storage location a host can also point somewhere else outright, through
Bowire:PluginDir — the CLI's --plugin-dir, the
BOWIRE_PLUGIN_DIR environment variable and an
appsettings.json entry all bind to that key. Before this type, that
override reached the loader alone, so a host started with
--plugin-dir X installed into X and then listed somewhere else.
Two tiers (#28 Phase D). "Everyone shares one
~/.bowire/plugins" has two failure modes at once: a user cannot
install a plugin for their own workflow without administrative rights, and
an administrator cannot provision one for everybody. So there are now two
directories — a machine-wide tier an admin manages, and the user's own
overlay on top of it. EnumeratePackages() walks them in
precedence order and is the only place that ordering is expressed.
Static, and set once at start-up, for the same reason BowirePaths is: several readers are static properties with no constructor to inject into. Anything that does have a constructor should keep taking the path as a parameter.
Properties
Current
Where a plugin install lands, and the tier the user owns: the configured directory when a host set one, the storage resolver's default otherwise.
public static string Current { get; }
Property Value
Remarks
A property rather than a captured field: Apply(string?) runs when the host is built, which can be after this type is first touched, and Current can be swapped later still. Reading through on every call is what keeps both honest.
IsConfigured
Whether a host explicitly configured the user directory.
public static bool IsConfigured { get; }
Property Value
MachineRoot
The machine-wide tier: %ProgramData%\Bowire\plugins on Windows,
/var/lib/bowire/plugins elsewhere.
public static string MachineRoot { get; }
Property Value
Remarks
Resolved even when the directory does not exist — most installs have no machine tier at all, and an absent directory reads as "no plugins there" rather than as an error.
Roots
The directories to search, in precedence order: the user's own first, then the machine tier.
public static IReadOnlyList<(string Path, BowirePluginTier Tier)> Roots { get; }
Property Value
Remarks
The user tier comes first so a locally installed plugin shadows a machine-wide one of the same package id — that is what makes it an overlay, and it is how someone tries a newer build without asking an administrator to change what everybody else gets.
An explicitly configured directory yields only that
directory. --plugin-dir /tmp/isolated is an operator saying
which plugins are in play, and quietly adding a machine tier they did
not ask for would make an isolated run stop being isolated.
Methods
Apply(string?)
Point every plugin-directory reader at directory.
Null, empty or whitespace clears the override and returns the resolver
default, so a host can call this unconditionally with whatever
Bowire:PluginDir yielded.
public static string Apply(string? directory)
Parameters
directorystring
Returns
- string
The user-tier directory in force after the call.
EnumeratePackages()
Every installed package directory across both tiers, in precedence order, with the tier it came from. A package id present in both is yielded once, from the higher-precedence tier.
public static IEnumerable<(string Directory, string PackageId, BowirePluginTier Tier)> EnumeratePackages()
Returns
Remarks
The single place the overlay rule is applied. Callers that scanned one
directory with Directory.GetDirectories should read this
instead — the alternative is each of them re-deciding what happens when
the same plugin exists twice, which is how the four readers in #549
came to disagree in the first place.
EnumeratePackagesUnder(string, bool)
The same walk, for a caller that resolved the user tier itself.
public static IEnumerable<(string Directory, string PackageId, BowirePluginTier Tier)> EnumeratePackagesUnder(string userRoot, bool includeMachineTier)
Parameters
userRootstringThe directory to treat as the user tier.
includeMachineTierboolWhether to search the machine tier as well. Pass
falsewhenuserRootcame from an operator naming a directory — an isolated run has to stay isolated.
Returns
Remarks
Exists because the Tool resolves the directory through
BowirePluginOptions, which owns a precedence chain
(--plugin-dir over the environment over configuration) that
Core has no notion of. Rather than have the loader trust that some
earlier call already pushed that answer into Apply(string?), it
passes what it resolved and gets the same overlay rule applied to it.