class Pod::Command::Ybin::Link

Public Class Methods

new(argv) click to toggle source
Calls superclass method
# File lib/cocoapods-ybin/command/ybin/link.rb, line 25
def initialize(argv)
  # @name = argv.shift_argument

  @names = argv.arguments! unless argv.arguments.empty?
  @list = argv.flag?('list', false)
  @link = argv.flag?('link', false)
  @remove = argv.flag?('remove', false)
  @remove_all = argv.flag?('remove-all', false)
  @lib_version = argv.flag?('lib-version', false)

  @config = Pod::Config.instance
  super
end
options() click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 16
def self.options
  [
    ['--list', '查询所有已映射源码库'],
    ['--remove', '删除源码映射(多个空格隔开)'],
    ['--remove-all', '删除所有源码映射'],
    ['--lib-version', '查询 Podfile 所有依赖库的版本']
  ]
end

Public Instance Methods

check_linked(lib_path, sourcePath, lib_name) click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 162
def check_linked(lib_path, sourcePath, lib_name)

  source_path = `dwarfdump "#{lib_path}" | grep -E "DW_AT_decl_file.*#{lib_name}.*\\.m|\\.c" | head -1 | cut -d \\" -f2`
  source_path = source_path.chomp.strip
  if File.exist?(source_path)
    UI.puts "🍺🍺🍺 Successfully! 源码映射成功\n".green
    recordLinknSuccessLib(lib_name, lib_path, sourcePath)
  else
    UI.puts "[Error] 源码 #{source_path} 不存在, 请检查源码版本 或 存储位置\n".red
  end
end
linkLibSource() click to toggle source

映射源码

# File lib/cocoapods-ybin/command/ybin/link.rb, line 74
def linkLibSource

  if @names.nil?
    UI.puts "[Error] 请输入需要映射的组件库. 示例: $ pod ybin link foo\n".red
    return
  else
    if @names.count > 1
      UI.puts "[Error] 不支持一次映射多个源码. 示例: $ pod ybin link foo\n".red
      return
    end
  end

  user_lib_name = @names.first.chomp.strip
  lib_version = get_lib_version(user_lib_name)
  if lib_version == nil || lib_version == ""
    print "\n[!]Podfile 无法获取".yellow " #{user_lib_name} ".green "版本号, 但仍支持源码映射\n".yellow
  else

    is_contain_lib = linked_list_contain(user_lib_name)
    if is_contain_lib
      print "\n[Error] #{user_lib_name} 已映射 (#{lib_version}), 如需重新映射,请先删除\n\n".red
      return
    else
      print "\n#{project_name} Using ".green "#{user_lib_name} (#{lib_version})\n".green
    end
  end

  config = config_with_asker
  lib_path = config["libPath"]
  sourcePath = config["sourcePath"]
  lib_name = source_lib_name(lib_path)

  lib_real_path = ""
  if Pathname.new(lib_path).extname == ".framework"
    lib_real_path = "#{lib_path}/#{lib_name}"
  elsif Pathname.new(lib_path).extname == ".a"
    lib_real_path = lib_path
  end

  if lib_real_path == "" || !File.exist?(lib_real_path)
    UI.puts "\n[Error] 二进制文件不存在, 请检查文件位置!\n".red
    return
  end

  if sourcePath == "" || !File.exist?(sourcePath)
    UI.puts "\n[Error] 源码文件不存在, 请检查文件位置!\n".red
    return
  end

  link_source_code(lib_real_path, sourcePath, lib_name)
end
linked_list() click to toggle source

查询映射列表

# File lib/cocoapods-ybin/command/ybin/link.rb, line 223
def linked_list

  if File.exist?(source_record_file_path)
    records = JSON.parse(File.read(source_record_file_path))
    if records.count > 0
      records.each.with_index(1) do |record, index|
        lib_version_s = record["lib_version"]
        lib_version_s = (lib_version_s == nil || lib_version_s == '') ? "" : "(#{lib_version_s})"
        UI.puts "#{index}. #{record["lib_name"]} #{lib_version_s} ".green "Source: #{record["source_path"]}".yellow
      end
    else
      UI.puts "\n无记录".green
    end
  else
    UI.puts "\n无记录".green
  end
  print "\n"
end
linked_remove() click to toggle source

移除单个映射

