def clean(plugins, **opts)
      @logger.debug("Cleaning Vagrant plugins of stale gems.")
      # Generate dependencies for all registered plugins
      plugin_deps = plugins.map do |name, info|
        gem_version = info['installed_gem_version']
        gem_version = info['gem_version'] if gem_version.to_s.empty?
        gem_version = "> 0" if gem_version.to_s.empty?
        Gem::Dependency.new(name, gem_version)
      end

      @logger.debug("Current plugin dependency list: #{plugin_deps}")

      # Load dependencies into a request set for resolution
      request_set = Gem::RequestSet.new(*plugin_deps)
      # Never allow dependencies to be remotely satisfied during cleaning
      request_set.remote = false

      # Sets that we can resolve our dependencies from. Note that we only
      # resolve from the current set as all required deps are activated during
      # init.
      current_set = generate_vagrant_set

      # Collect all plugin specifications
      plugin_specs = Dir.glob(plugin_gem_path.join('specifications/*.gemspec').to_s).map do |spec_path|
        Gem::Specification.load(spec_path)
      end

      # Include environment specific specification if enabled
      if env_plugin_gem_path
        plugin_specs += Dir.glob(env_plugin_gem_path.join('specifications/*.gemspec').to_s).map do |spec_path|
          Gem::Specification.load(spec_path)
        end
      end

      @logger.debug("Generating current plugin state solution set.")

      # Resolve the request set to ensure proper activation order
      solution = request_set.resolve(current_set)
      solution_specs = solution.map(&:full_spec)
      solution_full_names = solution_specs.map(&:full_name)

      # Find all specs installed to plugins directory that are not
      # found within the solution set.
      plugin_specs.delete_if do |spec|
        solution_full_names.include?(spec.full_name)
      end

      if env_plugin_gem_path
        # If we are cleaning locally, remove any global specs. If
        # not, remove any local specs
        if opts[:env_local]
          @logger.debug("Removing specifications that are not environment local")
          plugin_specs.delete_if do |spec|
            spec.full_gem_path.to_s.include?(plugin_gem_path.realpath.to_s)
          end
        else
          @logger.debug("Removing specifications that are environment local")
          plugin_specs.delete_if do |spec|
            spec.full_gem_path.to_s.include?(env_plugin_gem_path.realpath.to_s)
          end
        end
      end

      @logger.debug("Specifications to be removed - #{plugin_specs.map(&:full_name)}")

      # Now delete all unused specs
      plugin_specs.each do |spec|
        @logger.debug("Uninstalling gem - #{spec.full_name}")
        Gem::Uninstaller.new(spec.name,
          version: spec.version,
          install_dir: plugin_gem_path,
          all: true,
          executables: true,
          force: true,
          ignore: true,
        ).uninstall_gem(spec)
      end

      solution.find_all do |spec|
        plugins.keys.include?(spec.name)
      end
    end
def clean(plugins, **opts)
      @logger.debug("Cleaning Vagrant plugins of stale gems.")
      # Generate dependencies for all registered plugins
      plugin_deps = plugins.map do |name, info|
        gem_version = info['installed_gem_version']
        gem_version = info['gem_version'] if gem_version.to_s.empty?
        gem_version = "> 0" if gem_version.to_s.empty?
        Gem::Dependency.new(name, gem_version)
      end

      @logger.debug("Current plugin dependency list: #{plugin_deps}")

      # Load dependencies into a request set for resolution
      request_set = Gem::RequestSet.new(*plugin_deps)
      # Never allow dependencies to be remotely satisfied during cleaning
      request_set.remote = false

      # Sets that we can resolve our dependencies from. Note that we only
      # resolve from the current set as all required deps are activated during
      # init.
      current_set = generate_vagrant_set

      # Collect all plugin specifications
      plugin_specs = Dir.glob(plugin_gem_path.join('specifications/*.gemspec').to_s).map do |spec_path|
        Gem::Specification.load(spec_path)
      end

      # Include environment specific specification if enabled
      if env_plugin_gem_path
        plugin_specs += Dir.glob(env_plugin_gem_path.join('specifications/*.gemspec').to_s).map do |spec_path|
          Gem::Specification.load(spec_path)
        end
      end

      @logger.debug("Generating current plugin state solution set.")

      # Resolve the request set to ensure proper activation order
      solution = request_set.resolve(current_set)
      solution_specs = solution.map(&:full_spec)
      solution_full_names = solution_specs.map(&:full_name)

      # Find all specs installed to plugins directory that are not
      # found within the solution set.
      plugin_specs.delete_if do |spec|
        solution_full_names.include?(spec.full_name)
      end

      if env_plugin_gem_path
        # If we are cleaning locally, remove any global specs. If
        # not, remove any local specs
        if opts[:env_local]
          @logger.debug("Removing specifications that are not environment local")
          plugin_specs.delete_if do |spec|
            spec.full_gem_path.to_s.include?(plugin_gem_path.realpath.to_s)
          end
        else
          @logger.debug("Removing specifications that are environment local")
          plugin_specs.delete_if do |spec|
            spec.full_gem_path.to_s.include?(env_plugin_gem_path.realpath.to_s)
          end
        end
      end

      @logger.debug("Specifications to be removed - #{plugin_specs.map(&:full_name)}")

      # Now delete all unused specs
      plugin_specs.each do |spec|
        @logger.debug("Uninstalling gem - #{spec.full_name}")
        Gem::Uninstaller.new(spec.name,
          version: spec.version,
          install_dir: plugin_gem_path,
          all: true,
          executables: true,
          force: true,
          ignore: true,
        ).uninstall_gem(spec)
      end

      solution.find_all do |spec|
        plugins.keys.include?(spec.name)
      end
    end
Clean removes any unused gems.