class PhusionPassenger::Standalone::AppFinder

def self.looks_like_app_directory?(dir, options = {})

def self.looks_like_app_directory?(dir, options = {})
  options = options.dup
  ConfigUtils.load_local_config_file!(dir, options)
  return options[:app_type] ||
    STARTUP_FILES.any? do |file|
      File.exist?("#{dir}/#{file}")
    end
end

def determine_mode_and_execution_root(options)

def determine_mode_and_execution_root(options)
  @mode = :single
  if @dirs.empty?
    @execution_root = File.absolute_path_no_resolve(".")
  else
    @execution_root = File.absolute_path_no_resolve(@dirs[0])
  end
end

def filename_to_server_names(filename)

def filename_to_server_names(filename)
  basename = File.basename(filename)
  names = [basename]
  if basename !~ /^www\.$/i
    names << "www.#{basename}"
  end
  return names
end

def find_app_root

def find_app_root
  if @dirs.empty?
    return File.absolute_path_no_resolve(".")
  else
    return File.absolute_path_no_resolve(@dirs[0])
  end
end

def initialize(dirs, options = {})

def initialize(dirs, options = {})
  @dirs = dirs
  @options = options.dup
  determine_mode_and_execution_root(options)
end

def looks_like_app_directory?(dir, options = {})

def looks_like_app_directory?(dir, options = {})
  return AppFinder.looks_like_app_directory?(dir, options)
end

def monitor(termination_pipe)

def monitor(termination_pipe)
  raise "You must call #scan first" if !@apps
  watcher = PhusionPassenger::Utils::FileSystemWatcher.new(@watchlist, termination_pipe)
  if wait_on_io(termination_pipe, 3)
    return
  end
  while true
    changed = watcher.wait_for_change
    watcher.close
    if changed
      old_apps = @apps
      # The change could be caused by a write to some Passengerfile.json file.
      # Wait for a short period so that the write has a chance to finish.
      if wait_on_io(termination_pipe, 0.25)
        return
      end
      new_apps = scan
      watcher = PhusionPassenger::Utils::FileSystemWatcher.new(@watchlist, termination_pipe)
      if old_apps != new_apps
        yield(new_apps)
      end
      # Don't process change events again for a short while,
      # but do detect changes while waiting.
      if wait_on_io(termination_pipe, 3)
        return
      end
    else
      return
    end
  end
ensure
  watcher.close if watcher
end

def multi_mode?

def multi_mode?
  return !single_mode?
end

def scan

def scan
  apps = []
  watchlist = []
  if single_mode?
    app_root = find_app_root
    apps << {
      :server_names => ["_"],
      :root => app_root
    }
    watchlist << app_root
    WATCH_ENTRIES.each do |entry|
      if File.exist?("#{app_root}/#{entry}")
        watchlist << "#{app_root}/#{entry}"
      end
    end
    apps.map! do |app|
      @options.merge(app)
    end
  end
  @apps = apps
  @watchlist = watchlist
  return apps
end

def single_mode?

def single_mode?
  return @mode == :single
end

def wait_on_io(io, timeout)

timeout has been reached.
been reached. Returns true if the IO became readable, false if the
Wait until the given IO becomes readable, or until the timeout has
def wait_on_io(io, timeout)
  return !!select([io], nil, nil, timeout)
end