mise 2026.9.2

Dev tools, env vars, and tasks in one CLI
use std::path::PathBuf;

use eyre::Result;

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;
use crate::system::packages::brew::default_tap_url;

/// Add a Homebrew tap URL to [bootstrap.brew.taps]
#[derive(Debug, usage_rs::Args)]
#[usage(
    verbatim_doc_comment,
    example(
        r###"mise bootstrap packages brew tap railwaycat/emacsmacport
mise bootstrap packages brew tap acme/tools https://github.com/acme/homebrew-tools.git"###
    )
)]
pub(crate) struct SystemBrewTap {
    /// Tap name, e.g. `owner/repo`
    tap: String,

    /// Repository URL for the tap; defaults to GitHub's owner/homebrew-repo.git naming
    #[usage(value_hint = usage_rs::ValueHint::Url)]
    url: Option<String>,

    /// Write to the local config instead of the global config
    #[usage(long, short)]
    local: bool,

    /// Print the config change without writing it
    #[usage(long, short = 'n')]
    pub(super) dry_run: bool,

    /// Write to this config file or directory
    #[usage(
        long,
        short,
        visible_alias = "file",
        value_name = "PATH",
        conflicts = "local"
    )]
    path: Option<PathBuf>,
}

impl SystemBrewTap {
    pub(crate) 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(())
    }
}