command_mapper 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f40de593c4e0124a5c3075b9e89ec08e38fe7451af1ede8fc62030b89b694ec
4
- data.tar.gz: '0392b215a5dff4c4b2bffd34ec7df72fece82adbe7d260a975bd909edb9f962d'
3
+ metadata.gz: 254468c58bbee95ac037609a4ddefc34c026240b4933a37038df1bade5b7487e
4
+ data.tar.gz: 1fe51a7d6ad09b0b51c753bee28632e70292bfa9e9938896e22183c0327f48ae
5
5
  SHA512:
6
- metadata.gz: f5c09b88caea6446ac20238bbba137accd62552c413e5fa67d9dce9a62f2e3f027624c6a951ce59fc6c720f2683e80dcbe5d3e8942d85f472e5d25e12f5e5a85
7
- data.tar.gz: a8e1b267f3628fd23d2924f9d6f25534744af6c2af8a80d5cc3b3fa63bbdc1f35853dcda99871db67cbeea6f6824f3ed77a19b33bd8bd1bb1f5ca7750abf8a7b
6
+ metadata.gz: c1fc9b041fafa2d92300bcbf312e8b1d848450bd4691b6b0eea57fb401a8d20b8a73613328c69cc5d323e9b42313ecc2f3e66b8bcfff14454a8cdb5bd5db5467
7
+ data.tar.gz: 62fd74bd469bff9620c94a8c0710f6d309bb0611af7e58664fa7d04808ee40b14d3b076fb8143a6fdbd409a0fd35fb12682e535c30b41ed616200dc7be982bd2
data/ChangeLog.md CHANGED
@@ -1,3 +1,18 @@
1
+ ### 0.3.0 / 2022-11-11
2
+
3
+ * Added {CommandMapper::Types::Dec}.
4
+
5
+ ### 0.2.1 / 2022-04-22
6
+
7
+ * Properly validate in {CommandMapper::OptionValue#validate} when an option,
8
+ who's value is not required, is given `true`.
9
+ * Omit `nil` arguments from {CommandMapper::Command#command_argv} if the
10
+ argument is not required.
11
+ * Improve validation error message for {CommandMapper::Types::Num} when
12
+ initialized with a `range:` value.
13
+ * Improve validation error message for {CommandMapper::Types::Map} and
14
+ {CommandMapper::Types::Enum}.
15
+
1
16
  ### 0.2.0 / 2022-04-18
2
17
 
3
18
  * Added {CommandMapper::Command.spawn} and
data/README.md CHANGED
@@ -10,8 +10,8 @@
10
10
 
11
11
  ## Description
12
12
 
13
- Command Mapper maps a command's options and arguments to Class attributes to
14
- allow safely and securely executing commands.
13
+ Command Mapper maps an external command's options and arguments to Class
14
+ attributes to allow safely and securely executing commands.
15
15
 
16
16
  ## Features
17
17
 
@@ -20,10 +20,11 @@ allow safely and securely executing commands.
20
20
  * Supports common option types:
21
21
  * [Str][CommandMapper::Types::Str]: string values
22
22
  * [Num][CommandMapper::Types::Num]: numeric values
23
+ * [Dec][CommandMapper::Types::Dec]: decimal values
23
24
  * [Hex][CommandMapper::Types::Hex]: hexadecimal values
24
- * [Map][CommandMapper::Types::Map]: maps `true`/`false` to `yes`/`no`, or
25
- `enabled`/`disabled` (aka `--opt=yes|no` or
26
- `--opt=enabled|disabled` values).
25
+ * [Map][CommandMapper::Types::Map]: maps Ruby values to other String values.
26
+ * `Map::YesNo`: maps `true`/`false` to `yes`/`no`.
27
+ * `Map::EnabledDisabled`: Maps `true`/`false` to `enabled`/`disabled`.
27
28
  * [Enum][CommandMapper::Types::Enum]: maps a finite set of Symbols to a
28
29
  finite set of Strings (aka `--opt={foo|bar|baz}` values).
29
30
  * [List][CommandMapper::Types::List]: comma-separated list
@@ -50,6 +51,7 @@ allow safely and securely executing commands.
50
51
 
51
52
  [CommandMapper::Types::Str]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Str
52
53
  [CommandMapper::Types::Num]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Num
54
+ [CommandMapper::Types::Dec]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Dec
53
55
  [CommandMapper::Types::Hex]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Hex
54
56
  [CommandMapper::Types::Map]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Map
55
57
  [CommandMapper::Types::Enum]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Enum
@@ -314,6 +316,18 @@ Grep.run do |grep|
314
316
  end
315
317
  ```
316
318
 
319
+ Overriding the command name:
320
+
321
+ ```ruby
322
+ Grep.run(..., command_name: 'grep2')
323
+ ```
324
+
325
+ Specifying the direct path to the command:
326
+
327
+ ```ruby
328
+ Grep.run(..., command_path: '/path/to/grep')
329
+ ```
330
+
317
331
  ### Capturing output
318
332
 
319
333
  ```ruby
File without changes
data/examples/grep.rb ADDED
@@ -0,0 +1,62 @@
1
+ require 'command_mapper/command'
2
+
3
+ #
4
+ # Represents the `grep` command
5
+ #
6
+ class Grep < CommandMapper::Command
7
+
8
+ command "grep" do
9
+ option "--extended-regexp"
10
+ option "--fixed-strings"
11
+ option "--basic-regexp"
12
+ option "--perl-regexp"
13
+ option "--regexp", equals: true, value: true
14
+ option "--file", name: :patterns_file, equals: true, value: true
15
+ option "--ignore-case"
16
+ option "--no-ignore-case"
17
+ option "--word-regexp"
18
+ option "--line-regexp"
19
+ option "--null-data"
20
+ option "--no-messages"
21
+ option "--invert-match"
22
+ option "--version"
23
+ option "--help"
24
+ option "--max-count", equals: true, value: {type: Num.new}
25
+ option "--byte-offset"
26
+ option "--line-number"
27
+ option "--line-buffered"
28
+ option "--with-filename"
29
+ option "--no-filename"
30
+ option "--label", equals: true, value: true
31
+ option "--only-matching"
32
+ option "--quiet"
33
+ option "--binary-files", equals: true, value: true
34
+ option "--text"
35
+ option "-I", name: :binary
36
+ option "--directories", equals: true, value: true
37
+ option "--devices", equals: true, value: true
38
+ option "--recursive"
39
+ option "--dereference-recursive"
40
+ option "--include", equals: true, value: true
41
+ option "--exclude", equals: true, value: true
42
+ option "--exclude-from", equals: true, value: true
43
+ option "--exclude-dir", equals: true, value: true
44
+ option "--files-without-match", value: true
45
+ option "--files-with-matches"
46
+ option "--count"
47
+ option "--initial-tab"
48
+ option "--null"
49
+ option "--before-context", equals: true, value: {type: Num.new}
50
+ option "--after-context", equals: true, value: {type: Num.new}
51
+ option "--context", equals: true, value: {type: Num.new}
52
+ option "--group-separator", equals: true, value: true
53
+ option "--no-group-separator"
54
+ option "--color", equals: :optional, value: {required: false}
55
+ option "--colour", equals: :optional, value: {required: false}
56
+ option "--binary"
57
+
58
+ argument :patterns
59
+ argument :file, required: false, repeats: true
60
+ end
61
+
62
+ end
data/gemspec.yml CHANGED
@@ -1,8 +1,8 @@
1
1
  name: command_mapper
2
2
  summary: Safe and secure execution of commands.
3
3
  description:
4
- Command Mapper maps a command's arguments to Class attributes to allow safely
5
- and securely executing commands.
4
+ Command Mapper maps an external command's arguments to Class attributes to
5
+ allow safely and securely executing commands.
6
6
 
7
7
  license: MIT
8
8
  authors: Postmodern
@@ -24,6 +24,8 @@ module CommandMapper
24
24
  # @raise [ArgumentError]
25
25
  # The `type` keyword argument was given a `nil` value.
26
26
  #
27
+ # @api private
28
+ #
27
29
  def initialize(required: true, type: Types::Str.new)
28
30
  @required = required
29
31
 
@@ -62,6 +64,8 @@ module CommandMapper
62
64
  # Returns true if the value is valid, or `false` and a validation error
63
65
  # message if the value is not compatible.
64
66
  #
67
+ # @api semipublic
68
+ #
65
69
  def validate(value)
66
70
  if value.nil?
67
71
  if required?
@@ -30,6 +30,8 @@ module CommandMapper
30
30
  # @raise [ArgumentError]
31
31
  # The given `type:` must not be `false` or `nil`.
32
32
  #
33
+ # @api private
34
+ #
33
35
  def initialize(name, required: true, type: Types::Str.new, repeats: false)
34
36
  super(required: required, type: type)
35
37
 
@@ -56,6 +58,8 @@ module CommandMapper
56
58
  # Returns true if the value is valid, or `false` and a validation error
57
59
  # message if the value is not compatible.
58
60
  #
61
+ # @api semipublic
62
+ #
59
63
  def validate(value)
60
64
  if repeats?
61
65
  values = case value
@@ -101,6 +105,8 @@ module CommandMapper
101
105
  # @raise [ArgumentError]
102
106
  # The given value was incompatible with the argument.
103
107
  #
108
+ # @api semipublic
109
+ #
104
110
  def argv(argv=[],value)
105
111
  valid, message = validate(value)
106
112
 
@@ -5,6 +5,11 @@ require 'command_mapper/option'
5
5
  require 'shellwords'
6
6
 
7
7
  module CommandMapper
8
+ #
9
+ # Base class for all mapped commands.
10
+ #
11
+ # @api public
12
+ #
8
13
  class Command
9
14
 
10
15
  include Types
@@ -24,16 +29,6 @@ module CommandMapper
24
29
  # @return [Hash{String => String}]
25
30
  attr_reader :command_env
26
31
 
27
- # The option values to execute the command with.
28
- #
29
- # @return [Hash{String => Object}]
30
- attr_reader :command_options
31
-
32
- # The argument values to execute the command with.
33
- #
34
- # @return [Hash{String => Object}]
35
- attr_reader :command_arguments
36
-
37
32
  # The subcommand's options and arguments.
38
33
  #
39
34
  # @return [Command, nil]
@@ -51,7 +46,7 @@ module CommandMapper
51
46
  # @param [String, nil] command_path
52
47
  # Overrides the command with a custom path to the command.
53
48
  #
54
- # @param [Hash{String => String}] env
49
+ # @param [Hash{String => String}] command_env
55
50
  # Custom environment variables to pass to the command.
56
51
  #
57
52
  # @param [Hash{Symbol => Object}] kwargs
@@ -94,12 +89,16 @@ module CommandMapper
94
89
  # Initializes and runs the command.
95
90
  #
96
91
  # @param [Hash{Symbol => Object}] params
97
- # The option values.
92
+ # The option and argument values.
98
93
  #
99
- # @yield [self]
94
+ # @param [Hash{Symbol => Object}] kwargs
95
+ # Additional keywords arguments. These will be used to populate
96
+ # {#options} and {#arguments}, along with `params`.
97
+ #
98
+ # @yield [command]
100
99
  # The newly initialized command.
101
100
  #
102
- # @yieldparam [Command] self
101
+ # @yieldparam [Command] command
103
102
  #
104
103
  # @return [Boolean, nil]
105
104
  #
@@ -113,12 +112,16 @@ module CommandMapper
113
112
  # PID of the process.
114
113
  #
115
114
  # @param [Hash{Symbol => Object}] params
116
- # The option values.
115
+ # The option and argument values.
117
116
  #
118
- # @yield [self]
117
+ # @param [Hash{Symbol => Object}] kwargs
118
+ # Additional keywords arguments. These will be used to populate
119
+ # {#options} and {#arguments}, along with `params`.
120
+ #
121
+ # @yield [command]
119
122
  # The newly initialized command.
120
123
  #
121
- # @yieldparam [Command] self
124
+ # @yieldparam [Command] command
122
125
  #
123
126
  # @return [Integer]
124
127
  # The PID of the new command process.
@@ -138,12 +141,16 @@ module CommandMapper
138
141
  # output.
139
142
  #
140
143
  # @param [Hash{Symbol => Object}] params
141
- # The option values.
144
+ # The option and argument values.
142
145
  #
143
- # @yield [self]
146
+ # @param [Hash{Symbol => Object}] kwargs
147
+ # Additional keywords arguments. These will be used to populate
148
+ # {#options} and {#arguments}, along with `params`.
149
+ #
150
+ # @yield [command]
144
151
  # The newly initialized command.
145
152
  #
146
- # @yieldparam [Command] self
153
+ # @yieldparam [Command] command
147
154
  #
148
155
  # @return [String]
149
156
  # The stdout output of the command.
@@ -157,12 +164,19 @@ module CommandMapper
157
164
  # Initializes and executes the command and returns an IO object to it.
158
165
  #
159
166
  # @param [Hash{Symbol => Object}] params
160
- # The option values.
167
+ # The option and argument values.
161
168
  #
162
- # @yield [self]
169
+ # @param [String] mode
170
+ # The IO "mode" to open the IO pipe in.
171
+ #
172
+ # @param [Hash{Symbol => Object}] kwargs
173
+ # Additional keywords arguments. These will be used to populate
174
+ # {#options} and {#arguments}, along with `params`.
175
+ #
176
+ # @yield [command]
163
177
  # The newly initialized command.
164
178
  #
165
- # @yieldparam [Command] self
179
+ # @yieldparam [Command] command
166
180
  #
167
181
  # @return [IO]
168
182
  #
@@ -175,15 +189,15 @@ module CommandMapper
175
189
  # Initializes and runs the command through `sudo`.
176
190
  #
177
191
  # @param [Hash{Symbol => Object}] params
178
- # The option values.
192
+ # The option and argument values.
179
193
  #
180
194
  # @param [Hash{Symbol => Object}] kwargs
181
195
  # Additional keyword arguments for {#initialize}.
182
196
  #
183
- # @yield [self]
197
+ # @yield [command]
184
198
  # The newly initialized command.
185
199
  #
186
- # @yieldparam [Command] self
200
+ # @yieldparam [Command] command
187
201
  #
188
202
  # @return [Boolean, nil]
189
203
  #
@@ -360,6 +374,7 @@ module CommandMapper
360
374
  # All defined options.
361
375
  #
362
376
  # @return [Hash{Symbol => Argument}]
377
+ # The mapping of argument names and {Argument} objects.
363
378
  #
364
379
  # @api semipublic
365
380
  #
@@ -438,7 +453,8 @@ module CommandMapper
438
453
  #
439
454
  # All defined subcommands.
440
455
  #
441
- # @return [Hash{Symbol => Command}]
456
+ # @return [Hash{Symbol => Command.class}]
457
+ # The mapping of subcommand names and subcommand classes.
442
458
  #
443
459
  # @api semipublic
444
460
  #
@@ -535,8 +551,10 @@ module CommandMapper
535
551
  # Gets the value of an option or an argument.
536
552
  #
537
553
  # @param [Symbol] name
554
+ # The name of the option, argument, or subcommand.
538
555
  #
539
556
  # @return [Object]
557
+ # The value of the option, argument, or subcommand.
540
558
  #
541
559
  # @raise [ArgumentError]
542
560
  # The given name was not match any option or argument.
@@ -555,10 +573,13 @@ module CommandMapper
555
573
  # Sets an option or an argument with the given name.
556
574
  #
557
575
  # @param [Symbol] name
576
+ # The name of the option, argument, or subcommand.
558
577
  #
559
578
  # @param [Object] value
579
+ # The new value for the option, argument, or subcommand.
560
580
  #
561
581
  # @return [Object]
582
+ # The new value for the option, argument, or subcommand.
562
583
  #
563
584
  # @raise [ArgumentError]
564
585
  # The given name was not match any option or argument.
@@ -575,6 +596,7 @@ module CommandMapper
575
596
  # Returns an Array of command-line arguments for the command.
576
597
  #
577
598
  # @return [Array<String>]
599
+ # The formatted command-line arguments.
578
600
  #
579
601
  # @raise [ArgumentReqired]
580
602
  # A required argument was not set.
@@ -597,8 +619,10 @@ module CommandMapper
597
619
  self.class.arguments.each do |name,argument|
598
620
  value = self[name]
599
621
 
600
- if value.nil? && argument.required?
601
- raise(ArgumentRequired,"argument #{name} is required")
622
+ if value.nil?
623
+ if argument.required?
624
+ raise(ArgumentRequired,"argument #{name} is required")
625
+ end
602
626
  else
603
627
  argument.argv(additional_args,value)
604
628
  end
@@ -639,6 +663,8 @@ module CommandMapper
639
663
  # Runs the command.
640
664
  #
641
665
  # @return [Boolean, nil]
666
+ # Indicates whether the command exited successfully or not.
667
+ # `nil` indicates the command could not be found.
642
668
  #
643
669
  def run_command
644
670
  Kernel.system(@command_env,*command_argv)
@@ -674,6 +700,7 @@ module CommandMapper
674
700
  # Executes the command and returns an IO object to it.
675
701
  #
676
702
  # @return [IO]
703
+ # The IO object for the command's `STDIN`.
677
704
  #
678
705
  def popen_command(mode=nil)
679
706
  if mode then IO.popen(@command_env,command_argv,mode)
@@ -688,6 +715,8 @@ module CommandMapper
688
715
  # Additional keyword arguments for {Sudo#initialize}.
689
716
  #
690
717
  # @return [Boolean, nil]
718
+ # Indicates whether the command exited successfully or not.
719
+ # `nil` indicates the command could not be found.
691
720
  #
692
721
  def sudo_command(**sudo_kwargs,&block)
693
722
  sudo_params = sudo_kwargs.merge(command: command_argv)
@@ -718,6 +747,7 @@ module CommandMapper
718
747
  # The method name.
719
748
  #
720
749
  # @return [Boolean]
750
+ # Indicates that the method name is also an intenral method name.
721
751
  #
722
752
  def self.is_internal_method?(name)
723
753
  Command.instance_methods(false).include?(name.to_sym)
@@ -51,6 +51,8 @@ module CommandMapper
51
51
  # Specifies that the value should be appended to the option's flag
52
52
  # (ex: `-Fvalue`).
53
53
  #
54
+ # @api private
55
+ #
54
56
  def initialize(flag, name: nil, value: nil, repeats: false,
55
57
  # formatting options
56
58
  equals: nil,
@@ -81,6 +83,8 @@ module CommandMapper
81
83
  # Could not infer the name from the given option flag or was not given a
82
84
  # valid option flag.
83
85
  #
86
+ # @api private
87
+ #
84
88
  def self.infer_name_from_flag(flag)
85
89
  if flag.start_with?('--')
86
90
  name = flag[2..-1]
@@ -146,6 +150,8 @@ module CommandMapper
146
150
  # Returns true if the value is valid, or `false` and a validation error
147
151
  # message if the value is not compatible.
148
152
  #
153
+ # @api semipublic
154
+ #
149
155
  def validate(value)
150
156
  if accepts_value?
151
157
  if repeats?
@@ -173,6 +179,8 @@ module CommandMapper
173
179
  # @raise [ArgumentError]
174
180
  # The given value was incompatible with the option.
175
181
  #
182
+ # @api semipublic
183
+ #
176
184
  def argv(argv=[],value)
177
185
  valid, message = validate(value)
178
186
 
@@ -6,6 +6,26 @@ module CommandMapper
6
6
  #
7
7
  class OptionValue < Arg
8
8
 
9
+ #
10
+ # Validates whether a given value is compatible with the option {#type}.
11
+ #
12
+ # @param [Object] value
13
+ # The given value to validate.
14
+ #
15
+ # @return [true, (false, String)]
16
+ # Returns true if the value is valid, or `false` and a validation error
17
+ # message if the value is not compatible.
18
+ #
19
+ # @api semipublic
20
+ #
21
+ def validate(value)
22
+ if !required? && value == true
23
+ return true
24
+ else
25
+ super(value)
26
+ end
27
+ end
28
+
9
29
  #
10
30
  # Formats a value using the options {#type}.
11
31
  #
@@ -15,6 +35,8 @@ module CommandMapper
15
35
  # @return [String]
16
36
  # The formatted value.
17
37
  #
38
+ # @api semipublic
39
+ #
18
40
  def format(value)
19
41
  @type.format(value)
20
42
  end
@@ -0,0 +1,84 @@
1
+ require 'command_mapper/types/type'
2
+
3
+ module CommandMapper
4
+ module Types
5
+ #
6
+ # Represents a decimal value (ex: `1.5`).
7
+ #
8
+ # @since 0.3.0
9
+ #
10
+ class Dec < Type
11
+
12
+ # The optional range of acceptable decimal numbers.
13
+ #
14
+ # @return [Range<Float,Float>, nil]
15
+ #
16
+ # @api semipublic
17
+ attr_reader :range
18
+
19
+ #
20
+ # Initializes the decimal type.
21
+ #
22
+ # @param [Range<Float,Float>] range
23
+ # Specifies the range of acceptable numbers.
24
+ #
25
+ def initialize(range: nil)
26
+ @range = range
27
+ end
28
+
29
+ #
30
+ # Validates a value.
31
+ #
32
+ # @param [String, Numeric] value
33
+ # The given value to validate.
34
+ #
35
+ # @return [true, (false, String)]
36
+ # Returns true if the value is valid, or `false` and a validation error
37
+ # message if the value is not compatible.
38
+ #
39
+ # @api semipublic
40
+ #
41
+ def validate(value)
42
+ case value
43
+ when Float
44
+ # no-op
45
+ when String
46
+ unless value =~ /\A\d+(?:\.\d+)?\z/
47
+ return [false, "contains non-decimal characters (#{value.inspect})"]
48
+ end
49
+ else
50
+ unless value.respond_to?(:to_f)
51
+ return [false, "cannot be converted into a Float (#{value.inspect})"]
52
+ end
53
+ end
54
+
55
+ if @range
56
+ unless @range.include?(value.to_f)
57
+ return [false, "(#{value.inspect}) not within the range of acceptable values (#{range.inspect})"]
58
+ end
59
+ end
60
+
61
+ return true
62
+ end
63
+
64
+ #
65
+ # Formats a decimal value.
66
+ #
67
+ # @param [String, Float, #to_f] value
68
+ # The given value to format.
69
+ #
70
+ # @return [String]
71
+ # The formatted decimal value.
72
+ #
73
+ # @api semipublic
74
+ #
75
+ def format(value)
76
+ case value
77
+ when Float, String then value.to_s
78
+ else value.to_f.to_s
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -2,9 +2,17 @@ require 'command_mapper/types/map'
2
2
 
3
3
  module CommandMapper
4
4
  module Types
5
+ #
6
+ # Represents a mapping of Ruby values to their String equivalents.
7
+ #
5
8
  class Enum < Map
6
9
 
10
+ # The values of the enum.
11
+ #
7
12
  # @return [Array<Object>]
13
+ #
14
+ # @api semipublic
15
+ #
8
16
  attr_reader :values
9
17
 
10
18
  #
@@ -27,6 +27,8 @@ module CommandMapper
27
27
  #
28
28
  # @return [Boolean]
29
29
  #
30
+ # @api semipublic
31
+ #
30
32
  def leading_zero?
31
33
  @leading_zero
32
34
  end
@@ -41,6 +43,8 @@ module CommandMapper
41
43
  # Returns true if the value is valid, or `false` and a validation error
42
44
  # message if the value is not compatible.
43
45
  #
46
+ # @api semipublic
47
+ #
44
48
  def validate(value)
45
49
  case value
46
50
  when String
@@ -69,6 +73,8 @@ module CommandMapper
69
73
  # @return [String]
70
74
  # The formatted numeric value.
71
75
  #
76
+ # @api semipublic
77
+ #
72
78
  def format(value)
73
79
  case value
74
80
  when String
@@ -17,6 +17,8 @@ module CommandMapper
17
17
  # Returns true if the value is valid, or `false` and a validation error
18
18
  # message if the value is not compatible.
19
19
  #
20
+ # @api semipublic
21
+ #
20
22
  def validate(value)
21
23
  valid, message = super(value)
22
24
 
@@ -17,6 +17,8 @@ module CommandMapper
17
17
  # Returns true if the value is valid, or `false` and a validation error
18
18
  # message if the value is not compatible.
19
19
  #
20
+ # @api semipublic
21
+ #
20
22
  def validate(value)
21
23
  valid, message = super(value)
22
24
 
@@ -17,6 +17,8 @@ module CommandMapper
17
17
  # Returns true if the value is valid, or `false` and a validation error
18
18
  # message if the value is not compatible.
19
19
  #
20
+ # @api semipublic
21
+ #
20
22
  def validate(value)
21
23
  unless value.empty?
22
24
  unless File.exists?(value)