summaryrefslogtreecommitdiff
path: root/lib/rubygems/stub_specification.rb
blob: 08102b48ef6b01fe53635b29060c4213fdce3556 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
##
# 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 Gem::StubSpecification < Gem::BasicSpecification
  # :nodoc:
  PREFIX = "# stub: "

  OPEN_MODE = # :nodoc:
    if Object.const_defined? :Encoding then
      'r:UTF-8:-'
    else
      'r'
    end

  class StubLine # :nodoc: all
    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.loaded_from = filename
    @data            = nil
    @spec            = nil
  end

  ##
  # True when this gem has been activated

  def activated?
    loaded = Gem.loaded_specs[name]
    loaded && loaded.version == version
  end

  ##
  # If the gemspec contains a stubline, returns a StubLine instance. Otherwise
  # returns the full Gem::Specification.

  def data
    unless @data
      open loaded_from, 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

  private :data

  ##
  # Name of the gem

  def name
    @name ||= data.name
  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(loaded_from)
  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

  ##
  # Version of the gem

  def version
    @version ||= data.version
  end

end