pub struct Config {Show 17 fields
pub worktree: WorktreeConfig,
pub bootstrap: BootstrapConfig,
pub hooks: LifecycleHooksConfig,
pub doctor: DoctorConfig,
pub tui: TuiConfig,
pub theme: ThemeConfig,
pub git_tui: GitTuiConfig,
pub review: ReviewConfig,
pub labels: Vec<LabelConfig>,
pub milestones: Vec<MilestoneConfig>,
pub branch_types: Vec<BranchType>,
pub aliases: BTreeMap<String, String>,
pub gitmoji: BTreeMap<String, String>,
pub issue_template: IssueTemplateConfig,
pub pr_template: PrTemplateConfig,
pub exec: ExecConfig,
pub clean: CleanConfig,
}Fields§
§worktree: WorktreeConfig§bootstrap: BootstrapConfig§hooks: LifecycleHooksConfig§doctor: DoctorConfig§tui: TuiConfig§theme: ThemeConfig§git_tui: GitTuiConfig§review: ReviewConfig§labels: Vec<LabelConfig>[[labels]] table — declarative GitHub label set pushed via
gwm labels push. Issue #81. Absent block resolves to an empty
vec, so gwm labels push is a no-op on configs that never opt in.
Whitespace in name is preserved verbatim (e.g. "good first issue"); colour falls back to a deterministic pastel hash at
push time when omitted.
milestones: Vec<MilestoneConfig>[[milestones]] table — declarative GitHub milestone set pushed
via gwm milestones push. Issue #82. Same opt-in / no-op shape
as labels. due_on accepts both YYYY-MM-DD (the milestones
module materialises end-of-day UTC) and full RFC3339; state
defaults to "open" when omitted.
branch_types: Vec<BranchType>[[branch_types]] — per-repo override of the allowed branch types.
Empty (the default) means the built-in list from naming::BRANCH_TYPES
is used, keeping zero-friction for existing repos. See
Config::resolved_branch_types for the single lookup site shared
by BranchSpec::validate, gwm types and the TUI create picker.
aliases: BTreeMap<String, String>[aliases] table — repo-level CLI aliases expanded BEFORE clap
parses argv (issue #86). Maps alias name to argv-shell-tokenised
expansion (e.g. wip = "create feat 0 wip"). BTreeMap so the
ordering surfaced by gwm aliases list is deterministic.
Absent block resolves to an empty map — aliasing disabled, no
behaviour change for repos that never opt in. Shadowing a
built-in subcommand or visible alias is a config error surfaced
at load time by crate::aliases::validate_aliases; same for
values containing shell pipeline metachars.
gitmoji: BTreeMap<String, String>[gitmoji] table — branch type to Gitmoji shortcode overrides used
by gwm types --gitmoji and gwm commit-prefix.
issue_template: IssueTemplateConfig§pr_template: PrTemplateConfig§exec: ExecConfig[exec] — named command profiles for gwm exec --profile <name>
(issue #324). Absent block resolves to no profiles, so the inline
gwm exec -- <cmd> surface is unchanged. Frozen for 1.0: a profile’s
command is an argv array (no shell), diverging from the
string-shell command of [git_tui] / [review].
clean: CleanConfig[clean] — named directory-set profiles for gwm clean --profile <name> (issue #324). Absent block resolves to no profiles, so
gwm clean keeps cleaning the built-in target/node_modules/
dist/build set. A profile’s dirs is a COMPLETE set that
replaces the built-ins, never adds to them.
Implementations§
Source§impl Config
impl Config
Sourcepub fn load_for_repo(repo_root: &Path) -> Result<Self>
pub fn load_for_repo(repo_root: &Path) -> Result<Self>
Look for .gwm.toml in the given repo root, layered over the
user-level global config at global_config_path (issue #190).
Falls back to defaults when neither exists.
Sourcepub fn load_exec_config(repo_root: &Path) -> Result<ExecConfig>
pub fn load_exec_config(repo_root: &Path) -> Result<ExecConfig>
Load just the [exec] section (layered global → repo), tolerant of
errors elsewhere in the config but strict on [exec] itself. Used by
gwm exec --profile so an unrelated .gwm.toml problem doesn’t block
it. See [load_config_section].
“Strict on itself” means EVERY [exec.profiles.*] is validated (not just
the one the command selects), so gwm exec --profile good rejects the
same file Config::load_for_repo / gwm config validate / doctor reject
— a sibling profile’s semantic error can’t pass on the command path only.
Sourcepub fn load_exec_jobs_default(repo_root: Option<&Path>) -> Result<Option<u32>>
pub fn load_exec_jobs_default(repo_root: Option<&Path>) -> Result<Option<u32>>
Read ONLY the [exec] jobs default (issue #324), without validating the
[exec.profiles.*] semantics. Used by inline gwm exec -- <cmd> (no
--profile, no --jobs) which needs the parallelism default but uses no
profile — so a sibling profile’s semantic issue must not block it. A
shape error in [exec] (unknown field, wrong type) still surfaces.
repo_root is None for a bare repo (no workdir): the repo .gwm.toml
is skipped but the GLOBAL [exec] jobs still applies.
Sourcepub fn load_exec_jobs_default_layered(
global: Option<&Path>,
repo_root: Option<&Path>,
) -> Result<Option<u32>>
pub fn load_exec_jobs_default_layered( global: Option<&Path>, repo_root: Option<&Path>, ) -> Result<Option<u32>>
Like Self::load_exec_jobs_default but with the global config path
injected, so the global-vs-repo layering can be pinned by a test without
touching the runner’s real $HOME / $XDG_CONFIG_HOME.
Sourcepub fn load_clean_config(repo_root: Option<&Path>) -> Result<CleanConfig>
pub fn load_clean_config(repo_root: Option<&Path>) -> Result<CleanConfig>
Load just the [clean] section (layered global → repo), tolerant of
errors elsewhere but strict on [clean] itself. Used by gwm clean so
an unrelated .gwm.toml problem doesn’t block the built-in clean, while
a malformed [clean.profiles.default] still errors rather than silently
reverting to the built-in set before a destructive --yes. See
[load_config_section].
As with Self::load_exec_config, EVERY [clean.profiles.*] is
validated — a sibling profile that escapes the worktree can’t slip
through gwm clean --profile good while gwm config validate rejects it.
repo_root is None for a bare repo (no workdir): the repo .gwm.toml
is skipped but the GLOBAL [clean] section still applies (the built-ins
are used when no default profile is defined).
Sourcepub fn load_layered(
repo_root: &Path,
global_path: Option<&Path>,
) -> Result<Self>
pub fn load_layered( repo_root: &Path, global_path: Option<&Path>, ) -> Result<Self>
Load the effective config by deep-merging the user-level global
config (global_path, the base) under the repo’s .gwm.toml
(the override). Issue #190.
Merge rule: the repo wins on conflicting scalars; tables merge key-by-key recursively; arrays are replaced wholesale by the repo when present. Validation runs on the merged result, so a bad value from either layer fails at load. When neither file exists the bare default is returned — identical to the pre-#190 behaviour, which the absent-global case preserves byte-for-byte.
global_path is injected (rather than resolved internally) so
the merge contract can be pinned by a test without touching the
runner’s real $HOME / $XDG_CONFIG_HOME.
Sourcepub fn validate_bootstrap_guards(&self) -> Result<()>
pub fn validate_bootstrap_guards(&self) -> Result<()>
Pre-compile every [[bootstrap.guard]].deny_patterns entry so a
malformed regex surfaces at config load instead of being silently
dropped at evaluation time (issue #96).
Historically bootstrap.rs::guard_match wrapped Regex::new(pat)
in if let Ok(re) = …, which made a guard fail-open whenever one
of its patterns failed to compile: the bad pattern vanished and
the surviving patterns evaluated against the file as if nothing
was wrong. A refusal mechanism that silently refuses to refuse is
strictly worse than no mechanism — the user reads “guard passed”
and trusts a file that never went through the rule it was meant
to be filtered by.
The compiled regexes are deliberately discarded here: the goal
of this validator is to fail fast at load time, and caching a
Vec<Regex> on the Guard struct would force #[serde(skip)]
gymnastics on a type that round-trips through TOML.
Trust boundary: Config::load_for_repo is the primary
chokepoint this validator protects. bootstrap::guard_match
holds the matching defence-in-depth for Config values that
bypass the loader (test fixtures, programmatic constructors,
future APIs): a runtime Regex::new failure surfaces as a
StepStatus::Failed step and refuses the copy, instead of
silently dropping the pattern as the original #96 fail-open
did.
Sourcepub fn write_default(repo_root: &Path) -> Result<PathBuf>
pub fn write_default(repo_root: &Path) -> Result<PathBuf>
Write a default config to the given repo root.
Sourcepub fn write_preset(repo_root: &Path, body: &str) -> Result<PathBuf>
pub fn write_preset(repo_root: &Path, body: &str) -> Result<PathBuf>
Write a .gwm.toml body (a built-in preset, see crate::presets)
to the repo root, refusing to clobber an existing file. Factored out
of Self::write_default so gwm init --preset <name> seeds a
stack-specific template through the same idempotency guard.
pub fn guard_by_name(&self, name: &str) -> Option<&Guard>
Sourcepub fn resolved_branch_types(&self) -> ResolvedBranchTypes
pub fn resolved_branch_types(&self) -> ResolvedBranchTypes
Single lookup site for the allowed branch types. Returns the
[[branch_types]] block from .gwm.toml when present, falling
back to crate::naming::default_branch_types otherwise. Used
by BranchSpec::validate, gwm types, the TUI create picker
(and, future-pending, the pre-commit hook) so the list stays
consistent across surfaces.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Config
impl<'de> Deserialize<'de> for Config
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for Config
impl RefUnwindSafe for Config
impl Send for Config
impl Sync for Config
impl Unpin for Config
impl UnsafeUnpin for Config
impl UnwindSafe for Config
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more