Skip to content

feat: improve Homebrew backend with rich search results and JSON details#30

Merged
yashksaini-coder merged 2 commits into
mainfrom
feat/brew-backend-improvements
May 26, 2026
Merged

feat: improve Homebrew backend with rich search results and JSON details#30
yashksaini-coder merged 2 commits into
mainfrom
feat/brew-backend-improvements

Conversation

@yashksaini-coder
Copy link
Copy Markdown
Collaborator

Summary

Fixes #9

Rewrites the BrewManager search and details to return version and description information alongside every result.

Changes

Search: Fetch names via brew search --formula, then batch-enrich with brew info --json=v2 to add version and description. Respects max_search_results config. Results cached in SEARCH_CACHE.

Installed: Uses brew list --formula --versions to show actual version strings instead of the generic Installed label.

Updates: Uses brew outdated --verbose for version transition info (e.g. 1.1 < 1.2).

Details: Switched from text-parsing to structured brew info --json=v2, surfacing: Name, Version, Description, Homepage, License, Tap, Dependencies, and Installed Version.

Fixes #9

Rewrites the BrewManager search and details to return version and
description information alongside every result.

## Search

Previously: names only (no version, no description)
Now:
1. Names are fetched via `brew search --formula <query>` (fast)
2. A single batch `brew info --json=v2 <name1> <name2>...` call
   enriches all results with version and description
3. Results are cached in SEARCH_CACHE to avoid repeat CLI calls
4. Respects max_search_results config setting

## Installed Packages

Uses `brew list --formula --versions` so the Installed tab shows
actual version strings instead of the generic 'Installed' label.

## Updates

Uses `brew outdated --verbose` which includes version transition
info (e.g. '1.2 (installed 1.1)') in the version column.

## Details

Switched from text-parsing `brew info` to structured
`brew info --json=v2` parsing, surfacing: Name, Version,
Description, Homepage, License, Tap, Dependencies, and
Installed Version.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 26, 2026 05:53
@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
trx Ready Ready Preview, Comment May 26, 2026 6:31am

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the Homebrew (brew) package manager backend to return richer, structured package metadata (version/description in search results and structured JSON details), and introduces a new update_packages API on the PackageManager trait for upgrading selected packages.

Changes:

  • Homebrew search now enriches brew search results with batch brew info --json=v2 metadata and caches search results.
  • Homebrew installed/updates lists now surface real version strings (via brew list --versions and brew outdated --verbose).
  • Adds PackageManager::update_packages(...) and implements it for Apt/Arch/Brew plus CombinedManager.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
src/managers/mod.rs Extends PackageManager with update_packages and forwards it through CombinedManager.
src/managers/brew.rs Reworks brew search/details to use JSON metadata; adds caching; improves installed/updates version display; adds brew update_packages.
src/managers/arch.rs Adds Arch implementation of update_packages (pacman vs AUR split).
src/managers/apt.rs Adds Apt implementation of update_packages via apt install --only-upgrade.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/managers/brew.rs
Comment on lines +18 to +24
// Check cache first
{
let cache = SEARCH_CACHE.lock().unwrap();
if let Some(cached) = cache.get(query) {
return cached.clone();
}
}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. The cache key in brew.rs is now format!("brew:{}", query) so each backend in a CombinedManager has its own key namespace and searches can't overwrite each other's results.

Comment thread src/managers/brew.rs Outdated
Comment on lines +26 to +38
// Step 1: get matching package names via `brew search`
let names: Vec<String> = {
let output = Command::new("brew")
.args(["search", "--formula", query])
.output()
.ok();
match output {
Some(o) => String::from_utf8_lossy(&o.stdout)
.lines()
.map(|l| l.trim().to_string())
.filter(|l| !l.is_empty() && !l.starts_with("==>"))
.take(30)
.collect(),
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Config is now loaded before the names-fetch step; take(30) was replaced with take(fetch_limit) where fetch_limit = max_search_results.max(50) so we always return up to the configured maximum after score filtering.

Comment thread src/managers/brew.rs
Comment on lines +117 to +125
.filter_map(|line| {
let mut parts = line.split_whitespace();
let name = parts.next()?.to_string();
let version = parts.next().unwrap_or("").to_string();
Some(Package {
provider: "brew".to_string(),
name,
version,
description: String::new(),
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. In get_installed_details all whitespace-split tokens after the name are now collected and the last one is taken as the version (versions.last().copied().unwrap_or("")), correctly handling formulae installed with multiple parallel versions.

Comment thread src/managers/mod.rs Outdated

fn update_packages(&self, terminal: &mut DefaultTerminal, pkgs: &HashSet<String>) -> Result<(), Box<dyn std::error::Error>> {
for m in &self.managers {
m.update_packages(terminal, pkgs)?;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. CombinedManager::update_packages now partitions pkgs by manager: for each backend it intersects the input set with that manager's get_installed() result, so only packages that manager actually owns are forwarded to it.

Comment thread src/managers/arch.rs
Comment on lines +135 to +143
fn update_packages(&self, terminal: &mut DefaultTerminal, pkgs: &HashSet<String>) -> Result<(), Box<dyn std::error::Error>> {
let mut pacman_pkgs = HashSet::new();
let mut aur_pkgs = HashSet::new();
for name in pkgs {
if name.starts_with("aur/") { aur_pkgs.insert(name.clone()); } else { pacman_pkgs.insert(name.clone()); }
}
if !pacman_pkgs.is_empty() { pacman::pacman_install(terminal, &pacman_pkgs)?; }
if !aur_pkgs.is_empty() { yay::aur_install(terminal, &aur_pkgs, &self.aur_helper)?; }
Ok(())
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Replaced the broken aur/ prefix check (AUR package names from search_aur never carry this prefix) with provider-aware routing: when an AUR helper (e.g. yay) is configured, all packages are routed through it — it handles both official-repo and AUR packages transparently. aur_install already strips any aur/ prefix before invoking the helper binary. When no AUR helper is configured, pacman is used exclusively.

…ager partitioning, AUR routing

brew.rs:
- SEARCH_CACHE key now includes the provider ('brew:<query>') so that
  CombinedManager searches for different backends don't overwrite each
  other's results for the same query string.
- Replaced hardcoded take(30) with take(max_search_results) (with a small
  overfetch buffer) so the configured maximum is respected.
- get_installed_details: collect all version tokens from 'brew list
  --formula --versions' and take the last one, correctly handling formulae
  installed with multiple parallel versions.

mod.rs:
- CombinedManager::update_packages now partitions pkgs by manager: for each
  backend it intersects the package set with that manager's get_installed()
  result so no backend receives packages it doesn't own.

arch.rs:
- install/update_packages: replaced the broken 'aur/' prefix check (AUR
  package names never carry this prefix in practice) with provider-aware
  routing: when an AUR helper is configured, route all packages through it
  (it handles both official-repo and AUR packages); fall back to pacman
  otherwise. aur_install already strips any 'aur/' prefix before invoking
  the helper.

Addresses Copilot review comments on PR #30.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@yashksaini-coder yashksaini-coder merged commit 02730f2 into main May 26, 2026
2 checks passed
@yashksaini-coder yashksaini-coder deleted the feat/brew-backend-improvements branch May 28, 2026 04:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Homebrew (brew) backend support

2 participants