lib/license_finder/package_manager.rb
# frozen_string_literal: false
module LicenseFinder
# Super-class for the different package managers
# (Bundler, NPM, Pip, etc.)
#
# For guidance on adding a new package manager use the shared behavior
#
# it_behaves_like "a PackageManager"
#
# Additional guidelines are:
#
# - implement #current_packages, to return a list of `Package`s this package manager is tracking
# - implement #possible_package_paths, an array of `Pathname`s which are the possible locations which contain a configuration file/folder indicating the package manager is in use.
# - implement(Optional) #package_management_command, string for invoking the package manager
# - implement(Optional) #prepare_command, string for fetching dependencies for package manager (runs when the --prepare flag is passed to license_finder)
class PackageManager
include LicenseFinder::SharedHelpers
class << self
def takes_priority_over
nil
end
def id
name.split('::').last.downcase
end
end
def installed?(logger = Core.default_logger)
if package_management_command.nil?
logger.debug self.class, 'no command defined' # TODO: comment me out
true
elsif command_exists?(package_management_command)
logger.debug self.class, 'is installed', color: :green
true
else
logger.info self.class, 'is not installed', color: :red
false
end
end
# see class description
def package_management_command
nil
end
# see class description
def prepare_command
nil
end
def command_exists?(command)
_stdout, _stderr, status =
if LicenseFinder::Platform.windows?
Cmd.run("where #{command}")
else
Cmd.run("which #{command}")
end
status.success?
end
def initialize(options = {})
@prepare_no_fail = options[:prepare_no_fail]
@logger = options[:logger] || Core.default_logger
@project_path = options[:project_path]
@log_directory = options[:log_directory]
@ignored_groups = options[:ignored_groups]
end
def active?
path = detected_package_path
path&.exist?
end
def project_root?
active?
end
def detected_package_path
possible_package_paths.find(&:exist?)
end
def prepare
if prepare_command
stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prepare_command) }
unless status.success?
log_errors stderr
error_message = "Prepare command '#{prepare_command}' failed\n#{stderr}"
error_message == error_message.concat("\n#{stdout}\n") if !stdout.nil? && !stdout.empty?
raise error_message unless @prepare_no_fail
end
else
logger.debug self.class, 'no prepare step provided', color: :red
end
end
def current_packages_with_relations
begin
packages = current_packages
rescue StandardError => e
raise e unless @prepare_no_fail
packages = []
end
packages.each do |parent|
parent.children.each do |child_name|
child = packages.detect { |child_package| child_package.name == child_name }
child.parents << parent.name if child
end
end
packages
end
private
attr_reader :logger, :project_path
def log_errors(stderr)
log_errors_with_cmd(prepare_command, stderr)
end
def log_errors_with_cmd(prep_cmd, stderr)
logger.info(prep_cmd, 'did not succeed.', color: :red)
logger.info(prep_cmd, stderr, color: :red)
log_to_file(prep_cmd, stderr)
end
def log_to_file(prep_cmd, contents)
FileUtils.mkdir_p @log_directory
# replace whitespace with underscores and remove slashes
log_file_name = package_management_command&.gsub(/\s/, '_')&.delete('/')
log_file = File.join(@log_directory, "prepare_#{log_file_name || 'errors'}.log")
File.open(log_file, 'w') do |f|
f.write("Prepare command \"#{prep_cmd}\" failed with:\n")
f.write("#{contents}\n\n")
end
end
end
end
require 'license_finder/package'
require 'license_finder/package_managers/bower'
require 'license_finder/package_managers/go_workspace'
require 'license_finder/package_managers/go_15vendorexperiment'
require 'license_finder/package_managers/go_dep'
require 'license_finder/package_managers/gvt'
require 'license_finder/package_managers/glide'
require 'license_finder/package_managers/govendor'
require 'license_finder/package_managers/go_modules'
require 'license_finder/package_managers/trash'
require 'license_finder/package_managers/bundler'
require 'license_finder/package_managers/npm'
require 'license_finder/package_managers/pnpm'
require 'license_finder/package_managers/yarn'
require 'license_finder/package_managers/pip'
require 'license_finder/package_managers/pipenv'
require 'license_finder/package_managers/maven'
require 'license_finder/package_managers/mix'
require 'license_finder/package_managers/cocoa_pods'
require 'license_finder/package_managers/carthage'
require 'license_finder/package_managers/spm'
require 'license_finder/package_managers/gradle'
require 'license_finder/package_managers/rebar'
require 'license_finder/package_managers/erlangmk'
require 'license_finder/package_managers/nuget'
require 'license_finder/package_managers/dotnet'
require 'license_finder/package_managers/dep'
require 'license_finder/package_managers/conan'
require 'license_finder/package_managers/sbt'
require 'license_finder/package_managers/cargo'
require 'license_finder/package_managers/composer'
require 'license_finder/package_managers/conda'
require 'license_finder/package_managers/pub'