Method: ChefConfig::PathHelper.all_homes

Defined in:
lib/chef-config/path_helper.rb

.all_homes(*args, windows: ChefUtils.windows?) ⇒ Object

See self.home. This method performs a similar operation except that it yields all the different possible values of ‘HOME’ that one could have on this platform. Hence, on windows, if HOMEDRIVEHOMEPATH and USERPROFILE are different, the provided block will be called twice. This method goes out and checks the existence of each location at the time of the call.

The return is a list of all the returned values from each block invocation or a list of paths if no block is provided.



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/chef-config/path_helper.rb', line 249

def self.all_homes(*args, windows: ChefUtils.windows?)
  paths = []
  paths << ENV[@@per_tool_home_environment] if defined?(@@per_tool_home_environment) && @@per_tool_home_environment && ENV[@@per_tool_home_environment]
  paths << ENV["CHEF_HOME"] if ENV["CHEF_HOME"]
  if windows
    # By default, Ruby uses the following environment variables to determine Dir.home:
    # HOME
    # HOMEDRIVE HOMEPATH
    # USERPROFILE
    # Ruby only checks to see if the variable is specified - not if the directory actually exists.
    # On Windows, HOMEDRIVE HOMEPATH can point to a different location (such as an unavailable network mounted drive)
    # while USERPROFILE points to the location where the user application settings and profile are stored.  HOME
    # is not defined as an environment variable (usually).  If the home path actually uses UNC, then the prefix is
    # HOMESHARE instead of HOMEDRIVE.
    #
    # We instead walk down the following and only include paths that actually exist.
    # HOME
    # HOMEDRIVE HOMEPATH
    # HOMESHARE HOMEPATH
    # USERPROFILE

    paths << ENV["HOME"]
    paths << ENV["HOMEDRIVE"] + ENV["HOMEPATH"] if ENV["HOMEDRIVE"] && ENV["HOMEPATH"]
    paths << ENV["HOMESHARE"] + ENV["HOMEPATH"] if ENV["HOMESHARE"] && ENV["HOMEPATH"]
    paths << ENV["USERPROFILE"]
  end
  paths << Dir.home if ENV["HOME"]

  # Depending on what environment variables we're using, the slashes can go in any which way.
  # Just change them all to / to keep things consistent.
  # Note: Maybe this is a bad idea on some unixy systems where \ might be a valid character depending on
  # the particular brand of kool-aid you consume.  This code assumes that \ and / are both
  # path separators on any system being used.
  paths = paths.map { |home_path| home_path.gsub(path_separator(windows: windows), ::File::SEPARATOR) if home_path }

  # Filter out duplicate paths and paths that don't exist.
  valid_paths = paths.select { |home_path| home_path && Dir.exist?(home_path.force_encoding("utf-8")) }
  valid_paths = valid_paths.uniq

  # Join all optional path elements at the end.
  # If a block is provided, invoke it - otherwise just return what we've got.
  joined_paths = valid_paths.map { |home_path| File.join(home_path, *args) }
  if block_given?
    joined_paths.each { |p| yield p }
  else
    joined_paths
  end
end