fir-cli 0.2.3.1 → 1.0.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 +4 -4
- data/.gitignore +13 -82
- data/CHANGELOG +36 -0
- data/Gemfile +3 -1
- data/LICENSE.txt +1 -1
- data/README.md +83 -103
- data/Rakefile +1 -0
- data/bin/fir +9 -11
- data/fir-cli.gemspec +47 -26
- data/lib/fir/api.yml +5 -0
- data/lib/fir/cli.rb +107 -0
- data/lib/fir/patches/bin/pngcrush +0 -0
- data/lib/fir/patches/native_patch.rb +199 -0
- data/lib/fir/patches/os_patch.rb +22 -0
- data/lib/fir/patches/parser_patch.rb +165 -0
- data/lib/fir/patches.rb +5 -0
- data/lib/fir/util/build.rb +158 -0
- data/lib/fir/util/info.rb +79 -0
- data/lib/fir/util/login.rb +17 -0
- data/lib/fir/util/publish.rb +103 -0
- data/lib/fir/util.rb +45 -0
- data/lib/fir/version.rb +5 -0
- data/lib/fir-cli.rb +3 -0
- data/lib/fir.rb +87 -0
- data/lib/fir_cli.rb +3 -0
- metadata +57 -109
- data/Gemfile.lock +0 -45
- data/fir-cli.rb +0 -27
- data/lib/fir-cli/version.rb +0 -5
- data/lib/fir-cli-commands/00-info.rb +0 -17
- data/lib/fir-cli-commands/00-login.rb +0 -30
- data/lib/fir-cli-commands/00-profile.rb +0 -31
- data/lib/fir-cli-commands/00-upgrade.rb +0 -15
- data/lib/fir-cli-commands/00-version.rb +0 -10
- data/lib/fir-cli-commands/01-config.rb +0 -17
- data/lib/fir-cli-commands/100-resign_codesign.rb +0 -59
- data/lib/fir-cli-commands/100-resign_tapbeta.rb +0 -85
- data/lib/fir-cli-commands/101-resign.rb +0 -26
- data/lib/fir-cli-commands/11-publish.rb +0 -73
- data/lib/fir-cli-commands/12-build_ipa.rb +0 -153
- data/lib/fir-cli.chk.rb +0 -33
- data/lib/fir-cli.core.rb +0 -96
- data/lib/fir-cli.fir.rb +0 -49
- data/lib/fir-cli.opt.rb +0 -35
- data/lib/fir-cli.output.rb +0 -55
- data/lib/fir-cli.utils.rb +0 -108
- data/lib/lagunitas.ext.rb +0 -56
- data/lib/lagunitas.patch.rb +0 -51
- data/lib/user_config.patch.rb +0 -10
@@ -1,15 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
module Fir
|
3
|
-
class Cli
|
4
|
-
desc 'upgrade', '更新 fir-cli 的所有组件'
|
5
|
-
output_options
|
6
|
-
def upgrade
|
7
|
-
_puts '> gem update fir-cli'
|
8
|
-
`gem update fir-cli`
|
9
|
-
_extends.each do |gem|
|
10
|
-
_puts "> gem update #{gem}"
|
11
|
-
`gem update #{gem}`
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
module Fir
|
3
|
-
class Cli
|
4
|
-
desc 'config', '配置全局设置'
|
5
|
-
option :token, :aliases => '-t', :desc => '用户 token'
|
6
|
-
option :email, :aliases => '-e', :desc => '邮件地址'
|
7
|
-
# option :resign, :aliases => '-r', :desc => '是否以企业签名发布 ios 应用', :type => :boolean
|
8
|
-
option :private_key, :desc => '私密通道'
|
9
|
-
option :publish, :aliases => '-p', :desc => '编译打包自动发布至 FIR.im', :type => :boolean
|
10
|
-
output_options
|
11
|
-
def config(*args)
|
12
|
-
_set_config options.merge _convert_settings *args
|
13
|
-
_puts '> 设置完成,您现在使用的设置是'
|
14
|
-
@config.each { |conf| _puts "> #{Paint[conf[0].to_s.rjust(10), :blue]} => #{conf[1]}" }
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# # coding: utf-8
|
2
|
-
# module Fir
|
3
|
-
# class Cli
|
4
|
-
# def self.resign_local_options
|
5
|
-
# option :mobile_provision,
|
6
|
-
# :aliases => '-m'
|
7
|
-
# option :sign,
|
8
|
-
# :aliases => '-s'
|
9
|
-
# end
|
10
|
-
# desc 'resign_codesign IPA_FILE_PATH OUTPUT_PATH', '使用 codesign 指令进行签名'
|
11
|
-
# resign_local_options
|
12
|
-
# output_options
|
13
|
-
# def resign_codesign(ipath, opath)
|
14
|
-
# _chk_os! 'mac'
|
15
|
-
# _chk_opt! :mobile_provision, :sign
|
16
|
-
# mp_path, sign_name = _opt :mobile_provision, :sign
|
17
|
-
# mp_path = _path mp_path
|
18
|
-
# ipath = _path ipath
|
19
|
-
# opath = _path opath
|
20
|
-
# opath += '.ipa' if !opath.to_s.end_with? '.ipa'
|
21
|
-
# _edit(ipath, opath) do |_d|
|
22
|
-
# Dir.chdir(_d) do
|
23
|
-
# apps = Dir['Payload/*.app']
|
24
|
-
# if apps.length != 1
|
25
|
-
# _puts "! #{Paint['输入文件不是一个合法的 ipa 文件', :red]}"
|
26
|
-
# _exit
|
27
|
-
# end
|
28
|
-
# app = apps[0]
|
29
|
-
# _puts "> 替换 mobile provision"
|
30
|
-
# mp_dest_path = "#{app}/embedded.mobileprovision"
|
31
|
-
# File.unlink mp_dest_path if File.file? mp_dest_path
|
32
|
-
# FileUtils.cp mp_path, mp_dest_path
|
33
|
-
# frmwrk_dir = "#{app}/Frameworks"
|
34
|
-
# if File.directory? frmwrk_dir
|
35
|
-
# _puts "> 重签名 dylibs"
|
36
|
-
# Dir["#{frmwrk_dir}/*.dylib"].each do |_dylib|
|
37
|
-
# _exec "codesign -f -s \"#{sign_name}\" \"#{_dylib}\""
|
38
|
-
# end
|
39
|
-
# _puts "> 重签名 frameworks"
|
40
|
-
# Dir["#{frmwrk_dir}/*.framework"].each do |_framework|
|
41
|
-
# _exec "codesign -f -s \"#{sign_name}\" \"#{_framework}\""
|
42
|
-
# end
|
43
|
-
# end
|
44
|
-
|
45
|
-
# plugin_dir = "#{app}/PlugIns"
|
46
|
-
# if File.directory? plugin_dir
|
47
|
-
# _puts "> 重签名 plugins"
|
48
|
-
# Dir["#{plugin_dir}/*"].each do |_plugin|
|
49
|
-
# _exec "codesign -f -s \"#{sign_name}\" \"#{_plugin}\""
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
# _puts "> 重签名 #{app}"
|
53
|
-
# _exec "codesign -f -s \"#{sign_name}\" \"#{app}\" --deep"
|
54
|
-
# end
|
55
|
-
# end
|
56
|
-
# end
|
57
|
-
# end
|
58
|
-
# end
|
59
|
-
|
@@ -1,85 +0,0 @@
|
|
1
|
-
# # coding: utf-8
|
2
|
-
# module Fir
|
3
|
-
# class Cli
|
4
|
-
# def self.resign_tapbeta_options
|
5
|
-
# option :email, :aliases => '-e', :desc => '邮件地址'
|
6
|
-
# option :private_key, :desc => '私密通道'
|
7
|
-
# end
|
8
|
-
# desc 'resign_tapbeta IPA_FILE_PATH OUTPUT_PATH', '使用 resign.tapbeta.com 进行企业签名'
|
9
|
-
# resign_tapbeta_options
|
10
|
-
# output_options
|
11
|
-
# def resign_tapbeta(ipath, opath)
|
12
|
-
# _puts "! #{Paint['resign.tapbeta.com 签名服务风险提示', :red]}"
|
13
|
-
# _puts '! tapbeta 无法保证签名证书的长期有效性,苹果随时可'
|
14
|
-
# _puts '! 能封杀他们的企业账号,所有由这个企业账号签发的证'
|
15
|
-
# _puts '! 书都会失效。你如果使用该网站提供的证书进行应用签'
|
16
|
-
# _puts "! 发,请注意:#{Paint['当证书失效后,所有通过已失效证书签名', :red ]}"
|
17
|
-
# _puts "! #{Paint['的应用都会无法正常运行;同时托管在 fir.im 的应用', :red ]}"
|
18
|
-
# _puts "! #{Paint['将无法正常安装。', :red ]}"
|
19
|
-
# if _opt_email == nil
|
20
|
-
# @email = _prompt '请输入你的邮件地址:'
|
21
|
-
# if !@email || @email.length == 0
|
22
|
-
# _puts "! #{Paint['你需要提供邮件地址才能使用 resign.tapbeta.com 的', :red]}"
|
23
|
-
# _puts "! #{Paint['签名服务, 请使用', :red]} fir config --email=EMAIL #{Paint['进行设', :red]}"
|
24
|
-
# _puts "! #{Paint['置', :red]}"
|
25
|
-
# _exit
|
26
|
-
# elsif !_is_email? @email
|
27
|
-
# _puts_invalid_email
|
28
|
-
# _exit
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
# if !_is_ipa? ipath
|
32
|
-
# _puts "! #{Paint['只能给以 ipa 为扩展名的文件签名', :red]}"
|
33
|
-
# _exit
|
34
|
-
# end
|
35
|
-
# _puts '> 正在申请上传令牌...'
|
36
|
-
# upload_res = RestClient.post 'http://api.resign.tapbeta.com/public/upload',
|
37
|
-
# :email => @email,
|
38
|
-
# :private_key => _opt_private_key,
|
39
|
-
# :file => File.basename(ipath)
|
40
|
-
# form = JSON.parse upload_res.body, :symbolize_names => true
|
41
|
-
# tapbeta = {}
|
42
|
-
# form.each do |f|
|
43
|
-
# if /^tb_/.match f[0]
|
44
|
-
# tapbeta[f[0]] = f[1]
|
45
|
-
# form.delete f[0]
|
46
|
-
# end
|
47
|
-
# end
|
48
|
-
# form[:file] = File.new Pathname.new(Dir.pwd).join(ipath).cleanpath, 'rb'
|
49
|
-
# _puts '> 正在上传...'
|
50
|
-
# res = RestClient.post tapbeta[:tb_upload_url], form
|
51
|
-
|
52
|
-
# # Upyun's notify is fucking, handle it specific
|
53
|
-
# # if tapbeta[:tb_upload_url].include? 'upyun'
|
54
|
-
# # RestClient.get "#{form[:'notify-url']}?#{URI.encode_www_form JSON.parse res.body}"
|
55
|
-
# # end
|
56
|
-
|
57
|
-
|
58
|
-
# _puts '> 正在排队...'
|
59
|
-
# nped = true
|
60
|
-
# info = {}
|
61
|
-
# loop do
|
62
|
-
# res = RestClient.get "http://api.resign.tapbeta.com/public/#{tapbeta[:tb_upload_key]}",
|
63
|
-
# :params => { :__mr => 'eyJ1cmwiOiIkKHVybCkiLCAicmVzaWduU3RhdHVzIjogIiQocmVzaWduU3RhdHVzKSIsICJzdGF0dXMiOiAiJChzdGF0dXMpIn0=' }
|
64
|
-
# info = JSON.parse res.body, :symbolize_names => true
|
65
|
-
# if nped && info[:resignStatus] == 'doing'
|
66
|
-
# _puts '> 正在签名...'
|
67
|
-
# nped = false
|
68
|
-
# end
|
69
|
-
# if info[:status] == 'error'
|
70
|
-
# _puts "! #{Paint['签名失败', :red]}"
|
71
|
-
# _exit
|
72
|
-
# elsif info[:status] == 'timeout'
|
73
|
-
# _puts "! #{Paint['签名超时', :red]}"
|
74
|
-
# _exit
|
75
|
-
# end
|
76
|
-
# break if info[:url] != ''
|
77
|
-
# sleep 5
|
78
|
-
# end
|
79
|
-
# opath = Pathname.new(Dir.pwd).join(opath).cleanpath
|
80
|
-
# _puts "> 正在下载到 #{opath}..."
|
81
|
-
# `curl #{info[:url]} -o #{opath} -s`
|
82
|
-
# end
|
83
|
-
# end
|
84
|
-
# end
|
85
|
-
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# # coding: utf-8
|
2
|
-
# module Fir
|
3
|
-
# class Cli
|
4
|
-
# def self.resign_options
|
5
|
-
# option :resign_type,
|
6
|
-
# :desc => '选择使用哪种方式进行重签名,默认使用 tapbeta'
|
7
|
-
# resign_tapbeta_options
|
8
|
-
# resign_local_options
|
9
|
-
# end
|
10
|
-
# desc 'resign ORIGINAL_IPA OUTPUT_IPA [--resign-type=codesign]', '使用指定类型的签名方式'
|
11
|
-
# resign_options
|
12
|
-
# output_options
|
13
|
-
# def resign(ipath, opath)
|
14
|
-
# if !options[:resign_type]
|
15
|
-
# resign_tapbeta ipath, opath
|
16
|
-
# else
|
17
|
-
# begin
|
18
|
-
# method("resign_#{options[:resign_type]}".to_sym).call ipath, opath
|
19
|
-
# rescue NameError => e
|
20
|
-
# _puts "! #{Paint["没有 resign_#{options[:resign_type]} 的重签名方式"]}"
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
# end
|
24
|
-
# end
|
25
|
-
# end
|
26
|
-
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
module Fir
|
3
|
-
class Cli
|
4
|
-
desc 'publish APP_FILE_PATH', '将应用文件发布至 FIR.im(支持 ipa 文件和 apk 文件)'
|
5
|
-
def self.publish_options
|
6
|
-
# option :resign, :aliases => '-r', :desc => '设置是否进行企业签名', :type => :boolean
|
7
|
-
option :token, :aliases => '-t', :desc => '用户 token'
|
8
|
-
option :short, :aliases => '-s', :desc => '自定义短地址'
|
9
|
-
option :changelog, :aliases => '-c', :desc => '修改纪录,默认为空字符串', :default => ''
|
10
|
-
end
|
11
|
-
publish_options
|
12
|
-
# resign_options
|
13
|
-
output_options
|
14
|
-
def publish(path)
|
15
|
-
# if _opt_resign && _is_ipa?(path)
|
16
|
-
# tfile = Tempfile.new ["resign-#{SecureRandom.hex}", '.ipa']
|
17
|
-
# resign path, tfile.path
|
18
|
-
# path = tfile.path
|
19
|
-
# end
|
20
|
-
app = _info path, true
|
21
|
-
fir_app = _fir_info app[:identifier], app[:type]
|
22
|
-
|
23
|
-
id = fir_app[:id]
|
24
|
-
bundle_app = fir_app[:bundle][:pkg]
|
25
|
-
bundle_icon = fir_app[:bundle][:icon]
|
26
|
-
|
27
|
-
if app[:icons] != nil && app[:icons].length > 0
|
28
|
-
icon_path = app[:icons][0][:path]
|
29
|
-
|
30
|
-
if _is_ipa? path
|
31
|
-
_puts '> 转换图标...'
|
32
|
-
Pngdefry.defry icon_path, icon_path
|
33
|
-
end
|
34
|
-
|
35
|
-
_puts "> 上传图标..."
|
36
|
-
RestClient.post bundle_icon[:url],
|
37
|
-
:key => bundle_icon[:key],
|
38
|
-
:token => bundle_icon[:token],
|
39
|
-
:file => File.new(icon_path, 'rb')
|
40
|
-
|
41
|
-
_puts '> 上传图标成功'
|
42
|
-
end
|
43
|
-
|
44
|
-
_puts '> 上传应用...'
|
45
|
-
res = RestClient.post bundle_app[:url],
|
46
|
-
:key => bundle_app[:key],
|
47
|
-
:token => bundle_app[:token],
|
48
|
-
:file => File.new(path, 'rb')
|
49
|
-
_puts '> 上传应用成功'
|
50
|
-
upload_res = JSON.parse res.body, :symbolize_names => true
|
51
|
-
|
52
|
-
_fir_put fir_app[:id],
|
53
|
-
:name => app[:display_name] || app[:name],
|
54
|
-
:short => options[:short] || fir_app[:short],
|
55
|
-
# :desc => options[:describe] || fir_app[:desc]
|
56
|
-
# :show => options[:public] || fir_app[:show]
|
57
|
-
:source => 'fir-cli'
|
58
|
-
|
59
|
-
_fir_vput_complete upload_res[:versionOid],
|
60
|
-
:version => app[:version],
|
61
|
-
:versionShort => app[:short_version],
|
62
|
-
:devices => app[:devices],
|
63
|
-
:release_type => app[:release_type]
|
64
|
-
|
65
|
-
_fir_vput upload_res[:versionOid],
|
66
|
-
:changelog => options[:changelog]
|
67
|
-
|
68
|
-
# Get updated app info
|
69
|
-
fir_app = _fir_info app[:identifier], app[:type]
|
70
|
-
_puts "> #{_fir_url}/#{fir_app[:short]}"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,153 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
module Fir
|
3
|
-
class Cli
|
4
|
-
def self.build_ipa_options
|
5
|
-
option :workspace, :aliases => '-w', :desc => '编译指定路径中的 workspace', :type => :boolean
|
6
|
-
option :scheme, :aliases => '-s', :desc => '如果编译 workspace 则必须指定 scheme'
|
7
|
-
option :configuration, :aliases => '-C', :desc => '选择编译的配置,如 Release'
|
8
|
-
option :output, :aliases => '-o', :desc => '指定 ipa 的输出路径'
|
9
|
-
option :publish, :aliases => '-p', :desc => '设置是否发布到 FIR.im', :type => :boolean
|
10
|
-
end
|
11
|
-
desc 'build_ipa PATH [options] [settings]', '编译 ios app 项目'
|
12
|
-
build_ipa_options
|
13
|
-
publish_options
|
14
|
-
output_options
|
15
|
-
def build_ipa(path, *args)
|
16
|
-
_chk_os! 'mac'
|
17
|
-
settings = _convert_settings *args
|
18
|
-
|
19
|
-
path = _path(path).to_s
|
20
|
-
project_dir = (File.directory? path) ? path : (File.dirname path)
|
21
|
-
|
22
|
-
ipa_path = _path(options[:output]).to_s if options[:output]
|
23
|
-
if !ipa_path && !_opt_publish
|
24
|
-
_puts "! #{Paint['如果不发布到 FIR.im,则需要指定 ipa 文件的输出路径', :red]}"
|
25
|
-
_exit
|
26
|
-
end
|
27
|
-
if !ipa_path
|
28
|
-
Dir.mktmpdir do |_d|
|
29
|
-
ipa_path = _d.to_s
|
30
|
-
_build_ipa project_dir, settings, options,
|
31
|
-
:ipa_path => ipa_path
|
32
|
-
return _batch_publish ipa_path
|
33
|
-
end
|
34
|
-
end
|
35
|
-
_build_ipa project_dir, settings, options,
|
36
|
-
:ipa_path => ipa_path
|
37
|
-
return if !_opt_publish
|
38
|
-
if File.directory? ipa_path
|
39
|
-
_batch_publish ipa_path
|
40
|
-
elsif File.file? ipa_path
|
41
|
-
publish ipa_path
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
# *args 的每一个参数必须为 hash, 可以以任何顺序包含 settings, arguments, opts 的参数
|
47
|
-
# settings 的特点是 key 全部为大写字母
|
48
|
-
# arguments 的特点是 key 为 x_ 开头
|
49
|
-
# 不符合 settings 及 arguments 的为 opts
|
50
|
-
def _build_ipa(project_dir, *args)
|
51
|
-
ignore_args = %w(:project :workspace :sdk :scheme)
|
52
|
-
ignore_sets = %w(TARGET_BUILD_DIR)
|
53
|
-
|
54
|
-
setstr, argstr, opts = begin
|
55
|
-
_setstr, _argstr, _opts = ['', '-sdk iphoneos', {}]
|
56
|
-
args.inject(&:merge).each do |_k, _v|
|
57
|
-
_k = _k.to_s
|
58
|
-
if _k.match /^[_A-Z0-9]+$/
|
59
|
-
next if ignore_sets.include? _k
|
60
|
-
_setstr += " #{_k}"
|
61
|
-
_setstr += "=\"#{_v}\"" if _v
|
62
|
-
elsif _k.start_with? ':'
|
63
|
-
next if ignore_args.include? _k
|
64
|
-
_argstr += " -#{_k[1..-1]}"
|
65
|
-
_argstr += " \"#{_v}\"" if _v.class == String && !_v.empty?
|
66
|
-
else
|
67
|
-
_opts[_k.to_sym] = _v
|
68
|
-
end
|
69
|
-
end
|
70
|
-
[_setstr, _argstr, _opts]
|
71
|
-
end
|
72
|
-
project = begin
|
73
|
-
if _is_xcodeproject? project_dir
|
74
|
-
project_dir
|
75
|
-
elsif _is_workspace? project_dir
|
76
|
-
opts[:workspace] = true
|
77
|
-
project_dir
|
78
|
-
elsif opts[:workspace]
|
79
|
-
_spaces = Dir["#{project_dir}/*.xcworkspace"]
|
80
|
-
if _spaces.length == 0
|
81
|
-
_puts "! #{Paint['指定目录中找不到 workspace 文件,无法编译', :red]}"
|
82
|
-
_exit
|
83
|
-
end
|
84
|
-
_spaces[0]
|
85
|
-
else
|
86
|
-
_projs = Dir["#{project_dir}/*.xcodeproj"]
|
87
|
-
if _projs.length == 0
|
88
|
-
_puts "! #{Paint['指定目录中找不到 project 文件,无法编译', :red]}"
|
89
|
-
_exit
|
90
|
-
else
|
91
|
-
_projs[0]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
Dir.mktmpdir do |_d|
|
97
|
-
setstr += " TARGET_BUILD_DIR=#{_d} CONFIGURATION_BUILD_DIR=#{_d}"
|
98
|
-
if opts[:workspace]
|
99
|
-
unless opts[:scheme]
|
100
|
-
_puts "! #{Paint['如果编译 workspace, 则必须指定一个 scheme', :red]}"
|
101
|
-
_exit
|
102
|
-
end
|
103
|
-
argstr += " -workspace \"#{project}\" -scheme \"#{opts[:scheme]}\""
|
104
|
-
else
|
105
|
-
argstr += " -project \"#{project}\""
|
106
|
-
end
|
107
|
-
|
108
|
-
argstr += " -configuration \"#{opts[:configuration]}\"" if opts[:configuration]
|
109
|
-
|
110
|
-
# _puts '> 正在清除缓存'
|
111
|
-
# _exec "xcodebuild clean #{argstr} 2>&1"
|
112
|
-
_puts '> 正在编译'
|
113
|
-
_exec "xcodebuild build #{argstr} #{setstr} 2>&1"
|
114
|
-
Dir.chdir(_d) do
|
115
|
-
apps = Dir['*.app']
|
116
|
-
if opts[:ipa_path]
|
117
|
-
ipa_path = opts[:ipa_path]
|
118
|
-
if File.directory? ipa_path
|
119
|
-
apps.each do |app|
|
120
|
-
_ipa_path = File.join ipa_path, "#{File.basename app, '.app'}.ipa"
|
121
|
-
_zip_ipa File.join(_d, app), _ipa_path
|
122
|
-
end
|
123
|
-
elsif apps.length > 1
|
124
|
-
_puts "! #{Paint['项目编译输出了多个 app,需要指定一个已经存在的目录作为输出目录', :red]}"
|
125
|
-
_exit
|
126
|
-
elsif apps.length == 0
|
127
|
-
_puts "! #{Paint['项目编译没有输出 app,无法打包 ipa', :red]}"
|
128
|
-
_exit
|
129
|
-
else
|
130
|
-
ipa_path += '.ipa' unless ipa_path.end_with? '.ipa'
|
131
|
-
_zip_ipa File.join(_d, apps[0]), ipa_path
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
_puts '> 完成'
|
136
|
-
end
|
137
|
-
end
|
138
|
-
def _zip_ipa(app_path, ipa_path)
|
139
|
-
Dir.mktmpdir do |_d|
|
140
|
-
Dir.chdir(_d) do
|
141
|
-
Dir.mkdir "Payload"
|
142
|
-
FileUtils.cp_r app_path, 'Payload'
|
143
|
-
if File.file? ipa_path
|
144
|
-
_puts "> 删除已有文件 #{ipa_path}"
|
145
|
-
_exec "rm -r #{ipa_path}"
|
146
|
-
end
|
147
|
-
_puts "> 正在打包 app: #{File.basename app_path} 到 #{ipa_path}"
|
148
|
-
_exec "zip -qr #{ipa_path} Payload"
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
data/lib/fir-cli.chk.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
module Fir
|
3
|
-
class Cli
|
4
|
-
private
|
5
|
-
def _chk_login!(prompt = true)
|
6
|
-
if !_opt_token && prompt == true
|
7
|
-
token = _prompt_secret('请输入用户 token:')
|
8
|
-
@token = token if token.length > 0
|
9
|
-
end
|
10
|
-
if !@token
|
11
|
-
_puts_require_token
|
12
|
-
_exit
|
13
|
-
elsif !_user(@token)
|
14
|
-
_puts_invalid_token
|
15
|
-
_exit
|
16
|
-
end
|
17
|
-
end
|
18
|
-
def _chk_os!(os)
|
19
|
-
if _os != os
|
20
|
-
_puts "! #{Paint["该指令不支持在非 #{os} 系统执行", :red]}"
|
21
|
-
_exit
|
22
|
-
end
|
23
|
-
end
|
24
|
-
def _chk_opt!(*opts)
|
25
|
-
opts.each do |_opt|
|
26
|
-
if !_opt? _opt.to_sym
|
27
|
-
_puts "! #{Paint["缺少参数 #{_opt}", :red]}"
|
28
|
-
_exit
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
data/lib/fir-cli.core.rb
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
module Fir
|
3
|
-
class Cli
|
4
|
-
def initialize(*args)
|
5
|
-
super
|
6
|
-
@tmpfiles = []
|
7
|
-
_init_config
|
8
|
-
_load_config
|
9
|
-
_puts_welcome
|
10
|
-
end
|
11
|
-
private
|
12
|
-
def _info(path, more = false)
|
13
|
-
if _is_ipa? path
|
14
|
-
_ipa_info path, more
|
15
|
-
elsif _is_apk? path
|
16
|
-
_apk_info path, more
|
17
|
-
else
|
18
|
-
_puts "! #{Paint['只能支持后缀为 ipa 和 apk 的文件', :red]}"
|
19
|
-
_exit
|
20
|
-
end
|
21
|
-
end
|
22
|
-
def _apk_info(path, more = false)
|
23
|
-
path = _path path
|
24
|
-
apk = Android::Apk.new path
|
25
|
-
info = {
|
26
|
-
:type => 'android',
|
27
|
-
:identifier => apk.manifest.package_name,
|
28
|
-
:name => apk.label,
|
29
|
-
:version => apk.manifest.version_code,
|
30
|
-
:short_version => apk.manifest.version_name
|
31
|
-
}
|
32
|
-
if more
|
33
|
-
info[:icons] = apk.icon.map do |name, data|
|
34
|
-
tfile = Tempfile.new ["icon-#{SecureRandom.hex}", '.png']
|
35
|
-
tfile.write data
|
36
|
-
@tmpfiles.push tfile
|
37
|
-
{
|
38
|
-
:name => File.basename(name),
|
39
|
-
:path => tfile.path
|
40
|
-
}
|
41
|
-
end
|
42
|
-
end
|
43
|
-
info
|
44
|
-
end
|
45
|
-
def _ipa_info(path, more = false)
|
46
|
-
path = _path path
|
47
|
-
ipa = Lagunitas::IPA.new path
|
48
|
-
_puts '> 正在解析 ipa 文件...'
|
49
|
-
app = ipa.app
|
50
|
-
info = {
|
51
|
-
:type => 'ios',
|
52
|
-
:identifier => app.identifier,
|
53
|
-
:name => app.name,
|
54
|
-
:display_name => app.display_name,
|
55
|
-
:version => app.version,
|
56
|
-
:short_version => app.short_version,
|
57
|
-
:devices => app.devices,
|
58
|
-
:release_type => app.release_type,
|
59
|
-
:distribution_name => app.distribution_name
|
60
|
-
}
|
61
|
-
if more
|
62
|
-
if app.icons
|
63
|
-
info[:icons] = app.icons.sort { |a,b| -(a[:width] <=> b[:width]) }.map do |icon|
|
64
|
-
tfile = Tempfile.new ["icon-#{SecureRandom.hex}", '.png']
|
65
|
-
@tmpfiles.push tfile
|
66
|
-
FileUtils.cp icon[:path], tfile.path
|
67
|
-
{
|
68
|
-
:name => File.basename(icon[:path]),
|
69
|
-
:path => tfile.path
|
70
|
-
}
|
71
|
-
end
|
72
|
-
end
|
73
|
-
info[:plist] = app.info
|
74
|
-
app.mobileprovision.delete 'DeveloperCertificates' if app.mobileprovision
|
75
|
-
info[:mobileprovision] = app.mobileprovision
|
76
|
-
end
|
77
|
-
ipa.cleanup
|
78
|
-
info
|
79
|
-
end
|
80
|
-
def _batch_publish(*dirs)
|
81
|
-
_puts "! #{ Paint['至少需要提供一个文件夹', :red] }" if dirs.length == 0
|
82
|
-
dirs.each do |dir|
|
83
|
-
Dir.foreach(dir) do |_f|
|
84
|
-
if _is_ipa?(_f) || _is_apk?(_f)
|
85
|
-
_puts "> 正在发布 #{ _f }"
|
86
|
-
begin
|
87
|
-
publish File.join dir, _f
|
88
|
-
# rescue Exception => e
|
89
|
-
# _puts "! #{ _f } 失败:#{ e.to_s }"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
data/lib/fir-cli.fir.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
module Fir
|
3
|
-
class Cli
|
4
|
-
private
|
5
|
-
def _fir_url
|
6
|
-
@base_path ||= begin
|
7
|
-
path = @config['base_path'] || 'http://fir.im'
|
8
|
-
path = path.strip
|
9
|
-
path = path.end_with?('/') ? path.chop : path
|
10
|
-
end
|
11
|
-
end
|
12
|
-
def _fir_info(identifier, type = 'ios')
|
13
|
-
_puts "> 正在获取 #{identifier}@FIR.im 的应用信息..."
|
14
|
-
_chk_login!
|
15
|
-
body = { :token => @token, :type => type }
|
16
|
-
res = RestClient.get "#{_fir_url}/api/v2/app/info/#{identifier}?#{URI.encode_www_form body}"
|
17
|
-
JSON.parse res.body, :symbolize_names => true
|
18
|
-
end
|
19
|
-
def _fir_put(id, body)
|
20
|
-
_chk_login!
|
21
|
-
body[:token] = @token
|
22
|
-
_puts '> 正在更新 fir 的应用信息...'
|
23
|
-
RestClient.put "#{_fir_url}/api/v2/app/#{id}?#{URI.encode_www_form body}", body
|
24
|
-
_puts '> 更新成功'
|
25
|
-
end
|
26
|
-
def _fir_vput_complete(id, body)
|
27
|
-
_chk_login!
|
28
|
-
body[:token] = @token
|
29
|
-
_puts '> 正在更新 fir 的应用版本信息...'
|
30
|
-
RestClient.put "#{_fir_url}/api/v2/appVersion/#{id}/complete?#{URI.encode_www_form body}", body
|
31
|
-
_puts '> 更新成功'
|
32
|
-
end
|
33
|
-
def _fir_vput(id, body)
|
34
|
-
_chk_login!
|
35
|
-
body[:token] = @token
|
36
|
-
RestClient.put "#{_fir_url}/api/v2/appVersion/#{id}?#{URI.encode_www_form body}", body
|
37
|
-
end
|
38
|
-
def _user(token)
|
39
|
-
RestClient.get "#{_fir_url}/api/v2/user/me?token=#{token}" do |res|
|
40
|
-
case res.code
|
41
|
-
when 200
|
42
|
-
JSON.parse res.body, :symbolize_names => true
|
43
|
-
else
|
44
|
-
nil
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/lib/fir-cli.opt.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
module Fir
|
3
|
-
class Cli
|
4
|
-
no_commands do
|
5
|
-
# %w(token email verbose origin branch mobile_provision sign entitlements private_key).each do |_m|
|
6
|
-
%w(token email verbose origin branch mobile_provision entitlements private_key).each do |_m|
|
7
|
-
define_method "_opt_#{_m}" do
|
8
|
-
unless instance_variable_get("@#{_m}")
|
9
|
-
instance_variable_set("@#{_m}", options[_m.to_sym] || @config[_m] )
|
10
|
-
end
|
11
|
-
instance_variable_get("@#{_m}")
|
12
|
-
end
|
13
|
-
private "_opt_#{_m}".to_sym
|
14
|
-
end
|
15
|
-
# %w(publish resign quiet color trim).each do |_m|
|
16
|
-
%w(publish quiet color trim).each do |_m|
|
17
|
-
define_method "_opt_#{_m}" do
|
18
|
-
return false if options[_m.to_sym] == false
|
19
|
-
unless instance_variable_get("@#{_m}")
|
20
|
-
instance_variable_set("@#{_m}", options[_m.to_sym] || @config[_m] )
|
21
|
-
end
|
22
|
-
instance_variable_get("@#{_m}")
|
23
|
-
end
|
24
|
-
private "_opt_#{_m}".to_sym
|
25
|
-
end
|
26
|
-
end
|
27
|
-
private
|
28
|
-
def _opt (*opts)
|
29
|
-
opts.map { |_opt| method("_opt_#{_opt}").call }
|
30
|
-
end
|
31
|
-
def _opt? (*opts)
|
32
|
-
opts.each { |_opt| return false if !method("_opt_#{_opt}").call }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|