class Pod::Command::Diff

This is an example of a cocoapods plugin adding a top-level subcommand to the 'pod' command.

You can also create subcommands of existing or new commands. Say you wanted to add a subcommand to `list` to show newly deprecated pods, (e.g. `pod list deprecated`), there are a few things that would need to change.

@todo Create a PR to add your plugin to CocoaPods/cocoapods.org

in the `plugins.json` file, once your plugin is released.

Public Class Methods

new(argv) click to toggle source
Calls superclass method
# File lib/cocoapods-api-diff/command/diff.rb, line 39
def initialize(argv)
  @name = argv.shift_argument
  @version_a = Version.new(argv.shift_argument)
  @version_b = Version.new(argv.shift_argument)
  @platform = :ios

  @spec_sources = argv.option('spec-sources', 'master').split(',')
  repos = Dir["#{ENV['HOME']}/.cocoapods/repos/*"].select do |path|
    source = Pod::Source.new(path)
    matches = false
    @spec_sources.each do |s|
      if s == source.name || s == source.url
        matches = true
      end
    end
    matches
  end

  @sources = repos.map do |path|
    source = Pod::Source.new(path)
  end
  @sources = @sources || []

  super
end
options() click to toggle source
# File lib/cocoapods-api-diff/command/diff.rb, line 33
def self.options
  [
    ['--spec-sources=private,https://github.com/CocoaPods/Specs.git', 'The sources to pull dependent pods from (defaults to https://github.com/CocoaPods/Specs.git)'],
  ]
end

Public Instance Methods

clang_parse_headers(spec, platform) click to toggle source
# File lib/cocoapods-api-diff/command/diff.rb, line 146
def clang_parse_headers(spec, platform)

  consumer = spec.consumer(platform)

  public_header_files = []
  (consumer.public_header_files.length > 0 ? consumer.public_header_files : ["**/*.h"]).each do |file|
    public_header_files += Dir[file]
  end

  private_header_files = []
  consumer.private_header_files.each do |file|
    private_header_files += Dir[file]
  end

  public_header_files -= private_header_files
  public_header_files.select! do |file|
    !File.symlink?(file)
  end

  # Remove all import lines to avoid duplicate result and speed up
  public_header_files.each do |file|
    data = File.read(file)
    data.gsub!(/[#@](import|include|class)\s*.*/, '')
    data.gsub!(/(FOUNDATION_EXTERN|UIKIT_EXTERN)/, '')
    File.delete(file)
    File.write(file, data)
  end

  # UI.puts "public_header_files: #{public_header_files}"

  result = `clang \
    -Xclang -ast-print \
    -ObjC \
    -fno-diagnostics-color \
    -fsyntax-only \
    #{public_header_files.map{ |file| "\"#{file}\""}.join(" ")} \
    2> /dev/null
  `

  # TODO parse & sort

  return result
end
diff_results(result_a, result_b) click to toggle source
# File lib/cocoapods-api-diff/command/diff.rb, line 190
def diff_results(result_a, result_b)
  `git init`
  file = "#{@name}.h"
  File.write(file, result_a)
  `git add #{file}`
  `rm #{file}`
  File.write(file, result_b)

  system("git --no-pager diff #{file}")

end
get_spec_from_sources(sources, name, version) click to toggle source
# File lib/cocoapods-api-diff/command/diff.rb, line 109
def get_spec_from_sources(sources, name, version)
  spec = nil
  sources.each do |source|
    if source.versions(name).include?(version)
      spec = source.specification(name, version)
    end
  end
  return spec
end
install_pod(spec, platform_name, sandbox_root) click to toggle source
# File lib/cocoapods-api-diff/command/diff.rb, line 119
def install_pod(spec, platform_name, sandbox_root)
  # Remove useless dependencies & platform deployment_target
  spec.store_attribute(:dependencies, nil)
  spec.store_attribute(:dependencies, nil, @platform)
  spec.store_attribute(:platforms, {platform_name => 0})

  # Recreate podspec
  spec_path = "#{spec.name}-#{spec.version}.podspec.json"
  # UI.puts "podspec: #{spec.to_json}"
  File.write(spec_path, spec.to_json)

  podfile = Pod::Podfile.new do
    install!('cocoapods', :integrate_targets => false)
    platform(platform_name)
    target('api-diff') do
      pod(spec.name, podspec: spec_path)
    end
  end

  sandbox = Sandbox.new(sandbox_root)
  installer = Installer.new(sandbox, podfile)

  UI.puts "> Installing #{spec.name} #{spec.version}..."
  installer.install!

end
run() click to toggle source
# File lib/cocoapods-api-diff/command/diff.rb, line 83
def run
  Dir.mktmpdir('cocoapods-api-diff-') do |tmpDir|
    Dir.chdir(tmpDir) do
      UI.puts "> Create temp dir at: #{tmpDir}"

      spec_a = get_spec_from_sources(@sources, @name, @version_a)
      install_pod(spec_a, @platform, spec_a.version.to_s)
      result_a = nil
      Dir.chdir(File.join(spec_a.version.to_s, @name)) do
        result_a = clang_parse_headers(spec_a, @platform.to_s)
      end

      spec_b = get_spec_from_sources(@sources, @name, @version_b)
      sandbox_b = install_pod(spec_b, @platform, spec_b.version.to_s)
      result_b = nil
      Dir.chdir(File.join(spec_b.version.to_s, @name)) do
        result_b = clang_parse_headers(spec_b, @platform.to_s)
      end

      UI.puts "> Diff #{@name} #{@version_a} & #{@version_b}"
      diff_results(result_a, result_b)

    end
  end
end
validate!() click to toggle source
Calls superclass method
# File lib/cocoapods-api-diff/command/diff.rb, line 65
def validate!
  super
  help! 'A Pod name is required.' unless @name
  help! 'Version A is required.' unless @version_a
  help! 'Version B is required.' unless @version_b
  help! 'Version A and Version B are same.' unless @version_a != @version_b

  versions = []
  @sources.each do |source|
    versions += source.versions(@name) || []
  end

  help! "#{@name} can not be found in repo #{@spec_sources}." unless versions.length != 0
  help! "#{@name} (#{@version_a}) can not be found in repo #{@spec_sources}. Avaliable versions: #{versions.map{|v| v.to_s}}" unless versions.include?(@version_a)
  help! "#{@name} (#{@version_b}) can not be found in repo #{@spec_sources}. Avaliable versions: #{versions.map{|v| v.to_s}}" unless versions.include?(@version_b)

end