fir-cli 0.2.0 → 0.2.1.a

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,33 @@
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
@@ -0,0 +1,96 @@
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
@@ -2,34 +2,41 @@
2
2
  module Fir
3
3
  class Cli
4
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
5
12
  def _fir_info(identifier, type = 'ios')
6
13
  _puts "> 正在获取 #{identifier}@FIR.im 的应用信息..."
7
- _chk_login
14
+ _chk_login!
8
15
  body = { :token => @token, :type => type }
9
- res = RestClient.get "#{_base_path}/api/v2/app/info/#{identifier}?#{URI.encode_www_form body}"
16
+ res = RestClient.get "#{_fir_url}/api/v2/app/info/#{identifier}?#{URI.encode_www_form body}"
10
17
  JSON.parse res.body, :symbolize_names => true
11
18
  end
12
19
  def _fir_put(id, body)
13
- _chk_login
20
+ _chk_login!
14
21
  body[:token] = @token
15
22
  _puts '> 正在更新 fir 的应用信息...'
16
- RestClient.put "#{_base_path}/api/v2/app/#{id}?#{URI.encode_www_form body}", body
23
+ RestClient.put "#{_fir_url}/api/v2/app/#{id}?#{URI.encode_www_form body}", body
17
24
  _puts '> 更新成功'
18
25
  end
19
26
  def _fir_vput_complete(id, body)
20
- _chk_login
27
+ _chk_login!
21
28
  body[:token] = @token
22
29
  _puts '> 正在更新 fir 的应用版本信息...'
23
- RestClient.put "#{_base_path}/api/v2/appVersion/#{id}/complete?#{URI.encode_www_form body}", body
30
+ RestClient.put "#{_fir_url}/api/v2/appVersion/#{id}/complete?#{URI.encode_www_form body}", body
24
31
  _puts '> 更新成功'
25
32
  end
26
33
  def _fir_vput(id, body)
27
- _chk_login
34
+ _chk_login!
28
35
  body[:token] = @token
29
- RestClient.put "#{_base_path}/api/v2/appVersion/#{id}?#{URI.encode_www_form body}", body
36
+ RestClient.put "#{_fir_url}/api/v2/appVersion/#{id}?#{URI.encode_www_form body}", body
30
37
  end
31
38
  def _user(token)
32
- RestClient.get "#{_base_path}/api/v2/user/me?token=#{token}" do |res|
39
+ RestClient.get "#{_fir_url}/api/v2/user/me?token=#{token}" do |res|
33
40
  case res.code
34
41
  when 200
35
42
  JSON.parse res.body, :symbolize_names => true
