Manage your Ruby application's gem dependencies
Switch branches/tags
Clone or download
bundlerbot and theflow Merge #6708
6708: Fix only_update_to_newer_versions regression r=greysteil a=theflow

This is my attempt to fix #6529

### What was the end-user problem that led to this PR?

Running `bundle update` with `BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS: "true"` resulted in a gem getting downgraded to a really old version in a certain edge case. Ironically it wouldn't get downgraded when `BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS` was set to false.

### What was your diagnosis of the problem?

My diagnosis was that 47256d2 tried to solve the problem of still allowing manual downgrades in the Gemfile while `only_update_to_newer_versions` is true. But introduced a regression that prevented the `additional_base_requirements_for_resolve` method to work as intended:

This is the relevant change from that commit that tries to avoid adding the `>=` requirement if the  requirement in the Gemfile is different than the requirement in the lockfile (as far as I understand it):

```ruby
next requirements if @locked_deps[name] != dependencies_by_name[name]
```

I identified two problems
 1. `dependencies_by_name[name]` returns an array of `Bundler::Dependency`, where as 
`@locked_deps[name]` just returns a single `Bundler::Dependency`. Comparing the two will always be false.
 1. `@locked_deps` is always empty in case of `bundle update`. See: https://github.com/bundler/bundler/blob/3d9e6167a7df9ca89a030dfe95c7cdff293e74a9/lib/bundler/definition.rb#L95

### What is your fix for the problem, implemented in this PR?

My fixes:

 1. Make sure `dependencies_by_name` is a hash with `Bundler::Dependency` as values
 1. Fetch the `@locked_gems.dependencies` again instead of using `@locked_deps`
 1. The existing test worked for me with and without the `only_update_to_newer_versions` set to true, I replaced it with a reproduction of the edge case I was investigating (this is as minimal as I could make it)
 1. I've added a test for the manual downgrading case.

### Why did you choose this fix out of the possible options?

This is the only way I could make these cases work. It's possible there are other edge cases I don't understand.

Co-authored-by: Florian Munz <surf@theflow.de>
Latest commit 8501b1e Sep 26, 2018

README.md

Version     Build Status Code Climate Inline docs Slack

Bundler: a gem to bundle gems

Bundler makes sure Ruby applications run the same code on every machine.

It does this by managing the gems that the application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems.

Installation and usage

To install (or update to the latest version):

gem install bundler

To install a prerelease version (if one is available), run gem install bundler --pre. To uninstall Bundler, run gem uninstall bundler.

Bundler is most commonly used to manage your application's dependencies. For example, these commands will allow you to use Bundler to manage the rspec gem for your application:

bundle init
bundle add rspec
bundle install
bundle exec rspec

See bundler.io for the full documentation.

Troubleshooting

For help with common problems, see TROUBLESHOOTING.

Still stuck? Try filing an issue.

Other questions

To see what has changed in recent versions of Bundler, see the CHANGELOG.

To get in touch with the Bundler core team and other Bundler users, please see getting help.

Contributing

If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together the Bundler contributor guide with all of the information you need to get started.

If you'd like to request a substantial change to Bundler or to the Bundler documentation, refer to the Bundler RFC process for more information.

While some Bundler contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author’s affiliation with Ruby Together.

Supporting


Ruby Together pays some Bundler maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or (better yet) as a company to ensure that Bundler, RubyGems, and other shared tooling is around for years to come.

Code of Conduct

Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the Bundler code of conduct.

License

Bundler is available under an MIT License.