cocoapods-jsource 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1f41012354f907c69ab430275b225d557aae7816be39059850418b839aafda6
4
- data.tar.gz: 8f1e481b717aae28942f3e153da93e147499524c883fc6c3fd11f664044d491f
3
+ metadata.gz: 67322efccb2959369205ff4e95f974670f0f0dd9fc3a1b9f60bb94584958a42b
4
+ data.tar.gz: e51f5e1d5bb70389a5d7ba501c7e5f32a4b3c468bb02727fdfa64c67874a5819
5
5
  SHA512:
6
- metadata.gz: 6113c095233da159a99fad3311a1c999e377e64b4eaf4835ae3a5d7cedf687b0d8b0294c8c8e5cc8e66176b11d6b43d41f68bff094a90ec2cd029f9cad9d9733
7
- data.tar.gz: dcf0a3f39a72152b9b985cb83340f85a487e0f4c1a6aaf27783eef3f95622514c1ec97525b8802921086ac076480fe0dadc8f5e3255f64c07be0ce6686a60643
6
+ metadata.gz: 958bfe53fad947326aa12c53f313ff2f4cbbb0f0ad2ce6ff013c63a18226299237af9a989a6ebf419c8ee0542277cf1ae0d001ce204d0767e39735ee78da62fc
7
+ data.tar.gz: 29158cd9629837b9189e8ea7dfc8ff5a0b71b763eeafee391f41fe7da8d2ac6780fae8fa5871f04495153b00f24dc64ea4d4318bb7dad10b33169d5207aa3e05
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source "https://gems.ruby-china.com/"
2
2
 
3
3
  # Specify your gem's dependencies in cocoapods-jsource.gemspec
4
4
  gemspec
@@ -1,31 +1,34 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cocoapods-jsource (0.0.2)
4
+ cocoapods-jsource (0.0.3)
5
5
  cocoapods
6
6
 
7
7
  GEM
8
- remote: https://rubygems.org/
8
+ remote: https://gems.ruby-china.com/
9
9
  specs:
10
- CFPropertyList (3.0.0)
10
+ CFPropertyList (3.0.1)
11
11
  activesupport (4.2.11.1)
12
12
  i18n (~> 0.7)
13
13
  minitest (~> 5.1)
14
14
  thread_safe (~> 0.3, >= 0.3.4)
15
15
  tzinfo (~> 1.1)
16
+ algoliasearch (1.27.1)
17
+ httpclient (~> 2.8, >= 2.8.3)
18
+ json (>= 1.5.1)
16
19
  atomos (0.1.3)
17
20
  bacon (1.2.0)
18
- claide (1.0.2)
19
- cocoapods (1.7.5)
21
+ claide (1.0.3)
22
+ cocoapods (1.8.4)
20
23
  activesupport (>= 4.0.2, < 5)
21
24
  claide (>= 1.0.2, < 2.0)
22
- cocoapods-core (= 1.7.5)
25
+ cocoapods-core (= 1.8.4)
23
26
  cocoapods-deintegrate (>= 1.0.3, < 2.0)
24
27
  cocoapods-downloader (>= 1.2.2, < 2.0)
25
28
  cocoapods-plugins (>= 1.0.0, < 2.0)
26
29
  cocoapods-search (>= 1.0.0, < 2.0)
27
30
  cocoapods-stats (>= 1.0.0, < 2.0)
28
- cocoapods-trunk (>= 1.3.1, < 2.0)
31
+ cocoapods-trunk (>= 1.4.0, < 2.0)
29
32
  cocoapods-try (>= 1.1.0, < 2.0)
30
33
  colored2 (~> 3.1)
31
34
  escape (~> 0.0.4)
@@ -34,18 +37,20 @@ GEM
34
37
  molinillo (~> 0.6.6)
35
38
  nap (~> 1.0)
36
39
  ruby-macho (~> 1.4)
37
- xcodeproj (>= 1.10.0, < 2.0)
38
- cocoapods-core (1.7.5)
40
+ xcodeproj (>= 1.11.1, < 2.0)
41
+ cocoapods-core (1.8.4)
39
42
  activesupport (>= 4.0.2, < 6)
43
+ algoliasearch (~> 1.0)
44
+ concurrent-ruby (~> 1.1)
40
45
  fuzzy_match (~> 2.0.4)
41
46
  nap (~> 1.0)
42
47
  cocoapods-deintegrate (1.0.4)
43
- cocoapods-downloader (1.2.2)
48
+ cocoapods-downloader (1.3.0)
44
49
  cocoapods-plugins (1.0.0)
45
50
  nap
46
51
  cocoapods-search (1.0.0)
47
- cocoapods-stats (1.0.0)
48
- cocoapods-trunk (1.3.1)
52
+ cocoapods-stats (1.1.0)
53
+ cocoapods-trunk (1.4.1)
49
54
  nap (>= 0.8, < 2.0)
50
55
  netrc (~> 0.11)
51
56
  cocoapods-try (1.1.0)
@@ -55,12 +60,12 @@ GEM
55
60
  fourflusher (2.3.1)
56
61
  fuzzy_match (2.0.4)
57
62
  gh_inspector (1.1.3)
63
+ httpclient (2.8.3)
58
64
  i18n (0.9.5)
59
65
  concurrent-ruby (~> 1.0)
60
- metaclass (0.0.4)
61
- minitest (5.11.3)
62
- mocha (1.9.0)
63
- metaclass (~> 0.0.1)
66
+ json (2.2.0)
67
+ minitest (5.13.0)
68
+ mocha (1.10.1)
64
69
  mocha-on-bacon (0.2.3)
65
70
  mocha (>= 0.13.0)
66
71
  molinillo (0.6.6)
@@ -69,12 +74,12 @@ GEM
69
74
  netrc (0.11.0)
70
75
  prettybacon (0.0.2)
71
76
  bacon (~> 1.2)
72
- rake (12.3.2)
77
+ rake (13.0.1)
73
78
  ruby-macho (1.4.0)
74
79
  thread_safe (0.3.6)
75
80
  tzinfo (1.2.5)
76
81
  thread_safe (~> 0.1)
77
- xcodeproj (1.11.0)
82
+ xcodeproj (1.13.0)
78
83
  CFPropertyList (>= 2.3.3, < 4.0)
