fir-cli 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9dbb82db6a565fb7b448b2dd8643b8991250b022
4
- data.tar.gz: 8ebacaa4ee598e06fcdf645c0070cef5822f1205
3
+ metadata.gz: a24b1b028bb3fa518bb091e2ab408a7adda62fe8
4
+ data.tar.gz: 68f5fa9e8492ee4ebb397f254254fb5b307b82d0
5
5
  SHA512:
6
- metadata.gz: 8f53a74550bce7e5f7294f7f613b9db1e544b79cfb94fa1ef588590b8f7a92566d9589e56c2700d79c7ca38ce0cea37bcb3014ea9312b0e6a26d3eebc00ad0ab
7
- data.tar.gz: 67616767e8c833f3d73c246d05a06580a364723c4757b71ace737ff6e1c1c189e2f3ac94eceb0210d32d8e90f75af68993b24e657b16ac30cd35af17a842fafa
6
+ metadata.gz: a5423d1e143c6413724ab28bed45a95377b63fd8f6dafce2468a802e743cb83160f6821a0c71bae3f997500aeb292c7e16be0eda2156124a944d688dfca01b74
7
+ data.tar.gz: 8d74ec61bbcc0ed9b2f0d6f271222953c2b699e2667c3c407fc31a6bc88a9cc39b98ec11211c4444e05f5e421d00ec76ab9612ec0c270f215e3982e95fa90d26
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fir-cli (0.1.9)
4
+ fir-cli (0.2.0)
5
5
  highline (~> 1.6)
6
6
  lagunitas (= 0.0.1)
7
7
  paint (~> 0.9)
@@ -1,5 +1,5 @@
1
1
  module Fir
2
2
  class Cli
3
- VERSION = '0.1.9'
3
+ VERSION = '0.2.0'
4
4
  end
5
5
  end
@@ -6,7 +6,6 @@ module Fir
6
6
  option :email, :aliases => '-e', :desc => '邮件地址'
7
7
  option :resign, :aliases => '-r', :desc => '是否以企业签名发布 ios 应用', :type => :boolean
8
8
  option :publish, :aliases => '-p', :desc => '编译打包自动发布至 FIR.im', :type => :boolean
9
- git_options
10
9
  output_options
11
10
  def config
12
11
  if options.length > 0
@@ -2,97 +2,155 @@
2
2
  module Fir
3
3
  class Cli
4
4
  def self.build_ipa_options
5
- option :x_project, :desc => '选择编译的项目文件'
6
- option :x_scheme, :desc => '选择使用的 Scheme'
7
- option :x_target, :desc => '选择编译的 Target'
8
- option :x_alltarget, :desc => '编译全部 Target', :type => :boolean
9
- option :x_configuration, :desc => '选择编译使用的配置'
10
- option :output_ipa, :aliases => '-o', :desc => '指定 ipa 的输出路径'
11
- option :output_app, :desc => '指定 app 的输出路径'
12
- option :publish, :aliases => '-p', :desc => '设置是否直接发布到 FIR.im', :type => :boolean
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
13
10
  end
14
- desc 'build_ipa PATH [options] [settings]', '编译 ios app 项目,输出至 ODIR'
11
+ desc 'build_ipa PATH [options] [settings]', '编译 ios app 项目'
15
12
  build_ipa_options
16
13
  publish_options
17
14
  output_options
18
- def build_ipa(path, *settings)
15
+ def build_ipa(path, *args)
19
16
  if _os != 'mac'
20
17
  _puts "! #{Paint['不支持在非 mac 系统上编译打包', :red]}"
21
18
  exit 1
22
19
  end
23
- settings = _convert_settings *settings
24
- ipa_path = _path options[:output_ipa] if options[:output_ipa]
25
- if !ipa_path
26
- use_tmpfile = true
27
- ipa_path = Tempfile.new(["#{SecureRandom.hex}", '.ipa']).path
28
- end
29
- app_path = _path options[:output_app] if options[:output_app]
30
- mp_path = _path options[:mobileprovision] if options[:mobileprovision]
20
+ settings = _convert_settings *args
31
21
 
