Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate default_formula Requirement DSL #3661

Merged
merged 1 commit into from Jan 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions Library/Homebrew/build.rb
Expand Up @@ -48,9 +48,6 @@ def expand_reqs
Requirement.prune
elsif req.build? && dependent != formula
Requirement.prune
elsif req.satisfied? && (dep = req.to_dependency) && dep.installed?
deps << dep
Requirement.prune
end
end
end
Expand Down
21 changes: 3 additions & 18 deletions Library/Homebrew/cmd/deps.rb
Expand Up @@ -94,26 +94,14 @@ def condense_requirements(deps)
if ARGV.include?("--include-requirements")
deps
else
deps.map do |dep|
if dep.is_a? Dependency
dep
elsif dep.default_formula?
dep.to_dependency
end
end.compact
deps.select { |dep| dep.is_a? Dependency }
end
end

def dep_display_name(dep)
str = if dep.is_a? Requirement
if ARGV.include?("--include-requirements")
if dep.default_formula?
":#{dep.display_s} (#{dep_display_name(dep.to_dependency)})"
else
":#{dep.display_s}"
end
elsif dep.default_formula?
dep_display_name(dep.to_dependency)
":#{dep.display_s}"
else
# This shouldn't happen, but we'll put something here to help debugging
"::#{dep.name}"
Expand Down Expand Up @@ -207,7 +195,7 @@ def recursive_deps_tree(f, prefix, recursive)
max = dependables.length - 1
@dep_stack.push f.name
dependables.each_with_index do |dep, i|
next if !ARGV.include?("--include-requirements") && dep.is_a?(Requirement) && !dep.default_formula?
next if !ARGV.include?("--include-requirements") && dep.is_a?(Requirement)
tree_lines = if i == max
"└──"
else
Expand All @@ -223,9 +211,6 @@ def recursive_deps_tree(f, prefix, recursive)
else
"│ "
end
if dep.is_a?(Requirement) && dep.default_formula?
recursive_deps_tree(Formulary.factory(dep.to_dependency.name), prefix + prefix_addition, true)
end
if dep.is_a? Dependency
recursive_deps_tree(Formulary.factory(dep.name), prefix + prefix_addition, true)
end
Expand Down
4 changes: 1 addition & 3 deletions Library/Homebrew/cmd/uses.rb
Expand Up @@ -113,9 +113,7 @@ def uses
end
end

reqs.any? do |req|
req.name == ff.name || [ff.name, ff.full_name].include?(req.default_formula)
end
reqs.any? { |req| req.name == ff.name }
rescue FormulaUnavailableError
# Silently ignore this case as we don't care about things used in
# taps that aren't currently tapped.
Expand Down
8 changes: 1 addition & 7 deletions Library/Homebrew/formula.rb
Expand Up @@ -1486,15 +1486,10 @@ def recursive_requirements(&block)
# Returns a list of Dependency objects that are required at runtime.
# @private
def runtime_dependencies
runtime_dependencies = recursive_dependencies do |_, dependency|
recursive_dependencies do |_, dependency|
Dependency.prune if dependency.build?
Dependency.prune if !dependency.required? && build.without?(dependency)
end
runtime_requirement_deps = recursive_requirements do |_, requirement|
Requirement.prune if requirement.build?
Requirement.prune if !requirement.required? && build.without?(requirement)
end.map(&:to_dependency).compact
runtime_dependencies + runtime_requirement_deps
end

# Returns a list of formulae depended on by this formula that aren't
Expand Down Expand Up @@ -1552,7 +1547,6 @@ def to_hash
hsh["requirements"] = requirements.map do |req|
{
"name" => req.name,
"default_formula" => req.default_formula,
"cask" => req.cask,
"download" => req.download,
}
Expand Down
18 changes: 0 additions & 18 deletions Library/Homebrew/formula_installer.rb
Expand Up @@ -415,16 +415,6 @@ def check_requirements(req_map)
raise UnsatisfiedRequirements, fatals
end

def install_requirement_formula?(req_dependency, req, dependent, install_bottle_for_dependent)
return false unless req_dependency
return false if req.build? && dependent.installed?
return true unless req.satisfied?
return false if req.run?
return true if build_bottle?
return true if req.satisfied_by_formula?
install_bottle_for_dependent
end

def runtime_requirements(formula)
runtime_deps = formula.runtime_dependencies.map(&:to_formula)
recursive_requirements = formula.recursive_requirements do |dependent, _|
Expand All @@ -443,17 +433,9 @@ def expand_requirements
f.recursive_requirements do |dependent, req|
build = effective_build_options_for(dependent)
install_bottle_for_dependent = install_bottle_for?(dependent, build)
use_default_formula = install_bottle_for_dependent || build_bottle?
req_dependency = req.to_dependency(use_default_formula: use_default_formula)

