class Longleaf::FileSelector

Selects and allows for iteration over files which match a provided set of selection criteria

Constants

SPECIFICITY_PATH
SPECIFICITY_STORAGE_LOCATION

Attributes

specificity[R]

Public Class Methods

new(file_paths: nil, storage_locations: nil, physical_provider: Longleaf::PhysicalPathProvider.new, app_config:) click to toggle source

May only provide either file_paths or storage_locations

# File lib/longleaf/candidates/file_selector.rb, line 14
def initialize(file_paths: nil, storage_locations: nil, physical_provider: Longleaf::PhysicalPathProvider.new,
       app_config:)
  if nil_or_empty?(file_paths) && nil_or_empty?(storage_locations)
    raise ArgumentError.new("Must provide either file paths or storage locations")
  end
  if !nil_or_empty?(file_paths) && !nil_or_empty?(storage_locations)
    raise ArgumentError.new("Cannot provide both file paths and storage locations")
  end
  @app_config = app_config
  # The top level paths targeted by this selector
  @target_paths = file_paths&.map do |path|
    # Resolve relative paths against pwd
    pathname = Pathname.new(path)
    if !pathname.absolute?
      path = File.join(Dir.pwd, path)
    end
    path = File.expand_path(path)

    # adding trailing /'s to directories
    if Dir.exist?(path) && !path.end_with?('/')
      path + '/'
    else
      path
    end
  end
  # The set of storage locations to select file paths from
  @storage_locations = storage_locations
  @physical_provider = physical_provider
  # Validate that the selected storage locations are known
  if @storage_locations.nil?
    @specificity = SPECIFICITY_PATH
  else
    @specificity = SPECIFICITY_STORAGE_LOCATION
    locations = @app_config.location_manager.locations
    @storage_locations.each do |loc_name|
      unless locations.key?(loc_name)
        raise StorageLocationUnavailableError.new("Cannot select unknown storage location #{loc_name}.")
      end
    end
  end
end

Public Instance Methods

each() { |file_path| ... } click to toggle source

Iterate through the file paths for this selector and execute the provided block with each. A block is required.

# File lib/longleaf/candidates/file_selector.rb, line 117
def each
  file_path = next_path
  until file_path.nil?
    yield file_path

    file_path = next_path
  end
end
next_path() click to toggle source

Get the next logical file path for this selector. @return [String] an absolute path to the next file targeted by this selector, or nil if no more files selected

# File lib/longleaf/candidates/file_selector.rb, line 72
def next_path
  if @paths.nil?
    # Start the paths listing out from the targetted set of paths for this selector
    # In reverse order since using a LIFO structure
    @paths = target_paths.reverse
  end

  # No more paths to return
  return nil if @paths&.empty?

  # Get the most recently added path for depth first traversal of selected paths
  path = @paths.pop
  until path.nil? do
    @app_config.location_manager.verify_path_in_location(path)
    physical_path = @physical_provider.get_physical_path(path)
    separate_logical = physical_path != path
    if separate_logical
      @app_config.location_manager.verify_path_in_location(physical_path)
    end

    if File.exist?(physical_path)
      if File.directory?(physical_path)
        if separate_logical
          raise InvalidStoragePathError.new("Cannot specify physical path to a directory: #{physical_path}")
        end
        logger.debug("Expanding directory #{path}")
        # For a directory, add all children to file_paths
        Dir.entries(path).sort.reverse_each do |child|
          @paths << File.join(path, child) unless child == '.' or child == '..'
        end
      else
        logger.debug("Returning file #{path}")
        return path
      end
    else
      raise InvalidStoragePathError.new("File #{physical_path} does not exist.")
    end

    # Returned path was not a suitable file, try the next path
    path = @paths.pop
  end
end
storage_locations() click to toggle source

return [Array] a list of all storage locations being targeted by this selector

# File lib/longleaf/candidates/file_selector.rb, line 127
def storage_locations
  # Determine what storage_locations are represented by the given file paths
  if @storage_locations.nil? && !@target_paths.nil?
    loc_set = Set.new
    @target_paths.each do |path|
      loc = @app_config.location_manager.get_location_by_path(path)
      loc_set.add(loc.name) unless loc.nil?
    end
    @storage_locations = loc_set.to_a
  end

  if @storage_locations.nil?
    @storage_locations = Array.new
  end

  @storage_locations
end
target_paths() click to toggle source

@return [Array] a list of top level paths from which files will be selected

# File lib/longleaf/candidates/file_selector.rb, line 57
def target_paths
  # If starting from locations, initialize by expanding locations out to their actual paths
  if @target_paths.nil? && !@storage_locations.nil?
    @target_paths = Array.new
    @storage_locations.each do |loc_name|
      @target_paths << @app_config.location_manager.locations[loc_name].path
    end
  end

  @target_paths
end

Private Instance Methods

nil_or_empty?(value) click to toggle source
# File lib/longleaf/candidates/file_selector.rb, line 146
def nil_or_empty?(value)
  value.nil? || value.empty?
end