File: shell_command.rb

package info (click to toggle)
ruby-rspec 3.12.0c0e1m1s0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 6,752 kB
  • sloc: ruby: 69,818; sh: 1,861; makefile: 99
file content (126 lines) | stat: -rw-r--r-- 3,880 bytes parent folder | download | duplicates (4)
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
RSpec::Support.require_rspec_core "shell_escape"
require 'shellwords'

module RSpec
  module Core
    module Bisect
      # Provides an API to generate shell commands to run the suite for a
      # set of locations, using the given bisect server to capture the results.
      # @private
      class ShellCommand
        attr_reader :original_cli_args

        def initialize(original_cli_args)
          @original_cli_args = original_cli_args.reject { |arg| arg.start_with?("--bisect") }
        end

        def command_for(locations, server)
          parts = []

          parts << RUBY << load_path
          parts << open3_safe_escape(RSpec::Core.path_to_executable)

          parts << "--format"   << "bisect-drb"
          parts << "--drb-port" << server.drb_port

          parts.concat(reusable_cli_options)
          parts.concat(locations.map { |l| open3_safe_escape(l) })

          parts.join(" ")
        end

        def repro_command_from(locations)
          parts = []

          parts.concat environment_repro_parts
          parts << "rspec"
          parts.concat Formatters::Helpers.organize_ids(locations)
          parts.concat original_cli_args_without_locations

          parts.join(" ")
        end

        def original_locations
          parsed_original_cli_options.fetch(:files_or_directories_to_run)
        end

        def bisect_environment_hash
          if ENV.key?('SPEC_OPTS')
            { 'SPEC_OPTS' => spec_opts_without_bisect }
          else
            {}
          end
        end

        def spec_opts_without_bisect
          Shellwords.join(
            Shellwords.split(ENV.fetch('SPEC_OPTS', '')).reject do |arg|
              arg =~ /^--bisect/
            end
          )
        end

      private

        include RSpec::Core::ShellEscape
        # On JRuby, Open3.popen3 does not handle shellescaped args properly:
        # https://github.com/jruby/jruby/issues/2767
        if RSpec::Support::Ruby.jruby?
          # :nocov:
          alias open3_safe_escape quote
          # :nocov:
        else
          alias open3_safe_escape escape
        end

        def environment_repro_parts
          bisect_environment_hash.map do |k, v|
            %Q(#{k}="#{v}")
          end
        end

        def reusable_cli_options
          @reusable_cli_options ||= begin
            opts = original_cli_args_without_locations

            if (port = parsed_original_cli_options[:drb_port])
              opts -= %W[ --drb-port #{port} ]
            end

            parsed_original_cli_options.fetch(:formatters) { [] }.each do |(name, out)|
              opts -= %W[ --format #{name} -f -f#{name} ]
              opts -= %W[ --out #{out} -o -o#{out} ]
            end

            opts
          end
        end

        def original_cli_args_without_locations
          @original_cli_args_without_locations ||= begin
            files_or_dirs = parsed_original_cli_options.fetch(:files_or_directories_to_run)
            @original_cli_args - files_or_dirs
          end
        end

        def parsed_original_cli_options
          @parsed_original_cli_options ||= Parser.parse(@original_cli_args)
        end

        def load_path
          @load_path ||= "-I#{$LOAD_PATH.map { |p| open3_safe_escape(p) }.join(':')}"
        end

        # Path to the currently running Ruby executable, borrowed from Rake:
        # https://github.com/ruby/rake/blob/v10.4.2/lib/rake/file_utils.rb#L8-L12
        # Note that we skip `ENV['RUBY']` because we don't have to deal with running
        # RSpec from within a MRI source repository:
        # https://github.com/ruby/rake/commit/968682759b3b65e42748cd2befb2ff3e982272d9
        RUBY = File.join(
          RbConfig::CONFIG['bindir'],
          RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']).
          sub(/.*\s.*/m, '"\&"')
      end
    end
  end
end