Merge pull request #1253 from jawshooah/perf/relocate-text-files
keg_relocate: cache files rewritten during brew bottle
This commit is contained in:
		
						commit
						79e8cdd3ed
					
				@ -187,14 +187,11 @@ module Homebrew
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    keg.lock do
 | 
					    keg.lock do
 | 
				
			||||||
      original_tab = nil
 | 
					      original_tab = nil
 | 
				
			||||||
 | 
					      changed_files = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      begin
 | 
					      begin
 | 
				
			||||||
        unless ARGV.include? "--skip-relocation"
 | 
					        unless ARGV.include? "--skip-relocation"
 | 
				
			||||||
          keg.relocate_dynamic_linkage prefix, Keg::PREFIX_PLACEHOLDER,
 | 
					          changed_files = keg.replace_locations_with_placeholders
 | 
				
			||||||
            cellar, Keg::CELLAR_PLACEHOLDER
 | 
					 | 
				
			||||||
          keg.relocate_text_files prefix, Keg::PREFIX_PLACEHOLDER,
 | 
					 | 
				
			||||||
            cellar, Keg::CELLAR_PLACEHOLDER,
 | 
					 | 
				
			||||||
            repository, Keg::REPOSITORY_PLACEHOLDER
 | 
					 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        keg.delete_pyc_files!
 | 
					        keg.delete_pyc_files!
 | 
				
			||||||
@ -205,6 +202,7 @@ module Homebrew
 | 
				
			|||||||
        tab.poured_from_bottle = false
 | 
					        tab.poured_from_bottle = false
 | 
				
			||||||
        tab.HEAD = nil
 | 
					        tab.HEAD = nil
 | 
				
			||||||
        tab.time = nil
 | 
					        tab.time = nil
 | 
				
			||||||
 | 
					        tab.changed_files = changed_files
 | 
				
			||||||
        tab.write
 | 
					        tab.write
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        keg.find do |file|
 | 
					        keg.find do |file|
 | 
				
			||||||
@ -264,11 +262,7 @@ module Homebrew
 | 
				
			|||||||
        ignore_interrupts do
 | 
					        ignore_interrupts do
 | 
				
			||||||
          original_tab.write if original_tab
 | 
					          original_tab.write if original_tab
 | 
				
			||||||
          unless ARGV.include? "--skip-relocation"
 | 
					          unless ARGV.include? "--skip-relocation"
 | 
				
			||||||
            keg.relocate_dynamic_linkage Keg::PREFIX_PLACEHOLDER, prefix,
 | 
					            keg.replace_placeholders_with_locations changed_files
 | 
				
			||||||
              Keg::CELLAR_PLACEHOLDER, cellar
 | 
					 | 
				
			||||||
            keg.relocate_text_files Keg::PREFIX_PLACEHOLDER, prefix,
 | 
					 | 
				
			||||||
              Keg::CELLAR_PLACEHOLDER, cellar,
 | 
					 | 
				
			||||||
              Keg::REPOSITORY_PLACEHOLDER, repository
 | 
					 | 
				
			||||||
          end
 | 
					          end
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
				
			|||||||
@ -17,19 +17,19 @@ class Keg
 | 
				
			|||||||
    generic_fix_dynamic_linkage
 | 
					    generic_fix_dynamic_linkage
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def relocate_dynamic_linkage(old_prefix, new_prefix, old_cellar, new_cellar)
 | 
					  def relocate_dynamic_linkage(relocation)
 | 
				
			||||||
    mach_o_files.each do |file|
 | 
					    mach_o_files.each do |file|
 | 
				
			||||||
      file.ensure_writable do
 | 
					      file.ensure_writable do
 | 
				
			||||||
        if file.dylib?
 | 
					        if file.dylib?
 | 
				
			||||||
          id = dylib_id_for(file).sub(old_prefix, new_prefix)
 | 
					          id = dylib_id_for(file).sub(relocation.old_prefix, relocation.new_prefix)
 | 
				
			||||||
          change_dylib_id(id, file)
 | 
					          change_dylib_id(id, file)
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        each_install_name_for(file) do |old_name|
 | 
					        each_install_name_for(file) do |old_name|
 | 
				
			||||||
          if old_name.start_with? old_cellar
 | 
					          if old_name.start_with? relocation.old_cellar
 | 
				
			||||||
            new_name = old_name.sub(old_cellar, new_cellar)
 | 
					            new_name = old_name.sub(relocation.old_cellar, relocation.new_cellar)
 | 
				
			||||||
          elsif old_name.start_with? old_prefix
 | 
					          elsif old_name.start_with? relocation.old_prefix
 | 
				
			||||||
            new_name = old_name.sub(old_prefix, new_prefix)
 | 
					            new_name = old_name.sub(relocation.old_prefix, relocation.new_prefix)
 | 
				
			||||||
          end
 | 
					          end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          change_install_name(old_name, new_name, file) if new_name
 | 
					          change_install_name(old_name, new_name, file) if new_name
 | 
				
			||||||
 | 
				
			|||||||
