use eyre::Result;
use crate::config::{Config, Settings};
use crate::system;
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
pub struct DotfilesApply {
#[clap(value_name = "TARGET")]
targets: Vec<String>,
#[clap(long, short)]
force: bool,
#[clap(long, short = 'n')]
dry_run: bool,
#[clap(long, short)]
yes: bool,
}
impl DotfilesApply {
pub async fn run(self) -> Result<()> {
Settings::get().ensure_experimental("mise dotfiles")?;
let config = Config::get().await?;
let all_files = system::files::files_from_config(&config);
let files = all_files
.iter()
.filter(|req| {
system::files::matches_target(&req.target, &req.target_raw, &self.targets)
})
.cloned()
.collect::<Vec<_>>();
let all_edits = system::edits::edits_from_config(&config);
let edits = all_edits
.iter()
.filter(|req| system::edits::matches_target(req, &self.targets))
.cloned()
.collect::<Vec<_>>();
if files.is_empty()
&& edits.is_empty()
&& !self.targets.is_empty()
&& (!all_files.is_empty() || !all_edits.is_empty())
{
eyre::bail!(
"no dotfiles matched target filter: {}",
self.targets.join(", ")
);
}
if files.is_empty() && edits.is_empty() {
info!("no dotfiles configured in [dotfiles]");
return Ok(());
}
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,
};
system::files::apply(&config, &files, &opts)?;
}
if !edits.is_empty() {
let opts = system::edits::ApplyOpts {
dry_run: self.dry_run,
verbose: Settings::get().verbose,
yes: self.yes,
};
system::edits::apply(&config, &edits, &opts)?;
}
Ok(())
}
}
static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise dotfiles apply</bold>
$ <bold>mise dotfiles apply --dry-run</bold>
$ <bold>mise dotfiles apply --dry-run --verbose</bold>
$ <bold>mise dotfiles apply --force --yes</bold>
"#
);