module Pod class Command class JxedtCommand < Command class Header < JxedtCommand self.summary = 'header fix' self.description = <<-DESC 修改头文件引用问题。\n 例如修改#import "AFNetworking.h"或#import 这种头文件引用方式为#import \n 使用方式:\n 到Podfile文件所在目录执行以下命令\n 1. 修改某个组件的头文件引用\n pod jxedt headerfix --name=PodA --dir=PodA RealPath --write\n 2. 修改工程的头文件引用\n pod jxedt headerfix --dir=project path --write\n DESC self.command = 'headerfix' self.arguments = [ ] def self.options [ ['--name', '需要修改header引用的pod name。没有该参数则会认为修改的是工程中的文件'], ['--dir', '需要修改的文件夹路径,一般情况下为pod组件的真实目录。如果修改的pod组件是development pods,也可以不传该参数。'], ['--write', '修改命中的头文件引用,不写入则直接输出需要修改的文件和修改内容。默认false'], ['--suffix', '处理的文件后缀,默认处理\'h,m,mm,pch\'后缀的文件'], ['--header-regulation', 'header name的正则,默认为\'[\w+-]*\.h\',如果不满足也可以自定义'], ] end def initialize(argv) @pod_name = argv.option('name') @dir = argv.option('dir') @suffix = argv.option('suffix', 'h,m,mm,pch') @force_write = argv.flag?('write', false) @header_regulation = argv.option('header-regulation') super end def validate! super help! 'A podspec name or dir is required.' if @pod_name.nil? && @dir.nil? end def run @installer = installer_for_config help! '请检查命令执行路径,需要在Podfile文件所在目录执行' if @installer.nil? @installer.sandbox.prepare # sandbox prepare @installer.resolve_dependencies # 解析依赖 # @installer.integrate # 不需要执行也可以解析依赖关系 process_target_files = process_target_files! dependent_targets = dependent_targets! # 查找 public_header_mapping = {} dependent_targets.each {|target| next unless target.should_build? # 获取所有.h文件 all_header_files = target.all_files.select {|file| file.to_s =~ /#{header_name_regulation}$/ } # 建立header文件和product_module_name的映射 public_header_mapping.merge! all_header_files.reduce({}) { |hash, file| basename = File.basename(file) hash.update(basename.to_s => target.product_module_name) } } # 遍历需要处理的文件 record = [] process_target_files.each {|file_path| changed = false lines = File.readlines(file_path) # 获取命中的行 File.foreach(file_path).with_index {|line, num| matched = line =~ /^\s*#import\s*"#{header_name_regulation}"\s*\n$/ || line =~ /^\s*#import\s*<#{header_name_regulation}>\s*\n$/ next unless matched header_name = line.match(/(?<=")#{header_name_regulation}(?=")/) || line.match(/(?<=<)#{header_name_regulation}(?=>)/) next unless public_header_mapping.include?("#{header_name}") project_module_name = public_header_mapping["#{header_name}"] replace_line = "#import " << "<#{project_module_name}/#{header_name}>\n" lines[num] = replace_line changed = true record << "#{file_path} 第#{num}行,#{line} => #{replace_line}" } File.open(file_path, 'w') { |f| f.write(lines.join) } if changed && @force_write } puts "需要修改的地方共有:#{record.size} 处" puts JSON.pretty_generate(record) if record.size > 0 end def installer_for_config config = Pod::Config.instance return if config.podfile.nil? Pod::Installer.new(config.sandbox, config.podfile, config.lockfile) end def header_name_regulation @regulation = @header_regulation || '[\w+-]*\.h' # header name的规则 [a-zA-Z0-9_+-] @regulation end def process_target_files! process_target_files = [] unless @dir.nil? def walk(path, &action) return unless path.exist? path.children.each do |child| result = action.call(child, &action) walk(child, &action) if result and child.directory? end end path = Pathname.new(@dir) walk(path) do |child| if child.directory? and [".framework", ".xcframework", ".bundle", ".dSYM"].include? child.extname next false elsif child.file? suffix = @suffix.split(',').join('|') process_target_files << (path + child) if child.to_s =~ /.*\.(#{suffix})$/ next true else next true end end else process_target_files = @installer.pod_targets.flat_map {|target| suffix = @suffix.split(',').join('|') target.all_files.select {|file| file.to_s =~ /.*\.(#{suffix})$/ } if target.pod_name.to_s == @pod_name }.reject(&:nil?).uniq end process_target_files end def dependent_targets! dependent_targets = @installer.pod_targets unless @pod_name.nil? # 递归查找依赖 def recursion_dependent_targets(target) target.dependent_targets.flat_map {|t| targets = [t] targets += recursion_dependent_targets(t) if target.dependent_targets.size > 0 targets }.reject(&:nil?) end # 获取依赖 dependent_targets = @installer.pod_targets.flat_map {|target| recursion_dependent_targets(target) if target.pod_name.to_s == @pod_name }.reject(&:nil?).uniq end dependent_targets end end end end end