deal 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +11 -0
- data/Rakefile +13 -0
- data/bin/deal +10 -0
- data/deal.gemspec +25 -0
- data/lib/deal.rb +5 -0
- data/lib/deal/command.rb +209 -0
- data/lib/deal/command/text.rb +161 -0
- data/lib/deal/gem_version.rb +3 -0
- data/lib/deal/utils/deal_config.rb +297 -0
- data/lib/deal/utils/utils.rb +105 -0
- data/spec/command/thin_spec.rb +12 -0
- data/spec/spec_helper.rb +50 -0
- metadata +87 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9ae39b40eeecc6f975ba329d635d6253b8afeadaf1c3a13b2b6870bdedbbc4ee
|
|
4
|
+
data.tar.gz: 3f442e74e003f64498b314437064d2ee55f96ef1d34b67ba5b50568eec7757c5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c9a864205ff7a952dc7f37629105a38bf292f8427b03943c26f79eb3a47f2b2b028d46dc2733a6cd54a933d8952a2266c004495111bb0904b0e46cc1dd86013d
|
|
7
|
+
data.tar.gz: f799d1a78bcefeadd5681fc454beeb306d0ce9d64619cb389e301f249c97a79a4d0d6a738157173d77b64571c0edd18c3a3d574e3b1c734649fa519e94bae587
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2021 kyle.zhou <kyle.zhou@qq.com>
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
data/bin/deal
ADDED
data/deal.gemspec
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'deal/gem_version.rb'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'deal'
|
|
8
|
+
spec.version = Deal::VERSION
|
|
9
|
+
spec.authors = ['kyle.zhou']
|
|
10
|
+
spec.email = ['kyle.zhou@qq.com']
|
|
11
|
+
spec.description = %q{A short description of deal.}
|
|
12
|
+
spec.summary = %q{A longer description of deal.}
|
|
13
|
+
spec.homepage = 'https://github.com/EXAMPLE/deal'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
#spec.files = ["thin".freeze, "bin/deal".freeze]
|
|
18
|
+
#spec.executables = ["bin/thin".freeze, "bin/deal".freeze]
|
|
19
|
+
spec.executables = 'deal'
|
|
20
|
+
# spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
21
|
+
spec.require_paths = ['lib']
|
|
22
|
+
|
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
|
24
|
+
spec.add_development_dependency 'rake'
|
|
25
|
+
end
|
data/lib/deal.rb
ADDED
data/lib/deal/command.rb
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
|
|
2
|
+
require 'claide'
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'deal/utils/deal_config'
|
|
5
|
+
module Deal
|
|
6
|
+
|
|
7
|
+
class Command < CLAide::Command
|
|
8
|
+
include DealUtils
|
|
9
|
+
self.summary = 'Export a git repository and lfs files.'
|
|
10
|
+
# self.plugin_prefixes = %w(claide cocoapods)
|
|
11
|
+
self.arguments = [
|
|
12
|
+
# CLAide::Argument.new('TYPE', false )
|
|
13
|
+
]
|
|
14
|
+
# self.abstract_command = true
|
|
15
|
+
self.version = VERSION
|
|
16
|
+
self.command = 'deal'
|
|
17
|
+
self.description = <<-DESC
|
|
18
|
+
字符/文件/目录的匹配、替换、异常功能,
|
|
19
|
+
--config参数用于通过json输入配置,可以是json数组的形式表示多个配置,
|
|
20
|
+
--input 用于指定所搜的目录/文件,支持bash 目录通配符
|
|
21
|
+
--signs 表示匹配的字符,支持通配符
|
|
22
|
+
--judge_types 审判的类型,支持文件名称,目录名称,文件字符内容,静态库匹配
|
|
23
|
+
--judge_action 命中匹配字符后的动作,支持remove|replace|abort|report 类型
|
|
24
|
+
--replace 如果judge_action是replace的话,则此参数生效,用于指定替换字符
|
|
25
|
+
--include_paths 路径白名单
|
|
26
|
+
--exclude_paths 路径黑名单
|
|
27
|
+
|
|
28
|
+
DESC
|
|
29
|
+
|
|
30
|
+
def self.options
|
|
31
|
+
[
|
|
32
|
+
['--config', 'json or input files.'],
|
|
33
|
+
['--inputs', 'text,file or dir'],
|
|
34
|
+
['--signs', 'search items'],
|
|
35
|
+
['--judge_types', 'file|dir|text|mach-o,default is text'],
|
|
36
|
+
['--judge_action', 'which actions to match word."remove|replace|abort|report",default is abort'],
|
|
37
|
+
['--replace', 'replace word'],
|
|
38
|
+
['--include_paths', 'include search paths'],
|
|
39
|
+
['--exclude_paths', 'exclude search paths']
|
|
40
|
+
].concat(super)
|
|
41
|
+
end
|
|
42
|
+
def initialize(argv)
|
|
43
|
+
super
|
|
44
|
+
configs = argv.option('config')
|
|
45
|
+
@signs = argv.option('signs',"").split('|')
|
|
46
|
+
@include_paths = argv.option('include_paths',"" ).split('|')
|
|
47
|
+
@exclude_paths = argv.option('exclude_paths',"" ).split('|')
|
|
48
|
+
@judge_types = argv.option('judge_types',"text" ).split('|')
|
|
49
|
+
@replace = argv.option('replace','')
|
|
50
|
+
@judge_action = argv.option('judge_action','abort')
|
|
51
|
+
@configs = []
|
|
52
|
+
if configs
|
|
53
|
+
if FileTest.exist? configs
|
|
54
|
+
configs = File.read(configs)
|
|
55
|
+
begin
|
|
56
|
+
configs = JSON.parse(configs)
|
|
57
|
+
rescue Exception => e
|
|
58
|
+
puts e.message
|
|
59
|
+
puts e.backtrace.inspect
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
for config in configs
|
|
63
|
+
config = DealRule.new(config)
|
|
64
|
+
@configs.push config
|
|
65
|
+
end
|
|
66
|
+
else
|
|
67
|
+
logE "file:#{configs} not exist"
|
|
68
|
+
return
|
|
69
|
+
end
|
|
70
|
+
else
|
|
71
|
+
config = {}
|
|
72
|
+
config["signs"] = @signs
|
|
73
|
+
config["include_paths"] = @include_paths
|
|
74
|
+
config["exclude_paths"] = @exclude_paths
|
|
75
|
+
config["judge_types"] = @judge_types
|
|
76
|
+
config["replace"] = @replace
|
|
77
|
+
config["judge_action"] = @judge_action
|
|
78
|
+
config = DealRule.new(config)
|
|
79
|
+
@configs.push config
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@judge_count = 0
|
|
84
|
+
@total_count = 0
|
|
85
|
+
@progress = 0.0
|
|
86
|
+
|
|
87
|
+
@jump_file = {}
|
|
88
|
+
@results = []
|
|
89
|
+
inputs = argv.option('inputs',"").split('|')
|
|
90
|
+
logN "--inputs:#{inputs.join("\n")}"
|
|
91
|
+
@inputs = []
|
|
92
|
+
for input in inputs
|
|
93
|
+
ls = Dir.glob(input,File::FNM_DOTMATCH|File::FNM_PATHNAME)
|
|
94
|
+
ls = ls.map { |item|
|
|
95
|
+
item = Pathname.new item
|
|
96
|
+
if item.basename.to_s == '.' || item.basename.to_s == '..'
|
|
97
|
+
item = item.dirname
|
|
98
|
+
end
|
|
99
|
+
item.to_s
|
|
100
|
+
}
|
|
101
|
+
@inputs = @inputs.concat(ls)
|
|
102
|
+
end
|
|
103
|
+
if @inputs.length > 1
|
|
104
|
+
i = 0
|
|
105
|
+
while i<@inputs.length
|
|
106
|
+
base = @inputs[i]
|
|
107
|
+
j = 0
|
|
108
|
+
while j<@inputs.length
|
|
109
|
+
if @inputs[i]!= @inputs[j] && @inputs[j].index(@inputs[i]) == 0
|
|
110
|
+
@inputs.delete_at j
|
|
111
|
+
j-=1
|
|
112
|
+
end
|
|
113
|
+
j+=1
|
|
114
|
+
end
|
|
115
|
+
i += 1
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
logN "input glob:\n "+@inputs.join("\n")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def validate!
|
|
124
|
+
super
|
|
125
|
+
help! 'Please specify an config' unless @configs.length > 0
|
|
126
|
+
help! 'Please specify an input' unless @inputs
|
|
127
|
+
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# def handle_text(path)
|
|
131
|
+
# line_n = 0
|
|
132
|
+
# File.open(path, "r") do |aFile|
|
|
133
|
+
# aFile.each do |line|
|
|
134
|
+
# for config in @configs
|
|
135
|
+
# if result = config.judge_file_line(line)
|
|
136
|
+
# result.set_line_n(line_n)
|
|
137
|
+
# @results.push result
|
|
138
|
+
# end
|
|
139
|
+
# end
|
|
140
|
+
# line_n+=1
|
|
141
|
+
# end
|
|
142
|
+
# end
|
|
143
|
+
# end
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def deal_item(config,input)
|
|
147
|
+
if items = config.judge_item(input)
|
|
148
|
+
@results = @results.concat items
|
|
149
|
+
else
|
|
150
|
+
return
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
@judge_count += 1
|
|
154
|
+
progress = @judge_count*1.0/@total_count
|
|
155
|
+
if progress - @progress > 0.01
|
|
156
|
+
@progress = progress
|
|
157
|
+
logW "处理进度:#{format("%.2f",progress*100).to_f}%"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
if not File.directory?(input)
|
|
161
|
+
return
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
Dir.entries(input).each do |sub|
|
|
165
|
+
if sub != '.' && sub != '..'
|
|
166
|
+
deal_item(config,"#{input}/#{sub}")
|
|
167
|
+
else
|
|
168
|
+
@judge_count += 0.5
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def run
|
|
174
|
+
for config in @configs
|
|
175
|
+
for input in @inputs
|
|
176
|
+
if FileTest.directory? input
|
|
177
|
+
match = Pathname.new(input).join('**/*').to_s
|
|
178
|
+
@total_count += Dir.glob(match,File::FNM_DOTMATCH).size
|
|
179
|
+
else
|
|
180
|
+
@total_count += 1
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
logW "开始扫描,总共#{@total_count}个文件"
|
|
184
|
+
for input in @inputs
|
|
185
|
+
if FileTest.exist?(input)
|
|
186
|
+
deal_item config, input
|
|
187
|
+
else
|
|
188
|
+
logE input+' file does not exist'
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
progress = @judge_count*1.0/@total_count
|
|
194
|
+
logW "处理进度:100%"
|
|
195
|
+
|
|
196
|
+
logN '=============================='
|
|
197
|
+
logN "共进行了#{@judge_count}次匹配"
|
|
198
|
+
if @results.length == 0
|
|
199
|
+
logN '没有匹配到结果'
|
|
200
|
+
else
|
|
201
|
+
logN "匹配到 #{@results.length} 个结果,如下:"
|
|
202
|
+
for result in @results
|
|
203
|
+
logN result.to_s
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
logN '=============================='
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
require 'claide'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'deal/utils/deal_config'
|
|
4
|
+
module Deal
|
|
5
|
+
|
|
6
|
+
class Text < Command
|
|
7
|
+
include DealUtils
|
|
8
|
+
self.summary = 'Export a git repository and lfs files.'
|
|
9
|
+
# self.plugin_prefixes = %w(claide cocoapods)
|
|
10
|
+
self.arguments = [
|
|
11
|
+
# CLAide::Argument.new('TYPE', false )
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
self.description = <<-DESC
|
|
15
|
+
Longer description of git-thin.
|
|
16
|
+
include types 'text','Mach-O'
|
|
17
|
+
DESC
|
|
18
|
+
|
|
19
|
+
def self.options
|
|
20
|
+
[
|
|
21
|
+
['--config', 'json or input files.'],
|
|
22
|
+
['--input', 'text,file or dir'],
|
|
23
|
+
['--signs', 'search items'],
|
|
24
|
+
['--judge_types', 'file|dir|text|mach-o'],
|
|
25
|
+
['--judge_action', 'which actions to match word."remove|replace|abort",default is abort'],
|
|
26
|
+
['--replace', 'replace word'],
|
|
27
|
+
['--include_paths', 'include search paths'],
|
|
28
|
+
['--exclude_paths', 'exclude search paths']
|
|
29
|
+
].concat(super)
|
|
30
|
+
end
|
|
31
|
+
def initialize(argv)
|
|
32
|
+
super
|
|
33
|
+
configs = argv.option('config')
|
|
34
|
+
@include = argv.option('include',"")
|
|
35
|
+
@signs = argv.option('signs',"").split('|')
|
|
36
|
+
@include_paths = argv.option('include_paths',"" ).split('|')
|
|
37
|
+
@exclude_paths = argv.option('exclude_paths',"" ).split('|')
|
|
38
|
+
@judge_types = argv.option('judge_types',"" ).split('|')
|
|
39
|
+
@replace = argv.option('replace','')
|
|
40
|
+
@judge_action = argv.option('judge_action','abort')
|
|
41
|
+
@configs = []
|
|
42
|
+
if configs
|
|
43
|
+
if FileTest.exist? configs
|
|
44
|
+
configs = File.read(configs)
|
|
45
|
+
begin
|
|
46
|
+
configs = JSON.parse(configs)
|
|
47
|
+
rescue Exception => e
|
|
48
|
+
puts e.message
|
|
49
|
+
puts e.backtrace.inspect
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
for config in configs
|
|
53
|
+
config = DealRule.new(config)
|
|
54
|
+
@configs.push config
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
logE "file:#{configs} not exist"
|
|
58
|
+
return
|
|
59
|
+
end
|
|
60
|
+
else
|
|
61
|
+
config = {}
|
|
62
|
+
config["signs"] = @signs
|
|
63
|
+
config["include_paths"] = @include_paths
|
|
64
|
+
config["exclude_paths"] = @exclude_paths
|
|
65
|
+
config["judge_types"] = @judge_types
|
|
66
|
+
config["replace"] = @replace
|
|
67
|
+
config["judge_action"] = @judge_action
|
|
68
|
+
config = DealRule.new(config)
|
|
69
|
+
@configs.push config
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@judge_count = 0
|
|
74
|
+
@total_count = 0
|
|
75
|
+
@progress = 0.0
|
|
76
|
+
|
|
77
|
+
@jump_file = {}
|
|
78
|
+
@results = []
|
|
79
|
+
|
|
80
|
+
@input = argv.option('input')
|
|
81
|
+
@input = Dir.glob(@input,)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def validate!
|
|
87
|
+
super
|
|
88
|
+
help! 'Please specify an config' unless @configs.length > 0
|
|
89
|
+
help! 'Please specify an input' unless @input
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# def handle_text(path)
|
|
94
|
+
# line_n = 0
|
|
95
|
+
# File.open(path, "r") do |aFile|
|
|
96
|
+
# aFile.each do |line|
|
|
97
|
+
# for config in @configs
|
|
98
|
+
# if result = config.judge_file_line(line)
|
|
99
|
+
# result.set_line_n(line_n)
|
|
100
|
+
# @results.push result
|
|
101
|
+
# end
|
|
102
|
+
# end
|
|
103
|
+
# line_n+=1
|
|
104
|
+
# end
|
|
105
|
+
# end
|
|
106
|
+
# end
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def deal_item(config,input)
|
|
110
|
+
if items = config.judge_item(input)
|
|
111
|
+
@results = @results.concat items
|
|
112
|
+
else
|
|
113
|
+
return
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
@judge_count += 1
|
|
117
|
+
progress = @judge_count*1.0/@total_count
|
|
118
|
+
if progress - @progress > 0.01
|
|
119
|
+
@progress = progress
|
|
120
|
+
logW "处理进度:#{format("%.2f",progress*100).to_f}%"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
if not File.directory?(input)
|
|
124
|
+
return
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
Dir.entries(input).each do |sub|
|
|
128
|
+
if sub != '.' && sub != '..'
|
|
129
|
+
deal_item(config,"#{input}/#{sub}")
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def run
|
|
135
|
+
for config in @configs
|
|
136
|
+
if FileTest.exist?(@input)
|
|
137
|
+
if FileTest.directory? @input
|
|
138
|
+
match = Pathname.new(@input).join('**/*').to_s
|
|
139
|
+
@total_count = Dir.glob(match,File::FNM_DOTMATCH).size
|
|
140
|
+
else
|
|
141
|
+
@total_count = 1
|
|
142
|
+
end
|
|
143
|
+
deal_item config, @input
|
|
144
|
+
else
|
|
145
|
+
logE input+' file does not exist'
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
logN '=============================='
|
|
149
|
+
logN "共进行了#{@judge_count}次匹配"
|
|
150
|
+
if @results.length == 0
|
|
151
|
+
logN '没有匹配到结果'
|
|
152
|
+
else
|
|
153
|
+
logN '匹配到结果如下:'
|
|
154
|
+
for result in @results
|
|
155
|
+
logN result.to_s
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
logN '=============================='
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
module Deal
|
|
2
|
+
DEAL_TYPE_LINE=0
|
|
3
|
+
DEAL_TYPE_PATH=1
|
|
4
|
+
DEAL_TYPE_BINARY=2
|
|
5
|
+
|
|
6
|
+
JUDEG_TYPE = {
|
|
7
|
+
:FILE => "file",
|
|
8
|
+
:DIR => "dir",
|
|
9
|
+
:TEXT => "text",
|
|
10
|
+
:MACH => "mach_o",
|
|
11
|
+
}
|
|
12
|
+
JUDEG_ACTION = {
|
|
13
|
+
:REPLACE => "replace",
|
|
14
|
+
:REMOVE => "remove",
|
|
15
|
+
:ABORT => "abort",
|
|
16
|
+
:REPORT => "report",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class DealResult
|
|
20
|
+
def initialize(type,item,match_key,action)
|
|
21
|
+
@type = type
|
|
22
|
+
@item = item
|
|
23
|
+
@match_key = match_key
|
|
24
|
+
@action = action
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def set_line_n(line)
|
|
28
|
+
@line_n = line
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def set_path(path)
|
|
32
|
+
@file_path = path
|
|
33
|
+
end
|
|
34
|
+
def to_s
|
|
35
|
+
s = []
|
|
36
|
+
s.push '{'
|
|
37
|
+
s.push "type:#{@type}" if @type
|
|
38
|
+
s.push "match_item:#{@item}" if @item
|
|
39
|
+
s.push "match_key:#{@match_key}" if @match_key
|
|
40
|
+
s.push "action:#{@action}" if @action
|
|
41
|
+
s.push "file_path:#{@file_path}" if @file_path
|
|
42
|
+
s.push "line_number:#{@line_n}" if @line_n
|
|
43
|
+
s.push '}'
|
|
44
|
+
|
|
45
|
+
return s.join("\n")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
class DealRule
|
|
50
|
+
include DealUtils
|
|
51
|
+
|
|
52
|
+
def initialize(config)
|
|
53
|
+
config['signs'] = [] if not config['signs']
|
|
54
|
+
config['exclude_paths'] = [] if not config['exclude_paths']
|
|
55
|
+
config['include_paths'] = [] if not config['include_paths']
|
|
56
|
+
config['judge_types'] = [JUDEG_TYPE[:TEXT]] if not config['judge_types']
|
|
57
|
+
config['judge_action'] = JUDEG_ACTION[:ABORT] if not config['judge_action']
|
|
58
|
+
config['replace'] = '' if not config['replace']
|
|
59
|
+
|
|
60
|
+
@judge_types = config['judge_types']
|
|
61
|
+
@judge_action = config['judge_action']
|
|
62
|
+
@replace = config['replace']
|
|
63
|
+
|
|
64
|
+
@signs = config['signs'].map do |item|
|
|
65
|
+
Regexp.new item.strip
|
|
66
|
+
end
|
|
67
|
+
@exclude_paths = config['exclude_paths'].map do |item|
|
|
68
|
+
Regexp.new item.strip
|
|
69
|
+
end
|
|
70
|
+
@include_paths = config['include_paths'].map do |item|
|
|
71
|
+
Regexp.new item.strip
|
|
72
|
+
end
|
|
73
|
+
@judge_types = config['judge_types']
|
|
74
|
+
|
|
75
|
+
check_type
|
|
76
|
+
@need_content = @judge_types.include?(JUDEG_TYPE[:TEXT]) || @judge_types.include?(JUDEG_TYPE[:MACH])
|
|
77
|
+
logN to_s
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def to_s
|
|
81
|
+
ls = []
|
|
82
|
+
ls.push "{"
|
|
83
|
+
ls.push "signs:#{@signs.join("\n")}" if @signs.length > 0
|
|
84
|
+
ls.push "exclude_paths:#{@exclude_paths.join("\n")}" if @exclude_paths.length > 0
|
|
85
|
+
ls.push "include_paths:#{@include_paths.join("\n")}" if @include_paths.length > 0
|
|
86
|
+
ls.push "judge_types:#{@judge_types.join("\n")}" if @judge_types.length > 0
|
|
87
|
+
ls.push "judge_action:#{@judge_action}"
|
|
88
|
+
ls.push "replace:#{@replace}" if @replace
|
|
89
|
+
ls.push "}"
|
|
90
|
+
return ls.join("\n")
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
def check_type
|
|
94
|
+
pass = true
|
|
95
|
+
for type in @judge_types
|
|
96
|
+
if !JUDEG_TYPE.values.include? type
|
|
97
|
+
logE "judge_types values [#{type}] is invalid"
|
|
98
|
+
pass = false
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
if !JUDEG_ACTION.values.include? @judge_action
|
|
102
|
+
logE "judge_action value [#{type}] is invalid"
|
|
103
|
+
pass = false
|
|
104
|
+
end
|
|
105
|
+
if !pass
|
|
106
|
+
raise 'param is error'
|
|
107
|
+
exit 1
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
def include_path(path)
|
|
111
|
+
#0> File.fnmatch('**/.git',path+"/.git",File::FNM_PATHNAME | File::FNM_DOTMATCH)
|
|
112
|
+
if @include_paths.length > 0
|
|
113
|
+
match = false
|
|
114
|
+
for include in @include_paths
|
|
115
|
+
if include.match? path
|
|
116
|
+
match = true
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
if !match
|
|
120
|
+
return false
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
if @exclude_paths.length > 0
|
|
125
|
+
for exclude in @exclude_paths
|
|
126
|
+
if exclude.match? path
|
|
127
|
+
return false
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
return true
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def action(sign,line)
|
|
135
|
+
if @judge_action == JUDEG_ACTION[:REPLACE]
|
|
136
|
+
return @replace
|
|
137
|
+
elsif @judge_action == JUDEG_ACTION[:REMOVE]
|
|
138
|
+
return nil
|
|
139
|
+
elsif @judge_action == JUDEG_ACTION[:ABORT]
|
|
140
|
+
raise "
|
|
141
|
+
find a error, do ABORT action:
|
|
142
|
+
match key:#{sign.source}
|
|
143
|
+
match item:#{line}
|
|
144
|
+
"
|
|
145
|
+
elsif @judge_action == JUDEG_ACTION[:REPORT]
|
|
146
|
+
return line
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
def judge_item(path)
|
|
150
|
+
if !include_path(path)
|
|
151
|
+
logW 'jump path'
|
|
152
|
+
return
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
result = []
|
|
156
|
+
if FileTest.directory?(path)
|
|
157
|
+
if @judge_types.include?(JUDEG_TYPE[:DIR])
|
|
158
|
+
result = result.concat judge_path(path)
|
|
159
|
+
end
|
|
160
|
+
return result
|
|
161
|
+
else
|
|
162
|
+
if @judge_types.include?(JUDEG_TYPE[:FILE])
|
|
163
|
+
result = result.concat judge_path(path)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
if !@need_content
|
|
168
|
+
return result
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
lines = []
|
|
172
|
+
need_rewrite = false
|
|
173
|
+
if path.include? '.mm'
|
|
174
|
+
puts path
|
|
175
|
+
end
|
|
176
|
+
File.open(path, "r") do |aFile|
|
|
177
|
+
is_binary = false
|
|
178
|
+
while line=aFile.gets
|
|
179
|
+
need_replace = false
|
|
180
|
+
for i in 0...(line.length)
|
|
181
|
+
begin
|
|
182
|
+
if line[i].ord == 0
|
|
183
|
+
is_binary = true
|
|
184
|
+
break
|
|
185
|
+
end
|
|
186
|
+
rescue Exception =>e
|
|
187
|
+
is_binary = true
|
|
188
|
+
# logE "file prase error:#{e.to_s},path:#{path}"
|
|
189
|
+
break
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
if is_binary
|
|
194
|
+
break
|
|
195
|
+
end
|
|
196
|
+
for sign in @signs
|
|
197
|
+
if sign.match? line
|
|
198
|
+
action_tip = ''
|
|
199
|
+
ret = action sign,line
|
|
200
|
+
result.push ret
|
|
201
|
+
need_replace = true
|
|
202
|
+
if ret
|
|
203
|
+
lines.push ret
|
|
204
|
+
if ret != line
|
|
205
|
+
need_rewrite = true
|
|
206
|
+
action_tip = "rename to #{ret}"
|
|
207
|
+
end
|
|
208
|
+
else
|
|
209
|
+
action_tip = 'remove'
|
|
210
|
+
end
|
|
211
|
+
ret = DealResult.new('text',line,sign.source,action_tip)
|
|
212
|
+
ret.set_line_n lines.length
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
if !need_replace
|
|
216
|
+
lines.push line
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
if need_rewrite
|
|
222
|
+
begin
|
|
223
|
+
File.open(path, "w") do |aFile|
|
|
224
|
+
lines.each { |line|
|
|
225
|
+
aFile.puts line
|
|
226
|
+
}
|
|
227
|
+
end
|
|
228
|
+
rescue Exception =>e
|
|
229
|
+
logE "faile write open #{path}"
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
return result
|
|
233
|
+
|
|
234
|
+
# run_shell "file #{path}",true ,2 do |out ,err,status|
|
|
235
|
+
# if status == 0 && out.length > 0
|
|
236
|
+
# type = out[0]
|
|
237
|
+
# # if out[0].include? 'text'
|
|
238
|
+
# # result.concat judge_text path
|
|
239
|
+
# # elsif out[0].include? 'Mach-O'
|
|
240
|
+
# # result.concat judge_mach_o path
|
|
241
|
+
# # else
|
|
242
|
+
# # logW "jump file type:#{out[0]}, path:#{path}"
|
|
243
|
+
# # end
|
|
244
|
+
# end
|
|
245
|
+
# end
|
|
246
|
+
# if include_type type
|
|
247
|
+
# if type.include? 'text' || type.include?('JSON')
|
|
248
|
+
# process do
|
|
249
|
+
# result.concat judge_text path
|
|
250
|
+
# print path
|
|
251
|
+
# end
|
|
252
|
+
# elsif type.include? 'Mach-O'
|
|
253
|
+
# result.concat judge_mach_o path
|
|
254
|
+
# else
|
|
255
|
+
# logW "jump file type:#{type}, path:#{path}"
|
|
256
|
+
# end
|
|
257
|
+
# end
|
|
258
|
+
# return result
|
|
259
|
+
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def judge_path(path)
|
|
263
|
+
results = []
|
|
264
|
+
for sign in @signs
|
|
265
|
+
if sign.match? path.to_s
|
|
266
|
+
action_tip = ''
|
|
267
|
+
ret = action sign,path
|
|
268
|
+
if ret
|
|
269
|
+
if ret != path
|
|
270
|
+
item = Pathname.new path
|
|
271
|
+
target = item.dirname + ret
|
|
272
|
+
FileUtils.mv(path,target.to_s)
|
|
273
|
+
action_tip='rename to '+target
|
|
274
|
+
end
|
|
275
|
+
else
|
|
276
|
+
action_tip='remove files'
|
|
277
|
+
FileUtils.rm_rf path
|
|
278
|
+
end
|
|
279
|
+
return results.push DealResult.new('path',path,sign.source,action_tip)
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
return results
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def judge_mach_o(line)
|
|
286
|
+
# for match in @match_binary
|
|
287
|
+
# if match.match? path
|
|
288
|
+
# return DealResult.new(DEAL_TYPE_BINARY,line,match.to_s,@replace)
|
|
289
|
+
# end
|
|
290
|
+
# end
|
|
291
|
+
raise '暂未实现'
|
|
292
|
+
return []
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
end
|
|
297
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
require 'open3'
|
|
2
|
+
|
|
3
|
+
module DealUtils
|
|
4
|
+
def process
|
|
5
|
+
startTime = Time.new
|
|
6
|
+
if block_given?
|
|
7
|
+
yield
|
|
8
|
+
end
|
|
9
|
+
endTime = Time.new
|
|
10
|
+
logN "执行耗时:#{format("%.2f",(endTime-startTime)*1000).to_f}ms"
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def set_progress(index, char = '*')
|
|
15
|
+
print (char * (index / 2.5).floor).ljust(40, " "), " #{index}%\r"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run_shell(command,force = false,slient = false,retryCount = 0 )
|
|
19
|
+
# if not slient
|
|
20
|
+
# logC command
|
|
21
|
+
# end
|
|
22
|
+
if slient<2
|
|
23
|
+
logC command
|
|
24
|
+
end
|
|
25
|
+
stdin, stdout, stderr,wait_thr = Open3.popen3(command)
|
|
26
|
+
pid = wait_thr[:pid]
|
|
27
|
+
out_lines = []
|
|
28
|
+
error_lines = []
|
|
29
|
+
stdout.sync = true
|
|
30
|
+
out = Thread.new do
|
|
31
|
+
# while !stdout.eof?
|
|
32
|
+
# c = stdout.getc
|
|
33
|
+
# putc c
|
|
34
|
+
# end
|
|
35
|
+
stdout.each do |line|
|
|
36
|
+
out_lines.push line
|
|
37
|
+
if not slient
|
|
38
|
+
logN line
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
err = Thread.new do
|
|
43
|
+
stderr.each do |line|
|
|
44
|
+
error_lines.push line
|
|
45
|
+
if not slient
|
|
46
|
+
logW line
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
out.join
|
|
51
|
+
err.join
|
|
52
|
+
|
|
53
|
+
stderr.close
|
|
54
|
+
stdin.close
|
|
55
|
+
stdout.close
|
|
56
|
+
status = wait_thr.value
|
|
57
|
+
if status.exitstatus != 0
|
|
58
|
+
if !force
|
|
59
|
+
if retryCount > 0
|
|
60
|
+
sleep 1
|
|
61
|
+
run_shell command,force,slient,retryCount-1
|
|
62
|
+
return
|
|
63
|
+
else
|
|
64
|
+
if slient
|
|
65
|
+
logE error_lines
|
|
66
|
+
end
|
|
67
|
+
exit 1
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
unless block_given?
|
|
72
|
+
|
|
73
|
+
return [out_lines,error_lines,status.exitstatus]
|
|
74
|
+
else
|
|
75
|
+
yield out_lines, error_lines,status.exitstatus
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def print_console(str)
|
|
80
|
+
run_shell "echo #{str}"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def logInner(color_code,text)
|
|
84
|
+
clolr="\033[#{color_code}m"
|
|
85
|
+
nc="\033[0m"
|
|
86
|
+
puts "#{clolr}#{text}#{nc}"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# 打印不同级别的 log。根据级别不同,样式(颜色)不同
|
|
90
|
+
def logE(text)
|
|
91
|
+
logInner '31',"[ERROR] !!#{text}"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def logW(text)
|
|
95
|
+
logInner '33',"[WARNING] #{text}"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def logN(text)
|
|
99
|
+
logInner '32',"[NOTE] #{text}"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def logC(text)
|
|
103
|
+
logInner '34',"[COMMAND] #{text}"
|
|
104
|
+
end
|
|
105
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
ROOT = Pathname.new(File.expand_path('../../', __FILE__))
|
|
3
|
+
$:.unshift((ROOT + 'lib').to_s)
|
|
4
|
+
$:.unshift((ROOT + 'spec').to_s)
|
|
5
|
+
|
|
6
|
+
require 'bundler/setup'
|
|
7
|
+
require 'bacon'
|
|
8
|
+
require 'mocha-on-bacon'
|
|
9
|
+
require 'pretty_bacon'
|
|
10
|
+
require 'pathname'
|
|
11
|
+
require 'cocoapods'
|
|
12
|
+
|
|
13
|
+
Mocha::Configuration.prevent(:stubbing_non_existent_method)
|
|
14
|
+
|
|
15
|
+
require 'cocoapods_plugin'
|
|
16
|
+
|
|
17
|
+
#-----------------------------------------------------------------------------#
|
|
18
|
+
|
|
19
|
+
module Pod
|
|
20
|
+
|
|
21
|
+
# Disable the wrapping so the output is deterministic in the tests.
|
|
22
|
+
#
|
|
23
|
+
UI.disable_wrap = true
|
|
24
|
+
|
|
25
|
+
# Redirects the messages to an internal store.
|
|
26
|
+
#
|
|
27
|
+
module UI
|
|
28
|
+
@output = ''
|
|
29
|
+
@warnings = ''
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
attr_accessor :output
|
|
33
|
+
attr_accessor :warnings
|
|
34
|
+
|
|
35
|
+
def puts(message = '')
|
|
36
|
+
@output << "#{message}\n"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def warn(message = '', actions = [])
|
|
40
|
+
@warnings << "#{message}\n"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def print(message)
|
|
44
|
+
@output << message
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
#-----------------------------------------------------------------------------#
|
metadata
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: deal
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- kyle.zhou
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2021-02-05 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.3'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.3'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
description: A short description of deal.
|
|
42
|
+
email:
|
|
43
|
+
- kyle.zhou@qq.com
|
|
44
|
+
executables:
|
|
45
|
+
- deal
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- ".gitignore"
|
|
50
|
+
- Gemfile
|
|
51
|
+
- LICENSE.txt
|
|
52
|
+
- README.md
|
|
53
|
+
- Rakefile
|
|
54
|
+
- bin/deal
|
|
55
|
+
- deal.gemspec
|
|
56
|
+
- lib/deal.rb
|
|
57
|
+
- lib/deal/command.rb
|
|
58
|
+
- lib/deal/command/text.rb
|
|
59
|
+
- lib/deal/gem_version.rb
|
|
60
|
+
- lib/deal/utils/deal_config.rb
|
|
61
|
+
- lib/deal/utils/utils.rb
|
|
62
|
+
- spec/command/thin_spec.rb
|
|
63
|
+
- spec/spec_helper.rb
|
|
64
|
+
homepage: https://github.com/EXAMPLE/deal
|
|
65
|
+
licenses:
|
|
66
|
+
- MIT
|
|
67
|
+
metadata: {}
|
|
68
|
+
post_install_message:
|
|
69
|
+
rdoc_options: []
|
|
70
|
+
require_paths:
|
|
71
|
+
- lib
|
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
requirements: []
|
|
83
|
+
rubygems_version: 3.0.8
|
|
84
|
+
signing_key:
|
|
85
|
+
specification_version: 4
|
|
86
|
+
summary: A longer description of deal.
|
|
87
|
+
test_files: []
|