use std::path::PathBuf;
use eyre::{Result, bail};
use crate::config::config_file::ConfigFile;
use crate::config::config_file::mise_toml::MiseToml;
use crate::config::{ConfigPathOptions, resolve_target_config_path};
use crate::file::display_path;
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
pub struct SystemBrewTap {
tap: String,
#[clap(value_hint = clap::ValueHint::Url)]
url: Option<String>,
#[clap(long, short)]
local: bool,
#[clap(long, short = 'n')]
dry_run: bool,
#[clap(long, short, value_name = "PATH", conflicts_with = "local")]
path: Option<PathBuf>,
}
impl SystemBrewTap {
pub fn run(self) -> Result<()> {
let url = match self.url {
Some(url) => url,
None => default_tap_url(&self.tap)?,
};
let path = resolve_target_config_path(ConfigPathOptions {
global: !self.local,
path: self.path,
env: None,
cwd: None,
prefer_toml: true,
prevent_home_local: true,
})?;
if self.dry_run {
miseprintln!(
"{}: [bootstrap.brew.taps].\"{}\" = \"{}\"",
display_path(&path),
self.tap,
url
);
return Ok(());
}
let mut cf = if path.exists() {
MiseToml::from_file(&path)?
} else {
MiseToml::init(&path)
};
cf.update_bootstrap_brew_tap(&self.tap, &url)?;
cf.save()?;
info!("{}: added brew tap {}", display_path(&path), self.tap);
Ok(())
}
}
fn default_tap_url(tap: &str) -> Result<String> {
let mut parts = tap.split('/');
match (parts.next(), parts.next(), parts.next()) {
(Some(owner), Some(repo), None) if !owner.is_empty() && !repo.is_empty() => {
Ok(format!("https://github.com/{owner}/homebrew-{repo}.git"))
}
_ => bail!(
"tap '{tap}' must be in <owner>/<repo> format; supply an explicit URL for non-standard taps"
),
}
}
static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise bootstrap packages brew tap railwaycat/emacsmacport</bold>
$ <bold>mise bootstrap packages brew tap acme/tools https://github.com/acme/homebrew-tools.git</bold>
"#
);