File: run_with_capture_options.rb

package info (click to toggle)
ruby-process-executer 4.0.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 408 kB
  • sloc: ruby: 873; makefile: 4
file content (156 lines) | stat: -rw-r--r-- 4,941 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# frozen_string_literal: true

require_relative 'option_definition'
require_relative 'run_options'

module ProcessExecuter
  module Options
    # Define options for {ProcessExecuter.run_with_capture}
    #
    # @api public
    #
    class RunWithCaptureOptions < RunOptions
      # The default encoding used for stdout and stderr
      # if no other encoding is specified.
      #
      # @return [Encoding]
      #
      DEFAULT_ENCODING = Encoding::UTF_8

      # Determines the character encoding to use for stdout
      #
      # It prioritizes `stdout_encoding` if set, otherwise falls back to
      # `encoding`, and finally defaults to `DEFAULT_ENCODING` if neither
      # is available.
      #
      # @return [Encoding]
      #
      # @api private
      #
      def effective_stdout_encoding
        stdout_encoding || encoding || DEFAULT_ENCODING
      end

      # Determines the character encoding to use for stderr
      #
      # It prioritizes `stderr_encoding` if set, otherwise falls back to
      # `encoding`, and finally defaults to `DEFAULT_ENCODING` if neither
      # is available.
      #
      # @return [Encoding]
      #
      # @api private
      #
      def effective_stderr_encoding
        stderr_encoding || encoding || DEFAULT_ENCODING
      end

      private

      # The options allowed for objects of this class
      # @return [Array<OptionDefinition>]
      # @api private
      def define_options
        [
          *super,
          OptionDefinition.new(:merge_output, default: false, validator: method(:validate_merge_output)),
          OptionDefinition.new(:encoding, default: DEFAULT_ENCODING, validator: method(:validate_encoding_option)),
          OptionDefinition.new(:stdout_encoding, default: nil, validator: method(:validate_encoding_option)),
          OptionDefinition.new(:stderr_encoding, default: nil, validator: method(:validate_encoding_option))
        ].freeze
      end

      # Note any errors in the merge_output option
      #
      # Possible errors include:
      # - if the merge_output value is not a Boolean
      # - if merge_output: true and a stderr redirection is given
      # - if merge_output: true and stdout and stderr encodings are different
      #
      # @param _key [Symbol] the option key (not used)
      # @param _value [Object] the option value (not used)
      # @return [Void]
      # @api private
      def validate_merge_output(_key, _value)
        unless [true, false].include?(merge_output)
          errors << "merge_output must be true or false but was #{merge_output.inspect}"
        end

        return unless merge_output == true

        errors << 'Cannot give merge_output: true AND a stderr redirection' if stderr_redirection_source

        return if effective_stdout_encoding == effective_stderr_encoding

        errors << 'Cannot give merge_output: true AND give different encodings for stdout and stderr'
      end

      # Note an error if the encoding option is not valid
      # @param key [Symbol] the option key
      # @param value [Object] the option value
      # @return [Void]
      # @api private
      def validate_encoding_option(key, value)
        return unless valid_encoding_type?(key, value)

        return if value.nil? || value.is_a?(Encoding)

        validate_encoding_symbol(key, value) if value.is_a?(Symbol)

        validate_encoding_string(key, value) if value.is_a?(String)
      end

      # False if the value is not a valid encoding type, true otherwise
      #
      # @param key [Symbol] the option key
      #
      # @param value [Object] the option value
      #
      # @return [Boolean]
      #
      # @api private
      #
      def valid_encoding_type?(key, value)
        return true if value.nil? || value.is_a?(Encoding) || value.is_a?(Symbol) || value.is_a?(String)

        errors << "#{key} must be an Encoding object, String, Symbol (:binary, :default_external), " \
                  "or nil, but was #{value.inspect}"

        false
      end

      # Note an error if the encoding symbol is not valid
      #
      # @param key [Symbol] the option key
      #
      # @param value [Symbol] the option value
      #
      # @return [Void]
      #
      # @api private
      #
      def validate_encoding_symbol(key, value)
        return if %i[binary default_external].include?(value)

        errors << "#{key} when given as a symbol must be :binary or :default_external, " \
                  "but was #{value.inspect}"
      end

      # Note an error if the encoding string is not valid
      #
      # @param key [Symbol] the option key
      #
      # @param value [String] the option value
      #
      # @return [void]
      #
      # @api private
      #
      def validate_encoding_string(key, value)
        Encoding.find(value)
      rescue ::ArgumentError
        errors << "#{key} specifies an unknown encoding name: #{value.inspect}"
      end
    end
  end
end