Skip to content

bundle command "override" needs less destructive alternative #9903

Description

@hlascelles

Problem

The new version of bundler, 4.1.x, introduces a new override command. This allows a user to supply constraints on dependencies without necessarily making them concrete.

However, it is destructive, in that it removes any other constraints that other gems supply. Those constraints are probably there for a reason, and losing them should be a last resort.

However we do want the ability to supply constraints without declaring a concrete dependency. So either override should take a "replace" or "force" option, or we need an alternative to "override" like "constrain" or "resolve".

Steps to reproduce the problem

Consider this Gemfile:

source "https://rubygems.org"

gem "bootstrap", "4.6.2.1"

The resulting (simplified) lockfile looks like this:

GEM
  remote: https://rubygems.org/
  specs:
    autoprefixer-rails (10.4.21.0)
      execjs (~> 2)
    bootstrap (4.6.2.1)
      autoprefixer-rails (>= 9.1.0)
      popper_js (>= 1.16.1, < 2)
    execjs (2.10.2)
      json (>= 2)
    json (3.0.2)
    popper_js (1.16.1)

DEPENDENCIES
  bootstrap (= 4.6.2.1)

BUNDLED WITH
  4.1.0.beta1

Note that the only DEPENDENCIES is bootstrap.

Now say we want to add a constraint that popper_js must be 1.16.1 or above (in my simple example this is forced by bootstrap, but say we wanted to). We have two official options:

  1. Use a pin. However this would add popper_js as a concrete DEPENDENCIES.
source "https://rubygems.org"

gem "bootstrap", "4.6.2.1"
gem "popper_js", ">= 1.16.1", require: false # Now concrete! And even adding require: false does not help
  1. Use override. However this is worse as it destroys the "< 2" constraint that bootstrap has for popper_js.
source "https://rubygems.org"

gem "bootstrap", "4.6.2.1"
override "popper_js", version: ">= 1.16.1" # `bundle update` produces `2.11.8` which won't work with bootstrap 4.x

What we need

We need a way to say "I want this gem, if it is ever brought into this lockfile, to obey this additional constraint, and all present constraints. If this gem is not there concretely or transitively, it should not be in the lockfile."

Possible solutions

We could do one of a few things:

  1. For now, my gem bundler-resolutions demonstrates a solution to the above need - but it uses patches and since override is coming I'd like to see this functionality made official.
  2. Change override to be non-destructive by default - the supplied version should be /additional/ to present constraints. Maybe a param force: true could be supplied to overwrite all constraints?
  3. Add an alternative command like constraint or resolve.
source "https://rubygems.org"

gem "bootstrap", "4.6.2.1"
resolve "popper_js", version: ">= 1.16.1" 

I think I prefer option 3. Maybe even make that the only new DSL, and add a force: true param to that command?

This relates to #9517 and #8021

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions