Module: Omnibus::Util

Included in:
BuildVersion, Builder, Config, Fetcher, Fetcher, GitCache, GitRepository, HealthCheck, Packager::Base, Project, Software
Defined in:
lib/omnibus/util.rb

Constant Summary collapse

SHELLOUT_OPTIONS =

The default shellout options.

Returns:

  • (Hash)
{
  log_level: :internal,
  timeout: 7200, # 2 hours
  environment: {},
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



21
22
23
24
# File 'lib/omnibus/util.rb', line 21

def self.included(base)
  # This module requires logging is also available
  base.send(:include, Logging)
end

Instance Method Details

#compiler_safe_path(*pieces) ⇒ String

Convert the given path to be appropriate for usage with the given compiler

Parameters:

  • pieces (String, Array<String>)

    the pieces of the path to join and fix

Returns:

  • (String)

    the path with applied changes



198
199
200
201
202
# File 'lib/omnibus/util.rb', line 198

def compiler_safe_path(*pieces)
  path = File.join(*pieces)
  path = path.sub(%r{^([A-Za-z]):/}, "/\\1/") if ENV["MSYSTEM"]
  path
end

#copy_file(source, destination) ⇒ String

Copy the source file to the destination.

Parameters:

  • source (String)
  • destination (String)

Returns:

  • (String)

    the destination path



245
246
247
248
249
# File 'lib/omnibus/util.rb', line 245

def copy_file(source, destination)
  log.debug(log_key) { "Copying `#{source}' to `#{destination}'" }
  FileUtils.cp(source, destination)
  destination
end

#create_directory(*paths) ⇒ String

Create a directory at the given path.

Parameters:

  • paths (String, Array<String>)

    the path or list of paths to join to create

Returns:

  • (String)

    the path to the created directory



213
214
215
216
217
218
# File 'lib/omnibus/util.rb', line 213

def create_directory(*paths)
  path = File.join(*paths)
  log.debug(log_key) { "Creating directory `#{path}'" }
  FileUtils.mkdir_p(path)
  path
end

#create_file(*paths, &block) ⇒ String

Create a file at the given path. If a block is given, the contents of the block are written to the file. If the block is not given, the file is simply “touched”.

Parameters:

  • paths (String, Array<String>)

    the path or list of paths to join to create

Returns:

  • (String)

    the path to the created file



278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/omnibus/util.rb', line 278

def create_file(*paths, &block)
  path = File.join(*paths)
  log.debug(log_key) { "Creating file `#{path}'" }

  FileUtils.mkdir_p(File.dirname(path))

  if block
    File.open(path, "wb") { |f| f.write(yield) }
  else
    FileUtils.touch(path)
  end

  path
end

Create a symlink from a to b

Parameters:

  • a (String)
  • b (String)


299
300
301
302
# File 'lib/omnibus/util.rb', line 299

def create_link(a, b)
  log.debug(log_key) { "Linking `#{a}' to `#{b}'" }
  FileUtils.ln_s(a, b)
end

#path_keyString

The proper platform-specific “$PATH” key.

Returns:

  • (String)


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/omnibus/util.rb', line 42

def path_key
  # The ruby devkit needs ENV['Path'] set instead of ENV['PATH'] because
  # $WINDOWSRAGE, and if you don't set that your native gem compiles
  # will fail because the magic fixup it does to add the mingw compiler
  # stuff won't work.
  #
  # Turns out there is other build environments that only set ENV['PATH'] and if we
  # modify ENV['Path'] then it ignores that.  So, we scan ENV and returns the first
  # one that we find.
  #
  if windows?
    result = ENV.keys.grep(/\Apath\Z/i)
    case result.length
    when 0
      raise "The current omnibus environment has no PATH"
    when 1
      result.first
    else
      raise "The current omnibus environment has multiple PATH/Path variables."
    end
  else
    "PATH"
  end
end

#remove_directory(*paths) ⇒ String

Remove the directory at the given path.

Parameters:

  • paths (String, Array<String>)

    the path or list of paths to join to delete

Returns:

  • (String)

    the path to the removed directory



229
230
231
232
233
234
# File 'lib/omnibus/util.rb', line 229

def remove_directory(*paths)
  path = File.join(*paths)
  log.debug(log_key) { "Remove directory `#{path}'" }
  FileUtils.rm_rf(path)
  path
end

#remove_file(*paths) ⇒ String

Remove the file at the given path.

Parameters:

  • paths (String, Array<String>)

    the path or list of paths to join to delete

Returns:

  • (String)

    the path to the removed file



260
261
262
263
264
265
# File 'lib/omnibus/util.rb', line 260

def remove_file(*paths)
  path = File.join(*paths)
  log.debug(log_key) { "Removing file `#{path}'" }
  FileUtils.rm_f(path)
  path
end

#retry_block(logstr, retried_exceptions = [], retries = Omnibus::Config.fetcher_retries, &block) ⇒ Object

Retry the given block if a retriable exception is raised. Returns the value of the block call if successful.

Parameters:

  • logstr (String)

    Description of the action being retried. Used in log output.

  • retried_exceptions (Array<Exception>) (defaults to: [])

    List of exceptions to retry. Any other exceptions are raisesd.

  • retries (Integer) (defaults to: Omnibus::Config.fetcher_retries)

    Number of times to retry the given block.



157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/omnibus/util.rb', line 157

def retry_block(logstr, retried_exceptions = [], retries = Omnibus::Config.fetcher_retries, &block)
  yield
rescue Exception => e
  raise e unless retried_exceptions.any? { |eclass| e.is_a?(eclass) }

  if retries != 0
    log.info(log_key) { "Retrying failed #{logstr} due to #{e} (#{retries} retries left)..." }
    retries -= 1
    retry
  else
    log.error(log_key) { "#{logstr} failed - #{e.class}!" }
    raise
  end
end

#shellout(command, options = {}) ⇒ Mixlib::ShellOut #shellout(command_fragments, options = {}) ⇒ Mixlib::ShellOut

Shells out and runs command.

Overloads:

  • #shellout(command, options = {}) ⇒ Mixlib::ShellOut

    Parameters:

    • command (String)
    • options (Hash) (defaults to: {})

      the options passed to the initializer of the Mixlib::ShellOut instance.

  • #shellout(command_fragments, options = {}) ⇒ Mixlib::ShellOut

    Parameters:

    • command (Array<String>)

      command argv as individual strings

    • options (Hash) (defaults to: {})

      the options passed to the initializer of the Mixlib::ShellOut instance.

Returns:

  • (Mixlib::ShellOut)

    the underlying Mixlib::ShellOut instance which has stdout, stderr, status, and exitstatus populated with results of the command.



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
# File 'lib/omnibus/util.rb', line 82

def shellout(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  options = SHELLOUT_OPTIONS.merge(options)

  command_string = args.join(" ")
  in_msys = options.delete(:in_msys_bash) && ENV["MSYSTEM"]
  # Mixlib will handle escaping characters for cmd but our command might
  # contain '. For now, assume that won't happen because I don't know
  # whether this command is going to be played via cmd or through
  # ProcessCreate.
  command_string = "bash -c \'#{command_string}\'" if in_msys

  # Grab the log_level
  log_level = options.delete(:log_level)

  # Set the live stream if one was not given
  options[:live_stream] ||= log.live_stream(:internal)

  # Since Mixlib::ShellOut supports :environment and :env, we want to
  # standardize here
  if options[:env]
    options[:environment] = options.fetch(:environment, {}).merge(options[:env])
  end

  # Log any environment options given
  unless options[:environment].empty?
    log.public_send(log_level, log_key) { "Environment:" }
    options[:environment].sort.each do |key, value|
      log.public_send(log_level, log_key) { "  #{key}=#{value.inspect}" }
    end
  end

  # Log the actual command
  log.public_send(log_level, log_key) { "$ #{command_string}" }

  cmd = Mixlib::ShellOut.new(command_string, options)
  cmd.environment["HOME"] = "/tmp" unless ENV["HOME"]
  cmd.run_command
  cmd
end

#shellout!(*args) ⇒ Object

Similar to shellout method except it raises an exception if the command fails.

Raises:

See Also:



134
135
136
137
138
139
140
141
142
# File 'lib/omnibus/util.rb', line 134

def shellout!(*args)
  cmd = shellout(*args)
  cmd.error!
  cmd
rescue Mixlib::ShellOut::ShellCommandFailed
  raise CommandFailed.new(cmd)
rescue Mixlib::ShellOut::CommandTimeout
  raise CommandTimeout.new(cmd)
end

#windows_safe_path(*pieces) ⇒ String

Convert the given path to be appropiate for shelling out on Windows.

Parameters:

  • pieces (String, Array<String>)

    the pieces of the path to join and fix

Returns:

  • (String)

    the path with applied changes



180
181
182
183
184
185
186
187
188
# File 'lib/omnibus/util.rb', line 180

def windows_safe_path(*pieces)
  path = File.join(*pieces)

  if File::ALT_SEPARATOR
    path.gsub(File::SEPARATOR, File::ALT_SEPARATOR)
  else
    path
  end
end