@ -762,13 +762,12 @@ class FormulaInstaller
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    keg = Keg.new(formula.prefix)
 | 
					    keg = Keg.new(formula.prefix)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unless formula.bottle_specification.skip_relocation?
 | 
					    unless formula.bottle_specification.skip_relocation?
 | 
				
			||||||
      keg.relocate_dynamic_linkage Keg::PREFIX_PLACEHOLDER, HOMEBREW_PREFIX.to_s,
 | 
					      tab = Tab.for_keg(keg)
 | 
				
			||||||
        Keg::CELLAR_PLACEHOLDER, HOMEBREW_CELLAR.to_s
 | 
					      Tab.clear_cache
 | 
				
			||||||
 | 
					      keg.replace_placeholders_with_locations tab.changed_files
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    keg.relocate_text_files Keg::PREFIX_PLACEHOLDER, HOMEBREW_PREFIX.to_s,
 | 
					 | 
				
			||||||
      Keg::CELLAR_PLACEHOLDER, HOMEBREW_CELLAR.to_s,
 | 
					 | 
				
			||||||
      Keg::REPOSITORY_PLACEHOLDER, HOMEBREW_REPOSITORY.to_s
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Pathname.glob("#{formula.bottle_prefix}/{etc,var}/**/*") do |path|
 | 
					    Pathname.glob("#{formula.bottle_prefix}/{etc,var}/**/*") do |path|
 | 
				
			||||||
      path.extend(InstallRenamed)
 | 
					      path.extend(InstallRenamed)
 | 
				
			||||||
