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