escalator_ios 1.2.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/README.md +35 -0
- data/bin/escalator +10 -0
- data/escalator_ios.gemspec +27 -0
- data/lib/escalator/archive.rb +122 -0
- data/lib/escalator/combine.rb +116 -0
- data/lib/escalator/command/archive.rb +84 -0
- data/lib/escalator/command/combine.rb +116 -0
- data/lib/escalator/command/confuse.rb +86 -0
- data/lib/escalator/command/resign.rb +138 -0
- data/lib/escalator/command/setup.rb +91 -0
- data/lib/escalator/command/upload.rb +95 -0
- data/lib/escalator/command.rb +46 -0
- data/lib/escalator/confuse.rb +101 -0
- data/lib/escalator/group+.rb +13 -0
- data/lib/escalator/resign.rb +271 -0
- data/lib/escalator/setup.rb +79 -0
- data/lib/escalator/throw.rb +23 -0
- data/lib/escalator/upload.rb +57 -0
- data/lib/escalator.rb +25 -0
- data/resources/ExportOptions.plist +20 -0
- data/resources/IconInfo.plist +31 -0
- data/resources/zsh_plugin/escalator/_escalator +127 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f81824c1303fd2e05669bbbe309bcd5885f032e41a78beab761d0f2424adf6cf
|
4
|
+
data.tar.gz: 20b0f11fcb8942604669eb0db268d192dc4e1a548169890705a3890d3db2b8e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4eadf4fc8f5b55a2a6d6599afae552f05edef2397b149df3e018a6643703d2617cd08bc1c6b0821a885144f902ab9ad3836993182d2c718eb7e577c6b851cc46
|
7
|
+
data.tar.gz: 49593084775555eceadd1297743ade7d9d9ff927915b2c28ce569da3e3e4471f9a3cd3f9bd4c19259e16a760824ed9b9d55709c5fcf8e45adbf3632a4145786b
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# EscalatorIos
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/escalator_ios`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'escalator_ios'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install escalator_ios
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/escalator_ios.
|
data/bin/escalator
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# $: = $LOAD_PATH
|
2
|
+
|
3
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
4
|
+
|
5
|
+
require "escalator"
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = 'escalator_ios'
|
9
|
+
s.version = Escalator::VERSION
|
10
|
+
s.summary = "escalator!"
|
11
|
+
s.description = "For xcode project: confuse, archive, resign, upload"
|
12
|
+
s.authors = ["🔥起飞吧🔥"]
|
13
|
+
s.email = ["developer@gmail.com"]
|
14
|
+
s.homepage = 'https://rubygems.org/gems/escalator_ios'
|
15
|
+
s.license = 'MIT'
|
16
|
+
s.executables = Dir["bin/**/*"].map { |f| File.basename(f) }
|
17
|
+
s.files = Dir["lib/**/*"] + Dir["resources/**/*"] + ["README.md", "escalator_ios.gemspec"]
|
18
|
+
s.add_dependency "json", "~> 2.6.1"
|
19
|
+
# s.add_dependency "openssl", "~> 2.2.1"
|
20
|
+
s.add_dependency "ostruct", "~> 0.5.0"
|
21
|
+
s.add_dependency "fileutils", "~> 1.6.0"
|
22
|
+
s.add_dependency "xcodeproj", "~> 1.21.0"
|
23
|
+
s.add_dependency "fastlane", "~> 2.199.0"
|
24
|
+
s.add_dependency "colored2", "~> 3.1.2"
|
25
|
+
s.add_dependency "claide", "~> 1.0.3"
|
26
|
+
s.add_dependency "CFPropertyList", "~> 3.0.5"
|
27
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Escalator
|
2
|
+
|
3
|
+
class Archive
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def run command
|
8
|
+
@command = command
|
9
|
+
Throw.note "Begin archive #{File.basename File.dirname command.project_path} ..."
|
10
|
+
prepareContext
|
11
|
+
buildProject
|
12
|
+
archiveProject
|
13
|
+
exportAssets
|
14
|
+
exportCoverInfo
|
15
|
+
if command.show_output?
|
16
|
+
system "open #{command.output_path}"
|
17
|
+
end
|
18
|
+
Throw.note "Archive Success!"
|
19
|
+
"#{output_path}/#{product_name}.ipa"
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_accessor :command
|
25
|
+
|
26
|
+
attr_accessor :scheme
|
27
|
+
|
28
|
+
attr_accessor :assets_paths
|
29
|
+
|
30
|
+
attr_accessor :archive_path
|
31
|
+
|
32
|
+
attr_accessor :plist_path
|
33
|
+
|
34
|
+
attr_accessor :coverInfo_path
|
35
|
+
|
36
|
+
attr_accessor :cmd_source
|
37
|
+
|
38
|
+
attr_accessor :output_path
|
39
|
+
|
40
|
+
attr_accessor :product_name
|
41
|
+
|
42
|
+
def prepareContext
|
43
|
+
Throw.note "Prepare archive context ..."
|
44
|
+
tmpdir = ENV["TMPDIR"] + "escalator/archive"
|
45
|
+
if File.exist? tmpdir
|
46
|
+
FileUtils.rm_rf Dir["#{tmpdir}/*"]
|
47
|
+
else
|
48
|
+
FileUtils.mkdir_p tmpdir
|
49
|
+
end
|
50
|
+
@plist_path = "#{tmpdir}/ExportOptions.plist"
|
51
|
+
@scheme = Xcodeproj::Project.schemes(command.project_path).first
|
52
|
+
project = Xcodeproj::Project.open command.project_path
|
53
|
+
target = project.targets.first
|
54
|
+
@assets_paths = target.resources_build_phase.files.select { |f|
|
55
|
+
f.file_ref.real_path.extname == ".xcassets"
|
56
|
+
}.map { |f| f.file_ref.real_path.to_s }
|
57
|
+
build_settings = target.build_settings "Release"
|
58
|
+
enableBitCode = build_settings["ENABLE_BITCODE"] == "YES"
|
59
|
+
@product_name = build_settings["PRODUCT_NAME"]
|
60
|
+
if product_name == "$(TARGET_NAME)"
|
61
|
+
@product_name = target.name
|
62
|
+
end
|
63
|
+
@archive_path = "#{tmpdir}/#{product_name}.xcarchive"
|
64
|
+
base_path = File.dirname command.project_path
|
65
|
+
@coverInfo_path = base_path + "/CoverInfo.plist"
|
66
|
+
project_name = File.basename(command.project_path).split(".").first
|
67
|
+
workspace_path = "#{base_path}/#{project_name}.xcworkspace"
|
68
|
+
@cmd_source = "-project #{command.project_path}"
|
69
|
+
if File.exist? workspace_path
|
70
|
+
@cmd_source = "-workspace #{workspace_path}"
|
71
|
+
end
|
72
|
+
@output_path = File.expand_path "./#{File.basename base_path}", command.output_path
|
73
|
+
FileUtils.rm_rf output_path
|
74
|
+
options_path = File.expand_path "../../../resources/ExportOptions.plist", __FILE__
|
75
|
+
plist = CFPropertyList::List.new :file => options_path
|
76
|
+
data = CFPropertyList.native_types plist.value
|
77
|
+
data["method"] = command.method
|
78
|
+
data["uploadBitcode"] = enableBitCode
|
79
|
+
plist.value = CFPropertyList::guess data
|
80
|
+
plist.save plist_path
|
81
|
+
end
|
82
|
+
|
83
|
+
def buildProject
|
84
|
+
Throw.note "Begin build project ..."
|
85
|
+
cmd = "xcodebuild archive #{cmd_source} -scheme #{scheme} \
|
86
|
+
-configuration Release -arch arm64 -archivePath #{archive_path}"
|
87
|
+
system cmd
|
88
|
+
if !$?.success?
|
89
|
+
Throw.error "Build faild with #{cmd}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def archiveProject
|
94
|
+
Throw.note "Begin export ipa ..."
|
95
|
+
cmd = "xcodebuild -exportArchive -archivePath #{archive_path} \
|
96
|
+
-exportPath #{output_path} -exportOptionsPlist #{plist_path} \
|
97
|
+
-allowProvisioningUpdates"
|
98
|
+
system cmd
|
99
|
+
if !$?.success?
|
100
|
+
Throw.error "Export faild with #{cmd}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def exportAssets
|
105
|
+
Throw.note "Begin export assets ..."
|
106
|
+
assets_paths.each { |path|
|
107
|
+
FileUtils.cp_r path, output_path
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
def exportCoverInfo
|
112
|
+
Throw.note "Begin export CoverInfo.plist ..."
|
113
|
+
if File.exist? coverInfo_path
|
114
|
+
FileUtils.cp_r coverInfo_path, output_path
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Escalator
|
2
|
+
|
3
|
+
class Combine
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def run command
|
8
|
+
@command = command
|
9
|
+
prepareContext
|
10
|
+
excuteCommands
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_accessor :command
|
16
|
+
|
17
|
+
attr_accessor :arguments
|
18
|
+
|
19
|
+
def prepareContext
|
20
|
+
Throw.note "Prepare combine context ..."
|
21
|
+
plist = CFPropertyList::List.new :file => command.config_path
|
22
|
+
@arguments = CFPropertyList.native_types plist.value
|
23
|
+
end
|
24
|
+
|
25
|
+
def excuteCommands
|
26
|
+
Throw.note "Begin excute commands ..."
|
27
|
+
outputPath = command.work_path + "/_confuses"
|
28
|
+
if File.exist? outputPath
|
29
|
+
FileUtils.rm_rf outputPath
|
30
|
+
end
|
31
|
+
projectPaths = nil
|
32
|
+
if command.commands.include? "confuse"
|
33
|
+
projectPaths = Dir["#{command.input_path}/*/*.xcodeproj"]
|
34
|
+
args = ["confuse"] + arguments["keywords"]
|
35
|
+
projectPaths = projectPaths.map { |path|
|
36
|
+
Command.run args + [
|
37
|
+
"--project-path=#{path}",
|
38
|
+
"--output-path=#{outputPath}"
|
39
|
+
]
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
ipaPaths = nil
|
44
|
+
if command.commands.include? "archive"
|
45
|
+
outputPath = command.work_path + "/_packges"
|
46
|
+
if File.exist? outputPath
|
47
|
+
FileUtils.rm_rf outputPath
|
48
|
+
end
|
49
|
+
if !projectPaths
|
50
|
+
projectPaths = Dir["#{command.input_path}/*/*.xcodeproj"]
|
51
|
+
end
|
52
|
+
args = ["archive", arguments["method"]]
|
53
|
+
ipaPaths = projectPaths.map { |path|
|
54
|
+
Command.run args + [
|
55
|
+
"--project-path=#{path}",
|
56
|
+
"--output-path=#{outputPath}"
|
57
|
+
]
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
if command.commands.include? "resign"
|
62
|
+
if !ipaPaths
|
63
|
+
ipaPaths = Dir["#{command.input_path}/*/*.ipa"]
|
64
|
+
end
|
65
|
+
args = ["resign"] + ipaPaths + [
|
66
|
+
"--key-id=#{arguments["key_id"]}",
|
67
|
+
"--issuer-id=#{arguments["issuer_id"]}",
|
68
|
+
"--keyfile-path=#{arguments["keyfile_path"]}",
|
69
|
+
"--user-password=#{arguments["user_password"]}",
|
70
|
+
"--bundle-identifier=#{arguments["CFBundleIdentifier"]}",
|
71
|
+
"--short-version=#{arguments["CFBundleShortVersionString"]}",
|
72
|
+
"--bundle-version=#{arguments["CFBundleVersion"]}"
|
73
|
+
]
|
74
|
+
arg = arguments["apple_id"]
|
75
|
+
if arg
|
76
|
+
args << "--apple-id=#{arg}"
|
77
|
+
end
|
78
|
+
arg = arguments["CFBundleName"]
|
79
|
+
if arg
|
80
|
+
args << "--bundle-name=#{arg}"
|
81
|
+
end
|
82
|
+
arg = arguments["CFBundleDisplayName"]
|
83
|
+
if arg
|
84
|
+
args << "--display-name=#{arg}"
|
85
|
+
end
|
86
|
+
arg = arguments["CFBundleExecutable"]
|
87
|
+
if arg
|
88
|
+
args << "--executable-name=#{arg}"
|
89
|
+
end
|
90
|
+
arg = arguments["iconAssets_path"]
|
91
|
+
if arg
|
92
|
+
args << "--iconAssets-path=#{arg}"
|
93
|
+
end
|
94
|
+
ipaPaths = Command.run args
|
95
|
+
end
|
96
|
+
|
97
|
+
if command.commands.include? "upload"
|
98
|
+
if !ipaPaths
|
99
|
+
ipaPaths = Dir["#{command.input_path}/*/*.ipa"]
|
100
|
+
end
|
101
|
+
Command.run ["upload"] + ipaPaths + [
|
102
|
+
"--key-id=#{arguments["key_id"]}",
|
103
|
+
"--issuer-id=#{arguments["issuer_id"]}",
|
104
|
+
"--keyfile-path=#{arguments["keyfile_path"]}",
|
105
|
+
"--bundle-identifier=#{arguments["CFBundleIdentifier"]}"
|
106
|
+
]
|
107
|
+
end
|
108
|
+
|
109
|
+
Throw.note "==========================End!=========================="
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Escalator
|
2
|
+
|
3
|
+
class Command
|
4
|
+
|
5
|
+
class Archive < Command
|
6
|
+
|
7
|
+
class Help < CLAide::Help
|
8
|
+
|
9
|
+
def message
|
10
|
+
[
|
11
|
+
formatted_error_message,
|
12
|
+
"请执行: escalator archive --help".ansi.green
|
13
|
+
].compact.join("\n\n").insert 0, "\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :method
|
19
|
+
|
20
|
+
attr_reader :project_path
|
21
|
+
|
22
|
+
attr_reader :output_path
|
23
|
+
|
24
|
+
attr_reader :show_output
|
25
|
+
alias_method :show_output?, :show_output
|
26
|
+
|
27
|
+
self.command = "archive"
|
28
|
+
|
29
|
+
self.summary = "打包 Xcode 工程"
|
30
|
+
|
31
|
+
self.description = <<-DESC
|
32
|
+
利用 Xcode 工程的配置的编译选项, 和自定义参数, 自动打包 ipa 并导出
|
33
|
+
|
34
|
+
`METHOD` 为 ipa 包导出类型: #{"app-store".ansi.green}, #{"ad-hoc".ansi.green}
|
35
|
+
DESC
|
36
|
+
|
37
|
+
self.arguments = [
|
38
|
+
CLAide::Argument.new('METHOD', true, false)
|
39
|
+
]
|
40
|
+
|
41
|
+
def self.options
|
42
|
+
[
|
43
|
+
["--project-path=path", "path 为 .xcproject 源路径"],
|
44
|
+
["--output-path=path", "path 为 .ipa 以及部分重签资源的存放路径"],
|
45
|
+
["--show-output", "文件管理中展示输出文件夹, 默认: 否"]
|
46
|
+
].concat super
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize argv
|
50
|
+
@method = argv.arguments!.first
|
51
|
+
@project_path = argv.option "project-path", ""
|
52
|
+
@output_path = argv.option "output-path", ""
|
53
|
+
@show_output = argv.flag? "show-output", false
|
54
|
+
super
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate!
|
58
|
+
super
|
59
|
+
if !method
|
60
|
+
help! "未检测到 METHOD 参数"
|
61
|
+
elsif !%w(app-store ad-hoc).include? method
|
62
|
+
help! "METHOD 参数只能为 #{"app-store".ansi.green}, #{"ad-hoc".ansi.green}"
|
63
|
+
end
|
64
|
+
if project_path.empty?
|
65
|
+
help! "未检测到 --project-path 参数"
|
66
|
+
end
|
67
|
+
if output_path.empty?
|
68
|
+
help! "未检测到 --output-path 参数"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def help!(error_message = nil)
|
73
|
+
invoked_command_class.help!(error_message, Help)
|
74
|
+
end
|
75
|
+
|
76
|
+
def run
|
77
|
+
Escalator::Archive.run self
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Escalator
|
2
|
+
|
3
|
+
class Command
|
4
|
+
|
5
|
+
class Combine < Command
|
6
|
+
|
7
|
+
class Help < CLAide::Help
|
8
|
+
|
9
|
+
def message
|
10
|
+
[
|
11
|
+
formatted_error_message,
|
12
|
+
"请执行: escalator combine --help".ansi.green
|
13
|
+
].compact.join("\n\n").insert 0, "\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :commands
|
19
|
+
|
20
|
+
attr_reader :config_path
|
21
|
+
|
22
|
+
attr_reader :input_path
|
23
|
+
|
24
|
+
attr_reader :work_path
|
25
|
+
|
26
|
+
self.command = "combine"
|
27
|
+
|
28
|
+
self.summary = "组合 命令: confuse archive resign upload"
|
29
|
+
|
30
|
+
self.description = <<-DESC
|
31
|
+
可选择组合相关命令, 创建执行自定义任务流
|
32
|
+
|
33
|
+
`COMMAND` 要组合的命令, 支持 #{"confuse archive resign upload".ansi.green} 命令, 进行选择组合执行
|
34
|
+
|
35
|
+
注意命令的功能之间, 是否具备组合粘性:
|
36
|
+
|
37
|
+
#{"上一条命令的输出预期 => 下一条命令的输入预期 匹配".ansi.yellow}
|
38
|
+
|
39
|
+
`--input-path=path` 参数下目录结构要求:
|
40
|
+
|
41
|
+
1. #{"confuse archive".ansi.green} 为初始命令
|
42
|
+
|
43
|
+
--input-path
|
44
|
+
|
|
45
|
+
| --- 工程名 (支持多个)
|
46
|
+
| |
|
47
|
+
| ----- | --- .xcodeproj 文件
|
48
|
+
| |
|
49
|
+
| ----- | --- CoverInfo.plist 文件 (可缺省: 执行 #{"escalator setup".ansi.green} 获取配置模版)
|
50
|
+
|
51
|
+
2. #{"resign upload".ansi.green} 为初始命令
|
52
|
+
|
53
|
+
--input-path
|
54
|
+
|
|
55
|
+
| --- 工程名 (支持多个)
|
56
|
+
| |
|
57
|
+
| ----- | --- .ipa 文件
|
58
|
+
| | |
|
59
|
+
| ----- | --- .xcassets 文件 (ipa 对应工程下所有被引用的的 .xcassets)
|
60
|
+
| | |
|
61
|
+
| ----- | --- CoverInfo.plist 文件 (可缺省: 执行 #{"escalator setup".ansi.green} 获取配置模版)
|
62
|
+
DESC
|
63
|
+
|
64
|
+
self.arguments = [
|
65
|
+
CLAide::Argument.new('COMMAND', true, true)
|
66
|
+
]
|
67
|
+
|
68
|
+
def self.options
|
69
|
+
[
|
70
|
+
["--config-path=path", "path 为任务流需要的配置参数 ConfigInfo.plist 文件路径, 执行 #{"escalator setup".ansi.green} 获取配置模版"],
|
71
|
+
["--input-path=path", "path 为初始命令需要的输入根目录, 会自动检测需要的输入文件"],
|
72
|
+
["--work-path=path", "path 为脚本工作的根目录"]
|
73
|
+
].concat super
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize argv
|
77
|
+
@commands = argv.arguments!
|
78
|
+
@config_path = argv.option "config-path", ""
|
79
|
+
@input_path = argv.option "input-path", ""
|
80
|
+
@work_path = argv.option "work-path", ""
|
81
|
+
super
|
82
|
+
end
|
83
|
+
|
84
|
+
def validate!
|
85
|
+
super
|
86
|
+
if commands.empty?
|
87
|
+
help! "未检测到 COMMAND 参数"
|
88
|
+
end
|
89
|
+
cmds = (commands - (%w(confuse archive resign upload) & commands))
|
90
|
+
if !cmds.empty?
|
91
|
+
help! "检测到 非法参数: #{cmds.join ", "}"
|
92
|
+
end
|
93
|
+
if config_path.empty?
|
94
|
+
help! "未检测到 --config-path 参数"
|
95
|
+
end
|
96
|
+
if input_path.empty?
|
97
|
+
help! "未检测到 --input-path 参数"
|
98
|
+
end
|
99
|
+
if work_path.empty?
|
100
|
+
help! "未检测到 --work-path 参数"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def help!(error_message = nil)
|
105
|
+
invoked_command_class.help!(error_message, Help)
|
106
|
+
end
|
107
|
+
|
108
|
+
def run
|
109
|
+
Escalator::Combine.run self
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Escalator
|
2
|
+
|
3
|
+
class Command
|
4
|
+
|
5
|
+
class Confuse < Command
|
6
|
+
|
7
|
+
class Help < CLAide::Help
|
8
|
+
|
9
|
+
def message
|
10
|
+
[
|
11
|
+
formatted_error_message,
|
12
|
+
"请执行: escalator confuse --help".ansi.green
|
13
|
+
].compact.join("\n\n").insert 0, "\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :keywords
|
19
|
+
|
20
|
+
attr_reader :project_path
|
21
|
+
|
22
|
+
attr_reader :output_path
|
23
|
+
|
24
|
+
attr_reader :show_output
|
25
|
+
alias_method :show_output?, :show_output
|
26
|
+
|
27
|
+
self.command = "confuse"
|
28
|
+
|
29
|
+
self.summary = "混淆 Xcode 工程"
|
30
|
+
|
31
|
+
self.description = <<-DESC
|
32
|
+
使用置换关键词的方式混淆项目内容和文件名
|
33
|
+
|
34
|
+
`KEYWORD` 要置换的关键词, 关键词个数不限
|
35
|
+
|
36
|
+
支持混淆的文件类型: #{"h, hpp, pch, c, m, mm, cpp, swift, xib, storyboard".ansi.yellow}
|
37
|
+
|
38
|
+
支持 #{"Swift".ansi.yellow}, #{"OC".ansi.yellow} 混编模式
|
39
|
+
DESC
|
40
|
+
|
41
|
+
self.arguments = [
|
42
|
+
CLAide::Argument.new('KEYWORD', true, true)
|
43
|
+
]
|
44
|
+
|
45
|
+
def self.options
|
46
|
+
[
|
47
|
+
["--project-path=path", "path 为 .xcodeproj 源路径"],
|
48
|
+
["--output-path=path", "path 为混淆工程存放路径"],
|
49
|
+
["--show-output", "文件管理中展示输出文件夹, 默认: 否"]
|
50
|
+
].concat super
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize argv
|
54
|
+
@keywords = argv.arguments!.select { |arg| !arg.empty? }
|
55
|
+
@project_path = argv.option "project-path", ""
|
56
|
+
@output_path = argv.option "output-path", ""
|
57
|
+
@show_output = argv.flag? "show-output", false
|
58
|
+
super
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate!
|
62
|
+
super
|
63
|
+
if keywords.empty?
|
64
|
+
help! "未检测到 KEYWORD 参数"
|
65
|
+
end
|
66
|
+
if project_path.empty?
|
67
|
+
help! "未检测到 --project-path 参数"
|
68
|
+
end
|
69
|
+
if output_path.empty?
|
70
|
+
help! "未检测到 --output-path 参数"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def help!(error_message = nil)
|
75
|
+
invoked_command_class.help!(error_message, Help)
|
76
|
+
end
|
77
|
+
|
78
|
+
def run
|
79
|
+
Escalator::Confuse.run self
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|