[Rubygems-developers] PATCH: respect requirements of gems

Dick Davies rasputnik at hellooperator.net
Wed Apr 21 20:01:42 EDT 2004

Hi, I noticed tonight that if I install copland, it pulls in log4r as I'd expect.
But if I gem -u log4r, gem chugs away happily and removes the log4r, breaking copland.

I could think of several ways to fix this, ideally I guess gems should know what requires them,
but as I don't know enough about the gemspec format yet I think that might be a pig to do.

The patch below isn't perfect, but it lets you ask a Gem::Specification object what other gems need it.
I do the check in Uninstaller.remove(), I hope that's the right place.

It gives output like this:

0rasputin at lb:gems$ gem -u log4r
Attempting to uninstall gem 'log4r'
gem log4r-1.0.5 is required by the following gems: 
0rasputin at lb:gems$

Output should be one gem per line, but obviously I can't test that yet :)

Couple of areas that could use work:

* versions aren't accounted for, because I haven't read the code yet
* the list of Specs returned needs manipulation in the caller, but short of tossing an
  Exception I couldn't think of a better way. I don't think Specifications should
  be calling puts() themselves.
* I abuse the Cache a little :) It could be optimized a little, but hopefully it's not essential.
* there's no unit tests.  Once I get a bit more experience I'll write some test gems
  that just depend on each other for mocking this in unit tests.

patch follows (it's to specification.rb and installer.rb)


Index: lib/rubygems/installer.rb
RCS file: /var/cvs/rubygems/rubygems/lib/rubygems/installer.rb,v
retrieving revision 1.26
diff -r1.26 installer.rb
>       # check nothing depends on us
>       unless spec.users.empty?
>         puts "gem #{spec.full_name} is required by the following gems: "
>         spec.users.each { |s| puts s.full_name }
>         return false
>       end
Index: lib/rubygems/specification.rb
RCS file: /var/cvs/rubygems/rubygems/lib/rubygems/specification.rb,v
retrieving revision 1.29
diff -r1.29 specification.rb
>     ##
>     # list of gems that need us
>     #
>     # return:: [Array] list of Gem::Dependency objects 
>     #
>     def users
>       cache = Cache.from_installed_gems
>       users = []
>       cache.each do |name, spec|
>         spec.dependencies.each { |d|
>           users << spec if d.name == self.name
>         }
>       end
>       users
>     end


Fine's Corollary:
	Functionality breeds Contempt.
Rasputin :: Jack of All Trades - Master of Nuns

More information about the Rubygems-developers mailing list