class DarwinBrewCaskManager:
"""Homebrew cask manager for macOS (`brew install --cask`)."""
name = "cask"
def is_installed(self, package: str) -> bool:
brew = _ensure_brew()
if brew is None:
return False
# `brew list --cask <name>` exits 0 if the cask is installed.
res = run([brew, "list", "--cask", package], check=False)
return res.returncode == 0
def install(self, package: str) -> InstallResult:
brew = _ensure_brew()
if brew is None:
return InstallResult(
ok=False,
summary="brew not found on PATH",
details=(
"Homebrew is not installed. Install it from https://brew.sh "
"and ensure `brew` is available on your PATH."
),
)
logger.info(f"Installing cask {package} via brew...")
res = run([brew, "install", "--cask", package], check=False)
if res.returncode == 0:
return InstallResult(ok=True, summary=f"Installed cask {package}")
details = (res.stdout + "\n" + res.stderr).strip()
return InstallResult(ok=False, summary=f"Failed to install cask {package}", details=details)
def update(self) -> TaskResult:
# There is no dedicated "cask-only" update; reuse `brew update`.
brew = _ensure_brew()
if brew is None:
return TaskResult(
ok=False,
summary="brew cask update: failed",
details=(
"brew not found on PATH. Install Homebrew from https://brew.sh and try again."
),
)
res = run([brew, "update"], check=False)
if res.returncode == 0:
return TaskResult(ok=True, summary="brew update (casks): done")
details = (res.stdout + "\n" + res.stderr).strip()
return TaskResult(ok=False, summary="brew update (casks): failed", details=details)
def upgrade(self) -> TaskResult:
brew = _ensure_brew()
if brew is None:
return TaskResult(
ok=False,
summary="brew cask upgrade: failed",
details=(
"brew not found on PATH. Install Homebrew from https://brew.sh and try again."
),
)
res = run([brew, "upgrade", "--cask"], check=False)
if res.returncode == 0:
return TaskResult(ok=True, summary="brew upgrade --cask: done")
details = (res.stdout + "\n" + res.stderr).strip()
return TaskResult(ok=False, summary="brew upgrade --cask: failed", details=details)
def cleanup(self) -> TaskResult:
# `brew cleanup` also covers casks.
brew = _ensure_brew()
if brew is None:
return TaskResult(
ok=False,
summary="brew cask cleanup: failed",
details=(
"brew not found on PATH. Install Homebrew from https://brew.sh and try again."
),
)
res = run([brew, "cleanup"], check=False)
if res.returncode == 0:
return TaskResult(ok=True, summary="brew cleanup (casks): done")
details = (res.stdout + "\n" + res.stderr).strip()
return TaskResult(ok=False, summary="brew cleanup (casks): failed", details=details)