# File lib/cocoapods-ybin/command/ybin/link.rb, line 175
def linked_remove
  if @names.nil?
    UI.puts "[Error] 请输入要删除的组件库. 实例: $ pod ybin --remove xxx yyy zzz\n".red
    return
  end

  @names.each do  |name|

    lib_linked_path = get_lib_linked_path(name)
    if lib_linked_path.nil? || lib_linked_path == ""
      UI.puts "[Error] #{name} 的映射不存在, 无需移除".red
    else
      if File.exist?(lib_linked_path) && File.symlink?(lib_linked_path)
        FileUtils.rm_rf(lib_linked_path)
        removeLinkedFileRecord(name)
        UI.puts "#{name} 成功移除".green
      else
        UI.puts "[Error] #{name} 的映射不存在, 请手动核查: #{lib_linked_path}".red
      end
    end
  end
  print "\n"
end
linked_remove_all() click to toggle source

移除所有映射

# File lib/cocoapods-ybin/command/ybin/link.rb, line 200
def linked_remove_all

  if File.exist?(source_record_file_path)
    records = JSON.parse(File.read(source_record_file_path))

    if records.count > 0
      records.each.with_index(0) do |record, index|
        lib_linked_path = record["source_path"]
        lib_name = record["lib_name"]
        if File.exist?(lib_linked_path) && File.symlink?(lib_linked_path)
          FileUtils.rm_rf(lib_linked_path)
          removeLinkedFileRecord(lib_name)
          UI.puts "#{lib_name} removing...".green
        end
      end
      UI.puts "\n已全部移除\n".green
    else
      UI.puts "\n无记录\n".green
    end
  end
end
run() click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 45
def run

  if @link && @list && @remove && @remove_all && @lib_version
    UI.puts "[Error] 请选择合适的命令, 不支持同时多个Option\n".red
    help!
    return
  end

  if @list
    analyzerPodFileLock
    linked_list
  elsif @remove
    analyzerPodFileLock
    linked_remove
  elsif @remove_all
    analyzerPodFileLock
    linked_remove_all
  elsif @lib_version
    analyzerPodFileLock
    read_podfile_lock_version
  elsif @names
    analyzerPodFileLock
    linkLibSource
  else
    help!
  end
end
validate!() click to toggle source
Calls superclass method
# File lib/cocoapods-ybin/command/ybin/link.rb, line 39
def validate!
  super
  # help! 'A Pod option is required.' unless @name
  banner! if @help
end

Private Instance Methods

analyzerPodFileLock() click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 356
def analyzerPodFileLock

  podfile_lock = File.join(Pathname.pwd, "Podfile.lock")
  if File.exist?(podfile_lock)
  else
    UI.puts "\n[!] 未匹配到 Podfile.lock 文件, 无法获取 Pod 管理信息\n".red
    return
  end
  @lockfile ||= Lockfile.from_file(Pathname.new(podfile_lock))

  UI.section "ybin analyzer" do
    analyzer = Pod::Installer::Analyzer.new(config.sandbox, config.podfile, @lockfile)
    @analysis_result = analyzer.analyze
    @aggregate_targets = @analysis_result.targets
    @pod_targets = @analysis_result.pod_targets
  end
end
config_with_asker() click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 434
def config_with_asker
  config = {}
  template_source.each do |k, v|
    config[k] = get_require_path(v[:question])
  end
  print "\n"
  config
end
generate_record_item(lib_name, lib_path, source_path) click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 327
def generate_record_item(lib_name, lib_path, source_path)
  lib_version = get_lib_version(lib_name.chomp.strip)
  record_item = {:lib_name => lib_name, :lib_version => lib_version, :lib_path => lib_path, :source_path => source_path}
  record_item
end
get_lib_linked_path(lib_name) click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 412
def get_lib_linked_path(lib_name)

  lib_linked_path = ""
  if File.exist?(source_record_file_path)
    records = JSON.parse(File.read(source_record_file_path))
    records.each do |record|
      if record["lib_name"] == lib_name
        lib_linked_path = record["source_path"]
        break
      end
    end
  end
  lib_linked_path
end
get_lib_version(lib_name) click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 392
def get_lib_version(lib_name)
  if @analysis_result.nil?
    return
  end

  lib_version = ''
  root_specs = @analysis_result.specifications.map(&:root).uniq
  pods_to_install = @analysis_result.sandbox_state.added | @analysis_result.sandbox_state.changed
  root_specs.sort_by(&:name).each.with_index(1) do |spec, index|
    if pods_to_install.include?(spec.name)
    else
      if spec.name == lib_name
        lib_version = spec.version
        break
      end
    end
  end
  lib_version
end
get_require_path(question) click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 443
def get_require_path(question)

  Pod::UI.puts "\n#{question}".yellow
  answer = ''
  loop do
    print "->".green
    answer = STDIN.gets.chomp.strip
    next if answer.empty?
    break
  end
  answer
