From a04030a6f77adeb22f18101b527c07ba01d19c77 Mon Sep 17 00:00:00 2001 From: Vlad Shablinsky Date: Sun, 4 Sep 2016 00:01:01 +0300 Subject: [PATCH 1/5] formula_installer: don't allow pinned dependencies Prompt user to unpin pinned dependencies of the formula --- Library/Homebrew/formula_installer.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index cf595cf71f..1e2e8e978e 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -146,11 +146,21 @@ class FormulaInstaller raise FormulaInstallationAlreadyAttemptedError, formula if @@attempted.include?(formula) unless skip_deps_check? - unlinked_deps = formula.recursive_dependencies.map(&:to_formula).select do |dep| + recursive_deps = formula.recursive_dependencies + unlinked_deps = recursive_deps.map(&:to_formula).select do |dep| dep.installed? && !dep.keg_only? && !dep.linked_keg.directory? end raise CannotInstallFormulaError, "You must `brew link #{unlinked_deps*" "}` before #{formula.full_name} can be installed" unless unlinked_deps.empty? + + pinned_unsatisfied_deps = recursive_deps.select do |dep| + dep.to_formula.pinned? && !dep.satisfied?(inherited_options_for(dep)) + end + + unless pinned_unsatisfied_deps.empty? + raise CannotInstallFormulaError, + "You must `brew unpin #{pinned_unsatisfied_deps*" "}` as installing #{formula.full_name} requires the latest version of pinned dependencies" + end end end From f8ea7a4a0cd5f658f24d115bdec485fb4172a9d8 Mon Sep 17 00:00:00 2001 From: Vlad Shablinsky Date: Mon, 5 Sep 2016 22:40:08 +0300 Subject: [PATCH 2/5] reinstall: fail if pinned --- Library/Homebrew/cmd/reinstall.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index e98e906f6a..e51aace2ad 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -8,7 +8,13 @@ module Homebrew def reinstall FormulaInstaller.prevent_build_flags unless DevelopmentTools.installed? - ARGV.resolved_formulae.each { |f| reinstall_formula(f) } + ARGV.resolved_formulae.each do |f| + if f.pinned? + onoe "#{f.full_name} is pinned. You must unpin it to reinstall." + next + end + reinstall_formula(f) + end end def reinstall_formula(f) From 02a578d8421c3ae88d05e12e34c908ba4b18c877 Mon Sep 17 00:00:00 2001 From: Vlad Shablinsky Date: Sun, 4 Sep 2016 00:38:59 +0300 Subject: [PATCH 3/5] test_formula: eligible_kegs_for_cleanup_keg_pinned --- Library/Homebrew/test/test_formula.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Library/Homebrew/test/test_formula.rb b/Library/Homebrew/test/test_formula.rb index 7ebb178841..0e6650a95a 100644 --- a/Library/Homebrew/test/test_formula.rb +++ b/Library/Homebrew/test/test_formula.rb @@ -491,6 +491,31 @@ class FormulaTests < Homebrew::TestCase f3.rack.rmtree end + def test_eligible_kegs_for_cleanup_keg_pinned + f1 = Class.new(Testball) { version "0.1" }.new + f2 = Class.new(Testball) { version "0.2" }.new + f3 = Class.new(Testball) { version "0.3" }.new + + shutup do + f1.brew { f1.install } + f1.pin + f2.brew { f2.install } + f3.brew { f3.install } + end + + assert_equal HOMEBREW_LIBRARY.join("PinnedKegs/#{f1.name}").resolved_path, f1.prefix + + assert_predicate f1, :installed? + assert_predicate f2, :installed? + assert_predicate f3, :installed? + + assert_equal [Keg.new(f2.prefix)], shutup { f3.eligible_kegs_for_cleanup } + ensure + f1.unpin + [f1, f2, f3].each(&:clear_cache) + f3.rack.rmtree + end + def test_eligible_kegs_for_cleanup_head_installed f = formula do version "0.1" From f9b910eeb608bb8f2b7c9ed3beef86d5a5fe4da8 Mon Sep 17 00:00:00 2001 From: Vlad Shablinsky Date: Mon, 5 Sep 2016 23:33:37 +0300 Subject: [PATCH 4/5] FormulaInstaller#check_install_sanity test pinned Forbid to install formual if it has pinned dependencies. --- .../Homebrew/test/test_formula_installer.rb | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Library/Homebrew/test/test_formula_installer.rb b/Library/Homebrew/test/test_formula_installer.rb index 55b456fbae..f519d07151 100644 --- a/Library/Homebrew/test/test_formula_installer.rb +++ b/Library/Homebrew/test/test_formula_installer.rb @@ -92,3 +92,45 @@ class InstallTests < Homebrew::TestCase end end end + +class FormulaInstallerTests < Homebrew::TestCase + def test_check_install_sanity_pinned_dep + dep_name = "dependency" + dep_path = CoreTap.new.formula_dir/"#{dep_name}.rb" + dep_path.write <<-EOS.undent + class #{Formulary.class_s(dep_name)} < Formula + url "foo" + version "0.2" + end + EOS + + Formulary::FORMULAE.delete(dep_path) + dependency = Formulary.factory(dep_name) + + dependent = formula do + url "foo" + version "0.5" + depends_on "#{dependency.name}" + end + + dependency.prefix("0.1").join("bin/a").mkpath + HOMEBREW_LIBRARY.join("PinnedKegs").mkpath + FileUtils.ln_s dependency.prefix("0.1"), HOMEBREW_LIBRARY.join("PinnedKegs/#{dep_name}") + + dependency_keg = Keg.new(dependency.prefix("0.1")) + dependency_keg.link + + assert_predicate dependency_keg, :linked? + assert_predicate dependency, :pinned? + + fi = FormulaInstaller.new(dependent) + assert_raises(CannotInstallFormulaError) { fi.check_install_sanity } + ensure + dependency.unpin + dependency_keg.unlink + dependency_keg.uninstall + dependency.clear_cache + dep_path.unlink + Formulary::FORMULAE.delete(dep_path) + end +end From 846fa231564ce956203d5588784740e1ab0e8eb6 Mon Sep 17 00:00:00 2001 From: Vlad Shablinsky Date: Tue, 6 Sep 2016 00:19:19 +0300 Subject: [PATCH 5/5] test_integration_cmds: reinstall pinned --- Library/Homebrew/test/test_integration_cmds.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Library/Homebrew/test/test_integration_cmds.rb b/Library/Homebrew/test/test_integration_cmds.rb index c83d7522a1..9e6785b16b 100644 --- a/Library/Homebrew/test/test_integration_cmds.rb +++ b/Library/Homebrew/test/test_integration_cmds.rb @@ -531,6 +531,18 @@ class IntegrationCommandTests < Homebrew::TestCase assert foo_dir.exist? end + def test_reinstall_pinned + setup_test_formula "testball" + + HOMEBREW_CELLAR.join("testball/0.1").mkpath + HOMEBREW_LIBRARY.join("PinnedKegs").mkpath + FileUtils.ln_s HOMEBREW_CELLAR.join("testball/0.1"), HOMEBREW_LIBRARY.join("PinnedKegs/testball") + + assert_match "testball is pinned. You must unpin it to reinstall.", cmd("reinstall", "testball") + + HOMEBREW_LIBRARY.join("PinnedKegs").rmtree + end + def test_home setup_test_formula "testball"