79
84
  atomos (~> 0.1.3)
80
85
  claide (>= 1.0.2, < 2.0)
@@ -39,7 +39,6 @@ module Pod
39
39
  path
40
40
  end
41
41
 
42
-
43
42
  def cache_file
44
43
  cache_path = cache_dir
45
44
  return cache_path + "jsource.yaml"
@@ -55,6 +54,21 @@ module Pod
55
54
  cache_dict
56
55
  end
57
56
 
57
+ def version_from_path(component_name, path)
58
+ cache_dict = cache_object
59
+ version = nil
60
+ cache_dict.each do |name, verision_hash|
61
+ verision_hash.each do |version_string, detail_hash|
62
+ return version unless detail_hash.include? :source_paths
63
+ detail_hash[:source_paths].each do |binary_name, source_path|
64
+ return version_string if source_path == path and binary_name == component_name
65
+ end
66
+ end
67
+ end
68
+ return version
69
+ end
70
+
71
+
58
72
  def dump_to_yaml(hash)
59
73
  File.open(cache_file, "wb+") {|f| YAML.dump(hash, f) }
60
74
  end
@@ -1,6 +1,7 @@
1
-
2
1
  require "cocoapods-core/lockfile"
3
2
  require 'fileutils'
3
+ require 'cocoapods-jsource/command/xcode_manager'
4
+ require 'cocoapods'
4
5
 
5
6
  module Pod
6
7
  class Command
@@ -12,85 +13,286 @@ module Pod
12
13
  Add source code debugging capabilities to binary.
13
14
  DESC
14
15
 
15
- def self.options
16
- [
17
- ['--names', 'component names to be added'],
18
- ['--gits', 'component git url to be added'],
19
- ].concat(super)
20
- end
16
+ self.arguments = [
17
+ CLAide::Argument.new('NAMES', true),
18
+ ]
21
19
 
22
20
  def initialize(argv)
23
- @namesString = argv.option('names')
21
+ @namesString = argv.shift_argument
24
22
  @names = @namesString.split(',') unless @namesString.nil?
25
- @gitsString = argv.option('gits')
26
- @gits = @gitsString.split(',') unless @gitsString.nil?
23
+ @cache_dict = cache_object
24
+ @manager = XcodeManager.new(argv)
25
+ @remote = argv.flag?('remote')
26
+ @index = -1
27
27
  super
28
28
  end
29
29
 
30
+ def self.options
31
+ [
32
+ ['--remote', 'add components from internet'],
33
+ ].concat(super)
34
+ end
35
+
30
36
  def validate!
31
37
  super
32
- help! 'component name is required.' unless @names.length > 0
33
- help! 'component git url is required.' unless @gits.length > 0
34
- help! 'names number must be equal to gits number' unless @names.length == @gits.length
38
+ help! 'component name is required.' if @namesString.nil?
39
+ #help! 'component git url is required.' unless @gits.length > 0
40
+ #help! 'names number must be equal to gits number' unless @names.length == @gits.length
35
41
  help! 'podfile.lock file is required. you need pod install/update' unless File.exist? config.lockfile_path
36
42
  end
37
43
 
