cocoapods-mars 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,120 @@
1
+ # require 'json'
2
+ require 'plist'
3
+ require_relative '../project'
4
+
5
+ module Pod
6
+ class Command
7
+ class Vemars
8
+ class Create < Vemars
9
+ self.summary = 'Create iOS vemars project given name and appKey'
10
+ self.description = <<-DESC
11
+ Create one iOS vemars project given name and appKey
12
+ DESC
13
+
14
+ self.arguments = [
15
+ CLAide::Argument.new('NAME', false),
16
+ CLAide::Argument.new('VERSION', false),
17
+ ]
18
+
19
+ def self.options
20
+ options = [
21
+ ['--language=LANGUAGE', 'language should be objc or swift'],
22
+ ['--silent', 'do not run pod install'],
23
+ ['--bundle_id=bundle_id', 'the bundle_id from Vemars'],
24
+ ['--com=COM1,COM2', 'Selected components in vemars.'],
25
+ ['--config=CONFIG_PATH', 'config path of vemars.'],
26
+ ['--service_url=SERVICE_URL', 'url of vemars CLI service.'],
27
+ ['--git=GIT_URL', 'git url of demo repo'],
28
+ ['--pod_repo_no_update', 'do not run pod repo update'],
29
+ ['--sources','pod repos sources'],
30
+ ['--test','should run test']
31
+ ]
32
+ options.concat(super.reject { |option, _| option == '--silent' })
33
+ end
34
+
35
+ def initialize(argv)
36
+ @name = argv.shift_argument
37
+ @version = argv.shift_argument
38
+ @language = argv.option('language', 'objc')
39
+ git_url = argv.option('git', 'https://github.com/volcengine/ve_Template_iOS.git')
40
+ @silent = argv.flag?('silent', false)
41
+ @test = argv.flag?('test', false)
42
+ @repo_no_update = argv.flag?('pod_repo_no_update',false)
43
+ @appkey = argv.option('appkey', '')
44
+ @bundle_id = argv.option('bundle_id', nil)
45
+ @selected_components = argv.option('com', "").split(',')
46
+ @config_json = argv.option('config', nil)
47
+ service_url = argv.option('service_url',nil)
48
+ sources = argv.option('sources','https://github.com/volcengine/volcengine-specs.git,https://cdn.cocoapods.org/')
49
+ @project = VemarsProject.new(@appkey, @selected_components, @config_json, @version, @bundle_id, @name, @language, git_url,service_url,sources)
50
+ super
51
+ @additional_args = argv.remainder!
52
+ end
53
+
54
+ def validate!
55
+ super
56
+ if !@test
57
+ if @config_json.nil? || @config_json.empty?
58
+ help! 'An config.json for the project is required.'
59
+ end
60
+ unless File.exist? @config_json
61
+ help! "onekit-config.json is not found at #{Dir.pwd}"
62
+ end
63
+ end
64
+ # help! '信息有误' unless @project.validate?
65
+ end
66
+
67
+ def run
68
+ puts 'Hi, welcome to vemars!'
69
+ @project.generate
70
+ podInstallIfNeeded
71
+ if @test
72
+ runXcodeTest
73
+ else
74
+ openXcodeWorkSpace
75
+ end
76
+ end
77
+
78
+ def podInstallIfNeeded
79
+ puts "Current dir: #{Dir.pwd}"
80
+ project_dir = File.join(Dir.pwd, [@project.basicInfo.name, "Project"])
81
+ puts "Pod install directory: #{project_dir}"
82
+ if @silent
83
+ puts "Pod install skipped!"
84
+ puts "You can run Pod install in '#{project_dir}' later!"
85
+ puts "You can run Pod install in '#{project_dir}' later!"
86
+ puts "You can run Pod install in '#{project_dir}' later!"
87
+ return
88
+ end
89
+
90
+ Dir.chdir(project_dir) do
91
+ # system('bundle install')
92
+ # system('bundle exec pod install --repo-update')
93
+ if @repo_no_update
94
+ puts "pod install with no repo update"
95
+ system('pod install --no-repo-update')
96
+ else
97
+ system('pod install --repo-update')
98
+ end
99
+ end
100
+ end
101
+
102
+ def openXcodeWorkSpace
103
+ workspace_dir = File.join(Dir.pwd, [@project.basicInfo.name, "Project","'#{@project.basicInfo.name}'.xcworkspace"])
104
+ system("open -a /Applications/Xcode.app '#{workspace_dir}'")
105
+ end
106
+
107
+
108
+ def runXcodeTest
109
+ puts "run test with xcode build"
110
+ workspace_dir = File.join(Dir.pwd, [@project.basicInfo.name, "Project"])
111
+ Dir.chdir(workspace_dir) do
112
+ cmd = "xcodebuild clean build -workspace '#{@project.basicInfo.name}'.xcworkspace -scheme '#{@project.basicInfo.name}'_InHouse -configuration Debug -destination generic/platform=iOS -sdk iphonesimulator ARCHS=x86_64 ONLY_ACTIVE_ARCH=NO"
113
+ system cmd
114
+ end
115
+ end
116
+
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,92 @@
1
+ require_relative '../project'
2
+
3
+ module Pod
4
+ class Command
5
+ class Vemars
6
+ class Patch < Vemars
7
+ self.summary = 'Patch exisiting iOS project with vemars services'
8
+ self.description = <<-DESC
9
+ Patch exisiting iOS project with vemars services, given
10
+ project directory, same level where Podfile locates,
11
+ vemars baseline version and selected components within vemars
12
+ DESC
13
+
14
+ self.arguments = [
15
+ CLAide::Argument.new('VERSION', false),
16
+ ]
17
+
18
+ def self.options
19
+ options = [
20
+ ['--path=PODFILE_PATH', 'the /path/to/Dir_contains_Podfile'],
21
+ ['--com=COM1,COM2', 'Selected components in vemars.'],
22
+ ['--config=CONFIG_PATH', 'config path of vemars.'],
23
+ ['--service_url=SERVICE_URL', 'url of vemars CLI service.'],
24
+ ['--git=GIT_URL', 'git url of demo repo'],
25
+ ['--pod_repo_no_update', 'do not run pod repo update'],
26
+ ['--sources','pod repos sources']
27
+ ]
28
+ options.concat(super.reject { |option, _| option == '--silent' })
29
+ end
30
+
31
+ def initialize(argv)
32
+ @baseline = argv.shift_argument
33
+ @path = argv.option('path', '')
34
+ @selected_components = argv.option('com', '').split(',')
35
+ @config_json = argv.option('config', '/onekit-config.json')
36
+ @repo_no_update = argv.flag?('pod_repo_no_update',false)
37
+ git_url = argv.option('git', 'https://github.com/volcengine/ve_Template_iOS.git')
38
+ service_url = argv.option('service_url',nil)
39
+ sources = argv.option('sources','https://github.com/volcengine/volcengine-specs.git,https://cdn.cocoapods.org/')
40
+ @project = VemarsProject.new(@appkey, @selected_components, @config_json, @baseline, git_url, service_url,sources)
41
+ super
42
+ @additional_args = argv.remainder!
43
+ end
44
+
45
+ def validate!
46
+ super
47
+ if @path.nil? || @path.empty?
48
+ help! 'A project path where Podfile locates is required '
49
+ end
50
+ unless File.exist? @config_json
51
+ help! "onekit-config.json is not found at #{Dir.pwd}"
52
+ end
53
+ end
54
+
55
+ def run
56
+ @project.patch @path
57
+ podInstallIfNeeded
58
+ openXcodeWorkSpace
59
+ end
60
+
61
+ def podInstallIfNeeded
62
+ puts "Current dir: #{Dir.pwd}"
63
+ project_dir = @path
64
+ puts "Pod install directory: #{project_dir}"
65
+ if @silent
66
+ puts "Pod install skipped!"
67
+ puts "You can run Pod install in '#{project_dir}' later!"
68
+ return
69
+ end
70
+
71
+ Dir.chdir(project_dir) do
72
+ # system('bundle install')
73
+ # system('bundle exec pod install --repo-update')
74
+ if @repo_no_update
75
+ puts "pod install with no repo update"
76
+ system('pod install --no-repo-update')
77
+ else
78
+ system('pod install --repo-update')
79
+ end
80
+ end
81
+ end
82
+
83
+ def openXcodeWorkSpace
84
+ workspaces = Dir.entries(@path).select { |e| e.end_with?(".xcworkspace") }
85
+ full_path = File.join(@path, workspaces.first)
86
+ system("open -a /Applications/Xcode.app '#{full_path}'")
87
+ end
88
+
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,34 @@
1
+ module Pod
2
+ class Command
3
+ class Vemars < Command
4
+ require_relative 'vemars/create'
5
+ require_relative 'vemars/baselines'
6
+ require_relative 'vemars/components'
7
+ require_relative 'vemars/patch'
8
+
9
+ self.summary = 'vemars iOS project generation tool'
10
+ self.description = <<-DESC
11
+ Create a mars iOS project.
12
+ DESC
13
+
14
+ self.abstract_command = true
15
+ # self.default_subcommand = 'create'
16
+ self.command = 'mars'
17
+
18
+ # 解析命令别名
19
+ def self.parse(argv)
20
+ expanded_alias = argv.option('expanded-alias')
21
+ cmd = super(argv)
22
+ if cmd.class == Pod::Command::Vemars
23
+ if !expanded_alias.blank? && (arg = argv.shift_argument)
24
+ require 'shellwords'
25
+ new_argv = expanded_alias.shellsplit + argv.remainder
26
+ cmd = super(CLAide::ARGV.coerce(new_argv))
27
+ end
28
+ end
29
+ cmd
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1 @@
1
+ require 'cocoapods-vemars/command/vemars'
@@ -0,0 +1,3 @@
1
+ module CocoapodsVemars
2
+ VERSION = "0.0.12"
3
+ end
@@ -0,0 +1,14 @@
1
+
2
+ module Pod
3
+ class Podfile
4
+ module DSL
5
+ alias vemars_pod pod
6
+
7
+ def pod(name = nil, *requirements)
8
+ puts "name #{name}"
9
+ vemars_pod(name = nil, *requirements)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,111 @@
1
+ module Pod
2
+ class PodfileTemplate
3
+
4
+ attr_reader :componentsList
5
+ attr_reader :sources
6
+ attr_reader :baseline_version
7
+
8
+ IOS_VERSION = '9.0'.freeze
9
+
10
+ def initialize(baseline_version, componentsList, sources)
11
+ @baseline_version = baseline_version
12
+ @componentsList = componentsList
13
+ @sources = sources
14
+ end
15
+
16
+ def to_dsl
17
+ <<-SPEC
18
+
19
+ #{platform}
20
+
21
+ #plugin 'cocoapods-vemars'
22
+ install! 'cocoapods', :deterministic_uuids => false
23
+
24
+ #{source_template}
25
+
26
+ #{releasePod}
27
+ #{target}
28
+ #{post_install_setup}
29
+ SPEC
30
+ end
31
+
32
+ def platform
33
+ <<-SPEC
34
+ platform :ios, #{IOS_VERSION}
35
+ inhibit_all_warnings!
36
+ SPEC
37
+ end
38
+
39
+ def source_template
40
+ source_urls = sources.split(",")
41
+ "#{source_urls.map{ |url| "source '#{url}'"}.join("\n")}"
42
+ end
43
+
44
+ def releasePod
45
+ <<-SPEC
46
+
47
+ def release_pod
48
+ #baseline version #{baseline_version}
49
+ #{@componentsList.map { |component|
50
+ result = "\tpod '#{component.name}'"
51
+ if !component.version.nil?
52
+ result = result + ", '#{component.version}'"
53
+ end
54
+
55
+ if !component.subspecs.nil?
56
+ result = result + ", :subspecs => #{component.subspecs}"
57
+ end
58
+ result
59
+ }.join("\n")}
60
+ end
61
+ SPEC
62
+ end
63
+
64
+ def target
65
+ <<-SPEC
66
+ target 'Template_InHouse' do
67
+ release_pod
68
+ pod 'App/Debug', :path => './../DevPods/', :inhibitat_warnings => false
69
+ end
70
+ SPEC
71
+ end
72
+
73
+ def post_install_setup
74
+ <<-SPEC
75
+ def update_deployment_config(config = nil)
76
+ return if config.nil?
77
+ config.build_settings['ENABLE_BITCODE'] = 'NO'
78
+ if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 12.0
79
+ config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
80
+ end
81
+ end
82
+
83
+ post_install do |installer|
84
+ installer.pods_project.build_configurations.each do |config|
85
+ update_deployment_config(config)
86
+ end
87
+
88
+ installer.pods_project.targets.each do |target|
89
+ target.build_configurations.each do |config|
90
+ update_deployment_config(config)
91
+ end
92
+ end
93
+ ## for generate_multiple_pod_projects = true
94
+ installer.generated_projects.each do |project|
95
+ project.build_configurations.each do |config|
96
+ update_deployment_config(config)
97
+ end
98
+
99
+ project.targets.each do |target|
100
+ target.build_configurations.each do |config|
101
+ update_deployment_config(config)
102
+ end
103
+ end
104
+ end
105
+
106
+ end
107
+ SPEC
108
+ end
109
+ end
110
+
111
+ end
@@ -0,0 +1,35 @@
1
+ require 'Rest'
2
+
3
+ module Pod
4
+ class Baselines_api
5
+ include Concurrent::Async
6
+
7
+ BASELINES_URL = 'https://mars-fwk.vemarsdev.com/mpaas/baseline/baselines'.freeze
8
+ attr_accessor :result
9
+
10
+ public def initialize(url=BASELINES_URL)
11
+ @baseline_url = (url.blank? ? BASELINES_URL : url + "mpaas/baseline/baselines")
12
+ end
13
+
14
+ def getBaselines
15
+ body= "{\"technology_stack\": \"iOS\"}"
16
+ header = {"ContentType" => 'application/json'}
17
+ response = REST.post(@baseline_url, body, header)
18
+ if response.ok?
19
+ json = JSON.parse(response.body)
20
+ error_code = json["error_no"]
21
+ if error_code == 0
22
+ @result = json["data"]['baselines']
23
+ @result = @result.sort.reverse
24
+ puts "Version list: #{@result}"
25
+ else
26
+ puts "Error #{error_code}(#{json["error_msg"]}): #{json["err_detail"]}}"
27
+ end
28
+ else
29
+ puts "response status: #{response.status_code}"
30
+ end
31
+ end
32
+
33
+
34
+ end
35
+ end
@@ -0,0 +1,62 @@
1
+ require_relative 'baselines_api'
2
+ require_relative '../command/component'
3
+
4
+ module Pod
5
+ class Components_api
6
+ include Concurrent::Async
7
+
8
+ COMPONENTS_URL = 'https://mars-fwk.vemarsdev.com/mpaas/baseline/baseline_config'.freeze
9
+
10
+ attr_reader :source
11
+ attr_reader :baseline
12
+ attr_reader :component_list
13
+ attr_reader :baseline_api
14
+ attr_reader :components_url
15
+
16
+ public def initialize(baseline=nil,url=COMPONENTS_URL)
17
+ @baseline = baseline
18
+ @source = ""
19
+ @component_list = []
20
+ @baseline_api = Baselines_api.new(url)
21
+ @components_url = (url.blank? ? COMPONENTS_URL : url + "mpaas/baseline/baseline_config")
22
+ end
23
+
24
+ public def validate!
25
+ baseline_api.await.getBaselines
26
+ if @baseline.nil? && baseline_api.result.length() == 0
27
+ help! "No baselines info existed, please check with server admin"
28
+ elsif @baseline.nil? && baseline_api.result.length() > 0
29
+ @baseline = baseline_api.result[0]
30
+ elsif !@baseline.nil? && baseline_api.result.length() > 0
31
+ if !baseline_api.result.include?(@baseline)
32
+ puts "Invalid baseline version provided!"
33
+ help! "Invalid baseline version provided!"
34
+ end
35
+ end
36
+ end
37
+
38
+ public def getComponents(baseline=@baseline)
39
+ body= "{\"baseline_version\": \"#{baseline}\", \"technology_stack\": \"iOS\"}"
40
+ header = {"ContentType" => 'application/json'}
41
+ response = REST.post(@components_url, body, header)
42
+ deserilise(response)
43
+ return component_list
44
+ end
45
+
46
+ def deserilise(response)
47
+ if response.ok?
48
+ json = JSON.parse(response.body)
49
+ error_code = json["error_no"]
50
+ if error_code == 0
51
+ @source = json['data']['source']
52
+ @component_list = json['data']['iosPlugins'].map { |obj| Component.new(obj) }
53
+ else
54
+ puts "Error #{error_code}(#{json["error_msg"]}): #{json["err_detail"]}}"
55
+ end
56
+ else
57
+ puts "fail to get components, response status: #{response.status_code}"
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,203 @@
1
+ require_relative '../hook/podfile_template'
2
+ require_relative 'tailor'
3
+ require 'rexml/document'
4
+ include REXML
5
+ require "fileutils"
6
+ require 'tempfile'
7
+ require 'xcodeproj'
8
+
9
+ module Pod
10
+ class Patcher
11
+ include Pod
12
+
13
+ attr_reader :podfile_dir
14
+ attr_reader :template
15
+
16
+ def initialize(podfile_dir, baseline, components_details, source, git_url,demo_tag)
17
+ @podfile_dir = podfile_dir
18
+ @template = PodfileTemplate.new(baseline, components_details, source)
19
+ @components_details = components_details
20
+ @git_url = git_url
21
+ puts git_url
22
+ @hasInjectedSource = false
23
+ @hasInjectedVemarsPods = false
24
+ @demo_tag = demo_tag
25
+ end
26
+
27
+ def execute
28
+ insert_plist
29
+ plugin_demos
30
+ patch_podfile
31
+ end
32
+
33
+ private
34
+ attr_accessor :hasInjectedSource
35
+ attr_accessor :hasInjectedVemarsPods
36
+ attr_reader :components_details
37
+
38
+ def patch_podfile
39
+ podfile_path = find_podfile
40
+ if podfile_path.nil? || podfile_path.empty?
41
+ UI.puts "can not file project Podfile "
42
+ return
43
+ end
44
+ UI.puts "patching project with podfile path #{podfile_path}"
45
+
46
+ tempfile = Tempfile.new('podfile_temp')
47
+ sourceAnchors = source_anchors(podfile_path)
48
+ targetAnchors = target_anchor(podfile_path)
49
+
50
+ File.open(podfile_path, 'r') do |f|
51
+ f.each_line{ |line|
52
+ pre_inject, post_inject = inject_source(sourceAnchors, line)
53
+ if pre_inject.empty?
54
+ pre_inject = inject_vemarsPodsDef(targetAnchors, line)
55
+ end
56
+
57
+ if post_inject.empty?
58
+ post_inject = inject_releasePodInTarget(line)
59
+ end
60
+
61
+ if !pre_inject.empty?
62
+ tempfile.puts pre_inject
63
+ end
64
+ tempfile.puts line
65
+ if !post_inject.empty?
66
+ tempfile.puts post_inject
67
+ end
68
+ }
69
+ end
70
+ tempfile.close
71
+ FileUtils.mv(tempfile.path, podfile_path)
72
+ end
73
+
74
+ def plugin_demos
75
+ clone_project
76
+ tailor_demos
77
+ cleanup
78
+ end
79
+
80
+ def clone_project
81
+ if @demo_tag.nil?
82
+ system("git clone #{@git_url} ./.vemars")
83
+ else
84
+ system("git clone #{@git_url} ./.vemars -b #{@demo_tag} --config advice.detachedHead=false")
85
+ end
86
+ system("mv ./.vemars/DevPods ./DevPods")
87
+ end
88
+
89
+ def tailor_demos
90
+ tailor = DemoTailor.new(@components_details)
91
+ tailor.execute
92
+ end
93
+
94
+ def cleanup
95
+ system("rm -rf ./.vemars")
96
+ end
97
+
98
+ def find_podfile
99
+ locations = []
100
+
101
+ Dir.entries(Dir.pwd).select { |e| e.end_with?(".xcworkspace") }.each do |xcworkspace|
102
+ full_path = File.join(@podfile_dir, xcworkspace, "contents.xcworkspacedata")
103
+ if File.file?(full_path)
104
+ Document.new(File.new(full_path)).elements.each { |e|
105
+ e.elements.each ("FileRef"){ |ref|
106
+ locations << ref.attributes["location"]
107
+ }
108
+ }
109
+ end
110
+ end
111
+
112
+ project = locations.reject { |e| e.include?("Pods/Pods.xcodeproj") }.map { |location|
113
+ File.expand_path("Podfile",File.dirname(File.join(@podfile_dir,location[6..-1])))
114
+ }.select { |full_path| File.file?(full_path) }
115
+
116
+ if project.empty?
117
+
118
+ full_path = File.join(@podfile_dir, "Podfile")
119
+ return full_path if File.file?(full_path)
120
+
121
+ full_path = File.join(@podfile_dir, "Project", "Podfile")
122
+ return full_path if File.file?(full_path)
123
+ end
124
+
125
+ if project.empty?
126
+ UI.puts "can not find Podfile in #{@podfile_dir}"
127
+ end
128
+
129
+ return project.first
130
+ end
131
+
132
+
133
+
134
+ def insert_plist
135
+ puts "insert plist"
136
+ plist_dir = Dir.pwd + "/onekit-config.plist"
137
+ Dir.entries(Dir.pwd).select { |e| e.end_with?(".xcodeproj") }.each do |xcodeproj|
138
+ full_path = File.join(@podfile_dir, xcodeproj)
139
+ puts "insert plist in :#{full_path}"
140
+ project = Xcodeproj::Project.open(full_path)
141
+ file = project.new_file(plist_dir)
142
+ main_target = project.targets.first
143
+ main_target.add_resources([file])
144
+ project.save
145
+ end
146
+ end
147
+
148
+
149
+ def source_anchors(podfile)
150
+ result = []
151
+ File.open podfile do |file|
152
+ result = file.find_all { |line| line.include?('source') }
153
+ end
154
+ return result
155
+ end
156
+
157
+ def target_anchor(podfile)
158
+ result = []
159
+ File.open podfile do |file|
160
+ result = file.find_all { |line| line.include?('target "') | line.include?("target '") }
161
+ end
162
+ return result
163
+ end
164
+
165
+ ## return (pre-inject, post-inject)
166
+ def inject_source(anchor, line)
167
+ return '','' if @hasInjectedSource
168
+
169
+ pre_inject = ''
170
+ post_inject = ''
171
+ if anchor.empty?
172
+ pre_inject = @template.source_template
173
+ @hasInjectedSource = true
174
+
175
+ elsif line.include? anchor[anchor.length - 1]
176
+ post_inject = @template.source_template
177
+ @hasInjectedSource = true
178
+ end
179
+ return pre_inject,post_inject
180
+ end
181
+
182
+ ## return pre_inject
183
+ def inject_vemarsPodsDef(anchor, line)
184
+ return '' if @hasInjectedVemarsPods
185
+
186
+ if !anchor.empty? && line.include?(anchor[0])
187
+ @hasInjectedVemarsPods = true
188
+ return @template.releasePod, ''
189
+ end
190
+ return ''
191
+ end
192
+
193
+
194
+ ## return post_inject
195
+ def inject_releasePodInTarget(line)
196
+ if line.include?('target "') | line.include?("target '")
197
+ return "\trelease_pod \n\tpod 'App/Debug', :path => './DevPods/', :inhibitat_warnings => false"
198
+ end
199
+ return ''
200
+ end
201
+
202
+ end
203
+ end