cli_parser: Add depends, conflicts option constraints
This commit is contained in:
parent
20155c8df9
commit
36c1ad9f64
@ -13,6 +13,8 @@ module Homebrew
|
|||||||
@parsed_args = OpenStruct.new
|
@parsed_args = OpenStruct.new
|
||||||
# undefine tap to allow --tap argument
|
# undefine tap to allow --tap argument
|
||||||
@parsed_args.instance_eval { undef tap }
|
@parsed_args.instance_eval { undef tap }
|
||||||
|
@depends = []
|
||||||
|
@conflicts = []
|
||||||
instance_eval(&block)
|
instance_eval(&block)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -47,6 +49,14 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def depends(primary, secondary, mandatory: false)
|
||||||
|
@depends << [primary, secondary, mandatory]
|
||||||
|
end
|
||||||
|
|
||||||
|
def conflicts(primary, secondary)
|
||||||
|
@conflicts << [primary, secondary]
|
||||||
|
end
|
||||||
|
|
||||||
def option_to_name(name)
|
def option_to_name(name)
|
||||||
name.sub(/\A--?/, "").tr("-", "_")
|
name.sub(/\A--?/, "").tr("-", "_")
|
||||||
end
|
end
|
||||||
@ -57,6 +67,7 @@ module Homebrew
|
|||||||
|
|
||||||
def parse(cmdline_args = ARGV)
|
def parse(cmdline_args = ARGV)
|
||||||
@parser.parse(cmdline_args)
|
@parser.parse(cmdline_args)
|
||||||
|
check_constraint_violations
|
||||||
@parsed_args
|
@parsed_args
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -82,6 +93,57 @@ module Homebrew
|
|||||||
else name
|
else name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def option_passed?(name)
|
||||||
|
@parsed_args.respond_to?(name) || @parsed_args.respond_to?("#{name}?")
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_depends
|
||||||
|
@depends.each do |primary, secondary, required|
|
||||||
|
primary_passed = option_passed?(primary)
|
||||||
|
secondary_passed = option_passed?(secondary)
|
||||||
|
raise OptionDependencyError.new(primary, secondary) if required && primary_passed &&
|
||||||
|
!secondary_passed
|
||||||
|
raise OptionDependencyError.new(primary, secondary, missing: true) if secondary_passed &&
|
||||||
|
!primary_passed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_conflicts
|
||||||
|
@conflicts.each do |primary, secondary|
|
||||||
|
primary_passed = option_passed?(primary)
|
||||||
|
secondary_passed = option_passed?(secondary)
|
||||||
|
raise OptionConflictError.new(primary, secondary) if primary_passed && secondary_passed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_constraint_violations
|
||||||
|
check_conflicts
|
||||||
|
check_depends
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class OptionDependencyError < RuntimeError
|
||||||
|
def initialize(arg1, arg2, missing: false)
|
||||||
|
if !missing
|
||||||
|
message = <<~EOS
|
||||||
|
`#{arg1}` and `#{arg2}` should be passed together
|
||||||
|
EOS
|
||||||
|
else
|
||||||
|
message = <<~EOS
|
||||||
|
`#{arg2}` cannot be passed without `#{arg1}`
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
super message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class OptionConflictError < RuntimeError
|
||||||
|
def initialize(arg1, arg2)
|
||||||
|
super <<~EOS
|
||||||
|
`#{arg1}` and `#{arg2}` should not be passed together
|
||||||
|
EOS
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -57,6 +57,7 @@ module Homebrew
|
|||||||
switch "--no-browse"
|
switch "--no-browse"
|
||||||
switch :quiet
|
switch :quiet
|
||||||
switch :force
|
switch :force
|
||||||
|
switch :verbose
|
||||||
switch :debug
|
switch :debug
|
||||||
flag "--url", required: true
|
flag "--url", required: true
|
||||||
flag "--sha256", required: true
|
flag "--sha256", required: true
|
||||||
@ -65,6 +66,9 @@ module Homebrew
|
|||||||
flag "--revision", required: true
|
flag "--revision", required: true
|
||||||
flag "--version", required: true
|
flag "--version", required: true
|
||||||
flag "--message", required: true
|
flag "--message", required: true
|
||||||
|
depends :url, :sha256
|
||||||
|
depends :tag, :revision, mandatory: true
|
||||||
|
conflicts :url, :tag
|
||||||
end
|
end
|
||||||
|
|
||||||
# As this command is simplifying user run commands then let's just use a
|
# As this command is simplifying user run commands then let's just use a
|
||||||
|
@ -70,4 +70,41 @@ describe Homebrew::CLI::Parser do
|
|||||||
expect(args.files).to eq %w[random1.txt random2.txt]
|
expect(args.files).to eq %w[random1.txt random2.txt]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "test constraints" do
|
||||||
|
subject(:parser) {
|
||||||
|
described_class.new do
|
||||||
|
flag "--flag1"
|
||||||
|
flag "--flag2"
|
||||||
|
flag "--flag3"
|
||||||
|
flag "--flag4"
|
||||||
|
depends :flag1, :flag2, mandatory: true
|
||||||
|
depends :flag3, :flag4
|
||||||
|
conflicts :flag1, :flag3
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
it "raises exception on depends mandatory constraint violation" do
|
||||||
|
expect { parser.parse(["--flag1"]) }.to raise_error(Homebrew::CLI::OptionDependencyError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises exception on depends constraint violation" do
|
||||||
|
expect { parser.parse(["--flag2"]) }.to raise_error(Homebrew::CLI::OptionDependencyError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises exception for conflict violation" do
|
||||||
|
expect { parser.parse(["--flag1", "--flag3"]) }.to raise_error(Homebrew::CLI::OptionConflictError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises no exception" do
|
||||||
|
args = parser.parse(["--flag1", "--flag2"])
|
||||||
|
expect(args.flag1).to be true
|
||||||
|
expect(args.flag2).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises no exception for optional dependency" do
|
||||||
|
args = parser.parse(["--flag3"])
|
||||||
|
expect(args.flag3).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user