summaryrefslogtreecommitdiff
path: root/lib/bundler/ruby_version.rb
blob: 84bd2eff860165ca8c34b8983d3a21de8a0eeb63 (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
module Bundler
  class RubyVersion
    attr_reader :version, :patchlevel, :engine, :engine_version

    def initialize(version, patchlevel, engine, engine_version)
      # The parameters to this method must satisfy the
      # following constraints, which are verified in
      # the DSL:
      #
      # * If an engine is specified, an engine version
      #   must also be specified
      # * If an engine version is specified, an engine
      #   must also be specified
      # * If the engine is "ruby", the engine version
      #   must not be specified, or the engine version
      #   specified must match the version.

      @version        = version
      @engine         = engine || "ruby"
      # keep track of the engine specified by the user
      @input_engine   = engine
      @engine_version = engine_version || version
      @patchlevel     = patchlevel
    end

    def to_s
      output = "ruby #{version}"
      output << "p#{patchlevel}" if patchlevel
      output << " (#{engine} #{engine_version})" unless engine == "ruby"

      output
    end

    def ==(other)
      version == other.version &&
        engine == other.engine &&
        engine_version == other.engine_version &&
        patchlevel == other.patchlevel
    end

    def host
      @host ||= [
        RbConfig::CONFIG["host_cpu"],
        RbConfig::CONFIG["host_vendor"],
        RbConfig::CONFIG["host_os"]
      ].join("-")
    end

    def gem_version
      Gem::Version.new(version)
    end
  end

  # A subclass of RubyVersion that implements version,
  # engine and engine_version based upon the current
  # information in the system. It can be used anywhere
  # a RubyVersion object is expected, and can be
  # compared with a RubyVersion object.
  class SystemRubyVersion < RubyVersion
    def initialize(*)
      # override the default initialize, because
      # we will implement version, engine and
      # engine_version dynamically
    end

    def version
      RUBY_VERSION.dup
    end

    def gem_version
      @gem_version ||= Gem::Version.new(version)
    end

    def engine
      if defined?(RUBY_ENGINE)
        RUBY_ENGINE.dup
      else
        # not defined in ruby 1.8.7
        "ruby"
      end
    end

    def engine_version
      case engine
      when "ruby"
        RUBY_VERSION.dup
      when "rbx"
        Rubinius::VERSION.dup
      when "jruby"
        JRUBY_VERSION.dup
      else
        raise BundlerError, "RUBY_ENGINE value #{RUBY_ENGINE} is not recognized"
      end
    end

    def patchlevel
      RUBY_PATCHLEVEL.to_s
    end
  end

  class RubyVersionRequirement
    def initialize(version, patchlevel, engine, engine_version)
      @ruby_version = RubyVersion.new version, patchlevel, engine, engine_version
    end

    # Returns a tuple of these things:
    #   [diff, this, other]
    #   The priority of attributes are
    #   1. engine
    #   2. ruby_version
    #   3. engine_version
    def diff(other)
      if engine != other.engine && input_engine
        [:engine, engine, other.engine]
      elsif !version || !matches?(version, other.version)
        [:version, version, other.version]
      elsif input_engine && !matches?(engine_version, other.engine_version)
        [:engine_version, engine_version, other.engine_version]
      elsif patchlevel && (!patchlevel.is_a?(String) || !other.patchlevel.is_a?(String) || !matches?(patchlevel, other.patchlevel))
        [:patchlevel, patchlevel, other.patchlevel]
      else
        nil
      end
    end

    def gem_version
      @ruby_version.gem_version
    end

    def ==(other)
      version == other.version &&
        engine == other.engine &&
        engine_version == other.engine_version &&
        patchlevel == other.patchlevel
    end

    def input_engine
      @ruby_version.instance_variable_get(:@input_engine)
    end

    def engine
      @ruby_version.engine
    end

    def patchlevel
      @ruby_version.patchlevel
    end

    def engine_version
      @ruby_version.engine_version
    end

    def version
      @ruby_version.version
    end

    def to_s
      @ruby_version.to_s
    end

  private

    def matches?(requirement, version)
      Gem::Requirement.create(requirement).satisfied_by?(Gem::Version.new(version))
    end
  end
end