44
+ def have_cached(component_name, version, subspecs)
45
+ return false unless @cache_dict.has_key? component_name
46
+ pod_cache_dict = @cache_dict[component_name]
47
+ return false unless pod_cache_dict.has_key? version
48
+ return false unless pod_cache_dict[version].has_key? :source_paths
49
+ source_path_hash = pod_cache_dict[version][:source_paths]
50
+ return false unless source_path_hash.length > 0
51
+ if subspecs.length > 0
52
+ tem_list = subspecs & (source_path_hash.keys - [component_name])
53
+ return false unless tem_list == subspecs
54
+ subspecs.each do |binary_name|
55
+ return false unless source_path_hash.keys.include? binary_name
56
+ dir_path = source_path_hash[binary_name]
57
+ return false unless File.exist? dir_path
58
+ end
59
+ else
60
+ source_path_hash.each do |binary_name, dir_path|
61
+ return false unless File.exist? dir_path
62
+ end
63
+ end
64
+ return true
65
+ end
66
+
67
+ def spec_with_name(name, version)
68
+ set = config.sources_manager.search(Dependency.new(name, version))
69
+ if set
70
+ path = set.specification_paths_for_version(Version.new(version)).first
71
+ spec = Specification.from_file(path)
72
+ spec.root
73
+ else
74
+ raise Informative, "Unable to find a specification for `#{name}`"
75
+ end
76
+ end
77
+
78
+ def download_component_to_path(component_name, version, source_path_hash={})
79
+ source_path_hash.each do |binary_name, source_path|
80
+ sandbox_path = source_path.split("Pods")[0] + "Pods"
81
+ sandbox_component_path = "#{sandbox_path}/#{component_name}"
82
+ binary_path = "#{sandbox_path}/#{binary_name}"
83
+ if File.exist? sandbox_component_path
84
+ UI.puts "using #{binary_name} #{version}"
85
+ UI.puts "\t#{source_path.to_s}"
86
+ FileUtils.copy_entry(sandbox_component_path, binary_path) unless File.exist? binary_path
87
+ else
88
+ UI.puts "downloading #{binary_name} #{version}"
89
+ UI.puts "\t #{source_path.to_s}"
90
+ FileUtils.mkdir_p [binary_path] unless File.exist? binary_path
91
+ sandbox = Sandbox.new(sandbox_path)
92
+ spec = spec_with_name(component_name, version)
93
+ specs = { :ios => [spec] }
94
+ installer = Installer::PodSourceInstaller.new(sandbox, config.podfile, specs, :can_cache => true)
95
+ installer.install!
96
+ #installer.clean!
97
+ # TODO validtarget
98
+ # 改名
99
+ if binary_name != component_name and File.exist? sandbox_component_path
100
+ FileUtils.copy_entry(sandbox_component_path, binary_path) unless File.exist? binary_name
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ def local_have_source_files(component_name)
107
+ files = Dir::glob "Pods/#{component_name}/**/*.m"
108
+ if files and files.length > 0
109
+ return true
110
+ end
111
+ return false
112
+ end
113
+
114
+ def source_files(component_name)
115
+ return nil unless local_have_source_files component_name
116
+ souces = []
117
+ Dir::foreach "Pods/#{component_name}" do |path|
118
+ next if path.include? "Frameworks"
119
+ souces << path
120
+ end
121
+ souces
122
+ end
123
+
124
+ def get_file_list(path)
125
+ list = []
126
+ Dir.entries(path).each do |sub|
127
+ if sub != '.' && sub != '..'
128
+ if File.directory?("#{path}/#{sub}")
129
+ list << "#{path}/#{sub}"
130
+ list = list + get_file_list("#{path}/#{sub}")
131
+ else
132
+ list << "#{path}/#{sub}"
133
+ end
134
+ end
135
+ end
136
+ list
137
+ end
138
+
139
+ def local_component_to_path(component_name, version, source_paths_hash)
140
+ path = "Pods/#{component_name}"
141
+ # TODO 没有源码状态
142
+ if !File.exist? path
143
+ # copy files to source_paths
144
+ UI.puts "本地目录不存在,请执行pod install/update 或者输入远程仓库地址"
145
+ exit 1
146
+ end
147
+ #file_list = get_file_list path
148
+ source_paths_hash.each do |binary_name, source_path_list|
149
+ if source_path_list.length > 0
150
+ dest_file_path = source_path_list[0].split("Pods")[0] + "Pods/#{binary_name}"
151
+ UI.puts "copying #{binary_name} to #{dest_file_path}"
152
+ end
153
+ source_path_list.each do |dest_file_path|
154
+ origin_file = dest_file_path.split("Pods/#{binary_name}")[-1]
155
+ origin_file_path = path + origin_file
156
+ if !File.exist? origin_file_path
157
+ UI.warn "本地不存在#{origin_file_path}, 可能使用了虚拟subspec或者本地源码缓存有问题。推荐加上 --remote 参数"
158
+ exit 1
159
+ end
160
+ if File.directory? origin_file_path
161
+ FileUtils.mkdir_p [dest_file_path], :mode => 0700 unless File.exist? dest_file_path
162
+ else
163
+ parent_dir = File.dirname dest_file_path
164
+ FileUtils.mkdir_p [parent_dir], :mode => 0700 unless File.exist? parent_dir
165
+ FileUtils.copy origin_file_path, dest_file_path unless File.exist? dest_file_path
166
+ h_origin_file_path = origin_file_path.gsub(/(mm|m|c)$/, "h")
167
+ h_dest_file_path = dest_file_path.gsub(/(mm|m|c)$/, "h")
168
+ parent_dir = File.dirname h_dest_file_path
169
+ FileUtils.mkdir_p [parent_dir], :mode => 0700 unless File.exist? parent_dir
170
+ FileUtils.copy h_origin_file_path, h_dest_file_path unless File.exist? h_dest_file_path
171
+ end
172
+ end
173
+ end
174
+
175
+ end
176
+
177
+
178
+ def component_cache(component_name)
179
+ if @cache_dict.has_key? component_name
180
+ component_cache_dict = @cache_dict[component_name]
181
+ end
182
+ component_cache_dict
183
+ end
184
+
185
+
186
+ def local_source_paths(component_name, subspecs, source_paths_hash)
187
+ local_hash = {}
188
+ source_paths_hash.each do |binary_name, source_paths|
189
+ need_add = false
190
+ if binary_name != component_name
191
+ if subspecs.include? binary_name
192
+ need_add = true
193
+ end
194
+ if subspecs.length == 0
195
+ need_add = true
196
+ end
197
+ else
198
+ need_add = true
199
+ end
200
+ local_hash[binary_name] = source_paths if need_add
201
+ end
202
+ local_hash
203
+ end
204
+
205
+
206
+ def unite_source_paths_hash(source_paths_hash)
207
+ source_path_hash = {}
208
+ source_paths_hash.each do |binary_name, source_paths|
209
+ source_path_hash[binary_name] = source_paths[0].split("Pods")[0] + "Pods/#{binary_name}" if source_paths.length > 0
210
+ end
211
+ source_path_hash
212
+ end
213
+
38
214
  def run
39
- # 获取当前目录
40
- index = 0
41
- cache_dict = cache_object
215
+ # 在Pods 目录下创建Debug.xcodeproj 文件。
216
+ debug_xcodeproj = @manager.generate_debug_xcodeproj
217
+
218
+ # 获取源码,并添加到工程里。
42
219
  @names.each do |component_name|
43
- pod_cache_dict = {}
44
- if cache_dict.has_key? component_name
45
- pod_cache_dict = cache_dict[component_name]
46
- end
47
- version = component_version component_name
220
+ @index = @index + 1
221
+ version, subspecs = component_info component_name
48
222
  if version.length == 0
49
223
  UI.puts "#{component_name} 找不到对应的版本信息,不做任何处理"
50
224
  next
51
225
  end
52
- if pod_cache_dict.has_key? version
53
- UI.puts "#{component_name} #{version} 已经存在,缓存为 #{pod_cache_dict[version][:sourcelist].to_s}"
54
- next
55
- end
56
- git = @gits[index]
57
- # 获取subspec
58
- source_file_list = get_source_file_list_from_binary(component_name)
59
- if source_file_list.length == 0
60
- UI.puts "#{component_name} 找不到对应的二进制,不做任何处理"
61
- next
62
- end
63
- UI.puts "开始下载源码..."
64
- for source_path in source_file_list
65
- create_working_directory source_path
66
- cmd ="git clone -b #{component_name}-#{version} --depth 1 #{git} #{source_path} >/dev/null 2>&1"
67
- `#{cmd}`
226
+ source_path_hash = {}
227
+ if have_cached component_name, version, subspecs
228
+ UI.puts "Using #{component_name} #{version} in #{@cache_dict[component_name][version][:source_paths]}"
229
+ source_path_hash = @cache_dict[component_name][version][:source_paths]
230
+ else
231
+ source_paths_hash = source_paths_from_binary(component_name)
232
+ if source_paths_hash.length == 0
233
+ UI.puts "#{component_name} 找不到对应的二进制,不做任何处理"
234
+ next
235
+ end
236
+ source_paths_hash = local_source_paths component_name, subspecs, source_paths_hash
237
+ source_path_hash = unite_source_paths_hash source_paths_hash
238
+ if @remote
239
+ # 需要把值合并。
240
+ download_component_to_path component_name, version, source_path_hash
241
+ else
242
+ local_component_to_path component_name, version, source_paths_hash
243
+ end
244
+
68
245
  end
