use eyre::Result;
use crate::config::{Config, Settings};
use crate::system;
use crate::system::history::OperationScope;
#[derive(Debug, usage_rs::Args)]
#[usage(
verbatim_doc_comment,
example(
r###"mise bootstrap dotfiles apply
mise bootstrap dotfiles apply --dry-run
mise bootstrap dotfiles apply --force --yes"###
)
)]
pub(crate) struct DotfilesApply {
#[usage(value_name = "TARGET")]
targets: Vec<String>,
#[usage(long, short)]
force: bool,
#[usage(long, short = 'n')]
dry_run: bool,
#[usage(long, short)]
yes: bool,
}
impl DotfilesApply {
pub(crate) fn dry_run(&self) -> bool {
self.dry_run
}
pub(crate) fn requests(
&self,
config: &Config,
) -> Result<(
Vec<system::files::FileRequest>,
Vec<system::edits::EditRequest>,
)> {
super::select_requests(config, &self.targets)
}
pub(crate) async fn run(self) -> Result<bool> {
OperationScope::wrap("bootstrap dotfiles apply", self.dry_run, self.run_inner()).await
}
pub(crate) async fn run_inner(self) -> Result<bool> {
let config = Config::get().await?;
let (files, edits) = self.requests(&config)?;
if files.is_empty() && edits.is_empty() {
super::warn_if_dotfiles_ignored();
info!("no dotfiles configured in [dotfiles]");
return Ok(true);
}
if !files.is_empty() {
let opts = system::files::ApplyOpts {
dry_run: self.dry_run,
verbose: Settings::get().verbose,
force: self.force,
force_hint: "use --force",
yes: self.yes,
};
if !system::files::apply(&config, &files, &opts)? {
return Ok(false);
}
}
if !edits.is_empty() {
let opts = system::edits::ApplyOpts {
part: "dotfiles",
dry_run: self.dry_run,
verbose: Settings::get().verbose,
yes: self.yes,
};
if !system::edits::apply(&config, &edits, &opts)? {
return Ok(false);
}
}
Ok(true)
}
}