How is it possible to create interdependent gems, and still use Bundler?
Right now, if the Gemfile
for library-a
reads like this:
gem 'library-b'
gem 'library-c'
And the Gemfile
for library-b
reads like this:
gem 'library-a'
gem 'library-c'
And the Gemfile
for library-c
reads:
gem 'library-a', github: 'library-root/library-a', branch: 'master'
gem 'library-b', github: 'library-root/library-b', branch: 'master'
When you try to run bundle update
and/or bundle install
for library-c
, this is the output:
Your Gemfile requires gems that depend depend on each other,
creating an infinite loop. Please remove either gem 'library-a'
or gem 'library-b' and try again.
A variation of the same message will happen for library-a
or library-b
.
But if you use the following for library-c
, and use the same style for library-b
and library-a
, this will work:
gem.add_dependency 'library-a'
gem.add_dependency 'library-b'
However now, you will need to cut and push gems to RubyGems to test each revision, especially when using Travis CI. Whereas if you'd used Gemfile
definitions, even if you also used gemspec
definitions, the code being run or tested would have been pulled from a git repository, and could be updated up-to-the-minute without cutting and pushing gems.
I've posted two issues about this.
- https://github.com/bundler/bundler/issues/3594
- https://github.com/bundler/bundler/issues/3597
I need to have interdependent gems, and use git repositories as the source of the gem code.
For those who say just don't do it ... "it's Circular Dependency
", etc. I understand, but let's think about this. Is a gem really that complicated? It's just files with a certain structure. True, it has version information, and "dependencies" associated -- but those dependencies just need to be present. If a gem of the appropriate version exists already, it ought to just break out of a "circular dependency" and say, "hey, the gem's already here, let's just move forward" then.
Bundler
is a package management system; the above is not Circular Dependency
of objects it is Interdependency
of files ... if it were Objects inheriting from each other, definitely... I surrender. But this is a point where one package assumes another exists in the filesystem.
You could change the word depends
to expects the presence of
not requires specifically sequential instantiation of
.
Again gemspec
works. If it were Circular Dependency
that would be impossible. But gemspec
is clearer on its purpose as part of a package management system. It lets files be files.
gemspec
behavior? Both gems need each other? Cool! Download both gems. Easy, done.
Gemfile
behavior? Both gems need each other? Wait, what? Implode.
I want gemspec
"dependency" behavior, with Gemfile
source specificity power. Otherwise I'd just keep using gemspec
only.