32
- vars = {
33
- :ipa_path => ipa_path,
34
- :app_path => app_path
35
- }
36
- # TODO: pull from a git repo
37
- # if options[:git] != nil
38
- # git(path) { |_d| _build_ipa _d, settings, vars }
39
- # else
40
- # end
41
-
42
- path = _path path
22
+ path = _path(path).to_s
43
23
  project_dir = (Dir.exist? path) ? path : (File.dirname path)
44
- _build_ipa project_dir, settings, vars
45
24
 
25
+ ipa_path = _path(options[:output]).to_s if options[:output]
26
+ if !ipa_path && !_opt_publish
27
+ _puts "! #{Paint['如果不发布到 FIR.im,则需要指定 ipa 文件的输出路径', :red]}"
28
+ exit 1
29
+ end
30
+ if !ipa_path
31
+ Dir.mktmpdir do |_d|
32
+ ipa_path = _d.to_s
33
+ _build_ipa project_dir, settings, options,
34
+ :ipa_path => ipa_path
35
+ return _batch_publish ipa_path
36
+ end
37
+ end
38
+ _build_ipa project_dir, settings, options,
39
+ :ipa_path => ipa_path
46
40
  return if !_opt_publish
47
- publish ipa_path.to_s
41
+ if Dir.exists? ipa_path
42
+ _batch_publish ipa_path
43
+ elsif File.exists? ipa_path
44
+ publish ipa_path
45
+ end
48
46
  end
49
47
 
50
48
  private
49
+ # *args 的每一个参数必须为 hash, 可以以任何顺序包含 settings, arguments, opts 的参数
50
+ # settings 的特点是 key 全部为大写字母
51
+ # arguments 的特点是 key 为 x_ 开头
52
+ # 不符合 settings 及 arguments 的为 opts
51
53
  def _build_ipa(project_dir, *args)
52
- settings = {}
53
- vars = {}
54
- if args.length == 1
55
- args[0].each { |_k, _v| if _k.match /^[A-Z]+$/ then settings[_k] = _v else vars[_k] = _v end }
56
- else
57
- settings, vars = args[0..1]
58
- end
54
+ ignore_args = %w(:project :workspace :sdk :scheme)
55
+ ignore_sets = %w(TARGET_BUILD_DIR)
59
56
 
60
- settings = settings.select { |_k| _k != 'TARGET_BUILD_DIR' }
61
- .map { |_k, _v| "#{_k}=\"#{_v}\"" }
62
- .join(' ')
63
- arguments = '-sdk iphoneos'
64
- options.each do |_k, _v|
65
- break if !_k.start_with? 'x_'
66
- arguments += " -#{_k[2..-1]}" if _v
67
- arguments += " #{_v}" if _v.class == String
57
+ setstr, argstr, opts = begin
58
+ _setstr, _argstr, _opts = ['', '-sdk iphoneos', {}]
59
+ args.inject(&:merge).each do |_k, _v|
60
+ _k = _k.to_s
61
+ if _k.match /^[_A-Z0-9]+$/
62
+ next if ignore_sets.include? _k
63
+ _setstr += " #{_k}"
64
+ _setstr += "=\"#{_v}\"" if _v
65
+ elsif _k.start_with? ':'
66
+ next if ignore_args.include? _k
67
+ _argstr += " -#{_k[1..-1]}"
68
+ _argstr += " \"#{_v}\"" if _v.class == String && !_v.empty?
69
+ else
70
+ _opts[_k.to_sym] = _v
71
+ end
72
+ end
73
+ [_setstr, _argstr, _opts]
68
74
  end
69
- Dir.mktmpdir do |_d|
70
- settings += " TARGET_BUILD_DIR=#{_d}"
71
- Dir.chdir(project_dir) do
72
- _puts '> 正在清除缓存'
73
- _exec "xcodebuild clean 2>&1"
74
- _puts '> 正在编译'
75
- _exec "xcodebuild build #{arguments} #{settings} 2>&1"
75
+ project = begin
76
+ if _is_xcodeproject project_dir
77
+ project_dir
78
+ elsif _is_workspace project_dir
79
+ opts[:workspace] = true
80
+ project_dir
81
+ elsif opts[:workspace]
82
+ _spaces = Dir["#{project_dir}/*.xcworkspace"]
83
+ if _spaces.length == 0
84
+ _puts "! #{Paint['指定目录中找不到 workspace 文件,无法编译', :red]}"
85
+ exit 1
86
+ end
87
+ _spaces[0]
88
+ else
89
+ _projs = Dir["#{project_dir}/*.xcodeproj"]
90
+ if _projs.length == 0
91
+ _puts "! #{Paint['指定目录中找不到 project 文件,无法编译', :red]}"
92
+ exit 1
93
+ else
94
+ _projs[0]
95
+ end
76
96
  end