69
- pod_cache_dict[version] = {"git":git, "sourcelist":source_file_list, "version":version}
70
- cache_dict[component_name] = pod_cache_dict
71
- UI.puts "#{component_name} 源码创建成功,目录为 #{source_file_list.to_s}"
72
- index = index + 1
246
+
247
+ # add_component_to_debug
248
+ ENV["IS_SOURCE"] = "1"
249
+ spec = spec_with_name component_name, version
250
+ @manager.add_component_to_debug component_name, source_path_hash, debug_xcodeproj, spec
251
+ # add_component_to_cache
252
+ pod_cache_dict = {}
253
+ pod_cache_dict[version] = {"source_paths":source_path_hash, "version":version}
254
+ #if @use_remote
255
+ # pod_cache_dict[version]["git"] = @gits[@index]
256
+ #end
257
+ @cache_dict[component_name] = pod_cache_dict
258
+ UI.puts "#{component_name} 源码创建成功,目录为 #{source_path_hash.to_s}"
73
259
  end
74
- dump_to_yaml cache_dict
260
+ @manager.add_debug_to_workspace
261
+ dump_to_yaml @cache_dict
75
262
  end
76
263
 
77
- def component_version(component_name)
264
+ def component_info(component_name)
78
265
  return unless File.exist? config.lockfile_path
79
266
  version=""
80
267
  lockfile = Lockfile.from_file config.lockfile_path
81
268
  dependencies = lockfile.internal_data["DEPENDENCIES"]
269
+ subspecs = []
82
270
  dependencies.each do |dependency|
271
+ if !dependency.include? "(="
272
+ UI.puts "podfile中 #{component_name} 可能没有指定版本,需要指定确定的版本才能使用。"
273
+ exit 1
274
+ end
83
275
  list = dependency.split(" (")
84
276
  name = list[0]
