Class: Pod::Command::JxedtCommand::Header

Inherits:
Pod::Command::JxedtCommand show all
Defined in:
lib/cocoapods-jxedt/command/header/header.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(argv) ⇒ Header

Returns a new instance of Header.



30
31
32
33
34
35
36
37
38
39
# File 'lib/cocoapods-jxedt/command/header/header.rb', line 30

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')
    @verbose_flag = argv.flag?('verbose', false)
    @log_path = argv.option('log-path')
    super
end

Class Method Details

.optionsObject



19
20
21
22
23
24
25
26
27
28
29
# File 'lib/cocoapods-jxedt/command/header/header.rb', line 19

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\',如果不满足也可以自定义'],
        ['--verbose', '在屏幕上输出修改文件的详情'],
        ['--log-path', '需要修改文件内容导出路径']
    ]
end

Instance Method Details

#dependent_targets!Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/cocoapods-jxedt/command/header/header.rb', line 159

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

#header_name_regulationObject



122
123
124
125
# File 'lib/cocoapods-jxedt/command/header/header.rb', line 122

def header_name_regulation
    @regulation = @header_regulation || '[\w+-]*\.h'  # header name的规则 [a-zA-Z0-9_+-]
    @regulation
end

#installer_for_configObject



116
117
118
119
120
# File 'lib/cocoapods-jxedt/command/header/header.rb', line 116

def installer_for_config
    config = Pod::Config.instance
    return if config.podfile.nil?
    Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
end

#log_file_pathObject



179
180
181
182
183
184
# File 'lib/cocoapods-jxedt/command/header/header.rb', line 179

def log_file_path
    log_path = @log_path
    log_path << "/headerfix_output.txt" if log_path && File.directory?(log_path)
    return if log_path && (!File.exist?(File.dirname(log_path)))
    log_path
end

#process_target_files!Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/cocoapods-jxedt/command/header/header.rb', line 127

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

#runObject



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/cocoapods-jxedt/command/header/header.rb', line 46

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)
        }
    }

    # 遍历需要处理的文件
    files, failed, 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}")

            changed = true # 文件需要修改
            project_module_name = public_header_mapping["#{header_name}"]
            replace_line = "#import " << "<#{project_module_name}/#{header_name}>\n"
            lines[num] = replace_line
            record << "#{file_path} 第#{num}行,#{line} => #{replace_line}"
        }
        files << file_path if changed
        begin
            File.open(file_path, 'w') { |f| f.write(lines.join) } if changed && @force_write
        rescue
            failed << file_path
        ensure
            help! "因权限问题文件修改失败:\n#{file_path}" if failed.size > 0
        end
    }
    puts "需要修改文件共有:#{files.size} 个,需要修改的头文件的地方共有:#{record.size} 处"
    puts "已修改完成" if files.size > 0 && @force_write

    if files.size > 0
        logs = "            \u9700\u8981\u4FEE\u6539\u7684\u6587\u4EF6\uFF1A\n            \#{JSON.pretty_generate(files)}\n\n            \u6587\u4EF6\u4FEE\u6539\u8BE6\u60C5\uFF1A\n            \#{JSON.pretty_generate(record)}\n        LOGS\n        logs.gsub!('\\\\\"', '\"').gsub!('\\\\n', '') # \u53BB\u9664\u8F6C\u4E49\u5B57\u7B26\n        puts logs if @verbose_flag\n        File.open(log_file_path, 'w') { |file| file.write(\"\#{logs}\") } unless log_file_path.nil?\n    end\nend\n"

#validate!Object



41
42
43
44
# File 'lib/cocoapods-jxedt/command/header/header.rb', line 41

def validate!
    super
    help! 'A podspec name or dir is required.' if @pod_name.nil? && @dir.nil?
end