Skip to content

Instantly share code, notes, and snippets.

@jrafanie
Created June 16, 2016 18:44
Show Gist options
  • Save jrafanie/abd10640d31b88f77f7fcaaf6ef48b14 to your computer and use it in GitHub Desktop.
Save jrafanie/abd10640d31b88f77f7fcaaf6ef48b14 to your computer and use it in GitHub Desktop.
Fallout from fix of bundler path gems always causing re-resolve (https://github.com/bundler/bundler/pull/4618)
* Even with no changes to the gemspecs for path based gems, bundler will always
re-resolve.
* After fixing above, the following issues were uncovered because the re-resolve
was masking these problems.
1) When you have a path with multiple gemspecs in subdirectories:
When bundler creates a Bundler::Source::Path object at the toplevel directory,
it creates gem specifications for each gemspec but the path to the gemspec uses
the toplevel path and not the nested path.
gem
foo
foo.gemspec
bar
bar.gemspec
path "gem/" do
gem "foo"
gem "bar"
end
Or:
gem "foo", :path => "gem/"
gem "bar", :path => "gem/"
Bundler::Source::Path.new('path' => 'gem').specs =>
[Gem::Specification foo, 'path' => 'gem', Gem::Specification bar, 'path' => 'gem']]
It should be something like this:
Bundler::Source::Path.new('path' => 'gem').specs =>
[Gem::Specification foo, 'path' => 'gem/foo', Gem::Specification bar, 'path' => 'gem/bar']]
* dependencies_for_source_changed? looks for dependencies and locked dependencies
based on the source and because we have incorrectly marked multiple dendendencies
with the same source path, and therefore compare incorrectly... words
2) Bundler::Source::Path#specs always goes to the filesystem to retrieve specs.
When a Path is created in the LockfileParser, it does not directly populate the
specs for that source from the information in the lockfile.
p = Bundler::Source::Path.new
LazySpec.new("foo", "1.0").source = p
LazySpec.new("bar", "1.0").source = p
p.specs # Goes out to the filesystem which may have changed so might not match foo and bar
Later, when we try to compare the lockfile to the filesystem to detect changes,
we end up comparing the filesystem dependencies to itself, thus yielding "no changes detected."
* converge_locked_specs is responsible for using the parsed Gemfile.lock and removing
any entries from the lock which cannot be re-used because they have changed.
* nothing_changed? should be detecting any changes to the various gem types and
allow bundler to re-resolve on top of the partial tree we obtained from the
converge_locked_specs. When converge_locked_specs returns a partial tree with
path level changes removed, we'd expect nothing_changed? to return false but
instead it returns true because of bug #2. This causes a partial tree to be
written to the lockfile.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment