lhj-tools 0.1.0
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/.github/workflows/main.yml +16 -0
- data/.gitignore +12 -0
- data/.idea/dictionaries +6 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +78 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/lhj +6 -0
- data/bin/setup +8 -0
- data/lhj-tools.gemspec +41 -0
- data/lib/lhj/command/rename_image.rb +18 -0
- data/lib/lhj/command/trans.rb +21 -0
- data/lib/lhj/command/view.rb +148 -0
- data/lib/lhj/command/yapi.rb +303 -0
- data/lib/lhj/command.rb +13 -0
- data/lib/lhj/config.rb +365 -0
- data/lib/lhj/tools/version.rb +7 -0
- data/lib/lhj/tools.rb +11 -0
- metadata +234 -0
@@ -0,0 +1,303 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
module Lhj
|
7
|
+
class Command
|
8
|
+
class Yapi < Command
|
9
|
+
self.summary = '通过yapi接口生成请求'
|
10
|
+
|
11
|
+
def self.options
|
12
|
+
[
|
13
|
+
%w[--id api的id],
|
14
|
+
%w[--model-pre 模型的前缀],
|
15
|
+
%w[--save 保存生成文件]
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(argv)
|
20
|
+
@id = argv.option('id')
|
21
|
+
@model_pre_name = argv.option('model-pre')
|
22
|
+
@save = argv.flag?('save', false)
|
23
|
+
@http_url = ''
|
24
|
+
@http_headers = []
|
25
|
+
@data_json = {}
|
26
|
+
@models = []
|
27
|
+
@config_id = ''
|
28
|
+
@config_model_pre = 'ML'
|
29
|
+
@model_default_suffix = 'Model'
|
30
|
+
@type_trans = {}
|
31
|
+
@config_model_names = []
|
32
|
+
@model_names = []
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
load_config
|
38
|
+
fetch_model
|
39
|
+
print_methods
|
40
|
+
save_to_file if @save
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_ding
|
44
|
+
require 'net/http'
|
45
|
+
require 'uri'
|
46
|
+
body = { "msgtype" => "text", "text" => { "content" => "error:上传蒲公英超时失败!" } }.to_json
|
47
|
+
Net::HTTP.post(URI('https://oapi.dingtalk.com/robot/send?access_token=6a3519057170cdb1b7274edfe43934c84a0062ffe2c9bcced434699296a7e26e'), body, "Content-Type" => "application/json")
|
48
|
+
end
|
49
|
+
|
50
|
+
def puts_h(str)
|
51
|
+
puts str
|
52
|
+
@h_file_array ||= []
|
53
|
+
@h_file_array << str
|
54
|
+
end
|
55
|
+
|
56
|
+
def puts_m(str)
|
57
|
+
puts str
|
58
|
+
@m_file_array ||= []
|
59
|
+
@m_file_array << str
|
60
|
+
end
|
61
|
+
|
62
|
+
def save_to_file
|
63
|
+
@model_names = []
|
64
|
+
file_name = gen_model_name('')
|
65
|
+
h_file = File.join('.', "#{file_name}.h")
|
66
|
+
m_file = File.join('.', "#{file_name}.m")
|
67
|
+
File.write(h_file, @h_file_array.join("\n")) if @h_file_array.count > 0
|
68
|
+
File.write(m_file, @m_file_array.join("\n")) if @m_file_array.count > 0
|
69
|
+
puts "\n\n生成文件成功!所在路径:\n#{File.expand_path(h_file)} \n#{File.expand_path(m_file)}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def url_str
|
73
|
+
"#{@http_url}#{api_id}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def load_config
|
77
|
+
yml = File.join(Lhj::Config.instance.home_dir, 'yapi.yml')
|
78
|
+
config = YAML.load_file(yml)
|
79
|
+
config.each do |k, v|
|
80
|
+
@http_headers << "#{k}=#{v}" if (k.eql?('__wpkreporterwid_') || k.eql?('_yapi_token') || k.eql?('_yapi_uid'))
|
81
|
+
end
|
82
|
+
@http_url = config['url']
|
83
|
+
@config_id = config['id']
|
84
|
+
@config_model_pre = config['model_pre']
|
85
|
+
@config_model_suffix = config['model_suffix']
|
86
|
+
@config_model_names = config['model_names']
|
87
|
+
@type_trans = config['type_trans']
|
88
|
+
end
|
89
|
+
|
90
|
+
def api_id
|
91
|
+
@id || @config_id.to_s
|
92
|
+
end
|
93
|
+
|
94
|
+
def model_pre
|
95
|
+
@model_pre_name || @config_model_pre
|
96
|
+
end
|
97
|
+
|
98
|
+
def model_suffix
|
99
|
+
@config_model_suffix || @model_default_suffix
|
100
|
+
end
|
101
|
+
|
102
|
+
def req_model
|
103
|
+
uri = URI.parse(url_str)
|
104
|
+
req = Net::HTTP::Get.new(uri)
|
105
|
+
req['Cookie'] = @http_headers.join('; ')
|
106
|
+
res = Net::HTTP.start(uri.hostname, uri.port) do |http|
|
107
|
+
http.request(req)
|
108
|
+
end
|
109
|
+
puts res.body
|
110
|
+
JSON.parse(res.body)
|
111
|
+
end
|
112
|
+
|
113
|
+
def fetch_model
|
114
|
+
res_json = req_model
|
115
|
+
begin
|
116
|
+
puts "\n<===============打印返回数据模型-Begin=====================>\n"
|
117
|
+
fetch_res_boy(res_json)
|
118
|
+
print_models
|
119
|
+
print_models_implementation
|
120
|
+
puts "\n<===============打印返回数据模型-End=====================>\n"
|
121
|
+
end
|
122
|
+
begin
|
123
|
+
puts "\n<===============打印请求模型-Begin=====================>\n"
|
124
|
+
@models = []
|
125
|
+
@model_names = []
|
126
|
+
fetch_req_body(res_json)
|
127
|
+
print_models
|
128
|
+
print_models_implementation
|
129
|
+
puts "\n<===============打印请求模型-End=====================>\n"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def fetch_res_boy(res_json)
|
134
|
+
if res_json && res_json['data']
|
135
|
+
@data_json = res_json['data']
|
136
|
+
if @data_json['res_body']
|
137
|
+
begin
|
138
|
+
res_body = JSON.parse(@data_json['res_body'])
|
139
|
+
detail_obj = res_body['properties']['detailMsg'] || {}
|
140
|
+
detail_obj['name'] = gen_model_name('')
|
141
|
+
handle_model(detail_obj)
|
142
|
+
rescue => ex
|
143
|
+
puts ex
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def fetch_req_body(res_json)
|
150
|
+
if res_json && res_json['data']
|
151
|
+
@data_json = res_json['data']
|
152
|
+
if @data_json['req_body_other']
|
153
|
+
begin
|
154
|
+
res_body = JSON.parse(@data_json['req_body_other'])
|
155
|
+
res_body['name'] = gen_model_name('')
|
156
|
+
handle_model(res_body)
|
157
|
+
rescue => ex
|
158
|
+
puts ex
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def gen_model_name(name)
|
165
|
+
n = name.gsub(/vo|model|list/i, '').gsub(/(.*)s$/, '\1').gsub(/^\w/) { $&.upcase }
|
166
|
+
if n.length <= 0
|
167
|
+
n = @config_model_names.detect { |c| !@model_names.any? { |n| n.gsub(/#{model_pre}(.*)Model/, '\1').eql?(c) } }
|
168
|
+
end
|
169
|
+
model_name = "#{model_pre}#{n}#{model_suffix}"
|
170
|
+
@model_names << model_name
|
171
|
+
model_name
|
172
|
+
end
|
173
|
+
|
174
|
+
def handle_model(model)
|
175
|
+
p_type = model['type']
|
176
|
+
p_name = model['name']
|
177
|
+
p_properties = model['properties']
|
178
|
+
p_model = { name: p_name }
|
179
|
+
|
180
|
+
properties = []
|
181
|
+
if p_type.eql?('object')
|
182
|
+
p_properties.each do |k, v|
|
183
|
+
c_type = @type_trans[v['type']] || v['type']
|
184
|
+
c_model = { key: k, type: c_type, description: v['description'], default: '' }
|
185
|
+
if v['type'].eql?('object') || v['type'].eql?('array')
|
186
|
+
o = v['items'] || v
|
187
|
+
o['name'] = gen_model_name(k)
|
188
|
+
if v['type'].eql?('array') && v['items']['type'].eql?('string')
|
189
|
+
c_model[:type_name] = "NSString"
|
190
|
+
else
|
191
|
+
c_model[:type_name] = o['name']
|
192
|
+
handle_model(o)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
properties << c_model
|
196
|
+
end
|
197
|
+
p_model[:properties] = properties
|
198
|
+
@models << p_model
|
199
|
+
elsif p_type.eql?('array')
|
200
|
+
t = model['items']
|
201
|
+
t['name'] = p_name
|
202
|
+
handle_model(t)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def print_models
|
207
|
+
@models.each do |model|
|
208
|
+
model_name = model[:name] || ''
|
209
|
+
model_properties = model[:properties]
|
210
|
+
puts_h "@interface #{model_name} : NSObject"
|
211
|
+
model_properties.each do |m|
|
212
|
+
print_model(m)
|
213
|
+
end
|
214
|
+
puts_h "@end\n\n\n"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def print_models_implementation
|
219
|
+
@models.each do |model|
|
220
|
+
puts_m "@implementation #{model[:name]}"
|
221
|
+
str = model[:properties].filter { |p| p[:type].eql?('array') && !p[:type_name].eql?('NSString') }.map { |p| "@\"#{p[:key]}\": #{p[:type_name]}.class" }.join(', ')
|
222
|
+
if str && str.length > 0
|
223
|
+
puts_m "+(NSDictionary *)modelContainerPropertyGenericClass {"
|
224
|
+
puts_m " return @{#{str}};"
|
225
|
+
puts_m "}"
|
226
|
+
end
|
227
|
+
puts_m "@end\n"
|
228
|
+
puts "\n\n"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def print_model(m)
|
233
|
+
key = m[:key]
|
234
|
+
type_name = m[:type_name]
|
235
|
+
type = m[:type]
|
236
|
+
des = m[:description] || ''
|
237
|
+
des.gsub!(/\n/, ' ')
|
238
|
+
default = m[:default]
|
239
|
+
puts_h "///#{des} #{default}"
|
240
|
+
if type.eql?('integer')
|
241
|
+
puts_h "@property (nonatomic, assign) NSInteger #{key};"
|
242
|
+
if des.include?('分')
|
243
|
+
puts_h "/////////==========删掉其中一个属性"
|
244
|
+
puts_h "@property (nonatomic, strong) MLCentNumber *#{key};"
|
245
|
+
end
|
246
|
+
elsif type.eql?('cent')
|
247
|
+
puts_h "@property (nonatomic, strong) MLCentNumber *#{key};"
|
248
|
+
elsif type.eql?('string')
|
249
|
+
puts_h "@property (nonatomic, copy) NSString *#{key};"
|
250
|
+
elsif type.eql?('number')
|
251
|
+
puts_h "@property (nonatomic, strong) NSNumber *#{key};"
|
252
|
+
elsif type.eql?('float')
|
253
|
+
puts_h "@property (nonatomic, assign) CGFloat #{key};"
|
254
|
+
elsif type.eql?('double')
|
255
|
+
puts_h "@property (nonatomic, assign) double #{key};"
|
256
|
+
elsif type.eql?('boolean')
|
257
|
+
puts_h "@property (nonatomic, assign) BOOL #{key};"
|
258
|
+
elsif type.eql?('object')
|
259
|
+
puts_h "@property (nonatomic, strong) #{type_name} *#{key};"
|
260
|
+
elsif type.eql?('array')
|
261
|
+
puts_h "@property (nonatomic, strong) NSArray<#{type_name} *> *#{key};"
|
262
|
+
else
|
263
|
+
puts_h "@property (nonatomic, copy) NSString *#{key};"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def print_methods
|
268
|
+
puts "\n<===============方法调用=====================>\n"
|
269
|
+
puts_m "/**"
|
270
|
+
puts_m " * #{@data_json['title']} -- #{@data_json['username']}"
|
271
|
+
puts_m " */"
|
272
|
+
key_str = @data_json['path'].split('/').map { |s| s.gsub(/[^A-Za-z0-9]/, '').gsub(/^\w/) { $&.upcase } }.join('')
|
273
|
+
key = "k#{key_str}URL"
|
274
|
+
puts_m "static NSString * const #{key} = @\"#{@data_json['path']}\";"
|
275
|
+
puts_m "\n\n"
|
276
|
+
puts_h "@interface MLParamModel : NSObject"
|
277
|
+
@data_json['req_query'].each do |h|
|
278
|
+
des = h['desc']
|
279
|
+
puts_h "///#{des} #{h['example']}"
|
280
|
+
puts_h "@property (nonatomic, copy) NSString *#{h['name']};"
|
281
|
+
end
|
282
|
+
puts_h "@end"
|
283
|
+
puts "\n\n"
|
284
|
+
model = @models.last
|
285
|
+
if @data_json['method'].eql?('GET')
|
286
|
+
puts_m " [MLNetworkingManager getWithUrl:#{key} params:nil response:^(MLResponseMessage *responseMessage) {"
|
287
|
+
puts_m " if (response.resultCode == 0 && !response.error){"
|
288
|
+
puts_m " NSDictionary *detailMsg = response.detailMsg"
|
289
|
+
puts_m " #{model[:name]} *model = [#{model[:name]} yy_modelWithDictionary:detailMsg];" if model
|
290
|
+
puts_m " }"
|
291
|
+
puts_m " }];"
|
292
|
+
else
|
293
|
+
puts_m " [MLNetworkingManager postWithUrl:#{key} params:nil response:^(MLResponseMessage *responseMessage) {"
|
294
|
+
puts_m " if (response.resultCode == 0 && !response.error){"
|
295
|
+
puts_m " NSDictionary *detailMsg = response.detailMsg"
|
296
|
+
puts_m " #{model[:name]} *model = [#{model[:name]} yy_modelWithDictionary:detailMsg];" if model
|
297
|
+
puts_m " }"
|
298
|
+
puts_m " }];"
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
data/lib/lhj/command.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'claide'
|
2
|
+
|
3
|
+
module Lhj
|
4
|
+
class Command < CLAide::Command
|
5
|
+
require 'lhj/command/view'
|
6
|
+
require 'lhj/command/rename_image'
|
7
|
+
require 'lhj/command/trans'
|
8
|
+
require 'lhj/command/yapi'
|
9
|
+
|
10
|
+
self.abstract_command = true
|
11
|
+
self.command = 'lhj'
|
12
|
+
end
|
13
|
+
end
|
data/lib/lhj/config.rb
ADDED
@@ -0,0 +1,365 @@
|
|
1
|
+
|
2
|
+
module Lhj
|
3
|
+
# Stores the global configuration of CocoaPods.
|
4
|
+
#
|
5
|
+
class Config
|
6
|
+
# The default settings for the configuration.
|
7
|
+
#
|
8
|
+
# Users can specify custom settings in `~/.cocoapods/config.yaml`.
|
9
|
+
# An example of the contents of this file might look like:
|
10
|
+
#
|
11
|
+
# ---
|
12
|
+
# skip_repo_update: true
|
13
|
+
# new_version_message: false
|
14
|
+
#
|
15
|
+
DEFAULTS = {
|
16
|
+
:verbose => false,
|
17
|
+
:silent => false,
|
18
|
+
:skip_download_cache => !ENV['COCOAPODS_SKIP_CACHE'].nil?,
|
19
|
+
|
20
|
+
:new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?,
|
21
|
+
|
22
|
+
:cache_root => Pathname.new(Dir.home) + 'Library/Caches/CocoaPods',
|
23
|
+
}
|
24
|
+
|
25
|
+
# Applies the given changes to the config for the duration of the given
|
26
|
+
# block.
|
27
|
+
#
|
28
|
+
# @param [Hash<#to_sym,Object>] changes
|
29
|
+
# the changes to merge temporarily with the current config
|
30
|
+
#
|
31
|
+
# @yield [] is called while the changes are applied
|
32
|
+
#
|
33
|
+
def with_changes(changes)
|
34
|
+
old = {}
|
35
|
+
changes.keys.each do |key|
|
36
|
+
key = key.to_sym
|
37
|
+
old[key] = send(key) if respond_to?(key)
|
38
|
+
end
|
39
|
+
configure_with(changes)
|
40
|
+
yield if block_given?
|
41
|
+
ensure
|
42
|
+
configure_with(old)
|
43
|
+
end
|
44
|
+
|
45
|
+
public
|
46
|
+
|
47
|
+
#-------------------------------------------------------------------------#
|
48
|
+
|
49
|
+
# @!group UI
|
50
|
+
|
51
|
+
# @return [Boolean] Whether CocoaPods should provide detailed output about the
|
52
|
+
# performed actions.
|
53
|
+
#
|
54
|
+
attr_accessor :verbose
|
55
|
+
alias_method :verbose?, :verbose
|
56
|
+
|
57
|
+
# @return [Boolean] Whether CocoaPods should produce not output.
|
58
|
+
#
|
59
|
+
attr_accessor :silent
|
60
|
+
alias_method :silent?, :silent
|
61
|
+
|
62
|
+
# @return [Boolean] Whether CocoaPods is allowed to run as root.
|
63
|
+
#
|
64
|
+
attr_accessor :allow_root
|
65
|
+
alias_method :allow_root?, :allow_root
|
66
|
+
|
67
|
+
# @return [Boolean] Whether a message should be printed when a new version of
|
68
|
+
# CocoaPods is available.
|
69
|
+
#
|
70
|
+
attr_accessor :new_version_message
|
71
|
+
alias_method :new_version_message?, :new_version_message
|
72
|
+
|
73
|
+
#-------------------------------------------------------------------------#
|
74
|
+
|
75
|
+
# @!group Installation
|
76
|
+
|
77
|
+
# @return [Boolean] Whether the installer should skip the download cache.
|
78
|
+
#
|
79
|
+
attr_accessor :skip_download_cache
|
80
|
+
alias_method :skip_download_cache?, :skip_download_cache
|
81
|
+
|
82
|
+
public
|
83
|
+
|
84
|
+
#-------------------------------------------------------------------------#
|
85
|
+
|
86
|
+
# @!group Cache
|
87
|
+
|
88
|
+
# @return [Pathname] The directory where CocoaPods should cache remote data
|
89
|
+
# and other expensive to compute information.
|
90
|
+
#
|
91
|
+
attr_accessor :cache_root
|
92
|
+
|
93
|
+
def cache_root
|
94
|
+
@cache_root.mkpath unless @cache_root.exist?
|
95
|
+
@cache_root
|
96
|
+
end
|
97
|
+
|
98
|
+
public
|
99
|
+
|
100
|
+
#-------------------------------------------------------------------------#
|
101
|
+
|
102
|
+
# @!group Initialization
|
103
|
+
|
104
|
+
def initialize(use_user_settings = true)
|
105
|
+
configure_with(DEFAULTS)
|
106
|
+
|
107
|
+
unless ENV['CP_HOME_DIR'].nil?
|
108
|
+
@cache_root = home_dir + 'cache'
|
109
|
+
end
|
110
|
+
|
111
|
+
if use_user_settings && user_settings_file.exist?
|
112
|
+
require 'yaml'
|
113
|
+
user_settings = YAML.load_file(user_settings_file)
|
114
|
+
configure_with(user_settings)
|
115
|
+
end
|
116
|
+
|
117
|
+
unless ENV['CP_CACHE_DIR'].nil?
|
118
|
+
@cache_root = Pathname.new(ENV['CP_CACHE_DIR']).expand_path
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def verbose
|
123
|
+
@verbose && !silent
|
124
|
+
end
|
125
|
+
|
126
|
+
public
|
127
|
+
|
128
|
+
#-------------------------------------------------------------------------#
|
129
|
+
|
130
|
+
# @!group Paths
|
131
|
+
|
132
|
+
# @return [Pathname] the directory where repos, templates and configuration
|
133
|
+
# files are stored.
|
134
|
+
#
|
135
|
+
def home_dir
|
136
|
+
@home_dir ||= Pathname.new(ENV['CP_HOME_DIR'] || '~/.lhj').expand_path
|
137
|
+
end
|
138
|
+
|
139
|
+
# @return [Pathname] the directory where the CocoaPods sources are stored.
|
140
|
+
#
|
141
|
+
def repos_dir
|
142
|
+
@repos_dir ||= Pathname.new(ENV['CP_REPOS_DIR'] || (home_dir + 'repos')).expand_path
|
143
|
+
end
|
144
|
+
|
145
|
+
attr_writer :repos_dir
|
146
|
+
|
147
|
+
# @return [Source::Manager] the source manager for the spec repos in `repos_dir`
|
148
|
+
#
|
149
|
+
def sources_manager
|
150
|
+
return @sources_manager if @sources_manager && @sources_manager.repos_dir == repos_dir
|
151
|
+
@sources_manager = Source::Manager.new(repos_dir)
|
152
|
+
end
|
153
|
+
|
154
|
+
# @return [Pathname] the directory where the CocoaPods templates are stored.
|
155
|
+
#
|
156
|
+
def templates_dir
|
157
|
+
@templates_dir ||= Pathname.new(ENV['CP_TEMPLATES_DIR'] || (home_dir + 'templates')).expand_path
|
158
|
+
end
|
159
|
+
|
160
|
+
# @return [Pathname] the root of the CocoaPods installation where the
|
161
|
+
# Podfile is located.
|
162
|
+
#
|
163
|
+
def installation_root
|
164
|
+
@installation_root ||= begin
|
165
|
+
current_dir = Pathname.new(Dir.pwd.unicode_normalize(:nfkc))
|
166
|
+
current_path = current_dir
|
167
|
+
until current_path.root?
|
168
|
+
if podfile_path_in_dir(current_path)
|
169
|
+
installation_root = current_path
|
170
|
+
unless current_path == current_dir
|
171
|
+
UI.puts("[in #{current_path}]")
|
172
|
+
end
|
173
|
+
break
|
174
|
+
else
|
175
|
+
current_path = current_path.parent
|
176
|
+
end
|
177
|
+
end
|
178
|
+
installation_root || current_dir
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
attr_writer :installation_root
|
183
|
+
alias_method :project_root, :installation_root
|
184
|
+
|
185
|
+
# @return [Pathname] The root of the sandbox.
|
186
|
+
#
|
187
|
+
def sandbox_root
|
188
|
+
@sandbox_root ||= installation_root + 'Pods'
|
189
|
+
end
|
190
|
+
|
191
|
+
attr_writer :sandbox_root
|
192
|
+
alias_method :project_pods_root, :sandbox_root
|
193
|
+
|
194
|
+
# @return [Sandbox] The sandbox of the current project.
|
195
|
+
#
|
196
|
+
def sandbox
|
197
|
+
@sandbox ||= Sandbox.new(sandbox_root)
|
198
|
+
end
|
199
|
+
|
200
|
+
# @return [Podfile] The Podfile to use for the current execution.
|
201
|
+
# @return [Nil] If no Podfile is available.
|
202
|
+
#
|
203
|
+
def podfile
|
204
|
+
@podfile ||= Podfile.from_file(podfile_path) if podfile_path
|
205
|
+
end
|
206
|
+
attr_writer :podfile
|
207
|
+
|
208
|
+
# @return [Lockfile] The Lockfile to use for the current execution.
|
209
|
+
# @return [Nil] If no Lockfile is available.
|
210
|
+
#
|
211
|
+
def lockfile
|
212
|
+
@lockfile ||= Lockfile.from_file(lockfile_path) if lockfile_path
|
213
|
+
end
|
214
|
+
|
215
|
+
# Returns the path of the Podfile.
|
216
|
+
#
|
217
|
+
# @note The Podfile can be named either `CocoaPods.podfile.yaml`,
|
218
|
+
# `CocoaPods.podfile` or `Podfile`. The first two are preferred as
|
219
|
+
# they allow to specify an OS X UTI.
|
220
|
+
#
|
221
|
+
# @return [Pathname]
|
222
|
+
# @return [Nil]
|
223
|
+
#
|
224
|
+
def podfile_path
|
225
|
+
@podfile_path ||= podfile_path_in_dir(installation_root)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Returns the path of the Lockfile.
|
229
|
+
#
|
230
|
+
# @note The Lockfile is named `Podfile.lock`.
|
231
|
+
#
|
232
|
+
def lockfile_path
|
233
|
+
@lockfile_path ||= installation_root + 'Podfile.lock'
|
234
|
+
end
|
235
|
+
|
236
|
+
# Returns the path of the default Podfile pods.
|
237
|
+
#
|
238
|
+
# @note The file is expected to be named Podfile.default
|
239
|
+
#
|
240
|
+
# @return [Pathname]
|
241
|
+
#
|
242
|
+
def default_podfile_path
|
243
|
+
@default_podfile_path ||= templates_dir + 'Podfile.default'
|
244
|
+
end
|
245
|
+
|
246
|
+
# Returns the path of the default Podfile test pods.
|
247
|
+
#
|
248
|
+
# @note The file is expected to be named Podfile.test
|
249
|
+
#
|
250
|
+
# @return [Pathname]
|
251
|
+
#
|
252
|
+
def default_test_podfile_path
|
253
|
+
@default_test_podfile_path ||= templates_dir + 'Podfile.test'
|
254
|
+
end
|
255
|
+
|
256
|
+
# @return [Pathname] The file to use to cache the search data.
|
257
|
+
#
|
258
|
+
def search_index_file
|
259
|
+
cache_root + 'search_index.json'
|
260
|
+
end
|
261
|
+
|
262
|
+
private
|
263
|
+
|
264
|
+
#-------------------------------------------------------------------------#
|
265
|
+
|
266
|
+
# @!group Private helpers
|
267
|
+
|
268
|
+
# @return [Pathname] The path of the file which contains the user settings.
|
269
|
+
#
|
270
|
+
def user_settings_file
|
271
|
+
home_dir + 'config.yaml'
|
272
|
+
end
|
273
|
+
|
274
|
+
# Sets the values of the attributes with the given hash.
|
275
|
+
#
|
276
|
+
# @param [Hash{String,Symbol => Object}] values_by_key
|
277
|
+
# The values of the attributes grouped by key.
|
278
|
+
#
|
279
|
+
# @return [void]
|
280
|
+
#
|
281
|
+
def configure_with(values_by_key)
|
282
|
+
return unless values_by_key
|
283
|
+
values_by_key.each do |key, value|
|
284
|
+
if key.to_sym == :cache_root
|
285
|
+
value = Pathname.new(value).expand_path
|
286
|
+
end
|
287
|
+
instance_variable_set("@#{key}", value)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# @return [Array<String>] The filenames that the Podfile can have ordered
|
292
|
+
# by priority.
|
293
|
+
#
|
294
|
+
PODFILE_NAMES = [
|
295
|
+
'CocoaPods.podfile.yaml',
|
296
|
+
'CocoaPods.podfile',
|
297
|
+
'Podfile',
|
298
|
+
'Podfile.rb',
|
299
|
+
].freeze
|
300
|
+
|
301
|
+
public
|
302
|
+
|
303
|
+
# Returns the path of the Podfile in the given dir if any exists.
|
304
|
+
#
|
305
|
+
# @param [Pathname] dir
|
306
|
+
# The directory where to look for the Podfile.
|
307
|
+
#
|
308
|
+
# @return [Pathname] The path of the Podfile.
|
309
|
+
# @return [Nil] If not Podfile was found in the given dir
|
310
|
+
#
|
311
|
+
def podfile_path_in_dir(dir)
|
312
|
+
PODFILE_NAMES.each do |filename|
|
313
|
+
candidate = dir + filename
|
314
|
+
if candidate.file?
|
315
|
+
return candidate
|
316
|
+
end
|
317
|
+
end
|
318
|
+
nil
|
319
|
+
end
|
320
|
+
|
321
|
+
# Excludes the given dir from Time Machine backups.
|
322
|
+
#
|
323
|
+
# @param [Pathname] dir
|
324
|
+
# The directory to exclude from Time Machine backups.
|
325
|
+
#
|
326
|
+
# @return [void]
|
327
|
+
#
|
328
|
+
def exclude_from_backup(dir)
|
329
|
+
return if Gem.win_platform?
|
330
|
+
system('tmutil', 'addexclusion', dir.to_s, %i(out err) => File::NULL)
|
331
|
+
end
|
332
|
+
|
333
|
+
public
|
334
|
+
|
335
|
+
#-------------------------------------------------------------------------#
|
336
|
+
|
337
|
+
# @!group Singleton
|
338
|
+
|
339
|
+
# @return [Config] the current config instance creating one if needed.
|
340
|
+
#
|
341
|
+
def self.instance
|
342
|
+
@instance ||= new
|
343
|
+
end
|
344
|
+
|
345
|
+
# Sets the current config instance. If set to nil the config will be
|
346
|
+
# recreated when needed.
|
347
|
+
#
|
348
|
+
# @param [Config, Nil] the instance.
|
349
|
+
#
|
350
|
+
# @return [void]
|
351
|
+
#
|
352
|
+
class << self
|
353
|
+
attr_writer :instance
|
354
|
+
end
|
355
|
+
|
356
|
+
# Provides support for accessing the configuration instance in other
|
357
|
+
# scopes.
|
358
|
+
#
|
359
|
+
module Mixin
|
360
|
+
def config
|
361
|
+
Config.instance
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|