[Rubygems-developers] Gem-Spec Meta Information

Mehr, Assaph (Assaph) assaph at avaya.com
Mon Jul 26 19:50:06 EDT 2004



> One thing to note re: the generic hash approach.  In rubygems we
convert back and
> forth between ruby source and yaml.  We do this because when you use a
gem (with
> require_gem) I did not want to have to have folks load yaml...the
gemspecs are
> 'serialized' to ruby source and used from there.
> With the generic hash, we cannot generically convert that to source.
What we would
> have to do to support this is make the to_ruby serializer just store
the 'meta' hash
> as a here-doc string.  And add a message on the GemSpecification
object that unpacks
> it for you...like a 'metadata' method that either uses the meta
already there because
> it came from yaml, or unpacks it if it came from ruby.

> Does that make sense?

I implemented the to_ruby serialization so:

  if @meta && !@meta.empty?
    meta.each_pair do |k,v|
      result << "  s.meta[#{k}] = #{v}\n"
    end
  end

Does this make sense? It seems to work fine.
BTW, I use the keys on the meta as methods for the installer-builder.
Not very smart
as I can't be sure of the order. I'll fix this soon, but this is just a
prototype.
Here are sample snippets:

class AppGemInst
  FILE_TYPE       = 'do_ftype'
  FILE_ICON       = 'do_fileicon'
  APP_ICON        = 'do_appicon'
  HELP_FILE       = 'do_help'
  UPDATE_SERVER   = 'do_update'
  

  def initialize(gem)
    @spec = Gem::Format.from_file_by_path(gem).spec
    # pp @spec
  end
  
  def install
    if RUBY_PLATFORM =~ /mswin32/
      Win32Installer.new(@spec).generate
    end
  end
  
  class NullInstaller
    def initialize(spec)
      @spec = spec
      @meta = spec.meta
    end

    def generate
      @meta.each_pair { |k,v| send(k, v) }
    end
    
    # empty implementations:
    def do_ftype; end
    def do_fileicon; end
    def do_appicon; end
    def do_help; end
    def do_update; end
  end
  
  class Win32Installer < NullInstaller
    def do_ftype(extension)
      type_name = "#{@spec.name.gsub(/\s/,'').capitalize}File"
      ruby_cmd =
Win32::Registry::HKEY_CLASSES_ROOT.open('rbFile\\Shell\\open\\command')
do |reg|
        reg[""]
      end
      ruby = ruby_cmd.scan(/"(.+?)"/)[0][0]
      bindir = File.dirname ruby
      exe = File.join(bindir , @spec.executables[0]).gsub('/','\\')
      p [bindir, type_name, File.expand_path(exe)]
      
      %x{assoc #{extension}=#{type_name}}
      %x{ftype #{type_name}="#{ruby}" "#{exe}" %*}
    end
    
    def do_fileicon
      
  end
  
end

And here's the additions to specification.rb:

---
c:\langs\ruby\apps\rubygems.orig\rubygems\lib\rubygems\specification.rb
2004-07-05 11:53:24.000000000 +-1000
+++ c:\langs\ruby\apps\rubygems\lib\rubygems\specification.rb
2004-07-26 19:53:13.000000000 +-1000
@@ -1,477 +1,486 @@
     attr_reader :required_ruby_version

+    attr_reader :meta

     ##
       @test_suite_file = nil
       @required_ruby_version = Gem::Version::Requirement.new("> 0.0.0")
+      @meta = Hash.new
       self.platform = nil
       result << '@extension_requirements' if
extension_requirements.size > 0
       result << '@description' if @description
+      result << '@meta' unless @meta.empty?
       result
     end
       result << "  s.rubyforge_project = %q{#{rubyforge_project}}\n" if
rubyforge_project
       result << "  s.description = <<-EOS\n#{description}\nEOS\n" if
description
+      if @meta && !@meta.empty?
+        meta.each_pair do |k,v|
+          result << "  s.meta[#{k}] = #{v}\n"
+        end
+      end
       result << "end\n"
       result



More information about the Rubygems-developers mailing list