@@ -0,0 +1,33 @@
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).each do |_m|
6
+ define_method "_opt_#{_m}" do
7
+ unless instance_variable_get("@#{_m}")
8
+ instance_variable_set("@#{_m}", options[_m.to_sym] || @config[_m] )
9
+ end
10
+ instance_variable_get("@#{_m}")
11
+ end
12
+ private "_opt_#{_m}".to_sym
13
+ end
14
+ %w(publish resign quiet color trim).each do |_m|
15
+ define_method "_opt_#{_m}" do
16
+ return false if options[_m.to_sym] == false
17
+ unless instance_variable_get("@#{_m}")
18
+ instance_variable_set("@#{_m}", options[_m.to_sym] || @config[_m] )
19
+ end
20
+ instance_variable_get("@#{_m}")
21
+ end
22
+ private "_opt_#{_m}".to_sym
23
+ end
24
+ end
25
+ private
26
+ def _opt (*opts)
27
+ opts.map { |_opt| method("_opt_#{_opt}").call }
28
+ end
29
+ def _opt? (*opts)
30
+ opts.each { |_opt| return false if !method("_opt_#{_opt}").call }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,55 @@
1
+ # coding: utf-8
2
+ module Fir
3
+ class Cli
4
+ def self.output_options
5
+ option :verbose,
6
+ :desc => '设置输出辅助信息的详细程度',
7
+ :type => :string,
8
+ :enum => ['v', 'vv', 'vvv']
9
+ option :quiet,
10
+ :aliases => '-q',
11
+ :desc => '安静模式,不输出任何辅助信息',
12
+ :type => 'boolean'
13
+ option :color,
14
+ :desc => '设置输出带有颜色的信息',
15
+ :type => 'boolean'
16
+ end
17
+ private
18
+ def _puts(text)
19
+ return puts _format text if !/^[->!] /.match text
20
+ return if _opt_quiet
21
+ case _opt_verbose || 'vv' # If nothing about log is set, use the default option - vv
22
+ when 'v'
23
+ puts _format text if text.start_with?('!')
24
+ when 'vv'
25
+ puts _format text if text.start_with?('!') || text.start_with?('>')
26
+ when 'vvv'
27
+ puts _format text if text.start_with?('!') || text.start_with?('>') || text.start_with?('-')
28
+ end
29
+ end
30
+ def _format(text)
31
+ return text.gsub /\e\[\d+(?:;\d+)*m/, '' if _opt_color == false
32
+ text
33
+ end
34
+ def _puts_welcome
35
+ _puts "> #{Paint['欢迎使用 FIR.im 命令行工具,如需帮助请输入:', :green]} fir help"
36
+ end
37
+ def _puts_require_token
38
+ _puts "! #{Paint['用户 token 不能为空', :red]}"
39
+ end
40
+ def _puts_invalid_token
41
+ _puts "! #{Paint['输入的用户 token 不合法', :red]}"
42
+ end
43
+ def _puts_invalid_email
44
+ _puts "! #{Paint['输入的邮件地址不合法', :red]}"
45
+ end
46
+ def _prompt_secret(prompt)
47
+ prompt = '' if _opt_quiet
48
+ ask(prompt) { |_q| _q.echo = false }
49
+ end
50
+ def _prompt(prompt)
51
+ prompt = '' if _opt_quiet
52
+ ask(prompt) { |_q| _q }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,105 @@
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
+ def self.find_extends
12
+ `gem list --local`
13
+ .each_line("\n")
14
+ .map { |gem| /^[^\s]+/.match(gem)[0] }
15
+ .select { |gem| true if gem.start_with? 'fir-cli-' }
16
+ end
17
+ private
18
+ def _init_config
19
+ @uconfig = UserConfig.new '.fir'
20
+ @global_config = @uconfig['global.yaml']
21
+ end
22
+ def _load_config
23
+ @config = @uconfig[_profile]
24
+ end
25
+ def _set_config(configs)
26
+ if configs.length > 0
27
+ configs.each do |option|
28
+ _puts "> #{Paint[option[0].to_s.rjust(10), :blue]} : #{@config[option[0].to_s]} => #{option[1]}"
29
+ @config[option[0].to_s] = option[1]
30
+ end
31
+ if @config['token'] && !_user(@config['token'])
32
+ _puts_invalid_token
33
+ _exit
34
+ end
35
+ @config.save
36
+ end
37
+ end
38
+ def _profile
39
+ @global_config['profile'] || 'default.yaml'
40
+ end
41
+ def _path(path)
42
+ path = Pathname.new(Dir.pwd).join(path).cleanpath
43
+ end
44
+ def _is_ipa?(path)
45
+ path.end_with? '.ipa'
46
+ end
47
+ def _is_apk?(path)
48
+ path.end_with? '.apk'
49
+ end
50
+ def _is_workspace?(path)
51
+ path.end_with? '.xcworkspace'
52
+ end
53
+ def _is_xcodeproject?(path)
54
+ path.end_with? '.xcodeproj'
55
+ end
56
+ def _is_identifier?(str)
57
+ /^(?:(?:[a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*(?:[A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$/.match str
58
+ end
59
+ def _is_email?(str)
60
+ /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum)$/i.match str
61
+ end
62
+ def _os
63
+ return 'mac' if /darwin/ =~ RUBY_PLATFORM
64
+ return 'windows' if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
65
+ return 'linux'
66
+ end
67
+ def _exit
68
+ exit 1
69
+ end
70
+ def _exec(cmd)
71
+ output = `#{cmd}`
72
+ if $?.exitstatus != 0
73
+ puts output
74
+ _exit
75
+ end
76
+ end
77
+ def _convert_settings(*settings)
78
+ settings.reduce({}) do |hash, setting|
79
+ key,val = setting.split('=', 2).map(&:strip)
80
+ hash[key.to_sym] = val
81
+ hash
82
+ end
83
+ end
84
+ def _edit(ipath, opath=nil)
85
+ ipath = _path ipath
86
+ if !opath then opath = ipath else opath = _path opath end
87
+ extname = File.extname opath
88
+ Dir.mktmpdir do |_d|
89
+ Dir.chdir(_d) do
90
+
91
+ Zip::ZipFile.open(ipath) do |_z|
92
+ _z.each do |_entry|
93
+ entrypath = File.join _d, _entry.name
94
+ FileUtils.mkdir_p File.dirname entrypath
95
+ _z.extract _entry, entrypath unless File.file? entrypath
96
+ end
97
+ end
98
+ yield _d if block_given?
99
+ File.unlink opath if File.file? opath
100
+ _exec "zip -qr #{opath} Payload"
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
data/lib/lagunitas.ext.rb CHANGED
@@ -15,7 +15,7 @@ module Lagunitas
15
15
  end
16
16
  def mobileprovision?
17
17
  return true if @mobileprovision
18
- File.exists? File.join @path, 'embedded.mobileprovision'
18
+ File.file? File.join @path, 'embedded.mobileprovision'
19
19
  end
20
20
  def devices
21
21
  mobileprovision['ProvisionedDevices'] if mobileprovision
@@ -30,7 +30,7 @@ module Lagunitas
30
30
  end
31
31
  def metadata?
32
32
  return true if @metadata
33
- File.exists? File.join @root, 'iTunesMetadata.plist'
33
+ File.file? File.join @root, 'iTunesMetadata.plist'
34
34
  end
35
35
  def release_type
36
36
  @release_type ||= begin
@@ -19,8 +19,7 @@ module Lagunitas
19
19
  end
20
20
  def get_image(name)
21
21
  path = File.join @path, name
22
- return nil unless File.exist? path
23
-
22
+ return nil unless File.file? path
24
23
  dimensions = Pngdefry.dimensions(path)
25
24
  {
26
25
  path: path,
@@ -42,7 +41,7 @@ module Lagunitas
42
41
  zip_file.each do |f|
43
42
  f_path = File.join tmp_path, f.name
44
43
  FileUtils.mkdir_p File.dirname f_path
45
- zip_file.extract f, f_path unless File.exist? f_path
44
+ zip_file.extract f, f_path unless File.file? f_path
46
45
  end
47
46
  end
48
47
  tmp_path
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fir-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1.a
5
5
  platform: ruby
6
6
  authors:
7
7
  - FIR.im
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '1.6'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubyzip
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.9.9
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.9.9
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: bundler
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -171,11 +185,17 @@ files:
171
185
  - lib/fir-cli-commands/00-upgrade.rb
172
186
  - lib/fir-cli-commands/00-version.rb
173
187
  - lib/fir-cli-commands/01-config.rb
174
- - lib/fir-cli-commands/10-resign.rb
188
+ - lib/fir-cli-commands/100-resign_codesign.rb
189
+ - lib/fir-cli-commands/100-resign_tapbeta.rb
190
+ - lib/fir-cli-commands/101-resign.rb
175
191
  - lib/fir-cli-commands/11-publish.rb
176
192
  - lib/fir-cli-commands/12-build_ipa.rb
177
- - lib/fir-cli.core.ext.rb
178
- - lib/fir-cli.utils.ext.rb
193
+ - lib/fir-cli.chk.rb
194
+ - lib/fir-cli.core.rb
195
+ - lib/fir-cli.fir.rb
196
+ - lib/fir-cli.opt.rb
197
+ - lib/fir-cli.output.rb
198
+ - lib/fir-cli.utils.rb
179
199
  - lib/fir-cli/version.rb
180
200
  - lib/lagunitas.ext.rb
181
201
  - lib/lagunitas.patch.rb
@@ -196,9 +216,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
196
216
  version: '0'
197
217
  required_rubygems_version: !ruby/object:Gem::Requirement
198
218
  requirements:
199
- - - ">="
219
+ - - ">"
200
220
  - !ruby/object:Gem::Version
201
- version: '0'
221
+ version: 1.3.1
202
222
  requirements: []
203
223
  rubyforge_project:
204
224
  rubygems_version: 2.4.4