From 0400002695b7ccd2811d0728f1c2af3e8fb7f23f Mon Sep 17 00:00:00 2001 From: Gustavo Ribeiro Date: Mon, 16 Dec 2024 19:12:42 -0300 Subject: [PATCH] Prevent duplicate arguments/options --- lib/dry/cli/command.rb | 14 +++++++++++-- spec/unit/dry/cli/command_spec.rb | 33 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 spec/unit/dry/cli/command_spec.rb diff --git a/lib/dry/cli/command.rb b/lib/dry/cli/command.rb index 3e6a601..e445ce4 100644 --- a/lib/dry/cli/command.rb +++ b/lib/dry/cli/command.rb @@ -195,7 +195,12 @@ def self.example(*examples) # # Options: # # --help, -h # Print this help def self.argument(name, options = {}) - @arguments << Argument.new(name, options) + new_arg = Argument.new(name, options) + + duplicate_index = @arguments.find_index { _1.name == new_arg.name } + @arguments.delete_at(duplicate_index) unless duplicate_index.nil? + + @arguments << new_arg end # Command line option (aka optional argument) @@ -309,7 +314,12 @@ def self.argument(name, options = {}) # # Options: # # --port=VALUE, -p VALUE def self.option(name, options = {}) - @options << Option.new(name, options) + new_op = Option.new(name, options) + + duplicate_index = @options.find_index { _1.name == new_op.name } + @options.delete_at(duplicate_index) unless duplicate_index.nil? + + @options << new_op end # @since 0.1.0 diff --git a/spec/unit/dry/cli/command_spec.rb b/spec/unit/dry/cli/command_spec.rb new file mode 100644 index 0000000..c4006fb --- /dev/null +++ b/spec/unit/dry/cli/command_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +RSpec.describe "Command" do + describe "option definition" do + class CommandWithDuplicateOpts < Dry::CLI::Command + option :engine, desc: "1", values: %w[irb pry ripl] + option :engine, desc: "2", values: %w[test1 test2 test3] + end + + it "prevents duplicate options" do + opts = CommandWithDuplicateOpts.options + expect(opts.size).to eq(1) + op = opts.first + expect(op.name).to eq(:engine) + expect(op.desc).to eq("2: (test1/test2/test3)") + end + end + + describe "argument definition" do + class CommandWithDuplicateArgs < Dry::CLI::Command + argument :version, desc: "1" + argument :version, desc: "2" + end + + it "prevents duplicate arguments" do + opts = CommandWithDuplicateArgs.arguments + expect(opts.size).to eq(1) + op = opts.first + expect(op.name).to eq(:version) + expect(op.desc).to eq("2") + end + end +end