command_mapper 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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)