On Sun, May 23, 2010 at 1:21 AM, Chad Woolley <thewoolley...@gmail.com> wrote:
> 1. Are we doing it wrong? Does the RubyGems API provide a way to avoid
> this manual parsing?
> 2. Should there be a --[no-]platforms option to the 'list' command,
> which would have made these updates to the parsing logic unnecessary?

So, I found Eric Hodel's admonishment "Why aren't you using the
RubyGems API?" [1], but that's easier said than done.  James Tucker
followed with this example [2], but that doesn't help, because it
isn't a remote call (just gives an array of "name-version" local
entries).

The only thing the API provides now is Gem.source_index for local
gems, and Gem::SpecFetcher.fetcher for remote gems.  Both of these
return giant nested hashes and arrays of various nested values and
objects.  That's not too user-friendly or intuitive, which is why I
think people just end up parsing the output of gem list.

For example, here's the API call to see if a gem with the specified
name_to_find, version_to_find, and platform_to_find exists remotely:

name_to_find=/^json$/; version_to_find = '1.4.3';
platform_to_find='x86-mingw32';
Gem::SpecFetcher.fetcher.find_matching(Gem::Dependency.new(name_to_find,version_to_find),false,false).map{|spec_tuple|
spec = spec_tuple.first; spec[2] == platform_to_find }.any?{|found|
found == true}

Is there something simpler?  Maybe.  I'm not sure.  Like I said, not
very intuitive, and looking at the RubyGems code for examples doesn't
help much (e.g. the 225-line query_command#output_query_results)

What are the problems?

One problem is the lack of objects here.  Returning a giant nested
hash or array isn't a humane API.

A second problem is the coupling of the version and platform concepts.
 Ideally, I'd like to have these abstractions:

* A Gem has one or more Versions.
* Each Version has one or more Platforms.

Instead, SpecFetcher provides this representation of the platforms
supported by a specific gem name and version:

Gem::SpecFetcher.fetcher.find_matching(Gem::Dependency.new(/^json$/,'1.4.3'),true,false)

[[["json", #<Gem::Version "1.4.3">, "x86-mingw32"],
"http://rubygems.org/";], [["json", #<Gem::Version "1.4.3">, "ruby"],
"http://rubygems.org/";], [["json", #<Gem::Version "1.4.3">,
"x86-mswin32"], "http://rubygems.org/";]]

What can we do?

When I think of an "easy" API for this, it's kind of hard given these
issues.  Maybe we could at least provide something for the common use
case chef and geminstaller had, which is "does this gem name (and
optionally version/platform) exist remotely?"

exists_remotely?(name, version=nil, platform=nil)

where version and and platform would be defaulted to match anything.
This method could be anywhere, on Gem, or a FriendlyApi module mixed
into Gem; whatever as it is intuitive and easily found.

Anyway, just some thoughts, because it's not cool to tell people "Use
the API!" when that is only possible given a fairly deep understanding
of RubyGems internals...

-- Chad

[1] 
https://tickets.opscode.com/browse/CHEF-1168?focusedCommentId=13981&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_13981

[2] 
https://tickets.opscode.com/browse/CHEF-1168?focusedCommentId=13983&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_13983
_______________________________________________
Rubygems-developers mailing list
http://rubyforge.org/projects/rubygems
Rubygems-developers@rubyforge.org
http://rubyforge.org/mailman/listinfo/rubygems-developers

Reply via email to