77
- Dir.chdir(_d) do
78
- ipa_path = vars[:ipa_path]
79
- if ipa_path
80
- basename = File.basename Dir['*.app'][0], '.app'
81
- ipa_path = File.join(ipa_path, 'build_ipa.ipa') if Dir.exist? ipa_path
82
- _puts '> 正在打包'
83
- _exec 'mkdir Payload'
84
- _exec 'mv *.app ./Payload'
85
- _exec "rm #{ipa_path}" if File.exist? ipa_path
86
- _exec "zip -qr #{ipa_path} Payload"
97
+ end
98
+
99
+ Dir.mktmpdir do |_d|
100
+ setstr += " TARGET_BUILD_DIR=#{_d} CONFIGURATION_BUILD_DIR=#{_d}"
101
+ if opts[:workspace]
102
+ unless opts[:scheme]
103
+ _puts "! #{Paint['如果编译 workspace, 则必须指定一个 scheme', :red]}"
104
+ exit 1
87
105
  end
106
+ argstr += " -workspace \"#{project}\" -scheme \"#{opts[:scheme]}\""
107
+ else
108
+ argstr += " -project \"#{project}\""
109
+ end
110
+
111
+ argstr += " -configuration \"#{opts[:configuration]}\"" if opts[:configuration]
88
112
 
89
- if vars[:app_path]
90
- _puts '> 正在复制 app 文件'
91
- _exec "mv ./Payload/*.app #{vars[:app_path]}"
113
+ # _puts '> 正在清除缓存'
114
+ # _exec "xcodebuild clean #{argstr} 2>&1"
115
+ _puts '> 正在编译'
116
+ _exec "xcodebuild build #{argstr} #{setstr} 2>&1"
117
+ Dir.chdir(_d) do
118
+ apps = Dir['*.app']
119
+ if opts[:ipa_path]
120
+ ipa_path = opts[:ipa_path]
121
+ if Dir.exist? ipa_path
122
+ apps.each do |app|
123
+ _ipa_path = File.join ipa_path, "#{File.basename app, '.app'}.ipa"
124
+ _zip_ipa File.join(_d, app), _ipa_path
125
+ end
126
+ elsif apps.length > 1
127
+ _puts "! #{Paint['项目编译输出了多个 app,需要指定一个已经存在的目录作为输出目录', :red]}"
128
+ exit 1
129
+ elsif apps.length == 0
130
+ _puts "! #{Paint['项目编译没有输出 app,无法打包 ipa', :red]}"
131
+ exit 1
132
+ else
133
+ ipa_path += '.ipa' unless ipa_path.end_with? '.ipa'
134
+ _zip_ipa File.join(_d, apps[0]), ipa_path
135
+ end
92
136
  end
93
137
  end
94
138
  _puts '> 完成'
95
139
  end
96
140
  end
141
+ def _zip_ipa(app_path, ipa_path)
142
+ Dir.mktmpdir do |_d|
143
+ Dir.chdir(_d) do
144
+ Dir.mkdir "Payload"
145
+ FileUtils.cp_r app_path, 'Payload'
146
+ if File.exist? ipa_path
147
+ _puts "> 删除已有文件 #{ipa_path}"
148
+ _exec "rm -r #{ipa_path}"
149
+ end
150
+ _puts "> 正在打包 app: #{File.basename app_path} 到 #{ipa_path}"
151
+ _exec "zip -qr #{ipa_path} Payload"
152
+ end
153
+ end
154
+ end
97
155
  end
98
156
  end
@@ -71,6 +71,12 @@ module Fir
71
71
  def _is_apk(path)
72
72
  path.end_with? '.apk'
73
73
  end
74
+ def _is_workspace(path)
75
+ path.end_with? '.xcworkspace'
76
+ end
77
+ def _is_xcodeproject(path)
78
+ path.end_with? '.xcodeproj'
79
+ end
74
80
  def _is_identifier(str)
