cli_parser: Add depends, conflicts option constraints

This commit is contained in:
Gautham Goli 2018-04-01 22:01:06 +05:30
parent 20155c8df9
commit 36c1ad9f64
3 changed files with 103 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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