fir-cli 0.2.3.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|