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
168
169
170
171
172
173
174
175
176
177
  | 
require 'download_strategy'
require 'checksums'
require 'version'
class SoftwareSpec
  attr_reader :checksum, :mirrors, :specs
  def initialize url=nil, version=nil
    @url = url
    @version = version
    @mirrors = []
    @specs = {}
  end
  def download_strategy
    @download_strategy ||= DownloadStrategyDetector.detect(@url, @using)
  end
  def verify_download_integrity fn
    fn.verify_checksum @checksum
  rescue ChecksumMissingError
    opoo "Cannot verify package integrity"
    puts "The formula did not provide a download checksum"
    puts "For your reference the SHA1 is: #{fn.sha1}"
  rescue ChecksumMismatchError => e
    e.advice = <<-EOS.undent
    Archive: #{fn}
    (To retry an incomplete download, remove the file above.)
    EOS
    raise e
  end
  # The methods that follow are used in the block-form DSL spec methods
  Checksum::TYPES.each do |cksum|
    class_eval %Q{
      def #{cksum}(val=nil)
        if val.nil?
          @checksum if @checksum.nil? or @checksum.hash_type == :#{cksum}
        else
          @checksum = Checksum.new(:#{cksum}, val)
        end
      end
    }
  end
  def url val=nil, specs={}
    return @url if val.nil?
    @url = val
    @using = specs.delete(:using)
    @specs.merge!(specs)
  end
  def version val=nil
    @version ||= case val
      when nil then Version.parse(@url)
      when Hash
        key, value = val.shift
        scheme = VersionSchemeDetector.new(value).detect
        scheme.new(key)
      else Version.new(val)
      end
  end
  def mirror val
    @mirrors ||= []
    @mirrors << val
  end
end
class HeadSoftwareSpec < SoftwareSpec
  def initialize url=nil, version=Version.new(:HEAD)
    super
  end
  def verify_download_integrity fn
    return
  end
end
class Bottle < SoftwareSpec
  attr_writer :url
  attr_reader :revision, :root_url, :cellar
  # TODO: Can be removed when all bottles migrated to underscored cat symbols.
  attr_reader :cat_without_underscores
  def initialize
    super
    @revision = 0
    @cellar = '/usr/local/Cellar'
    @cat_without_underscores = false
  end
  # Checksum methods in the DSL's bottle block optionally take
  # a Hash, which indicates the platform the checksum applies on.
  Checksum::TYPES.each do |cksum|
    class_eval %Q{
      def #{cksum}(val=nil)
        @#{cksum} ||= Hash.new
        case val
        when nil
          @#{cksum}[MacOS.cat]
        when Hash
          key, value = val.shift
          @#{cksum}[value] = Checksum.new(:#{cksum}, key)
        end
        if @#{cksum}.has_key? MacOS.cat
          @checksum = @#{cksum}[MacOS.cat]
        elsif @#{cksum}.has_key? MacOS.cat_without_underscores
          @checksum = @#{cksum}[MacOS.cat_without_underscores]
          @cat_without_underscores = true
        end
      end
    }
  end
  def root_url val=nil
    val.nil? ? @root_url : @root_url = val
  end
  def cellar val=nil
    val.nil? ? @cellar : @cellar = val
  end
  def revision val=nil
    val.nil? ? @revision : @revision = val
  end
  # Used in the old bottle DSL to set @revision, but acts as an
  # as accessor for @version to preserve the interface
  # TODO: Can be removed when no bottles are using `version` any more.
  def version val=nil
    if val.nil?
      return @version ||= Version.parse(@url)
    else
      @revision = val
    end
  end
end
# Used to annotate formulae that duplicate OS X provided software
# or cause conflicts when linked in.
class KegOnlyReason
  attr_reader :reason, :explanation
  def initialize reason, explanation=nil
    @reason = reason
    @explanation = explanation
    @valid = case @reason
      when :provided_pre_mountain_lion then MacOS.version < :mountain_lion
      else true
      end
  end
  def valid?
    @valid
  end
  def to_s
    case @reason
    when :provided_by_osx then <<-EOS.undent
      Mac OS X already provides this software and installing another version in
      parallel can cause all kinds of trouble.
      #{@explanation}
      EOS
    when :provided_pre_mountain_lion then <<-EOS.undent
      Mac OS X already provides this software in versions before Mountain Lion.
      #{@explanation}
      EOS
    else
      @reason
    end.strip
  end
end
  |