75
81
  /^(?:(?:[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
76
82
  end
@@ -175,7 +181,7 @@ module Fir
175
181
  }
176
182
  if more
177
183
  if app.icons
178
- info[:icons] = app.icons.reverse.map do |icon|
184
+ info[:icons] = app.icons.sort { |a,b| -(a[:width] <=> b[:width]) }.map do |icon|
179
185
  tfile = Tempfile.new ["icon-#{SecureRandom.hex}", '.png']
180
186
  @tmpfiles.push tfile
181
187
  FileUtils.cp icon[:path], tfile.path
@@ -222,5 +228,20 @@ module Fir
222
228
  hash
223
229
  end
224
230
  end
231
+ def _batch_publish(*dirs)
232
+ _puts "! #{ Paint['至少需要提供一个文件夹', :red] }" if dirs.length == 0
233
+ dirs.each do |dir|
234
+ Dir.foreach(dir) do |_f|
235
+ if _is_ipa(_f) || _is_apk(_f)
236
+ _puts "> 正在发布 #{ _f }"
237
+ begin
238
+ publish File.join dir, _f
239
+ rescue Exception => e
240
+ _puts "! #{ _f } 失败:#{ e.to_s }"
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end
225
246
  end
226
247
  end
@@ -6,17 +6,29 @@ module Lagunitas
6
6
  @root = root
7
7
  end
8
8
  def icons
9
- @icons ||= begin
10
- icons = []
11
- info['CFBundleIcons']['CFBundlePrimaryIcon']['CFBundleIconFiles'].each do |name|
12
- icons << get_image(name)
13
- icons << get_image("#{name}@2x")
14
- end
15
- icons.delete_if { |i| !i }
16
- rescue
17
- # info['CFBundleIcons'] might be nil
18
- nil
9
+ icons = []
10
+ info['CFBundleIcons']['CFBundlePrimaryIcon']['CFBundleIconFiles'].each do |name|
11
+ icons << get_image(name)
12
+ icons << get_image("#{name}.png")
13
+ icons << get_image("#{name}@2x.png")
14
+ icons << get_image("#{name}@3x.png")
19
15
  end
16
+ icons.delete_if { |i| !i }
17
+ rescue
18
+ nil
19
+ end
20
+ def get_image(name)
21
+ path = File.join @path, name
22
+ return nil unless File.exist? path
23
+
24
+ dimensions = Pngdefry.dimensions(path)
25
+ {
26
+ path: path,
27
+ width: dimensions.first,
28
+ height: dimensions.last
29
+ }
30
+ rescue Errno::ENOENT
31
+ nil
20
32
  end
21
33
  end
22
34
  class IPA
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.1.9
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - FIR.im
@@ -165,7 +165,6 @@ files:
165
165
  - bin/fir
166
166
  - fir-cli.gemspec
167
167
  - fir-cli.rb
168
- - lib/fir-cli-commands/00-git.rb
169
168
  - lib/fir-cli-commands/00-info.rb
170
169
  - lib/fir-cli-commands/00-login.rb
171
170
  - lib/fir-cli-commands/00-profile.rb
@@ -1,33 +0,0 @@
1
- # coding: utf-8
2
- module Fir
3
- class Cli
4
- def self.git_options
5
- option :git, :desc => '设置 git 源'
6
- option :origin, :desc => '设置 git clone 的 origin'
7
- option :branch, :desc => '设置 git clone 的 branch'
8
- end
9
- no_commands do
10
- def git(path)
11
- arguments = '--depth 1'
12
- %w(origin branch).each do |_m|
13
- opt = method("_opt_#{_m}".to_sym).call
14
- arguments += " --#{_m} #{opt}" if opt
15
- end
16
-
17
- Dir.mktmpdir do |dir|
18
- _puts "> 克隆源代码 #{_opt_git}#{path}"
19
- Dir.chdir(dir) do
20
- _exec "git clone -q #{_opt_git}#{path} ./ #{arguments}"
21
- yield dir if block_given?
22
- end
23
- end
24
- end
25
- end
26
- private
27
- def _opt_git
28
- default = @config['git'] || 'git@github.com'
29
- return default if options[:git] == 'git'
30
- options[:git] || default
31
- end
32
- end
33
- end