Skip to content

formula: handle non-VCS head in outdated - #24412

Merged
MikeMcQuaid merged 1 commit into
Homebrew:mainfrom
ZTJun:outdated-non-vcs-head
Nov 1, 2026
Merged

MikeMcQuaid merged 1 commit into
Homebrew:mainfrom
ZTJun:outdated-non-vcs-head

Conversation

@ZTJun

@ZTJun ZTJun commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

brew outdated crashes for formulae installed from HEAD whose head spec
is not a VCS URL:

Error: undefined method 'last_commit' for an instance of CurlDownloadStrategy

Formula#latest_head_pkg_version calls downloader.last_commit
unconditionally, but that method only exists on VCSDownloadStrategy. A
formula's head can point to a plain archive URL (e.g.
fredowski/pspp/pspp uses head ".../latest-source.tar.gz"), which gives
a CurlDownloadStrategy.

The crash triggers whenever a HEAD keg is deemed outdated without
--fetch-HEAD: after the formula's stable version is bumped past the one
recorded in the keg's tab, head_version_outdated? returns true via the
stable comparison and the unguarded last_commit call runs. Verbose
output is the default in interactive shells, so plain brew outdated
hits this too. Introduced by #20940.

To reproduce: brew install --HEAD a formula whose head is an archive
URL, wait until its stable version is bumped (or lower the "stable"
version recorded in the keg's INSTALL_RECEIPT.json), then run
brew outdated in a terminal or brew outdated -v anywhere.

When head_spec.downloader is not a VCSDownloadStrategy there is no
upstream commit to report, so return the installed HEAD version and let
verbose output fall back to printing latest HEAD, as it did before
#20940. Adds a regression test.


  • Have you followed our Contributing guidelines?
  • Have you checked for other open Pull Requests for the same change?
  • Have you explained what your changes do? Performance claims (e.g. "this is faster") must include brew benchmark results.
  • Have you explained why you'd like these changes included, not just what they do?
  • For bug fixes, have you given step-by-step brew commands to reproduce the bug?
  • Have you written new tests (excluding integration tests)? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) locally?

  • I did not use AI/LLM to create this PR, or I disclosed the tool/model below and reviewed its output; I did not attribute commits to AI and will answer maintainer questions and review comments myself without AI/LLM.

Drafted with AI assistance (Devin, SWE-2); code, tests and prose reviewed by me before submission.

- `latest_head_pkg_version` called `downloader.last_commit`
  unconditionally, but a `head` spec can point to an archive URL whose
  downloader is not a `VCSDownloadStrategy` and has no `last_commit`
- `brew outdated` crashed for HEAD kegs considered outdated via the
  stable version check, e.g. `pspp (HEAD)` after a stable bump
- fall back to the installed HEAD version so verbose output prints
  `latest HEAD` as it did before
@coderabbitai

coderabbitai Bot commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 64ad93cc-28be-4500-9f66-5b018b8dff32
Commits

Reviewing files that changed from the base of the PR and between a687be2 and 680aab9.

Files selected for processing: 2
  • Library/Homebrew/formula.rb
  • Library/Homebrew/test/formula_spec.rb

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Summary

Summary by CodeRabbit

  • Bug Fixes
    • Corrected package version reporting for installed HEAD builds that use non-version-control download sources.

Changes

The HEAD package version method now returns the latest installed version when the HEAD downloader is not a VCS downloader. A test checks that this returns package version HEAD with revision 0 when the installed tab records stable version 1.0.

HEAD package version handling

Layer / File(s) Summary
Handle non-VCS HEAD versions
Library/Homebrew/formula.rb, Library/Homebrew/test/formula_spec.rb
The method returns the latest installed version for non-VCS HEAD downloaders. The test checks the HEAD package version and revision 0 when the installed tab records stable version 1.0. VCS downloaders retain the existing commit-based version calculation.
Merge Risk: Minimal · up to 680aa

The non-VCS HEAD fallback and regression coverage are aligned with the stated fix.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title "formula: handle non-VCS head in outdated" matches the main change. The PR makes Formula#latest_head_pkg_version return the installed HEAD version when the HEAD downloader is not a VCSDownlo…
Description check Passed The description explains the crash in brew outdated for formulae whose head spec is a plain archive URL. It names the cause (an unguarded downloader.last_commit call), gives reproduction steps, and de…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "formula: handle non-VCS head in outdated" matches the main change. The PR makes Formula#latest_head_pkg_version return the installed HEAD version when the HEAD downloader is not a VCSDownloadStrategy, which stops the brew outdated crash. The title is specific and concise, and it names the affected area.

Full details: Description check

Explanation

The description explains the crash in brew outdated for formulae whose head spec is a plain archive URL. It names the cause (an unguarded downloader.last_commit call), gives reproduction steps, and describes the fix and the regression test. It is directly related to the changeset.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the PR! Why use a non-VCS head URL? Want to figure out what makes most sense, particularly given this has been broken for a year and you're first to complain.

@ZTJun

ZTJun commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the PR! Why use a non-VCS head URL? Want to figure out what makes most sense, particularly given this has been broken for a year and you're first to complain.

I think it's not a choice on my end — fredowski/pspp/pspp (a third-party tap) declares head ".../latest-source.tar.gz", a rolling source tarball rather than a VCS checkout. I've seen that the DSL permits it, audit doesn't flag it, and installs that already exist carry it regardless.

Probably nobody hit it before because it needs a narrow combination: a non-VCS head, a --HEAD install, a stable bump afterwards, and verbose or interactive output. pspp only started crashing for me when its stable went 2.1.2 → 2.1.3.

On direction: for a non-VCS downloader there is no upstream commit to report, and fetching the archive would defeat --fetch-HEAD. Returning the installed version restores the pre-#20940 latest HEAD output, matching the existing VCSDownloadStrategy guards in head_version_outdated?/update_head_version.
Displaying the bumped stable version instead (e.g. < 2.1.3) was the other option, but brew upgrade still targets HEAD for these kegs, so latest HEAD is the honest output even if it carries less information, I think.
Maybe to pair this with an audit deprecation of non-VCS heads or take a different fallback if you prefer. But I am convinced the guard seems needed either way, so outdated doesn't NoMethodError on existing installs.

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

@MikeMcQuaid
MikeMcQuaid added this pull request to the merge queue Nov 1, 2026
Merged via the queue into Homebrew:main with commit c93e4b5 Nov 1, 2026
54 checks passed
@ZTJun
ZTJun deleted the outdated-non-vcs-head branch November 4, 2026 04:41
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.

2 participants

⌂ 换网址