Class: SystemWrapper

Inherits:
Object show all
Defined in:
lib/ceedling/system_wrapper.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSystemWrapper

Returns a new instance of SystemWrapper.



30
31
32
# File 'lib/ceedling/system_wrapper.rb', line 30

def initialize()
  @argv = ARGV.clone.freeze
end

Class Method Details

.time_stopwatch_sObject



20
21
22
23
24
25
26
27
28
# File 'lib/ceedling/system_wrapper.rb', line 20

def self.time_stopwatch_s
  # Wall clock time that can be adjusted for a variety of reasons and lead to
  # unexpected negative durations -- only option on Windows.
  return Time.now() if SystemWrapper.windows?

  # On Posix systems, this time value is a steadily increasing count from
  # a known system event (usually restart) and is more better
  return Process.clock_gettime( Process::CLOCK_MONOTONIC, :float_second )
end

.windows?Boolean

Memoized: host_os is fixed for the process lifetime. Guard against nil? rather than ||= so false (non-Windows) is cached correctly.

Returns:

  • (Boolean)


15
16
17
18
# File 'lib/ceedling/system_wrapper.rb', line 15

def self.windows?
  return @windows unless @windows.nil?
  @windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|msys|ucrt/i) ? true : false
end

Instance Method Details

#add_load_path(path) ⇒ Object



128
129
130
131
# File 'lib/ceedling/system_wrapper.rb', line 128

def add_load_path(path)
  # Prevent trouble with string freezing by dup()ing paths here
  $LOAD_PATH.unshift( path.dup() )
end

#constants_include?(item) ⇒ Boolean

Returns:

  • (Boolean)


142
143
144
145
# File 'lib/ceedling/system_wrapper.rb', line 142

def constants_include?(item)
  # forcing to strings provides consistency across Ruby versions
  return Object.constants.map{|constant| constant.to_s}.include?(item.to_s)
end

#env_get(name) ⇒ Object



55
56
57
# File 'lib/ceedling/system_wrapper.rb', line 55

def env_get(name)
  return ENV[name]
end

#env_set(name, value) ⇒ Object



51
52
53
# File 'lib/ceedling/system_wrapper.rb', line 51

def env_set(name, value)
  ENV[name] = value
end

#eval(string) ⇒ Object



39
40
41
# File 'lib/ceedling/system_wrapper.rb', line 39

def eval(string)
  return eval(string)
end

#get_cmdlineObject



47
48
49
# File 'lib/ceedling/system_wrapper.rb', line 47

def get_cmdline
  return @argv
end

#require_file(path) ⇒ Object



133
134
135
# File 'lib/ceedling/system_wrapper.rb', line 133

def require_file(path)
  require(path)
end

#ruby_success?Boolean

Returns:

  • (Boolean)


137
138
139
140
# File 'lib/ceedling/system_wrapper.rb', line 137

def ruby_success?
  # We are successful if we've never had an exit code that went boom (either because it's empty or it was 0)
  return ($exit_code.nil? || ($exit_code == 0)) && ($!.nil? || $!.is_a?(SystemExit) && $!.success?)
end

#search_pathsObject



43
44
45
# File 'lib/ceedling/system_wrapper.rb', line 43

def search_paths
  return ENV['PATH'].split(File::PATH_SEPARATOR)
end

#shell_backticks(command:, boom: false) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/ceedling/system_wrapper.rb', line 98

def shell_backticks(command:, boom:false)
  output = `#{command}`.freeze
  $exit_code = ($?.exitstatus).freeze if boom
  return {
    :output    => output.freeze,
    :stdout    => "",
    :stderr    => "",
    :status    => nil,
    :exit_code => ($?.exitstatus).freeze
  }
end

#shell_capture3(command:, boom: false) ⇒ Object

If set, boom allows a non-zero exit code in results. Otherwise, disabled boom forces a success exit code but collects errors.



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
# File 'lib/ceedling/system_wrapper.rb', line 66

def shell_capture3(command:, boom:false) 
  # Beginning with later versions of Ruby2, simple exit codes were replaced
  # by the more capable and robust Process::Status.
  # Parts of Process::Status's behavior is similar to an integer exit code in
  # some operations but not all.
  exit_code = 0
  
  stdout, stderr, status = Open3.capture3(command)

  # If boom, then capture the actual exit code.
  # Otherwise, leave it as zero as though execution succeeded.
  exit_code = status.exitstatus.freeze if boom and !status.nil?

  # (Re)set the global system exit code so everything matches
  $exit_code = exit_code if exit_code != 0
  
  return {
    # Combine stdout & stderr streams for complete output
    output: (stdout + stderr).to_s.freeze, 

    # Individual streams for detailed logging
    stdout: stdout.freeze, #TODO PROBABLY DROP THESE TOO
    stderr: stderr.freeze,

    # Relay full Process::Status
    status: status.freeze,

    # Provide simple exit code accessor
    exit_code: exit_code.freeze
  }
end

#shell_system(command:, args: [], verbose: false, boom: false) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/ceedling/system_wrapper.rb', line 110

def shell_system(command:, args:[], verbose:false, boom:false)
  result = nil

  if verbose
    # Allow console output
    result = system( command, *args )
  else
    # Shush the console output
    result = system( command, *args, [:out, :err] => File::NULL )
  end

  $exit_code = ($?.exitstatus).freeze if boom
  return {
    :result    => result.freeze,
    :exit_code => ($?.exitstatus).freeze
  }
end

#time_now(format = nil) ⇒ Object



59
60
61
62
# File 'lib/ceedling/system_wrapper.rb', line 59

def time_now(format=nil)
  return Time.now.asctime if format.nil?
  return Time.now.strftime( format )
end

#windows?Boolean

class method so as to be mockable for tests

Returns:

  • (Boolean)


35
36
37
# File 'lib/ceedling/system_wrapper.rb', line 35

def windows?
  return SystemWrapper.windows?
end