diff options
Diffstat (limited to 'Library/Homebrew/cmd/bottle.rb')
| -rw-r--r-- | Library/Homebrew/cmd/bottle.rb | 458 |
1 files changed, 0 insertions, 458 deletions
diff --git a/Library/Homebrew/cmd/bottle.rb b/Library/Homebrew/cmd/bottle.rb deleted file mode 100644 index 1980fbe9d..000000000 --- a/Library/Homebrew/cmd/bottle.rb +++ /dev/null @@ -1,458 +0,0 @@ -#: @hide_from_man_page -#: * `bottle` [`--verbose`] [`--no-rebuild`] [`--keep-old`] [`--skip-relocation`] [`--root-url=<root_url>`]: -#: * `bottle` `--merge` [`--no-commit`] [`--keep-old`] [`--write`]: -#: -#: Generate a bottle (binary package) from a formula installed with -#: `--build-bottle`. - -require "formula" -require "utils/bottles" -require "tab" -require "keg" -require "formula_versions" -require "utils/inreplace" -require "erb" -require "extend/pathname" - -BOTTLE_ERB = <<-EOS - bottle do - <% if !root_url.start_with?(BottleSpecification::DEFAULT_DOMAIN) %> - root_url "<%= root_url %>" - <% end %> - <% if prefix != BottleSpecification::DEFAULT_PREFIX %> - prefix "<%= prefix %>" - <% end %> - <% if cellar.is_a? Symbol %> - cellar :<%= cellar %> - <% elsif cellar != BottleSpecification::DEFAULT_CELLAR %> - cellar "<%= cellar %>" - <% end %> - <% if rebuild > 0 %> - rebuild <%= rebuild %> - <% end %> - <% checksums.each do |checksum_type, checksum_values| %> - <% checksum_values.each do |checksum_value| %> - <% checksum, osx = checksum_value.shift %> - <%= checksum_type %> "<%= checksum %>" => :<%= osx %> - <% end %> - <% end %> - end -EOS - -MAXIMUM_STRING_MATCHES = 100 - -module Homebrew - def keg_contain?(string, keg, ignores) - @put_string_exists_header, @put_filenames = nil - - def print_filename(string, filename) - unless @put_string_exists_header - opoo "String '#{string}' still exists in these files:" - @put_string_exists_header = true - end - - @put_filenames ||= [] - unless @put_filenames.include? filename - puts "#{Tty.red}#{filename}#{Tty.reset}" - @put_filenames << filename - end - end - - result = false - - keg.each_unique_file_matching(string) do |file| - # skip document file. - next if Metafiles::EXTENSIONS.include? file.extname - - linked_libraries = Keg.file_linked_libraries(file, string) - result ||= !linked_libraries.empty? - - if ARGV.verbose? - print_filename(string, file) unless linked_libraries.empty? - linked_libraries.each do |lib| - puts " #{Tty.gray}-->#{Tty.reset} links to #{lib}" - end - end - - text_matches = [] - - # Use strings to search through the file for each string - Utils.popen_read("strings", "-t", "x", "-", file.to_s) do |io| - until io.eof? - str = io.readline.chomp - next if ignores.any? { |i| i =~ str } - next unless str.include? string - offset, match = str.split(" ", 2) - next if linked_libraries.include? match # Don't bother reporting a string if it was found by otool - - result = true - text_matches << [match, offset] - end - end - - if ARGV.verbose? && !text_matches.empty? - print_filename string, file - text_matches.first(MAXIMUM_STRING_MATCHES).each do |match, offset| - puts " #{Tty.gray}-->#{Tty.reset} match '#{match}' at offset #{Tty.em}0x#{offset}#{Tty.reset}" - end - - if text_matches.size > MAXIMUM_STRING_MATCHES - puts "Only the first #{MAXIMUM_STRING_MATCHES} matches were output" - end - end - end - - keg_contain_absolute_symlink_starting_with?(string, keg) || result - end - - def keg_contain_absolute_symlink_starting_with?(string, keg) - absolute_symlinks_start_with_string = [] - keg.find do |pn| - if pn.symlink? && (link = pn.readlink).absolute? - if link.to_s.start_with?(string) - absolute_symlinks_start_with_string << pn - end - end - end - - if ARGV.verbose? - unless absolute_symlinks_start_with_string.empty? - opoo "Absolute symlink starting with #{string}:" - absolute_symlinks_start_with_string.each do |pn| - puts " #{pn} -> #{pn.resolved_path}" - end - end - end - - !absolute_symlinks_start_with_string.empty? - end - - def bottle_output(bottle) - erb = ERB.new BOTTLE_ERB - erb.result(bottle.instance_eval { binding }).gsub(/^\s*$\n/, "") - end - - def bottle_formula(f) - unless f.installed? - return ofail "Formula not installed or up-to-date: #{f.full_name}" - end - - unless f.tap - return ofail "Formula not from core or any taps: #{f.full_name}" - end - - if f.bottle_disabled? - ofail "Formula has disabled bottle: #{f.full_name}" - puts f.bottle_disable_reason - return - end - - unless Utils::Bottles::built_as? f - return ofail "Formula not installed with '--build-bottle': #{f.full_name}" - end - - unless f.stable - return ofail "Formula has no stable version: #{f.full_name}" - end - - if ARGV.include? "--no-rebuild" - rebuild = 0 - elsif ARGV.include? "--keep-old" - rebuild = f.bottle_specification.rebuild - else - ohai "Determining #{f.full_name} bottle rebuild..." - versions = FormulaVersions.new(f) - rebuilds = versions.bottle_version_map("origin/master")[f.pkg_version] - rebuilds.pop if rebuilds.last.to_i > 0 - rebuild = rebuilds.empty? ? 0 : rebuilds.max.to_i + 1 - end - - filename = Bottle::Filename.create(f, Utils::Bottles.tag, rebuild) - bottle_path = Pathname.pwd/filename - - tar_filename = filename.to_s.sub(/.gz$/, "") - tar_path = Pathname.pwd/tar_filename - - prefix = HOMEBREW_PREFIX.to_s - cellar = HOMEBREW_CELLAR.to_s - - ohai "Bottling #{filename}..." - - keg = Keg.new(f.prefix) - relocatable = false - skip_relocation = false - - keg.lock do - original_tab = nil - - begin - unless ARGV.include? "--skip-relocation" - keg.relocate_dynamic_linkage prefix, Keg::PREFIX_PLACEHOLDER, - cellar, Keg::CELLAR_PLACEHOLDER - keg.relocate_text_files prefix, Keg::PREFIX_PLACEHOLDER, - cellar, Keg::CELLAR_PLACEHOLDER - end - - keg.delete_pyc_files! - - Tab.clear_cache - tab = Tab.for_keg(keg) - original_tab = tab.dup - tab.poured_from_bottle = false - tab.HEAD = nil - tab.time = nil - tab.write - - keg.find do |file| - if file.symlink? - # Ruby does not support `File.lutime` yet. - # Shellout using `touch` to change modified time of symlink itself. - system "/usr/bin/touch", "-h", - "-t", tab.source_modified_time.strftime("%Y%m%d%H%M.%S"), file - else - file.utime(tab.source_modified_time, tab.source_modified_time) - end - end - - cd cellar do - safe_system "tar", "cf", tar_path, "#{f.name}/#{f.pkg_version}" - tar_path.utime(tab.source_modified_time, tab.source_modified_time) - relocatable_tar_path = "#{f}-bottle.tar" - mv tar_path, relocatable_tar_path - # Use gzip, faster to compress than bzip2, faster to uncompress than bzip2 - # or an uncompressed tarball (and more bandwidth friendly). - safe_system "gzip", "-f", relocatable_tar_path - mv "#{relocatable_tar_path}.gz", bottle_path - end - - if bottle_path.size > 1*1024*1024 - ohai "Detecting if #{filename} is relocatable..." - end - - if prefix == "/usr/local" - prefix_check = File.join(prefix, "opt") - else - prefix_check = prefix - end - - ignores = [] - if f.deps.any? { |dep| dep.name == "go" } - ignores << %r{#{Regexp.escape(HOMEBREW_CELLAR)}/go/[\d\.]+/libexec} - end - - relocatable = true - if ARGV.include? "--skip-relocation" - skip_relocation = true - else - relocatable = false if keg_contain?(prefix_check, keg, ignores) - relocatable = false if keg_contain?(cellar, keg, ignores) - if prefix != prefix_check - relocatable = false if keg_contain_absolute_symlink_starting_with?(prefix, keg) - end - skip_relocation = relocatable && !keg.require_install_name_tool? - end - puts if !relocatable && ARGV.verbose? - rescue Interrupt - ignore_interrupts { bottle_path.unlink if bottle_path.exist? } - raise - ensure - ignore_interrupts do - original_tab.write if original_tab - unless ARGV.include? "--skip-relocation" - keg.relocate_dynamic_linkage Keg::PREFIX_PLACEHOLDER, prefix, - Keg::CELLAR_PLACEHOLDER, cellar - keg.relocate_text_files Keg::PREFIX_PLACEHOLDER, prefix, - Keg::CELLAR_PLACEHOLDER, cellar - end - end - end - end - - root_url = ARGV.value("root-url") - # Use underscored version for legacy reasons. Remove at some point. - root_url ||= ARGV.value("root_url") - - bottle = BottleSpecification.new - bottle.root_url(root_url) if root_url - if relocatable - if skip_relocation - bottle.cellar :any_skip_relocation - else - bottle.cellar :any - end - else - bottle.cellar cellar - bottle.prefix prefix - end - bottle.rebuild rebuild - sha256 = bottle_path.sha256 - bottle.sha256 sha256 => Utils::Bottles.tag - - old_spec = f.bottle_specification - if ARGV.include?("--keep-old") && !old_spec.checksums.empty? - bad_fields = [:root_url, :prefix, :cellar, :rebuild].select do |field| - old_spec.send(field) != bottle.send(field) - end - bad_fields.delete(:cellar) if old_spec.cellar == :any && bottle.cellar == :any_skip_relocation - unless bad_fields.empty? - bottle_path.unlink if bottle_path.exist? - odie "--keep-old is passed but there are changes in: #{bad_fields.join ", "}" - end - end - - output = bottle_output bottle - - puts "./#{filename}" - puts output - - if ARGV.include? "--json" - json = { - f.full_name => { - "formula" => { - "pkg_version" => f.pkg_version.to_s, - "path" => f.path.to_s.strip_prefix("#{HOMEBREW_REPOSITORY}/"), - }, - "bottle" => { - "root_url" => bottle.root_url, - "prefix" => bottle.prefix, - "cellar" => bottle.cellar.to_s, - "rebuild" => bottle.rebuild, - "tags" => { - Utils::Bottles.tag.to_s => { - "filename" => filename.to_s, - "sha256" => sha256, - }, - } - }, - "bintray" => { - "package" => Utils::Bottles::Bintray.package(f.name), - "repository" => Utils::Bottles::Bintray.repository(f.tap), - }, - }, - } - File.open("#{filename.prefix}.bottle.json", "w") do |file| - file.write Utils::JSON.dump json - end - end - end - - def merge - write = ARGV.include? "--write" - - bottles_hash = ARGV.named.reduce({}) do |hash, json_file| - deep_merge_hashes hash, Utils::JSON.load(IO.read(json_file)) - end - - bottles_hash.each do |formula_name, bottle_hash| - ohai formula_name - - bottle = BottleSpecification.new - bottle.root_url bottle_hash["bottle"]["root_url"] - cellar = bottle_hash["bottle"]["cellar"] - if cellar == "any" || cellar == "any_skip_relocation" - cellar = cellar.to_sym - end - bottle.cellar cellar - bottle.prefix bottle_hash["bottle"]["prefix"] - bottle.rebuild bottle_hash["bottle"]["rebuild"] - bottle_hash["bottle"]["tags"].each do |tag, tag_hash| - bottle.sha256 tag_hash["sha256"] => tag.to_sym - end - - output = bottle_output bottle - - if write - path = Pathname.new("#{HOMEBREW_REPOSITORY/bottle_hash["formula"]["path"]}") - update_or_add = nil - - Utils::Inreplace.inreplace(path) do |s| - if s.include? "bottle do" - update_or_add = "update" - if ARGV.include? "--keep-old" - mismatches = [] - bottle_block_contents = s[/ bottle do(.+?)end\n/m, 1] - bottle_block_contents.lines.each do |line| - line = line.strip - next if line.empty? - key, value, _, tag = line.split " ", 4 - valid_key = %w[root_url prefix cellar rebuild sha1 sha256].include? key - next unless valid_key - - value = value.to_s.delete ":'\"" - tag = tag.to_s.delete ":" - - if !tag.empty? - if !bottle_hash["bottle"]["tags"][tag].to_s.empty? - mismatches << "#{key} => #{tag}" - else - bottle.send(key, value => tag.to_sym) - end - next - end - - old_value = bottle_hash["bottle"][key].to_s - next if key == "cellar" && old_value == "any" && value == "any_skip_relocation" - mismatches << key if old_value.empty? || value != old_value - end - unless mismatches.empty? - odie "--keep-old was passed but there were changes in #{mismatches.join(", ")}!" - end - output = bottle_output bottle - end - puts output - string = s.sub!(/ bottle do.+?end\n/m, output) - odie "Bottle block update failed!" unless string - else - if ARGV.include? "--keep-old" - odie "--keep-old was passed but there was no existing bottle block!" - end - puts output - update_or_add = "add" - if s.include? "stable do" - indent = s.slice(/^ +stable do/).length - "stable do".length - string = s.sub!(/^ {#{indent}}stable do(.|\n)+?^ {#{indent}}end\n/m, '\0' + output + "\n") - else - string = s.sub!( - /( - \ {2}( # two spaces at the beginning - (url|head)\ ['"][\S\ ]+['"] # url or head with a string - ( - ,[\S\ ]*$ # url may have options - (\n^\ {3}[\S\ ]+$)* # options can be in multiple lines - )?| - (homepage|desc|sha1|sha256|version|mirror)\ ['"][\S\ ]+['"]| # specs with a string - rebuild\ \d+ # rebuild with a number - )\n+ # multiple empty lines - )+ - /mx, '\0' + output + "\n") - end - odie "Bottle block addition failed!" unless string - end - end - - unless ARGV.include? "--no-commit" - short_name = formula_name.split("/", -1).last - pkg_version = bottle_hash["formula"]["pkg_version"] - - path.parent.cd do - safe_system "git", "commit", "--no-edit", "--verbose", - "--message=#{short_name}: #{update_or_add} #{pkg_version} bottle.", - "--", path - end - end - else - puts output - end - end - end - - def bottle - if ARGV.include? "--merge" - merge - else - ARGV.resolved_formulae.each do |f| - bottle_formula f - end - end - end -end |