277
+ if name.include? "/"
278
+ name_list = name.split("/")
279
+ subspec = name.gsub(/\//,"")
280
+ name = name_list[0]
281
+ end
85
282
  next unless name == component_name
86
- version = list[-1].sub(")", "").sub("=", "").sub(" ", "")
283
+ version = list[-1].split("/")[0].sub(")", "").sub("=", "").sub(" ", "") if version == ""
284
+ subspecs << subspec if subspec
285
+ spec = spec_with_name component_name, version
286
+ spec.default_subspecs.each do |subspec_spec|
287
+ subspecs = subspecs | ["#{component_name}#{subspec_spec}"]
288
+ end
87
289
  end
88
- version
290
+ return version, subspecs
89
291
  end
90
292
 
91
293
  # 根据组件名获取组件的源码调试地址
92
- def get_source_file_list_from_binary(component_name)
93
- source_file_list = []
294
+ def source_paths_from_binary(component_name)
295
+ source_path_hash = {}
94
296
  component_pod_path = config.sandbox_root + component_name
95
297
  binary_path_list = `find #{component_pod_path} -name "#{component_name}*" -type l`.strip.split("\n").sort
96
298
  binary_hash = {}
@@ -102,29 +304,38 @@ module Pod
102
304
  end
103
305
  if binary_hash.length == 0
104
306
  UI.puts "#{component_name} 找不到二进制组件或者找不到对应的版本信息,不做任何处理"
105
- return source_file_list
307
+ exit 1
106
308
  end
107
309
 
108
310
  binary_hash.each do |binary_name, binary_path|
109
311
  libbinary_file_name = "lib#{component_name}.a"
110
- source_path_list = []
111
- UI.puts "正在解析二进制#{binary_path}源码位置"
312
+ at_name_list = []
112
313
  if binary_name.to_s.end_with? libbinary_file_name
113
314
  # .a 文件
114
- source_path_list = `dwarfdump -arch x86_64 #{binary_path} | grep 'AT_name.*#{binary_name}'`.strip.split("\n").sort
315
+ at_name_list = `dwarfdump -arch x86_64 #{binary_path} | grep 'AT_name.*#{binary_name}'`.strip.split("\n").sort
115
316
  else
116
317
  # framework 文件
117
- source_path_list = `dwarfdump -arch x86_64 #{binary_path} | grep 'DW_AT_name.*#{binary_name}'`.strip.split("\n").sort
318
+ at_name_list = `dwarfdump -arch x86_64 #{binary_path} | grep 'DW_AT_name.*#{binary_name}'`.strip.split("\n").sort
118
319
  end
119
- source_path_list.each do |tmp_source_path|
320
+ #if source_file.length == 0
321
+ # UI.puts "在#{binary_path} 里没有找到合适的调试信息~"
322
+ # next
323
+ #end
324
+ source_list = []
325
+ at_name_list.each do |tmp_source_path|
120
326
  if tmp_source_path.include?("Pods/#{binary_name}")
121
- source_path = tmp_source_path.strip.split("(\"")[-1].split(binary_name)[0] + "#{binary_name}"
122
- source_file_list << source_path if source_path.to_s.length > 0
123
- break
327
+ source_path = tmp_source_path.strip.split("(\"")[-1].split("\")")[0]
328
+ source_list << source_path if source_path.to_s.length > 0
124
329
  end
125
330
  end
331
+ if source_list.length == 0
332
+ UI.puts "#{component_name} 没有找到调试信息, 可能是早期打的组件。建议这个组件重新生成。"
333
+ exit 1
334
+ else
335
+ source_path_hash[binary_name] = source_list
336
+ end
126
337
  end
127
- source_file_list
338
+ source_path_hash
128
339
  end
129
340
 
130
341
 
@@ -1,4 +1,3 @@
1
-
2
1
  require "cocoapods-core/lockfile"
3
2
  require 'fileutils'
4
3
 
@@ -6,10 +5,22 @@ module Pod
6
5
  class Command
7
6
  class Jsource < Command
8
7
  class Clean < Jsource
9
- self.summary = 'Add source debugging function'
8
+ self.summary = 'Clean source debugging function'
10
9
 
11
10
  self.description = <<-DESC
12
- Clean the cache of the jsource(s) whose name matches `NAME`.
11
+ Remove the cache for a given pod, or clear the cache completely.
12
+
13
+ If you want to clean Debug_xcodeproj, please add "NAME",
14
+ if you want to clean all, please add "—all"
15
+
16
+ If you want to clear the cache, add "--cache":
17
+
18
+ If there is multiple cache for various versions of the requested pod, you
19
+ will be asked which one to clean. Use `--all` to clean them all.
20
+
21
+ If you do not give a pod `NAME`, you need to specify the `--all` flag
22
+ (this is to avoid cleaning all the cache by mistake).
23
+
13
24
  DESC
14
25
 
15
26
  self.arguments = [
@@ -18,46 +29,57 @@ module Pod
18
29
 
19
30
  def self.options
20
31
  [
21
- ['--all', 'Remove all the cached pods without asking'],
32
+ ['--all', 'Remove all the project debug pods without asking'],
33
+ ['--cache', 'Remove all the cached pods without asking']
22
34
  ].concat(super)
23
35
  end
24
36
 
25
37
  def initialize(argv)
26
38
  @pod_name = argv.shift_argument
27
39
  @wipe_all = argv.flag?('all')
40
+ @wipe_cache = argv.flag?('cache')
28
41
  @cache_dict = cache_object
42
+ @manager = XcodeManager.new(argv)
29
43
  super
30
44
  end
31
45
 
32
46
  def validate!
33
47
  super
34
- if @pod_name.nil? && !@wipe_all
35
- # Security measure, to avoid removing the pod cache too agressively by mistake
36
- help! 'You should either specify a pod name or use the --all flag'
48
+ if @pod_name.nil?
49
+ help! 'You should use the --all flag' if @wipe_all.nil?
37
50
  end
38
51
  end
39
52
 
40
53
  def run
41
54
  if @pod_name.nil?
42
55
  # Note: at that point, @wipe_all is always true (thanks to `validate!`)
43
- # Remove all
44
- clear_cache
56
+ if @wipe_all
57
+ if @wipe_cache
58
+ clear_cache
59
+ else
60
+ @manager.clean_debug
61
+ end
62
+ end
45
63
  else
46
64
  # Remove only cache for this pod
47
- cache_descriptors = @cache_dict[@pod_name].values
48
- if cache_descriptors.nil?
49
- UI.notice("No cache for pod named #{@pod_name} found")
50
- elsif cache_descriptors.count > 1 && !@wipe_all
51
- # Ask which to remove
52
- choices = cache_descriptors.map { |c| "#{@pod_name} v#{c[:version]}" }
53
- index = UI.choose_from_array(choices, 'Which pod cache do you want to remove?')
54
- remove_caches([cache_descriptors[index]])
65
+ if @wipe_cache
66
+ cache_descriptors = @cache_dict[@pod_name].values
67
+ if cache_descriptors.nil?
68
+ UI.notice("No cache for pod named #{@pod_name} found")
69
+ elsif cache_descriptors.count > 1 && !@wipe_all
70
+ # Ask which to remove
71
+ choices = cache_descriptors.map { |c| "#{@pod_name} v#{c[:version]}" }
72
+ index = UI.choose_from_array(choices, 'Which pod cache do you want to remove?')
73
+ # 删除debug
74
+ remove_caches([cache_descriptors[index]])
75
+ else
76
+ # Remove all found cache of this pod
77
+ remove_caches(cache_descriptors)
78
+ end
55
79
  else
56
- # Remove all found cache of this pod
57
- remove_caches(cache_descriptors)
80
+ @manager.remove_component_from_debug(@pod_name)
58
81
  end
59
82
  end
60
- dump_to_yaml @cache_dict
61
83
  end
62
84
 
63
85
  private
@@ -70,11 +92,11 @@ module Pod
70
92
  #
71
93
  def remove_caches(cache_descriptors)
72
94
  cache_descriptors.each do |desc|
73
- sourcelist = desc[:sourcelist]
74
- next if sourcelist.length == 0
75
- sourcelist.each do |source|
76
- UI.puts "Removing cache #{source} (#{desc[:version]})"
77
- parent = source.split("Pods")[0]
95
+ source_paths = desc[:source_paths]
96
+ next if source_paths.length == 0
97
+ source_paths.each do |binary_name, source_path|
98
+ UI.puts "Removing cache #{source_path} (#{desc[:version]})"
99
+ parent = source_path.split("Pods")[0]
78
100
  FileUtils.rm_rf(parent) if File.exist? parent
79
101
  end
80
102
  if @cache_dict[@pod_name].has_key? desc[:version]
@@ -85,30 +107,27 @@ module Pod
85
107
  end
86
108
  end
87
109
  end
110
+ dump_to_yaml @cache_dict
88
111
  end
89
112
 
90
113
  def clear_cache
91
114
  @cache_dict.each do |pod_name, version_dict|
92
115
  version_dict.each do |version, pod_dict|
93
- git=""
94
- source=""
95
- git=pod_dict[:git] if pod_dict.has_key? :git
96
- sourcelist=pod_dict[:sourcelist] if pod_dict.has_key? :sourcelist
97
- sourcelist.each do |source|
98
- UI.message("Removing the #{pod_name} jsource cache dir #{cache_dir}") do
99
- parent = source.split("Pods")[0]
116
+ source_paths=pod_dict[:source_paths] if pod_dict.has_key? :source_paths
117
+ source_paths.each do |binary_name, source_path|
118
+ UI.message("Removing the #{binary_name} jsource cache dir #{source_path}") do
119
+ parent = source_path.split("Pods")[0]
100
120
  FileUtils.rm_rf(parent) if File.exist? parent
101
121
  end
102
122
  end
103
-
104
123
  end
105
124
  end
106
125
  UI.message("Removing the jsource configuration dir #{cache_file}") do
107
126
  FileUtils.rm_rf(cache_file)
108
127
  @cache_dict = {}
109
128
  end
129
+ dump_to_yaml @cache_dict
110
130
  end
111
-
112
131
  end
113
132
  end
114
133
  end
@@ -17,15 +17,18 @@ module Pod
17
17
  ]
18
18
 
19
19
  def self.options
20
- [[
21
- '--short', 'Only print the path relative to the cache root'
22
- ]].concat(super)
20
+ [
21
+ ['--short', 'Only print the path relative to the cache root'],
22
+ ['--cache', 'Only print the cached pods']
23
+ ].concat(super)
23
24
  end
24
25
 
25
26
  def initialize(argv)
26
27
  @pod_name = argv.shift_argument
27
28
  @short_output = argv.flag?('short')
29
+ @pod_cache = argv.flag?('cache')
28
30
  @cache_dict = cache_object
31
+ @manager = XcodeManager.new(argv)
29
32
  super
30
33
  end
31
34
 
@@ -33,9 +36,19 @@ module Pod
33
36
  return if @cache_dict.nil?
34
37
  result = ""
35
38
  if @pod_name
36
- result = @cache_dict[@pod_name] if @cache_dict.has_key? @pod_name
39
+ if @pod_cache
40
+ result = @cache_dict[@pod_name] if @cache_dict.has_key? @pod_name
41
+ else
42
+ # 获取debug里 这个pod_name 的关键信息
43
+ result = @manager.component_in_debug @pod_name
44
+ end
37
45
  else
38
- result = @cache_dict
46
+ if @pod_cache
47
+ result = @cache_dict
48
+ else
49
+ # 获取debug里所有的group信息。
50
+ result = @manager.all_components_in_debug
51
+ end
39
52
  end
40
53
  if @short_output
41
54
  result = result.keys
@@ -0,0 +1,218 @@
1
+ require 'xcodeproj'
2
+ require 'cocoapods'
3
+ require 'cocoapods-jsource/command/xcodeproj_extern'
4
+
5
+ module Pod
6
+ class Command
7
+ class Jsource < Command
8
+ class XcodeManager < Jsource
9
+
10
+ def initialize(argv)
11
+ @debug_path = 'Pods/Debug.xcodeproj'
12
+ @workspace_name = `ls | grep .xcworkspace`.strip
13
+ @cache_dict = cache_object
14
+ super
15
+ end
16
+
17
+ def validate!
18
+ super
19
+ help! '请先pod install/update 之后,在运行这个命令' if !File.exist? @workspace_name or !File.exist? "Pods"
20
+ end
21
+
22
+ def generate_debug_xcodeproj()
23
+ debug_xcodeproj = get_debug_xcodeproj
24
+ if debug_xcodeproj.nil?
25
+ debug_xcodeproj = Xcodeproj::Project.new(@debug_path)
26
+ # 去掉Frameworks和Products
27
+ #debug_xcodeproj.groups.each do |component_group|
28
+ # component_group.clear
29
+ # component_group.remove_from_project
30
+ #end
31
+ end
32
+ debug_xcodeproj
33
+ end
34
+
35
+ def get_debug_xcodeproj()
36
+ debug_xcodeproj = nil
37
+ if File.exist? @debug_path
38
+ debug_xcodeproj = Xcodeproj::Project.open(@debug_path)
39
+ end
40
+ debug_xcodeproj
41
+ end
42
+
43
+ def add_files_to_group(debug_xcodeproj, group, files=[])
44
+ Dir.foreach(group.real_path).sort_by { |object| object.to_s }.each do |entry|
45
+ filePath = File.join(group.real_path, entry)
46
+ next unless files.length == 0 or files.include? filePath
47
+ ext_name = File.extname(entry)
48
+ # 过滤目录和.DS_Store文件
49
+ if !File.directory?(filePath) && entry != ".DS_Store" then
50
+ # 向group中增加文件引用
51
+ group.new_reference(filePath)
52
+ # 目录情况下, 递归添加
53
+ elsif File.directory?(filePath) && entry != '.' && entry != '..' then
54
+ hierarchy_path = group.hierarchy_path[1, group.hierarchy_path.length]
55
+ subGroup = debug_xcodeproj.main_group.find_subpath(hierarchy_path + '/' + entry, true)
56
+ subGroup.set_source_tree('<group>')
57
+ subGroup.set_path(group.real_path + entry)
58
+ add_files_to_group(debug_xcodeproj, subGroup, files)
59
+ end
60
+ end
61
+ end
62
+
63
+ # 感觉没啥必要
64
+ def include_component(component_name, source_path, debug_xcodeproj)
65
+ debug_xcodeproj.groups.each do |group|
66
+ return true if group.name == component_name and File.exist? group.path
67
+ end
68
+ return false
69
+ end
70
+
71
+
72
+ def all_components_in_debug()
73
+ component_info = {}
74
+ debug_xcodeproj = get_debug_xcodeproj
75
+ if debug_xcodeproj.nil?
76
+ return component_info
77
+ end
78
+ debug_xcodeproj.groups.each do |component_group|
79
+ detail_hash = {}
80
+ source_path_hash = {}
81
+ source_path_hash[component_group.display_name] = component_group.real_path.to_s
82
+ detail_hash[:source_paths] = source_path_hash
83
+ version = version_from_path component_group.display_name, component_group.real_path.to_s
84
+ detail_hash[:version] = version if version
85
+ component_info[component_group.display_name] = detail_hash if detail_hash.length > 0
86
+ end
87
+ component_info
88
+ end
89
+
90
+ def component_in_debug(component_name)
91
+ all_component_hash = all_components_in_debug
92
+ component_hash = {}
93
+ all_component_hash.each do |binary_name, detail_hash|
94
+ if binary_name.start_with? component_name
95
+ component_hash[binary_name] = detail_hash
96
+ end
97
+ end
98
+ component_hash
99
+ end
100
+
101
+ def avaliable_dirs(file_path, dest_file_path)
102
+ dir_list = []
103
+ if file_path.to_s == dest_file_path.to_s
104
+ return dir_list
105
+ else
106
+ parent_dir = File.dirname file_path
107
+ dir_list << parent_dir
108
+ dir_list = dir_list | avaliable_dirs(parent_dir, dest_file_path)
109
+ end
110
+ dir_list
111
+ end
112
+
113
+ def avaliable_file(group, spec)
114
+ component_name = spec.name
115
+ subspec = group.name.gsub(/#{component_name}/, "")
116
+ files = []
117
+ if subspec
118
+ spec.subspecs.each do |subspec_spec|
119
+ next unless subspec_spec.name == "#{component_name}/#{subspec}"
120
+ source_files = "#{group.real_path}/#{subspec_spec.attributes_hash["source_files"]}"
121
+ tmp_files = Dir.glob (source_files)
122
+ # 找到所有的文件夹
123
+ tmp_files.each do |file_path|
124
+ files << file_path
125
+ parent_path = File.dirname file_path
126
+ if !files.include? parent_path
127
+ files = files | avaliable_dirs(file_path, group.real_path)
128
+ end
129
+ end
130
+ break
131
+ end
132
+ end
133
+ files
134
+ end
135
+
136
+ def add_component_to_debug(component_name, source_path_hash, debug_xcodeproj, spec)
137
+ source_path_hash.each do |binary_name, source_path|
138
+ # 将源码添加到Debug.xcodeproj 里。
139
+ UI.puts "add #{binary_name} to Debug.xcodeproj"
140
+ component_group = debug_xcodeproj.main_group.find_subpath(binary_name, true)
141
+ component_group.set_source_tree('<absolute>')
142
+ component_group.set_path(source_path)
143
+ component_group.clear
144
+ files = avaliable_file component_group, spec
145
+ add_files_to_group(debug_xcodeproj, component_group, files)
146
+ end
147
+ debug_xcodeproj.save
148
+ end
149
+
150
+ def remove_component_from_debug(component_name)
151
+ debug_xcodeproj = get_debug_xcodeproj
152
+ if debug_xcodeproj.nil?
153
+ return
154
+ end
155
+ debug_xcodeproj.groups.each do |component_group|
156
+ if component_group.display_name.start_with? component_name
157
+ UI.puts "removing #{component_group.display_name} from Debug.xcodeproj"
158
+ if !component_group.empty?
159
+ component_group.clear
160
+ component_group.remove_from_project
161
+ end
162
+ end
163
+ end
164
+ debug_xcodeproj.save
165
+ end
166
+
167
+ def clean_debug()
168
+ debug_xcodeproj = get_debug_xcodeproj
169
+ remove_debug_from_workspace
170
+ if debug_xcodeproj
171
+ FileUtils.rm_rf [@debug_path]
172
+ end
173
+
174
+ end
175
+
176
+ def component_count_in_debug(debug_xcodeproj)
177
+ count = debug_xcodeproj.groups.length
178
+ if count >= 2
179
+ return count - 2
180
+ else
181
+ UI.puts "获取component的个数可能发成错误"
182
+ end
183
+ return count
184
+ end
185
+
186
+ def add_debug_to_workspace()
187
+ # 获取主工程的名字。
188
+ if File.exist? @workspace_name
189
+ workspace = Xcodeproj::Workspace.new_from_xcworkspace @workspace_name
190
+ else
191
+ UI.puts "找不到对应的workspace: #{@workspace_name},请检查。"
192
+ exit 1
193
+ end
194
+ if !workspace.schemes.values.include? File.realdirpath @debug_path
195
+ workspace << @debug_path
196
+ workspace.save_as @workspace_name
197
+ end
198
+ end
199
+
200
+ def remove_debug_from_workspace()
201
+ if File.exist? @workspace_name
202
+ workspace = Xcodeproj::Workspace.new_from_xcworkspace @workspace_name
203
+ else
204
+ UI.puts "找不到对应的workspace: #{@workspace_name},请检查。"
205
+ exit 1
206
+ end
207
+ if workspace.schemes.values.include? File.realdirpath @debug_path
208
+ workspace >> @debug_path
209
+ workspace.save_as @workspace_name
210
+ end
211
+ end
212
+
213
+ end
214
+ end
215
+ end
216
+ end
217
+
218
+
@@ -0,0 +1,34 @@
1
+ require 'xcodeproj'
2
+ require "rexml/xpath"
3
+
4
+ module Xcodeproj
5
+ # Provides support for generating, reading and serializing Xcode Workspace
6
+ # documents.
7
+ #
8
+ class Workspace
9
+
10
+ # removes a new path to the list of the of projects contained in the
11
+ # workspace.
12
+ # @param [String, Xcodeproj::Workspace::FileReference] path_or_reference
13
+ # A string or Xcode::Workspace::FileReference containing a path to an Xcode project
14
+ #
15
+ # @raise [ArgumentError] Raised if the input is neither a String nor a FileReference
16
+ #
17
+ # @return [void]
18
+ #
19
+ def >>(path_or_reference)
20
+ return unless @document && @document.respond_to?(:root)
21
+ debug_element = nil
22
+ @document.elements.each("*/FileRef") do |element|
23
+ location = element.attributes["location"]
24
+ if location == "group:#{path_or_reference}"
25
+ debug_element = element
26
+ end
27
+ end
28
+ @document.root.delete_element(debug_element)
29
+ load_schemes_from_project File.expand_path(path_or_reference)
30
+ end
31
+ end
32
+
33
+ end
34
+
@@ -1,3 +1,3 @@
1
1
  module CocoapodsJsource
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/test.rb CHANGED
@@ -1,7 +1,131 @@
1
+ require 'xcodeproj'
2
+ require 'cocoapods'
1
3
 
2
- `cd /Users/handa/Documents/lianjia/C/lianjia_ios_platc;pod jsource add --names=Lianjia_Beike_Home --gits=http://gerrit.lianjia.com/mobile_ios/Lianjia_Beike_Home`
3
-
4
+ `cd /Users/handa/Downloads/Example;pod jsource add --help`
5
+ #`cd /Users/handa/Downloads/Example;pod jsource clean LJRefresh --cache`
6
+ #`cd /Users/handa/Documents/lianjia/C/lianjia_ios_platc;pod jsource add LJBaseToolKit`
7
+ #`cd /Users/handa/Downloads/Example;pod jsource add LJRefresh http://gerrit.lianjia.com/mobile_ios/LJRefresh`
8
+ #
4
9
 
5
10
  # `cd /Users/handa/Documents/test/testZSource;pod jsource list`
6
11
 
7
- # `cd /Users/handa/Documents/test/testZSource;pod jsource clean LJCache`
12
+ # `cd /Users/handa/Documents/test/testZSource;pod jsource clean LJCache`
13
+ #
14
+ #`cd /Users/handa/Documents/lianjia/LJBaseContext/Example; pod update`
15
+
16
+ # require 'cocoapods-core'
17
+ # spec = Pod::Specification.from_file("/Users/handa/Documents/lianjia/LJPlatBPodSpecs/LJMessengerSDK/2.30.3.0/LJMessengerSDK.podspec")
18
+
19
+
20
+ def addFilesToGroup(project, aTarget, aGroup)
21
+ Dir.foreach(aGroup.real_path) do |entry|
22
+ filePath = File.join(aGroup.real_path, entry)
23
+ # 过滤目录和.DS_Store文件
24
+ if !File.directory?(filePath) && entry != ".DS_Store" then
25
+ # 向group中增加文件引用
26
+ fileReference = aGroup.new_reference(filePath)
27
+ # 如果不是头文件则继续增加到Build Phase中,PB文件需要加编译标志
28
+ if filePath.to_s.end_with?("pbobjc.m", "pbobjc.mm") then
29
+ aTarget.add_file_references([fileReference], '-fno-objc-arc')
30
+ elsif filePath.to_s.end_with?(".m", ".mm", ".cpp") then
31
+ aTarget.source_build_phase.add_file_reference(fileReference, true)
32
+ elsif filePath.to_s.end_with?(".plist") then
33
+ aTarget.resources_build_phase.add_file_reference(fileReference, true)
34
+ end
35
+ # 目录情况下, 递归添加
36
+ elsif File.directory?(filePath) && entry != '.' && entry != '..' then
37
+ hierarchy_path = aGroup.hierarchy_path[1, aGroup.hierarchy_path.length]
38
+ subGroup = project.main_group.find_subpath(hierarchy_path + '/' + entry, true)
39
+ subGroup.set_source_tree('<group>')
40
+ subGroup.set_path(aGroup.real_path + entry)
41
+ addFilesToGroup(project, aTarget, subGroup)
42
+ end
43
+ end
44
+ end
45
+
46
+
47
+
48
+ def addFilesToGroupNew(project, aGroup)
49
+ Dir.foreach(aGroup.real_path) do |entry|
50
+ filePath = File.join(aGroup.real_path, entry)
51
+ # 过滤目录和.DS_Store文件
52
+ if !File.directory?(filePath) && entry != ".DS_Store" then
53
+ # 向group中增加文件引用
54
+ aGroup.new_reference(filePath)
55
+ # 目录情况下, 递归添加
56
+ elsif File.directory?(filePath) && entry != '.' && entry != '..' then
57
+ hierarchy_path = aGroup.hierarchy_path[1, aGroup.hierarchy_path.length]
58
+ subGroup = project.main_group.find_subpath(hierarchy_path + '/' + entry, true)
59
+ subGroup.set_source_tree('<group>')
60
+ subGroup.set_path(aGroup.real_path + entry)
61
+ addFilesToGroupNew(project,subGroup)
62
+ end
63
+ end
64
+ end
65
+
66
+ # 添加Pods/JSources.xcodeproj
67
+
68
+ # 在Pods/JSources.xcodeproj 添加group Pods
69
+ #
70
+ # 在Pods目录添加每个组件的调试信息。
71
+ #
72
+ # 如果不指定-u 则用的是本地的源码,如果指定-u,则用的是网络里的源码。
73
+ #
74
+ #
75
+ #
76
+ #project_path = '/Users/handa/Documents/lianjia/cocoapods-jsource/test.xcodeproj'
77
+ #project = ""
78
+ #if File.exist? project_path
79
+ # project = Xcodeproj::Project.open(project_path)
80
+ #else
81
+ # project = Xcodeproj::Project.new(project_path)
82
+ #end
83
+ #
84
+ #path = "/var/folders/qb/qcgb09sx36l65jj4vglxz3nw0000gq/T/cocoapods-uru6ziwd/Pods/LJRefresh/LJRefresh/"
85
+ #exampleGroup=project.main_group.new_group("LJRefresh", path)
86
+ #exampleGroup.set_source_tree('<absolute>')
87
+ ##target = project.new_target(:application,"LJRefresh",:ios)
88
+ #addFilesToGroupNew(project, exampleGroup)
89
+ #
90
+ #
91
+ #
92
+ #project.save
93
+ #
94
+ #
95
+ #new_path = "/Users/handa/Downloads/Example/"
96
+ #file = "Example.xcworkspace"
97
+ #Dir.chdir(new_path)
98
+ ##workspace = Xcodeproj::Workspace.new_from_xcworkspace(file)
99
+ #
100
+ #ref = Xcodeproj::Workspace::FileReference.new(project_path)
101
+ ##if workspace.include? ref
102
+ ## print "already included"
103
+ ##else
104
+ ## workspace << project_path
105
+ ##end
106
+ ##workspace.save_as(file)
107
+ #
108
+ #new_path = "/Users/handa/Downloads/Example/Pods/Pods.xcodeproj"
109
+ #if File.exist? new_path
110
+ # pod_project = Xcodeproj::Project.open(new_path)
111
+ #end
112
+
113
+
114
+ #
115
+ #`mkdir Pods/JSources`
116
+ #jsource_group=pod_project.main_group.new_group("JSources", "./Pods/JSources")
117
+ #
118
+ #
119
+ #jsource_group.add_referrer(ref)
120
+ #
121
+ #
122
+ #
123
+ #pod_project.save
124
+
125
+
126
+
127
+ #config = Pod::Config.instance
128
+ #installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
129
+ #installer.repo_update = false
130
+ #installer.update = false
131
+ #installer.generated_pod_targets
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-jsource
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - handa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-04 00:00:00.000000000 Z
11
+ date: 2020-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cocoapods
@@ -72,6 +72,8 @@ files:
72
72
  - lib/cocoapods-jsource/command/jsource/add.rb
73
73
  - lib/cocoapods-jsource/command/jsource/clean.rb
74
74
  - lib/cocoapods-jsource/command/jsource/list.rb
75
+ - lib/cocoapods-jsource/command/xcode_manager.rb
76
+ - lib/cocoapods-jsource/command/xcodeproj_extern.rb
75
77
  - lib/cocoapods-jsource/gem_version.rb
76
78
  - lib/cocoapods_plugin.rb
77
79
  - spec/command/jsource_spec.rb