end
linked_list_contain(lib_name) click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 245
def linked_list_contain(lib_name)

  is_contain_lib = false
  if File.exist?(source_record_file_path)
    records = JSON.parse(File.read(source_record_file_path))
    records.each.with_index(1) do |record, index|
      if record["lib_name"] == lib_name
        is_contain_lib = true
        break
      end
    end
  end
  is_contain_lib
end
project_name() click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 284
def project_name
  targets = @aggregate_targets.map(&:user_project_path).compact.uniq
  project_name = ""
  if targets.count == 1
    project_name = targets.first.basename('.xcodeproj')
  end
  project_name
end
read_podfile_lock_version() click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 374
def read_podfile_lock_version
  if @analysis_result.nil?
    return
  end

  UI.section "#{project_name} 通过 Cocoapods 管理的依赖库(含 dependency)版本:".yellow do
    root_specs = @analysis_result.specifications.map(&:root).uniq
    pods_to_install = @analysis_result.sandbox_state.added | @analysis_result.sandbox_state.changed
    root_specs.sort_by(&:name).each.with_index(1) do |spec, index|
      if pods_to_install.include?(spec.name)
      else
        UI.puts "#{index}. #{spec}".green
      end
    end
    print "\n"
  end
end
recordLinknSuccessLib(lib_name, lib_path, sourcePath) click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 293
def recordLinknSuccessLib(lib_name, lib_path, sourcePath)

  if File.exist?(source_record_file_path)
    record = JSON.parse(File.read(source_record_file_path))

    record_libNames = Array.new
    record.each do |sub|
      record_libNames.push(sub['lib_name'])
    end

    if record_libNames.include?(lib_name)

      replace_index = record_libNames.index(lib_name)
      record[replace_index] = generate_record_item(lib_name, lib_path, sourcePath)
      record_item_json = JSON.generate(record)

      FileUtils.rm_rf(source_record_file_path) if File.exist?(source_record_file_path)
      File.open(source_record_file_path, 'w') { |file| file.write(record_item_json)}
    else

      record.push(generate_record_item(lib_name, lib_path, sourcePath))
      record_item_json = JSON.generate(record)

      FileUtils.rm_rf(source_record_file_path) if File.exist?(source_record_file_path)
      File.open(source_record_file_path, 'w') { |file| file.write(record_item_json)}
    end
  else
    record_items = Array.new
    record_items.push(generate_record_item(lib_name, lib_path, sourcePath))
    record_item_json = JSON.generate(record_items)
    File.open(source_record_file_path, 'w') { |file| file.write(record_item_json)}
  end
end
removeLinkedFileRecord(lib_name) click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 333
def removeLinkedFileRecord(lib_name)

  if File.exist?(source_record_file_path)
    records = JSON.parse(File.read(source_record_file_path))

    lib_name_index = -1
    records.each.with_index(0) do |record, index|
      if record["lib_name"] == lib_name
        lib_name_index = index
        break
      end
    end

    if lib_name_index >= 0
      records.delete_at(lib_name_index)
      record_item_json = JSON.generate(records)

      FileUtils.rm_rf(source_record_file_path) if File.exist?(source_record_file_path)
      File.open(source_record_file_path, 'w') { |file| file.write(record_item_json)}
    end
  end
end
source_lib_name(filePath) click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 273
def source_lib_name(filePath)
  file_name = ""
  if Pathname.new(filePath).extname == ".framework"
    file_name = File.basename(filePath, ".framework")
  elsif Pathname.new(filePath).extname == ".a"
    file_name = File.basename(filePath, ".a")
    file_name = file_name[3..file_name.length]
  end
  file_name
end
source_record_file_path() click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 268
def source_record_file_path
  source_r_path = File.join(source_root.to_s, 'ybin_source_links.json')
  source_r_path
end
source_root() click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 260
def source_root
  cache_root_dir_name = ".ybin"
  user_home_path = Dir.home
  cache_root_path = File.join(user_home_path, cache_root_dir_name);
  FileUtils.mkdir_p(cache_root_path) unless File.exist? cache_root_path
  cache_root_path
end
template_source() click to toggle source
# File lib/cocoapods-ybin/command/ybin/link.rb, line 427
def template_source
  {
    'libPath' => { question: '1/2 请输入静态二进制库的路径(如:/Users/xxx/Workspace/xxx.a 或 /Users/xxx/Workspace/xxx.framework)' },
    'sourcePath' => { question: '2/2 源码路径(注意: 版本是否匹配)' },
  }
end