aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/utils/bottles.rb
blob: 3a61cf215e70238a2e84321f24a0de10dbf46f58 (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
require "tab"
require "extend/ARGV"

module Utils
  class Bottles
    class << self
      def tag
        @bottle_tag ||= "#{ENV["HOMEBREW_PROCESSOR"]}_#{ENV["HOMEBREW_SYSTEM"]}".downcase.to_sym
      end

      def built_as?(f)
        return false unless f.installed?
        tab = Tab.for_keg(f.installed_prefix)
        tab.built_as_bottle
      end

      def file_outdated?(f, file)
        filename = file.basename.to_s
        return unless f.bottle && filename.match(Pathname::BOTTLE_EXTNAME_RX)

        bottle_ext = filename[native_regex, 1]
        bottle_url_ext = f.bottle.url[native_regex, 1]

        bottle_ext && bottle_url_ext && bottle_ext != bottle_url_ext
      end

      def native_regex
        /(\.#{Regexp.escape(tag.to_s)}\.bottle\.(\d+\.)?tar\.gz)$/o
      end

      def receipt_path(bottle_file)
        path = Utils.popen_read("tar", "-tzf", bottle_file).lines.map(&:chomp).find do |line|
          line =~ %r{.+/.+/INSTALL_RECEIPT.json}
        end
        raise "This bottle does not contain the file INSTALL_RECEIPT.json: #{bottle_file}" unless path
        path
      end

      def resolve_formula_names(bottle_file)
        receipt_file_path = receipt_path bottle_file
        receipt_file = Utils.popen_read("tar", "-xOzf", bottle_file, receipt_file_path)
        name = receipt_file_path.split("/").first
        tap = Tab.from_file_content(receipt_file, "#{bottle_file}/#{receipt_file_path}").tap

        if tap.nil? || tap.core_tap?
          full_name = name
        else
          full_name = "#{tap}/#{name}"
        end

        [name, full_name]
      end

      def resolve_version(bottle_file)
        PkgVersion.parse receipt_path(bottle_file).split("/")[1]
      end

      def formula_contents(bottle_file,
          name: resolve_formula_names(bottle_file)[0])
        bottle_version = resolve_version bottle_file
        formula_path = "#{name}/#{bottle_version}/.brew/#{name}.rb"
        contents = Utils.popen_read "tar", "-xOzf", bottle_file, formula_path
        raise BottleFormulaUnavailableError.new(bottle_file, formula_path) unless $CHILD_STATUS.success?
        contents
      end
    end

    class Bintray
      def self.package(formula_name)
        package_name = formula_name.to_s.dup
        package_name.tr!("+", "x")
        package_name.sub!(/(.)@(\d)/, "\\1:\\2") # Handle foo@1.2 style formulae.
        package_name
      end

      def self.repository(tap = nil)
        if tap.nil? || tap.core_tap?
          "bottles"
        else
          "bottles-#{tap.repo}"
        end
      end
    end

    class Collector
      def initialize
        @checksums = {}
      end

      def fetch_checksum_for(tag)
        tag = find_matching_tag(tag)
        return self[tag], tag if tag
      end

      def keys
        @checksums.keys
      end

      def [](key)
        @checksums[key]
      end

      def []=(key, value)
        @checksums[key] = value
      end

      def key?(key)
        @checksums.key?(key)
      end

      private

      def find_matching_tag(tag)
        tag if key?(tag)
      end
    end
  end
end

require "extend/os/bottles"