if (req.optional? || req.recommended?) && build.without?(req)
Requirement.prune
elsif req.build? && use_default_formula && req_dependency&.installed?
Requirement.prune
elsif install_requirement_formula?(req_dependency, req, dependent, install_bottle_for_dependent)
deps.unshift(req_dependency)
formulae.unshift(req_dependency.to_formula)
Requirement.prune
elsif req.satisfied?
Requirement.prune
elsif !runtime_requirements.include?(req) && install_bottle_for_dependent
Expand Down
3 changes: 1 addition & 2 deletions Library/Homebrew/os/mac/linkage_checker.rb
Expand Up @@ -62,8 +62,7 @@ def check_undeclared_deps
formula.build.without?(dep)
end
declared_deps = formula.deps.reject { |dep| filter_out.call(dep) }.map(&:name)
declared_requirement_deps = formula.requirements.reject { |req| filter_out.call(req) }.map(&:default_formula).compact
declared_dep_names = (declared_deps + declared_requirement_deps).map { |dep| dep.split("/").last }
declared_dep_names = declared_deps.map { |dep| dep.split("/").last }
undeclared_deps = @brewed_dylibs.keys.reject do |full_name|
name = full_name.split("/").last
next true if name == formula.name
Expand Down
39 changes: 6 additions & 33 deletions Library/Homebrew/requirement.rb
Expand Up @@ -9,13 +9,11 @@
class Requirement
include Dependable

attr_reader :tags, :name, :cask, :download, :default_formula
attr_reader :tags, :name, :cask, :download

def initialize(tags = [])
@default_formula = self.class.default_formula
@cask ||= self.class.cask
@download ||= self.class.download
@formula = nil
tags.each do |tag|
next unless tag.is_a? Hash
@cask ||= tag[:cask]
Expand Down Expand Up @@ -56,12 +54,6 @@ def satisfied?
result = self.class.satisfy.yielder { |p| instance_eval(&p) }
@satisfied_result = result
return false unless result

