Specify source when using gem install with two sources - ruby

We do have an internal gem server (http://my.gem.server) and at this server we store the gem foo-1.2.3.gem
Our users add this server to the gem source. Our gem source looks like::
*** CURRENT SOURCES ***
https://rubygems.org/
http://my.gem.server/
So far it was working wonderfully.
Then someone at the community created the foo-0.0.1.gem
Now, when our internal clients perform a gem install, the foo-0.0.1.gem from the community is installed instead of our foo-1.2.3.gem
We have tried putting our source before the standard rubygems.org but still get the same results.
Does anyone know how can I tell gem install to get the gem from our internal source?
It would be even better if it would just hit the community source if it does not find on ours.

You have two options:
Specify the source in the command
gem install --source http://my.gem.server/ install foo
Edit the ${HOME}/.gemrc file
change
:sources:
- http://rubygems.org
- http://my.gem.server
to
:sources:
- http://my.gem.server
- http://rubygems.org

In your Gemfile, separate all gems into source blocks:
source "http://my.gem.server/" do
gem "foo"
end
source "https://rubygems.org/" do
gem "rails"
end
Having global source lines and/or using :source to disambiguate can open you to security issues, as these don't actually work the way you would expect:
http://collectiveidea.com/blog/archives/2016/10/06/bundlers-multiple-source-security-vulnerability/
Any internal gem name might get claimed on rubygems.org and suddenly get installed instead.

To add on to #ptierno's answer, if you have a Gemfile or .gemspec you can use the :source parameter.
gem 'foo', :source => 'http://my.gem.server'
Which gives priority to that server for that gem only.

Related

Ruby Gem conflicts between local gem and system installed gem

I have a Gemfile that looks something like this:
source 'http://rubygems.org'
gemspec
gem "parent_gem", "0.1.3", :path => "#{File.expand_path(__FILE__)}/../vendor/gems/parent_gem-0.1.3"
parent_gem depends on child_gem-1.4.1, which we have packaged in the /vender/gems folder in the package. If a user installs child_gem-1.6.0 on their host on Ubuntu, they will get a Gem::ConflictError because it will try to use 1.6 and log child_gem-1.6.0 conflicts with child_gem (~> 1.4.1). However, if a user runs it on Amazon Linux, it works fine and uses the packaged child gem.
If I run gem list child_gem, I get the following output on both systems:
*** LOCAL GEMS ***
child_gem (1.6.1)
gem list parent_gem returns nothing because it's not installed separated and only exists in the package's vendor directory.
In the files that initiates the script, there is this line:
Gem.use_paths(nil, Gem.path << "/opt/my-app/vendor")
And the /opt/my-app/vendor directory includes child_gem-1.4.1.
Ultimately, I know that setting up the package properly with Bundler should resolve the issue, but I'm trying to understand why this is an issue.
How does Ruby decide where to look for a gem on a system? And where do I look to understand why it works on Amazon Linux but not Ubuntu?

Bundler: using shared gem when it exists, rather than downloading from gem server

Say, I have Gemfile like following.
source "GEM_REPOSITORY"
gem 'gem_A'
# gem_A has no additional dependency
gem 'gem_B'
# gem_B depends on gem_B_1 and gem_B_2
When I run bundle install, I want Bundler to do the following.
If a gem already exists in "local system-wide gems", it copies the gem from local.
If a gem doesn't exist in local, it looks for GEM_REPOSITORY.
I looked for some related articles, and found some of likely-answers like
Ruby Bundler multiple sources in Gemfile
SOURCE PRIORITY
But none of the above looks like the answer for me.
Using source repository priority does't work. Because in the example above, if dependent gem (say, gem_B_1) exits in local but the target gem (gem_B) doesn't exist in local, it'll download both of above from the remote repository.
Are there any work around for doing this?
If not, don't you guys think it's necessary considering the cost of the implementation and the effect?
This is the current behavior.
When running gem install, directly or via bundle install, gem will first build a dependency graph with all the needed gems. If the gem is found locally it will use it, otherwise it will try to download it from the specified source.
If you want, try it yourself.
bundle gem gem_a
bundle gem gem_b
cd gem_a
vim gem_a.gemspec
add
spec.add_dependency 'multi_json', '~> 1.10.1'
or any dependency you want to the gem and run bundle install.
cd ../gem_b
vim Gemfile
and add
gem 'gem_a', path: '../gem_a'
then run
bundle install --verbose
you will see that the multi_json or whatever dependency of gem_a uses the local version and does not download anything.
This is of course also true for gems from remote sources.

Ruby Bundler multiple sources in Gemfile

I need to ensure some of my gems are installed from our own gem repository rather than rubygems, while the rest are installed from rubygems. Can I set this up in the Gemfile without worrying about a naming conflict with a identically named gem in Rubygems? How Can I determine where the gem is downloaded from?
eg
Gemfile:
source :rubygems
gem 'gemfromrubygems1'
gem 'gemfromrubygems2'
source "http://our.own.gem.repo.com/the/path/to/it"
gem 'gemfromourrepo'
Bundler 1.7 has a new feature that allows you to select the source for specific gems by nesting them in a block:
source "https://rubygems.org"
gem 'gemfromrubygems1'
gem 'gemfromrubygems2'
source "http://our.own.gem.repo.com/the/path/to/it" do
gem 'gemfromourrepo'
end
or specifying it as an option:
source "https://rubygems.org"
gem 'gemfromrubygems1'
gem 'gemfromrubygems2'
gem 'gemfromourrepo', source: "http://our.own.gem.repo.com/the/path/to/it"
See http://bundler.io/v1.7/gemfile.html for details.
According to the Source Priority section in the Gemfile manpage sources are searched from last entered to first entered.
Based on what you said, it sounds like you want to always prefer your gem over rubygems.org. As long as you don't need to vary your preference (ie. some dups from rubygems.org and some dups from your private repo) then your problem is solved simply with the following Gemfile:
source 'https://rubygems.org'
source 'http://our.own.gem.repo.com/the/path/to/it'
gem 'gemfromrubygems1'
gem 'gemfromrubygems2'
gem 'gemfromourrepo'
The only way I found seems like a horrible hack.
Bundler will search for the best version of your gem starting at the source listed last and then searching all the sources listed previously. It doesn't matter where the source lines are relative to the gem lines, only relative to each other.
I tried to make it work using :git and :path, but neither of those work for gemservers. That leaves matching the best version.
If you set the version of your gem to something like 2.mine.1 and push that to your server, you can constrain the version in your Gemfile.
source :rubygems
source 'http://myrepo'
gem 'gemfromourrepo', '~> 2.ourrepo'
Then the best matching version should be one from your server. There's a chance someone could push their own gem of the same name with 2.ourrepo.2 to rubygems, but that is unlikely if it is unique.
The path command might be able to help. It allows you to set gem specific sources
gem "foo", "1.0", :path => "bar"
Source:http://bundler.io/v1.3/man/gemfile.5.html

Ruby Gem server not serving gems?

I am trying to make a new acceptance agent for teamcity...I followed this article http://docs.rubygems.org/read/chapter/18...
I created a website in IIS called gemserver and having a port 910. it has gems folder which has ancient gems like activerecord-sqlserver-adapter-1.0.0.9250...
I don't know the mime-type for .gem extension so I just put application/x-ruby-gem. Although manually when I put machinename:910/gems/Gem_Name I am able to download it.
but when i use bundle install it gives below error
Fetching source index for http://gems.github.com/
Fetching source index for my server url
Could not reach rubygems repository http://gems.github.com/, my server url:
910/, http://rubygems.org/
Fetching source index for http://rubygems.org/
Could not find gem 'activerecord-sqlserver-adapter (= 1.0.0.9250, runtime)' in a
ny of the gem sources listed in your Gemfile.
Please find below Gemfile.
source "http://computerName:910/"
source :gemcutter
gem 'rake', '0.8.7'
gem 'cucumber', '0.6.2'
gem 'watir', '1.6.5'
gem 'activerecord', '2.3.8'
gem 'activerecord-sqlserver-adapter', '1.0.0.9250'
gem 'rspec', '1.3.0'
gem 'parseexcel', '0.5.2'
gem 'win32-api', '1.4.5'
gem 'nokogiri', '1.4.1'
gem 'win32-eventlog', '0.5.2'
gem 'win32console'
Use the ip address instead of computername and see if that fixes your 504 problem
Now try to update your gems, if you get a 404 error when trying to access a folder called /quick then run the generate_index command with the --legacy option
gem generate_index --legacy
Add .rz mimetype to your IIS so that it can serve the rzip files. In IIS mime types, add the following mapping:
.rz -> application/x-rzip
I don't know the mime-type for .gem extension so I just put application/x-ruby-gem. Although manually when I put machinename:910/gems/Gem_Name I am able to download it.
Your gem client is complaining that the source index can't be reached, not the gem itself.
In the article you linked to, item 4.2.4 instructs:
Run the generate_index gem command in order to generate the yaml and yaml.Z files needed by the RubyGems client.
Make sure generate_index created the yaml and yaml.Z files in your gems directory. Check if they are accessible. This is the source index that your gems client is looking for.
For example, GitHub's gem source index file is located here: http://gems.github.com/gems/yaml

Installing a gem from Github with Bundler

I am trying to use the instructions here to install a pre-released version of a gem with bundler.
The "bundle install" output lists the gem as getting installed, but "gem list" fails to find it.
My Gemfile:
source :gemcutter
gem 'sinatra', '1.1.0', :git => 'http://github.com/sinatra/sinatra.git'
gem 'RedCloth', '4.2.3'
Here is a gist with the rest of my sample code.
Has anyone gotten this scenario to work?
NOTE: I am also using RVM (on OS X). bundle show does list the gem (and dependencies) as existing, but I am not able to properly resolve them.
Thanks.
I would look at the load paths, and further debug from there, example:
...(master) $ irb
irb(main):001:0> $LOAD_PATH.count
=> 8
irb(main):004:0> require 'bundler/setup'
=> true
irb(main):005:0> $LOAD_PATH.count
=> 112
irb(main):006:0>
Bundler configures the load path for you, this means not all the gems are included on your load path by default.
Additionally, from the bundler git help:
Because Rubygems lacks the ability to handle gems from git, any gems installed from a git repository will not show up in gem list. They will, however, be available after running Bundler.setup.
Best regards, hope this helps
ED
Bundler might have installed it locally to your app. This could vary wildly, depending on OS and whether you are using RVM.
What is the output of bundle show sinatra?
In my case, sinatra was installed here:
/home/marshall/.rvm/gems/ruby-1.8.7-p302#3846859/bundler/gems/sinatra-9cfa74a7f352
Sinatra doesn't show in the gems list, but the server launches correctly if I execute rackup.
Gems installed via bundler on Engine Yard go to a different folder to isolate them.
it's usually /data/APP_NAME/shared/bundled_gems
To be sure, check your .bundle/config file on your APP folder at Engine Yard
It looks like there is an issue using Shotgun and Bundler (git repositories only).
If I use rackup to start up my app, all is well. I am going to investigate a little more and then file a bug with one (or both) of the projects.

Resources