Comments (11)
I think your
tap_migrations.json
inpe/old-tap
should be{ "example": "pe/new-tap/example" }
Looking at other examples I don't think so: https://github.com/brewsci/homebrew-science/blob/5d14d2fda3934c0eb8243c1cbdb9fb4621ec110b/tap_migrations.json
I tried it with pe/homebrew-old-tap@cc86591. Same error.
from brew.
While playing around, I just noticed that the same error also applies to formulae, not only to casks.
Step-by-step reproduction instructions (by running brew commands)
https://github.com/pe/homebrew-old-tap/blob/5a0e91e527c5962096e62fa277c896a1c285faef/tap_migrations.json#L3
https://github.com/pe/homebrew-new-tap/blob/d755222b381ccbea385f7884b97b9b8b9f19429e/Formula/examplef.rb#L1
~ ❯ brew install examplef --verbose --debug
Warning: Formula pe/old-tap/examplef was renamed to pe/new-tap/examplef.
Error: Formulae found in multiple taps:
* pe/new-tap/examplef
* pe/new-tap/examplef
Please use the fully-qualified name (e.g. pe/new-tap/examplef) to refer to a specific formula.
/opt/homebrew/Library/Homebrew/formulary.rb:837:in `try_new'
/opt/homebrew/Library/Homebrew/formulary.rb:1227:in `block in loader_for'
/opt/homebrew/Library/Homebrew/formulary.rb:1226:in `each'
/opt/homebrew/Library/Homebrew/formulary.rb:1226:in `loader_for'
/opt/homebrew/Library/Homebrew/formulary.rb:1008:in `factory'
/opt/homebrew/Library/Homebrew/cli/parser.rb:709:in `block in formulae'
/opt/homebrew/Library/Homebrew/cli/parser.rb:705:in `each'
/opt/homebrew/Library/Homebrew/cli/parser.rb:705:in `filter_map'
/opt/homebrew/Library/Homebrew/cli/parser.rb:705:in `formulae'
/opt/homebrew/Library/Homebrew/cli/parser.rb:363:in `parse'
/opt/homebrew/Library/Homebrew/abstract_command.rb:53:in `initialize'
/opt/homebrew/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/sorbet-runtime-0.5.11385/lib/types/private/abstract/declare.rb:37:in `new'
/opt/homebrew/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/sorbet-runtime-0.5.11385/lib/types/private/abstract/declare.rb:37:in `block in declare_abstract'
/opt/homebrew/Library/Homebrew/brew.rb:90:in `<main>'
The exact same code also exists here:
brew/Library/Homebrew/formulary.rb
Lines 829 to 831 in f1a7d97
from brew.
I think your tap_migrations.json
in pe/old-tap
should be
{
"example": "pe/new-tap/example"
}
from brew.
I think I found the source of the issue. The same cask is found twice. Once in the new tap and once in the old but mapped to the new tap.
If I inspect loaders
from this code:
brew/Library/Homebrew/cask/cask_loader.rb
Lines 459 to 461 in 5e6a43e
I get this:
[
#<Cask::CaskLoader::FromNameLoader:0x0000000125cac788 @token="example", @path=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Casks/example.rb>, @tap=#<Tap:0x0000000122de3898 @user="pe", @repo="new-tap", @name="pe/new-tap", @full_name="pe/homebrew-new-tap", @path=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap>, @git_repo=#<GitRepository:0x0000000122e0f6f0 @pathname=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap>>, @alias_dir=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Aliases>, @alias_files=[], @alias_table={}, @formula_renames={}, @tap_migrations={}, @potential_formula_dirs=[#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Formula>, #<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/HomebrewFormula>, #<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap>], @formula_dir=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap>, @formula_files=[], @formula_files_by_name={}, @cask_renames={}, @cask_dir=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Casks>, @cask_files=[#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Casks/example.rb>], @cask_files_by_name={"example"=>#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Casks/example.rb>}>>,
#<Cask::CaskLoader::FromNameLoader:0x0000000125caa410 @token="example", @path=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Casks/example.rb>, @tap=#<Tap:0x0000000122de3898 @user="pe", @repo="new-tap", @name="pe/new-tap", @full_name="pe/homebrew-new-tap", @path=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap>, @git_repo=#<GitRepository:0x0000000122e0f6f0 @pathname=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap>>, @alias_dir=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Aliases>, @alias_files=[], @alias_table={}, @formula_renames={}, @tap_migrations={}, @potential_formula_dirs=[#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Formula>, #<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/HomebrewFormula>, #<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap>], @formula_dir=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap>, @formula_files=[], @formula_files_by_name={}, @cask_renames={}, @cask_dir=#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Casks>, @cask_files=[#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Casks/example.rb>], @cask_files_by_name={"example"=>#<Pathname:/opt/homebrew/Library/Taps/pe/homebrew-new-tap/Casks/example.rb>}>>
]
The only difference is the object_id.
Changing the above code like so fixes the issue.
loaders = Tap.select { |tap| tap.installed? && !tap.core_cask_tap? }
.filter_map { |tap| super("#{tap}/#{token}", warn:) }
.select { |tap| tap.path.exist? }
.uniq{ |cask| cask.tap } # this line was added by me
But my knowledge of this codebase is none and my ruby is very limited. I can't judge if this is a good idea or not.
How to proceed? Should I just create a PR and we'll discuss there? Would you want any tests for this change? Where? Are there other places where this is also necessary?
from brew.
I can't judge if this is a good idea or not.
My Ruby-fu is limited too, but I'm pretty sure that:
- the whole point of migrations is that the formula/cask no longer exists in the old tap
- taps are processed in alpha-sorted order, so if your old tap sorts before the new one (e.g.
pe/tap1 -> pe/tap2
), your fix will pick the wrong tap
from brew.
- the whole point of migrations is that the formula/cask no longer exists in the old tap
Yes, this. You should delete the formula/cask from the old file or it won't work as expected.
from brew.
How to proceed? Should I just create a PR and we'll discuss there?
Yes, this would be best.
Would you want any tests for this change? Where?
Ideally the corresponding _spec.rb
file to the source file(s) you edit. That can wait until we've validated the approach with a draft PR, though.
from brew.
taps are processed in alpha-sorted order, so if your old tap sorts before the new one (e.g. pe/tap1 -> pe/tap2), your fix will pick the wrong tap
I don't think that the order matters because both casks are identical (except for the object_id). The cask from the old tap was already migrated to the new one, that's why they are identical.
- the whole point of migrations is that the formula/cask no longer exists in the old tap
Yes, this. You should delete the formula/cask from the old file or it won't work as expected.
I did delete it in the old tap and get this error nevertheless. See What were you trying to do (and why)?.
How to proceed? Should I just create a PR and we'll discuss there?
Yes, this would be best.
OK. Will do.
from brew.
brew/Library/Homebrew/cask/cask_loader.rb
Lines 459 to 461 in ff950e6
I suspect what's happening here is that we're getting identical cask loaders because the call to super
evaluates cask renames and migrations so it's possible that the original tap that the cask was migrated from is returning the cask loader for the new tap.
brew/Library/Homebrew/cask/cask_loader.rb
Lines 205 to 212 in ff950e6
The super
call leads to the Cask::CaskLoader::FromTapLoader.try_new
method which calls the Cask::CaskLoader.tap_cask_token_type
method. Normally it just returns the cask token, tap and type specified but if the cask has been renamed or migrated it returns the new token, tap and type. Since they are identical, just removing duplicates by path makes sense here. Tap would also work but path is a bit more specific.
Ideally, we'd figure out how to refactor this so that this doesn't happen in this sort of situation but I'm not really sure what that would look like.
from brew.
@reitermarkus Could you take a look at this if you get a chance as you did a bunch of migration work recently? Thanks ❤️
from brew.
Fixed by #17385
from brew.
Related Issues (20)
- Failed to install Homebrew Portable Ruby (and your system version is too old)! HOT 4
- Improve error/warning when `brew install` refuses to install a formula from a tap with the same name as an already installed keg HOT 7
- shellenv.sh: csh/tcsh: Broken code for setting envvar MANPATH HOT 1
- Make `autoremove` idempotent HOT 12
- Run xattr -r -d com.apple.quarantine App.app on casks on Apple Silicon MacOS HOT 20
- Homebrew's brew alias is broken after update this morning on Debian machines HOT 2
- Are all of the `undef`s we use really necessary? HOT 27
- HOMEBREW_PIP_INDEX_URL is misleading and does not work-as-intended with some mirrors
- “Error: comparison of PkgVersion with String failed” when running `brew upgrade` HOT 3
- brew upgrade or install fails with comparison of PkgVersion with String HOT 1
- Brew link step fail if installing multiple formulae with common symlink using a system with symlinked /home HOT 6
- golang not update to 1.23.0 HOT 2
- Happened ruby runtime error on macOS Sequoia HOT 2
- Homebrew no longer correctly reads `HOMEBREW_DOCKER_REGISTRY_BASIC_AUTH_TOKEN` from /etc/homebrew/brew.env
- environment file variables are not honored
- `brew install` call `gh attestation verify` Disrespect `XDG_CACHE_HOME` HOT 3
- Fix failing tests and write other tests as well HOT 1
- Suggest to change the way to read file in export_homebrew_env_file HOT 4
- Add a more customizable ENV file loading process HOT 2
- Download does not start immediately, a lot of network traffic (file is downloaded twice?) HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from brew.