if parent = satisfied_result_parent
parent.to_s =~ %r{(#{Regexp.escape(HOMEBREW_CELLAR)}|#{Regexp.escape(HOMEBREW_PREFIX)}/opt)/([\w+-.@]+)}
@formula = Regexp.last_match(2)
end

true
end

Expand All @@ -71,10 +63,6 @@ def fatal?
self.class.fatal || false
end

def default_formula?
self.class.default_formula || false
end

def satisfied_result_parent
return unless @satisfied_result.is_a?(Pathname)
parent = @satisfied_result.resolved_path.parent
Expand Down Expand Up @@ -124,24 +112,6 @@ def inspect
"#<#{self.class.name}: #{name.inspect} #{tags.inspect}>"
end

def formula
@formula || self.class.default_formula
end

def satisfied_by_formula?
!@formula.nil?
end

def to_dependency(use_default_formula: false)
if use_default_formula && default_formula?
Dependency.new(self.class.default_formula, tags, method(:modify_build_environment), name)
elsif formula =~ HOMEBREW_TAP_FORMULA_REGEX
TapDependency.new(formula, tags, method(:modify_build_environment), name)
elsif formula
Dependency.new(formula, tags, method(:modify_build_environment), name)
end
end

def display_s
name
end
Expand All @@ -167,8 +137,11 @@ class << self
include BuildEnvironment::DSL

attr_reader :env_proc, :build
attr_rw :fatal, :default_formula
attr_rw :cask, :download
attr_rw :fatal, :cask, :download

def default_formula(val = nil)
# odeprecated "Requirement.default_formula"
end

def satisfy(options = nil, &block)
return @satisfied if options.nil? && !block_given?
Expand Down
60 changes: 0 additions & 60 deletions Library/Homebrew/test/formula_installer_spec.rb
Expand Up @@ -132,64 +132,4 @@ class #{Formulary.class_s(dep_name)} < Formula
fi.check_install_sanity
}.to raise_error(CannotInstallFormulaError)
end

describe "#install_requirement_formula?", :needs_compat do
before do
@requirement = Python3Requirement.new
@requirement_dependency = @requirement.to_dependency
@install_bottle_for_dependent = false
allow(@requirement).to receive(:satisfied?).and_return(satisfied?)
allow(@requirement).to receive(:satisfied_by_formula?).and_return(satisfied_by_formula?)
allow(@requirement).to receive(:build?).and_return(build?)
@dependent = formula do
url "foo"
version "0.1"
depends_on :python3
end
allow(@dependent).to receive(:installed?).and_return(installed?)
@fi = FormulaInstaller.new(@dependent)
end

subject { @fi.install_requirement_formula?(@requirement_dependency, @requirement, @dependent, @install_bottle_for_dependent) }

context "it returns false when requirement is satisfied" do
let(:satisfied?) { true }
let(:satisfied_by_formula?) { false }
let(:build?) { false }
let(:installed?) { false }
it { is_expected.to be false }
end

context "it returns false when requirement is satisfied but default formula is installed" do
let(:satisfied?) { true }
let(:satisfied_by_formula?) { false }
let(:build?) { false }
let(:installed?) { false }
it { is_expected.to be false }
end

context "it returns false when requirement is :build and dependent is installed" do
let(:satisfied?) { false }
let(:satisfied_by_formula?) { false }
let(:build?) { true }
let(:installed?) { true }
it { is_expected.to be false }
end

context "it returns true when requirement isn't satisfied" do
let(:satisfied?) { false }
let(:satisfied_by_formula?) { false }
let(:build?) { false }
let(:installed?) { false }
it { is_expected.to be true }
end

context "it returns true when requirement is satisfied by a formula" do
let(:satisfied?) { true }
let(:satisfied_by_formula?) { true }
let(:build?) { false }
let(:installed?) { false }
it { is_expected.to be true }
end
end
end
55 changes: 0 additions & 55 deletions Library/Homebrew/test/requirement_spec.rb
Expand Up @@ -2,7 +2,6 @@
require "requirement"

describe Requirement do
alias_matcher :have_a_default_formula, :be_a_default_formula
alias_matcher :be_a_build_requirement, :be_a_build

subject { klass.new }
Expand Down Expand Up @@ -173,60 +172,6 @@
its(:option_names) { are_expected.to eq(["foo"]) }
end

describe "#default_formula?" do
context "#default_formula specified" do
let(:klass) do
Class.new(described_class) do
default_formula "foo"
end
end

it { is_expected.to have_a_default_formula }
end

context "#default_formula omitted" do
it { is_expected.not_to have_a_default_formula }
end
end

describe "#to_dependency" do
let(:klass) do
Class.new(described_class) do
default_formula "foo"
end
end

it "returns a Dependency for its default Formula" do
expect(subject.to_dependency).to eq(Dependency.new("foo"))
end

context "#modify_build_environment" do
context "with error" do
let(:klass) do
Class.new(described_class) do
class ModifyBuildEnvironmentError < StandardError; end

default_formula "foo"

satisfy do
true
end

env do
raise ModifyBuildEnvironmentError
end
end
end

it "raises an error" do
expect {
subject.to_dependency.modify_build_environment
}.to raise_error(klass.const_get(:ModifyBuildEnvironmentError))
end
end
end
end

describe "#modify_build_environment" do
context "without env proc" do
let(:klass) { Class.new(described_class) }
Expand Down
11 changes: 11 additions & 0 deletions docs/Building-Against-Non-Homebrew-Dependencies.md
@@ -0,0 +1,11 @@
# Building Against Non-Homebrew Dependencies

## History

Originally Homebrew was a build-from-source package manager and all user environment variables and non-Homebrew-installed software were available to builds. Since then Homebrew added `Requirement`s to specify dependencies on non-Homebrew software (such as those provided by `brew cask` like X11/XQuartz), the `superenv` build system to strip out unspecified dependencies, environment filtering to stop the user environment leaking into Homebrew builds and `default_formula` to specify that a `Requirement` can be satisifed by a particular formula.

As Homebrew became primarily a binary package manager, most users were fulfilling `Requirement`s with the `default_formula`, not with arbitrary alternatives. To improve quality and reduce variation, Homebrew now exclusively supports using the default formula, as an ordinary dependency, and no longer supports using arbitrary alternatives.

## Today

If you wish to build against custom non-Homebrew dependencies that are provided by Homebrew (e.g. a non-Homebrew, non-macOS `ruby`) then you must [create and maintain your own tap](How-to-Create-and-Maintain-a-Tap.md) as these formulae will not be accepted in Homebrew/homebrew-core. Once you have done that you can specify `env :std` in the formula which will allow a e.g. `which ruby` to access your existing `PATH` variable and allow compilation to link against this Ruby.
1 change: 1 addition & 0 deletions docs/README.md
Expand Up @@ -33,6 +33,7 @@
- [Python for Formula Authors](Python-for-Formula-Authors.md)
- [Migrating A Formula To A Tap](Migrating-A-Formula-To-A-Tap.md)
- [Rename A Formula](Rename-A-Formula.md)
- [Building Against Non-Homebrew Dependencies](Building-Against-Non-Homebrew-Dependencies.md)
- [How To Create (And Maintain) A Tap](How-to-Create-and-Maintain-a-Tap.md)
- [Brew Test Bot](Brew-Test-Bot.md)
- [Prose Style Guidelines](Prose-Style-Guidelines.md)
Expand Down