On 23 May 2010, at 07:40, Chad Woolley wrote:

> 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.

Oooh, you're using --remote. Ok, now I understand the problem! sorry about that.

> 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)

Gem::SpecFetcher.fetcher.list.values.flatten(1).map { |n, v, p| [n,v.to_s] 
}.uniq[0..3] # =>
        [["_", "1.2"], ["-", "1"], ["2Performant", "0.0.2"], ["360_services", 
"1.1.3"]]

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

What kind of objects do you want that are more humane? Simple data structures 
can be coerced easily, and everyone knows how to wrangle them.

> 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.

Gem::SpecFetcher.fetcher.list.values.flatten(1).group_by { |n,v,p| n }

> 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?

What exactly are you trying to do, and what for? I know 'chef', but what 
specific tasks?

> 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?"

Yes, the platform portion is an issue. The API was originally built to satisfy 
local platform settings, obviously overridable by the --platform option, but 
that is currently singleton, and not a good choice for you guys, I agree.

It's still not /that/ bad, all things considered:

Gem::SpecFetcher.fetcher.list(true, true).values.flatten(1).find { |n,v,p| n == 
name && v == version && p == platform }

> 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.

Or on Gem::SpecFetcher?

> 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...

Written using irb(1) in about 5 minutes.

_______________________________________________
Rubygems-developers mailing list
http://rubyforge.org/projects/rubygems
Rubygems-developers@rubyforge.org
http://rubyforge.org/mailman/listinfo/rubygems-developers

Reply via email to