class Pod::Command::Whitelist

Public Class Methods

new(argv) click to toggle source
Calls superclass method
# File lib/cocoapods-whitelist/command/whitelist.rb, line 29
def initialize(argv)
  @whitelist_url = argv ? argv.option('config', DEFAULT_WHITELIST_URL) : DEFAULT_WHITELIST_URL
  @pospec_path = argv ? argv.option('podspec') : nil
  @fail_on_error = argv ? argv.flag?('fail-on-error') : false
  @outfile = argv ? argv.option('outfile') : nil
  @failure = false
  super
end
options() click to toggle source
Calls superclass method
# File lib/cocoapods-whitelist/command/whitelist.rb, line 21
def self.options
  [ ['--config=CONFIG', 'Config file or URL for the blacklist'],
    ['--podspec=PODSPEC', 'Podspec file to be lint'],
    ['--fail-on-error', 'Raise an exception in case of error'],
    ['--outfile=PATH', 'Output the linter results to a file']
  ].concat(super)
end

Public Instance Methods

get_podspec_specifications() click to toggle source
# File lib/cocoapods-whitelist/command/whitelist.rb, line 120
def get_podspec_specifications
  if @pospec_path
    return [Pod::Specification.from_file(@pospec_path)]
  end

  # Search .podspec in current directory
  podspecs = Dir.glob("./*.podspec")

  if podspecs.count == 0
    # Search .podspec in parent directory.
    # Some projects has Podfile into a subdirectory ("Example"), and run "pod install" from there.
    podspecs = Dir.glob("../*.podspec")
  end

  return podspecs.map { |path|  Pod::Specification.from_file(path) }
end
prepare_outfile() click to toggle source
# File lib/cocoapods-whitelist/command/whitelist.rb, line 149
def prepare_outfile
  if @outfile == nil
    return
  end

  if File.exist?(@outfile)
    FileUtils.rm(@outfile)
  elsif File.dirname(@outfile)
    FileUtils.mkdir_p(File.dirname(@outfile))
  end
end
run() click to toggle source
# File lib/cocoapods-whitelist/command/whitelist.rb, line 42
def run
  prepare_outfile
  whitelist = WhitelistResolver.instance.get_whitelist(@whitelist_url)
  specifications = get_podspec_specifications

  if specifications.empty?
      UI.puts "No Podspec found".yellow
      return
  end

  specifications.map do |specification|
    validate_dependencies(JSON.parse(specification.to_json), whitelist)
  end

  show_result_message
end
show_error_message(message) click to toggle source
# File lib/cocoapods-whitelist/command/whitelist.rb, line 137
def show_error_message(message)
  unless @outfile == nil
    IO.write(@outfile, "#{message}\n", mode: 'a')
  end

  if @fail_on_error
    UI.puts message.red
  else
    UI.puts message.yellow
  end
end
show_result_message() click to toggle source
# File lib/cocoapods-whitelist/command/whitelist.rb, line 59
def show_result_message
  return unless @failure
  message = "Please check your dependencies.\nYou can see the allowed dependencies at #{@whitelist_url}"
  show_error_message(message)
  if @fail_on_error
    raise Informative.new()
  end
end
validate!() click to toggle source
# File lib/cocoapods-whitelist/command/whitelist.rb, line 38
def validate!
  help! "A whitelist file or URL is needed." unless @whitelist_url
end
validate_dependencies(podspec, whitelist, parentName = nil) click to toggle source

Checks the dependencies the project contains are in the whitelist

# File lib/cocoapods-whitelist/command/whitelist.rb, line 69
def validate_dependencies(podspec, whitelist, parentName = nil)
  pod_name = parentName ? "#{parentName}/#{podspec['name']}" : podspec['name']
  UI.puts "Verifying dependencies in #{pod_name}".green

  dependencies = podspec["dependencies"] ? podspec["dependencies"] : []
  not_allowed = []

  dependencies.each do |name, versions|
    # Skip subspec dependency
    next if parentName && name.start_with?("#{parentName}/")

    if versions.length != 1
      not_allowed.push("#{name} (#{versions.join(", ")}) Reason: A specific version must be defined for every dependency (just one). " +
      "Suggestion: find this dependency in your Podspec and add the version listed in the whitelist.")
      next
    end

    allowedDependency = whitelist.select { |item|
      name.start_with?(item.name.match(POD_NAME_REGEX).captures[POD_BASE_REGEX_POSITION]) && (!item.version || versions.grep(/#{item.version}/).any?) && (item.target == 'production')
    }

    # Checks if any of the allowed dependencies are expired, if so, fail with error
    allowedDependency.each { |dependency|
      if dependency.expire?
        not_allowed.push("#{name} Reason: Expired version. Please check the whitelist.")
      end
    }

    if allowedDependency.empty?
      not_allowed.push("#{name} (#{versions.join(", ")}) Reason: Specified version hasn't match any whitelisted version or Pod name is not valid")
      next
    end
  end

  if not_allowed.any?
    severity = @fail_on_error ? "Error" : "Warning"
    show_error_message(" #{severity}: Found dependencies not allowed:")
    not_allowed.each {|dependency| show_error_message("  - #{dependency}")}
    @failure = true
  else
    UI.puts " OK".green
  end

  # Validate subspecs dependencies
  if podspec["subspecs"]
    podspec["subspecs"].each do |subspec|
      validate_dependencies(subspec, whitelist, pod_name)
    end
  end
end