module Gem # Gem::StubSpecification reads the stub: line from the gemspec # This prevents us having to eval the entire gemspec in order to # find out certain information. class StubSpecification < BasicSpecification # :nodoc: PREFIX = "# stub: " OPEN_MODE = # :nodoc: if Object.const_defined? :Encoding then 'r:UTF-8:-' else 'r' end # :nodoc: class StubLine attr_reader :parts def initialize(data) @parts = data[PREFIX.length..-1].split(" ") end def name @parts[0] end def version Gem::Version.new @parts[1] end def platform Gem::Platform.new @parts[2] end def require_paths @parts[3..-1].join(" ").split("\0") end end def initialize(filename) self.filename = filename @data = nil @spec = nil end ## # Name of the gem def name @name ||= data.name end ## # Version of the gem def version @version ||= data.version end ## # Platform of the gem def platform @platform ||= data.platform end ## # Require paths of the gem def require_paths @require_paths ||= data.require_paths end ## # The full Gem::Specification for this gem, loaded from evalling its gemspec def to_spec @spec ||= Gem::Specification.load(filename) end ## # True when this gem has been activated def activated? loaded = Gem.loaded_specs[name] loaded && loaded.version == version end ## # Is this StubSpecification valid? i.e. have we found a stub line, OR does # the filename contain a valid gemspec? def valid? data end private ## # If the gemspec contains a stubline, returns a StubLine instance. Otherwise # returns the full Gem::Specification. def data unless @data open filename, OPEN_MODE do |file| begin file.readline # discard encoding line stubline = file.readline.chomp @data = StubLine.new(stubline) if stubline.start_with?(PREFIX) rescue EOFError end end end @data ||= to_spec end end end