@ -776,7 +775,7 @@ class FormulaInstaller
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
    FileUtils.rm_rf formula.bottle_prefix
 | 
					    FileUtils.rm_rf formula.bottle_prefix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tab = Tab.for_keg(formula.prefix)
 | 
					    tab = Tab.for_keg(keg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CxxStdlib.check_compatibility(
 | 
					    CxxStdlib.check_compatibility(
 | 
				
			||||||
      formula, formula.recursive_dependencies,
 | 
					      formula, formula.recursive_dependencies,
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,14 @@ class Keg
 | 
				
			|||||||
  CELLAR_PLACEHOLDER = "@@HOMEBREW_CELLAR@@".freeze
 | 
					  CELLAR_PLACEHOLDER = "@@HOMEBREW_CELLAR@@".freeze
 | 
				
			||||||
  REPOSITORY_PLACEHOLDER = "@@HOMEBREW_REPOSITORY@@".freeze
 | 
					  REPOSITORY_PLACEHOLDER = "@@HOMEBREW_REPOSITORY@@".freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Relocation = Struct.new(:old_prefix, :old_cellar, :old_repository,
 | 
				
			||||||
 | 
					                          :new_prefix, :new_cellar, :new_repository) do
 | 
				
			||||||
 | 
					    # Use keyword args instead of positional args for initialization
 | 
				
			||||||
 | 
					    def initialize(**kwargs)
 | 
				
			||||||
 | 
					      super(*members.map { |k| kwargs[k] })
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def fix_dynamic_linkage
 | 
					  def fix_dynamic_linkage
 | 
				
			||||||
    symlink_files.each do |file|
 | 
					    symlink_files.each do |file|
 | 
				
			||||||
      link = file.readlink
 | 
					      link = file.readlink
 | 
				
			||||||
@ -15,21 +23,54 @@ class Keg
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
  alias generic_fix_dynamic_linkage fix_dynamic_linkage
 | 
					  alias generic_fix_dynamic_linkage fix_dynamic_linkage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def relocate_dynamic_linkage(_old_prefix, _new_prefix, _old_cellar, _new_cellar)
 | 
					  def relocate_dynamic_linkage(_relocation)
 | 
				
			||||||
    []
 | 
					    []
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def relocate_text_files(old_prefix, new_prefix, old_cellar, new_cellar,
 | 
					  def replace_locations_with_placeholders
 | 
				
			||||||
                          old_repository, new_repository)
 | 
					    relocation = Relocation.new(
 | 
				
			||||||
    files = text_files | libtool_files
 | 
					      old_prefix: HOMEBREW_PREFIX.to_s,
 | 
				
			||||||
 | 
					      old_cellar: HOMEBREW_CELLAR.to_s,
 | 
				
			||||||
 | 
					      old_repository: HOMEBREW_REPOSITORY.to_s,
 | 
				
			||||||
 | 
					      new_prefix: PREFIX_PLACEHOLDER,
 | 
				
			||||||
 | 
					      new_cellar: CELLAR_PLACEHOLDER,
 | 
				
			||||||
 | 
					      new_repository: REPOSITORY_PLACEHOLDER
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    relocate_dynamic_linkage(relocation)
 | 
				
			||||||
 | 
					    replace_text_in_files(relocation)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    files.group_by { |f| f.stat.ino }.each_value do |first, *rest|
 | 
					  def replace_placeholders_with_locations(files)
 | 
				
			||||||
 | 
					    relocation = Relocation.new(
 | 
				
			||||||
 | 
					      old_prefix: PREFIX_PLACEHOLDER,
 | 
				
			||||||
 | 
					      old_cellar: CELLAR_PLACEHOLDER,
 | 
				
			||||||
 | 
					      old_repository: REPOSITORY_PLACEHOLDER,
 | 
				
			||||||
 | 
					      new_prefix: HOMEBREW_PREFIX.to_s,
 | 
				
			||||||
 | 
					      new_cellar: HOMEBREW_CELLAR.to_s,
 | 
				
			||||||
 | 
					      new_repository: HOMEBREW_REPOSITORY.to_s
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    relocate_dynamic_linkage(relocation)
 | 
				
			||||||
 | 
					    replace_text_in_files(relocation, files: files)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def replace_text_in_files(relocation, files: nil)
 | 
				
			||||||
 | 
					    files ||= text_files | libtool_files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    changed_files = []
 | 
				
			||||||
 | 
					    files.map(&path.method(:join)).group_by { |f| f.stat.ino }.each_value do |first, *rest|
 | 
				
			||||||
      s = first.open("rb", &:read)
 | 
					      s = first.open("rb", &:read)
 | 
				
			||||||
      changed = s.gsub!(old_cellar, new_cellar)
 | 
					
 | 
				
			||||||
      changed = s.gsub!(old_prefix, new_prefix) || changed
 | 
					      replacements = {
 | 
				
			||||||
      changed = s.gsub!(old_repository, new_repository) || changed
 | 
					        relocation.old_prefix => relocation.new_prefix,
 | 
				
			||||||
 | 
					        relocation.old_cellar => relocation.new_cellar,
 | 
				
			||||||
 | 
					        relocation.old_repository => relocation.new_repository,
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      regexp = Regexp.union(replacements.keys)
 | 
				
			||||||
 | 
					      changed = s.gsub!(regexp, replacements)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      next unless changed
 | 
					      next unless changed
 | 
				
			||||||
 | 
					      changed_files << first.relative_path_from(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      begin
 | 
					      begin
 | 
				
			||||||
        first.atomic_write(s)
 | 
					        first.atomic_write(s)
 | 
				
			||||||
@ -41,6 +82,7 @@ class Keg
 | 
				
			|||||||
        rest.each { |file| FileUtils.ln(first, file, force: true) }
 | 
					        rest.each { |file| FileUtils.ln(first, file, force: true) }
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					    changed_files
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def detect_cxx_stdlibs(_options = {})
 | 
					  def detect_cxx_stdlibs(_options = {})
 | 
				
			||||||
 | 
				
			|||||||
@ -1,20 +1,24 @@
 | 
				
			|||||||
class Metafiles
 | 
					require "set"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module Metafiles
 | 
				
			||||||
  # https://github.com/github/markup#markups
 | 
					  # https://github.com/github/markup#markups
 | 
				
			||||||
  EXTENSIONS = %w[
 | 
					  EXTENSIONS = Set.new %w[
 | 
				
			||||||
    .adoc .asc .asciidoc .creole .html .markdown .md .mdown .mediawiki .mkdn
 | 
					    .adoc .asc .asciidoc .creole .html .markdown .md .mdown .mediawiki .mkdn
 | 
				
			||||||
    .org .pod .rdoc .rst .rtf .textile .txt .wiki
 | 
					    .org .pod .rdoc .rst .rtf .textile .txt .wiki
 | 
				
			||||||
  ].freeze
 | 
					  ].freeze
 | 
				
			||||||
  BASENAMES = %w[
 | 
					  BASENAMES = Set.new %w[
 | 
				
			||||||
    about authors changelog changes copying copyright history license licence
 | 
					    about authors changelog changes copying copyright history license licence
 | 
				
			||||||
    news notes notice readme todo
 | 
					    news notes notice readme todo
 | 
				
			||||||
  ].freeze
 | 
					  ].freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.list?(file)
 | 
					  module_function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def list?(file)
 | 
				
			||||||
    return false if %w[.DS_Store INSTALL_RECEIPT.json].include?(file)
 | 
					    return false if %w[.DS_Store INSTALL_RECEIPT.json].include?(file)
 | 
				
			||||||
    !copy?(file)
 | 
					    !copy?(file)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.copy?(file)
 | 
					  def copy?(file)
 | 
				
			||||||
    file = file.downcase
 | 
					    file = file.downcase
 | 
				
			||||||
    ext  = File.extname(file)
 | 
					    ext  = File.extname(file)
 | 
				
			||||||
    file = File.basename(file, ext) if EXTENSIONS.include?(ext)
 | 
					    file = File.basename(file, ext) if EXTENSIONS.include?(ext)
 | 
				
			||||||
 | 
				
			|||||||
@ -303,6 +303,7 @@ class Tab < OpenStruct
 | 
				
			|||||||
      "unused_options" => unused_options.as_flags,
 | 
					      "unused_options" => unused_options.as_flags,
 | 
				
			||||||
      "built_as_bottle" => built_as_bottle,
 | 
					      "built_as_bottle" => built_as_bottle,
 | 
				
			||||||
      "poured_from_bottle" => poured_from_bottle,
 | 
					      "poured_from_bottle" => poured_from_bottle,
 | 
				
			||||||
 | 
					      "changed_files" => changed_files && changed_files.map(&:to_s),
 | 
				
			||||||
      "time" => time,
 | 
					      "time" => time,
 | 
				
			||||||
      "source_modified_time" => source_modified_time.to_i,
 | 
					      "source_modified_time" => source_modified_time.to_i,
 | 
				
			||||||
      "HEAD" => self.HEAD,
 | 
					      "HEAD" => self.HEAD,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								Library/Homebrew/test/fixtures/receipt.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								Library/Homebrew/test/fixtures/receipt.json
									
									
									
									
										vendored
									
									
								
							@ -9,6 +9,10 @@
 | 
				
			|||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "built_as_bottle": false,
 | 
					  "built_as_bottle": false,
 | 
				
			||||||
  "poured_from_bottle": true,
 | 
					  "poured_from_bottle": true,
 | 
				
			||||||
 | 
					  "changed_files": [
 | 
				
			||||||
 | 
					    "INSTALL_RECEIPT.json",
 | 
				
			||||||
 | 
					    "bin/foo"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
  "time": 1403827774,
 | 
					  "time": 1403827774,
 | 
				
			||||||
  "HEAD": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
 | 
					  "HEAD": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
 | 
				
			||||||
  "alias_path": "/usr/local/Library/Taps/homebrew/homebrew-core/Aliases/test-formula",
 | 
					  "alias_path": "/usr/local/Library/Taps/homebrew/homebrew-core/Aliases/test-formula",
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@ class TabTests < Homebrew::TestCase
 | 
				
			|||||||
                   "unused_options"       => @unused.as_flags,
 | 
					                   "unused_options"       => @unused.as_flags,
 | 
				
			||||||
                   "built_as_bottle"      => false,
 | 
					                   "built_as_bottle"      => false,
 | 
				
			||||||
                   "poured_from_bottle"   => true,
 | 
					                   "poured_from_bottle"   => true,
 | 
				
			||||||
 | 
					                   "changed_files"        => [],
 | 
				
			||||||
                   "time"                 => nil,
 | 
					                   "time"                 => nil,
 | 
				
			||||||
                   "source_modified_time" => 0,
 | 
					                   "source_modified_time" => 0,
 | 
				
			||||||
                   "HEAD"                 => TEST_SHA1,
 | 
					                   "HEAD"                 => TEST_SHA1,
 | 
				
			||||||
@ -33,6 +34,7 @@ class TabTests < Homebrew::TestCase
 | 
				
			|||||||
    tab = Tab.empty
 | 
					    tab = Tab.empty
 | 
				
			||||||
    assert_empty tab.unused_options
 | 
					    assert_empty tab.unused_options
 | 
				
			||||||
    assert_empty tab.used_options
 | 
					    assert_empty tab.used_options
 | 
				
			||||||
 | 
					    assert_nil tab.changed_files
 | 
				
			||||||
    refute_predicate tab, :built_as_bottle
 | 
					    refute_predicate tab, :built_as_bottle
 | 
				
			||||||
    refute_predicate tab, :poured_from_bottle
 | 
					    refute_predicate tab, :poured_from_bottle
 | 
				
			||||||
    assert_predicate tab, :stable?
 | 
					    assert_predicate tab, :stable?
 | 
				
			||||||
@ -105,9 +107,11 @@ class TabTests < Homebrew::TestCase
 | 
				
			|||||||
    tab = Tab.from_file(path)
 | 
					    tab = Tab.from_file(path)
 | 
				
			||||||
    source_path = "/usr/local/Library/Taps/hombrew/homebrew-core/Formula/foo.rb"
 | 
					    source_path = "/usr/local/Library/Taps/hombrew/homebrew-core/Formula/foo.rb"
 | 
				
			||||||
    runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }]
 | 
					    runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }]
 | 
				
			||||||
 | 
					    changed_files = %w[INSTALL_RECEIPT.json bin/foo]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert_equal @used.sort, tab.used_options.sort
 | 
					    assert_equal @used.sort, tab.used_options.sort
 | 
				
			||||||
    assert_equal @unused.sort, tab.unused_options.sort
 | 
					    assert_equal @unused.sort, tab.unused_options.sort
 | 
				
			||||||
 | 
					    assert_equal changed_files, tab.changed_files
 | 
				
			||||||
    refute_predicate tab, :built_as_bottle
 | 
					    refute_predicate tab, :built_as_bottle
 | 
				
			||||||
    assert_predicate tab, :poured_from_bottle
 | 
					    assert_predicate tab, :poured_from_bottle
 | 
				
			||||||
    assert_predicate tab, :stable?
 | 
					    assert_predicate tab, :stable?
 | 
				
			||||||
@ -187,6 +191,7 @@ class TabTests < Homebrew::TestCase
 | 
				
			|||||||
    assert_equal @tab.unused_options.sort, tab.unused_options.sort
 | 
					    assert_equal @tab.unused_options.sort, tab.unused_options.sort
 | 
				
			||||||
    assert_equal @tab.built_as_bottle, tab.built_as_bottle
 | 
					    assert_equal @tab.built_as_bottle, tab.built_as_bottle
 | 
				
			||||||
    assert_equal @tab.poured_from_bottle, tab.poured_from_bottle
 | 
					    assert_equal @tab.poured_from_bottle, tab.poured_from_bottle
 | 
				
			||||||
 | 
					    assert_equal @tab.changed_files, tab.changed_files
 | 
				
			||||||
    assert_equal @tab.tap, tab.tap
 | 
					    assert_equal @tab.tap, tab.tap
 | 
				
			||||||
    assert_equal @tab.spec, tab.spec
 | 
					    assert_equal @tab.spec, tab.spec
 | 
				
			||||||
    assert_equal @tab.time, tab.time
 | 
					    assert_equal @tab.time, tab.time
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user