cocoapods-swordfish 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +35 -0
- data/lib/cocoapods_plugin.rb +86 -0
- data/lib/gem_version.rb +11 -0
- data/lib/swordfish/command/archive.rb +187 -0
- data/lib/swordfish/command/auto.rb +192 -0
- data/lib/swordfish/command/config.rb +70 -0
- data/lib/swordfish/command/repo/update.rb +42 -0
- data/lib/swordfish/command/spec/create.rb +78 -0
- data/lib/swordfish/command/spec/push.rb +114 -0
- data/lib/swordfish/command/swordfish.rb +41 -0
- data/lib/swordfish/command.rb +2 -0
- data/lib/swordfish/config/config.rb +137 -0
- data/lib/swordfish/config/config_asker.rb +57 -0
- data/lib/swordfish/config/config_builder.rb +216 -0
- data/lib/swordfish/helpers/build_helper.rb +160 -0
- data/lib/swordfish/helpers/build_utils.rb +94 -0
- data/lib/swordfish/helpers/framework.rb +85 -0
- data/lib/swordfish/helpers/framework_builder.rb +451 -0
- data/lib/swordfish/helpers/library.rb +54 -0
- data/lib/swordfish/helpers/library_builder.rb +90 -0
- data/lib/swordfish/helpers/sources_helper.rb +38 -0
- data/lib/swordfish/helpers/spec_creator.rb +167 -0
- data/lib/swordfish/helpers/spec_files_helper.rb +76 -0
- data/lib/swordfish/helpers/spec_source_creator.rb +266 -0
- data/lib/swordfish/helpers/upload_helper.rb +94 -0
- data/lib/swordfish/hmap/hmap_generator.rb +59 -0
- data/lib/swordfish/hmap/pod_target.rb +92 -0
- data/lib/swordfish/hmap/podfile_dsl.rb +36 -0
- data/lib/swordfish/hmap/post_install_hook_context.rb +41 -0
- data/lib/swordfish/hmap/xcconfig.rb +99 -0
- data/lib/swordfish/hmap.rb +4 -0
- data/lib/swordfish/native/acknowledgements.rb +27 -0
- data/lib/swordfish/native/analyzer.rb +55 -0
- data/lib/swordfish/native/file_accessor.rb +28 -0
- data/lib/swordfish/native/installation_options.rb +25 -0
- data/lib/swordfish/native/installer.rb +135 -0
- data/lib/swordfish/native/linter.rb +25 -0
- data/lib/swordfish/native/path_source.rb +33 -0
- data/lib/swordfish/native/pod_source_installer.rb +19 -0
- data/lib/swordfish/native/pod_target_installer.rb +94 -0
- data/lib/swordfish/native/podfile.rb +105 -0
- data/lib/swordfish/native/podfile_env.rb +36 -0
- data/lib/swordfish/native/podfile_generator.rb +195 -0
- data/lib/swordfish/native/podspec_finder.rb +24 -0
- data/lib/swordfish/native/resolver.rb +223 -0
- data/lib/swordfish/native/source.rb +35 -0
- data/lib/swordfish/native/sources_manager.rb +19 -0
- data/lib/swordfish/native/specification.rb +31 -0
- data/lib/swordfish/native/target_architectures.rb +79 -0
- data/lib/swordfish/native/target_validator.rb +41 -0
- data/lib/swordfish/native/validator.rb +39 -0
- data/lib/swordfish/native.rb +16 -0
- data/lib/swordfish.rb +2 -0
- metadata +167 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
# !/usr/bin/env ruby
|
2
|
+
require 'swordfish/hmap/xcconfig'
|
3
|
+
require 'swordfish/hmap/hmap_generator'
|
4
|
+
require 'swordfish/hmap/podfile_dsl'
|
5
|
+
|
6
|
+
SAVED_HMAP_DIR='prebuilt-hmaps'
|
7
|
+
|
8
|
+
module Pod
|
9
|
+
class Target
|
10
|
+
attr_accessor :prebuilt_hmap_target_names
|
11
|
+
def save_hmap(hmap)
|
12
|
+
if hmap.empty? == false
|
13
|
+
target_hmap_name="#{name}.hmap"
|
14
|
+
relative_hmap_path = "#{SAVED_HMAP_DIR}/#{target_hmap_name}"
|
15
|
+
target_hmap_path = sandbox.root.to_s + "/#{relative_hmap_path}"
|
16
|
+
hmaps_dir = sandbox.root.to_s + "/#{SAVED_HMAP_DIR}"
|
17
|
+
unless File.exist?(hmaps_dir)
|
18
|
+
Dir.mkdir(hmaps_dir)
|
19
|
+
end
|
20
|
+
if hmap.save_to(target_hmap_path)
|
21
|
+
reset_header_search_with_relative_hmap_path(relative_hmap_path)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
def add_prebuilt_hmap_target(name)
|
26
|
+
@prebuilt_hmap_target_names = Array.new if @prebuilt_hmap_target_names == nil
|
27
|
+
@prebuilt_hmap_target_names << name
|
28
|
+
end
|
29
|
+
def concat_prebuilt_hmap_targets(names)
|
30
|
+
@prebuilt_hmap_target_names = Array.new if @prebuilt_hmap_target_names == nil
|
31
|
+
@prebuilt_hmap_target_names.concat(names) if names
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class PodTarget
|
36
|
+
def reset_header_search_with_relative_hmap_path(hmap_path)
|
37
|
+
if build_settings.instance_of?(Hash)
|
38
|
+
build_settings.each do |config_name, setting|
|
39
|
+
config_file = setting.xcconfig
|
40
|
+
config_file.reset_header_search_with_relative_hmap_path(hmap_path, @prebuilt_hmap_target_names.uniq)
|
41
|
+
# https://github.com/CocoaPods/CocoaPods/issues/1216
|
42
|
+
# just turn off private xcconfig's USE_HEADERMAP flag
|
43
|
+
config_file.set_use_hmap(false)
|
44
|
+
config_path = xcconfig_path(config_name)
|
45
|
+
config_file.save_as(config_path)
|
46
|
+
end
|
47
|
+
elsif build_settings.instance_of?(BuildSettings::PodTargetSettings)
|
48
|
+
config_file = build_settings.xcconfig
|
49
|
+
config_file.reset_header_search_with_relative_hmap_path(hmap_path, @prebuilt_hmap_target_names.uniq)
|
50
|
+
# https://github.com/CocoaPods/CocoaPods/issues/1216
|
51
|
+
# just turn off private xcconfig's USE_HEADERMAP flag
|
52
|
+
config_file.set_use_hmap(false)
|
53
|
+
config_path = xcconfig_path
|
54
|
+
config_file.save_as(config_path)
|
55
|
+
else
|
56
|
+
Pod::UI.notice 'Unknown build settings'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
def recursively_add_dependent_headers_to_hmap(hmap, generate_type)
|
60
|
+
dependent_targets.each do |depend_target|
|
61
|
+
# set public header for dependent target
|
62
|
+
depend_target.generate_hmap(hmap, generate_type, true, true) if depend_target.respond_to?(:generate_hmap)
|
63
|
+
concat_prebuilt_hmap_targets(depend_target.prebuilt_hmap_target_names) if depend_target.prebuilt_hmap_target_names
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_hmap(hmap, generate_type, only_public_headers=true, add_dependency=false)
|
68
|
+
# There is no need to add headers of target defines module to hmap.
|
69
|
+
unless defines_module?
|
70
|
+
unless $hmap_black_pod_list.include?(name)
|
71
|
+
add_prebuilt_hmap_target(name)
|
72
|
+
# Create hmap for current target if not in black list.
|
73
|
+
hmap.add_hmap_with_header_mapping(only_public_headers ? public_header_mappings_by_file_accessor : header_mappings_by_file_accessor, generate_type, name, product_module_name)
|
74
|
+
# Recursively add dependent targets if needed.
|
75
|
+
recursively_add_dependent_headers_to_hmap(hmap, generate_type) if add_dependency
|
76
|
+
else
|
77
|
+
Pod::UI.message "- skip target in black list :#{name}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
class AggregateTarget
|
83
|
+
def reset_header_search_with_relative_hmap_path(hmap_path)
|
84
|
+
# override xcconfig
|
85
|
+
xcconfigs.each do |config_name, config_file|
|
86
|
+
config_file.reset_header_search_with_relative_hmap_path(hmap_path, @prebuilt_hmap_target_names.uniq)
|
87
|
+
config_path = xcconfig_path(config_name)
|
88
|
+
config_file.save_as(config_path)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# !/usr/bin/env ruby
|
2
|
+
# built-in black list pods
|
3
|
+
# you can use hmap_black_pod_list to add other pods
|
4
|
+
#
|
5
|
+
$hmap_enable = false
|
6
|
+
$hmap_black_pod_list = []
|
7
|
+
$strict_mode = false
|
8
|
+
$prebuilt_hmap_for_pod_targets = true
|
9
|
+
|
10
|
+
module Pod
|
11
|
+
class Podfile
|
12
|
+
module DSL
|
13
|
+
|
14
|
+
def set_hmap_enable()
|
15
|
+
$hmap_enable = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_hmap_black_pod_list(pods)
|
19
|
+
if pods != nil && pods.size() > 0
|
20
|
+
$hmap_black_pod_list.concat(pods)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
# if use strict mode, main project can only use `#import <PodTargetName/SomeHeader.h>`
|
24
|
+
# `#import <SomeHeader.h>` will get 'file not found' error
|
25
|
+
# as well as PodTarget dependent on other PodTarget
|
26
|
+
def set_hmap_use_strict_mode
|
27
|
+
$strict_mode = true
|
28
|
+
end
|
29
|
+
# turn off prebuilt hmap for targets in pod project except the `main` target
|
30
|
+
def turn_prebuilt_hmap_off_for_pod_targets
|
31
|
+
$prebuilt_hmap_for_pod_targets = false
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# !/usr/bin/env ruby
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Installer
|
5
|
+
class PostInstallHooksContext
|
6
|
+
attr_accessor :aggregate_targets
|
7
|
+
version = Gem::Version.new(Pod::VERSION)
|
8
|
+
if version < Gem::Version.new('1.7.0')
|
9
|
+
# Method `generate` has two args
|
10
|
+
class << self
|
11
|
+
alias old_generate generate
|
12
|
+
def generate(sandbox, aggregate_targets)
|
13
|
+
context = old_generate(sandbox, aggregate_targets)
|
14
|
+
UI.info "- generate method of post install hook context hooked"
|
15
|
+
context.aggregate_targets = aggregate_targets
|
16
|
+
context
|
17
|
+
end
|
18
|
+
end
|
19
|
+
elsif version < Gem::Version.new('1.10.0')
|
20
|
+
# Method `generate` has three args
|
21
|
+
class << self
|
22
|
+
alias old_generate generate
|
23
|
+
def generate(sandbox, pods_project, aggregate_targets)
|
24
|
+
context = old_generate(sandbox, pods_project, aggregate_targets)
|
25
|
+
UI.info "- generate method of post install hook context hooked"
|
26
|
+
context.aggregate_targets = aggregate_targets
|
27
|
+
context
|
28
|
+
end
|
29
|
+
end
|
30
|
+
else
|
31
|
+
# PostInstallHooksContext inherited from BaseContext, just override `generate`
|
32
|
+
def self.generate(sandbox, pods_project, aggregate_targets)
|
33
|
+
context = super
|
34
|
+
UI.info "- generate method of post install hook context override"
|
35
|
+
context.aggregate_targets = aggregate_targets
|
36
|
+
context
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# !/usr/bin/env ruby
|
2
|
+
|
3
|
+
module Xcodeproj
|
4
|
+
class Config
|
5
|
+
def remove_attr_with_key(key)
|
6
|
+
unless key == nil
|
7
|
+
@attributes.delete(key)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
def remove_header_search_path(prebuilt_hmap_target_names=nil)
|
11
|
+
header_search_paths = @attributes['HEADER_SEARCH_PATHS']
|
12
|
+
if header_search_paths
|
13
|
+
new_paths = Array.new
|
14
|
+
header_search_paths.split(' ').each do |p|
|
15
|
+
unless search_path_should_be_deleted?(p, prebuilt_hmap_target_names)
|
16
|
+
new_paths << p
|
17
|
+
end
|
18
|
+
end
|
19
|
+
if new_paths.size > 0
|
20
|
+
@attributes['HEADER_SEARCH_PATHS'] = new_paths.join(' ')
|
21
|
+
else
|
22
|
+
remove_attr_with_key('HEADER_SEARCH_PATHS')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
remove_system_option_in_other_cflags(prebuilt_hmap_target_names)
|
26
|
+
end
|
27
|
+
def search_path_should_be_deleted?(search_path, prebuilt_hmap_target_names=nil)
|
28
|
+
# Check if the path should be deleted from search list
|
29
|
+
# 1. It must be at the ${PODS_ROOT} directory
|
30
|
+
# 2. It has generated hmap
|
31
|
+
ret = false
|
32
|
+
if search_path.include?('${PODS_ROOT}/Headers')
|
33
|
+
if prebuilt_hmap_target_names
|
34
|
+
ret = prebuilt_hmap_target_names.select { |name| search_path.include?(name) }.empty? == false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
ret
|
38
|
+
end
|
39
|
+
def remove_system_option_in_other_cflags(prebuilt_hmap_target_names=nil)
|
40
|
+
# ----------------------------------------------
|
41
|
+
# -I<dir>, --include-directory <arg>, --include-directory=<arg>
|
42
|
+
# Add directory to include search path. For C++ inputs, if there are multiple -I options,
|
43
|
+
# these directories are searched in the order they are given before the standard system directories are searched.
|
44
|
+
# If the same directory is in the SYSTEM include search paths, for example if also specified with -isystem, the -I option will be ignored
|
45
|
+
#
|
46
|
+
# -isystem<directory>
|
47
|
+
# Add directory to SYSTEM include search path
|
48
|
+
# ----------------------------------------------
|
49
|
+
flags = @attributes['OTHER_CFLAGS']
|
50
|
+
if flags
|
51
|
+
new_flags = ''
|
52
|
+
is_isystem_flag = false
|
53
|
+
flags.split(' ').each do |substr|
|
54
|
+
append_str = substr
|
55
|
+
# Previous flag is `isystem`
|
56
|
+
if is_isystem_flag
|
57
|
+
is_isystem_flag = false
|
58
|
+
if search_path_should_be_deleted?(append_str, prebuilt_hmap_target_names)
|
59
|
+
next
|
60
|
+
else
|
61
|
+
# recover
|
62
|
+
append_str = "-isystem #{append_str}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if append_str == '-isystem'
|
67
|
+
is_isystem_flag = true
|
68
|
+
next
|
69
|
+
end
|
70
|
+
|
71
|
+
if new_flags.length > 0
|
72
|
+
new_flags += ' '
|
73
|
+
end
|
74
|
+
new_flags += append_str
|
75
|
+
end
|
76
|
+
|
77
|
+
if new_flags.length > 0
|
78
|
+
@attributes['OTHER_CFLAGS'] = new_flags
|
79
|
+
else
|
80
|
+
remove_attr_with_key('OTHER_CFLAGS')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
def reset_header_search_with_relative_hmap_path(hmap_path, prebuilt_hmap_target_names=nil)
|
85
|
+
# Delete associate search paths
|
86
|
+
remove_header_search_path(prebuilt_hmap_target_names)
|
87
|
+
# Add hmap file to search path
|
88
|
+
new_paths = Array["${PODS_ROOT}/#{hmap_path}"]
|
89
|
+
header_search_paths = @attributes['HEADER_SEARCH_PATHS']
|
90
|
+
if header_search_paths
|
91
|
+
new_paths.concat(header_search_paths.split(' '))
|
92
|
+
end
|
93
|
+
@attributes['HEADER_SEARCH_PATHS'] = new_paths.join(' ')
|
94
|
+
end
|
95
|
+
def set_use_hmap(use=false)
|
96
|
+
@attributes['USE_HEADERMAP'] = (use ? 'YES' : 'NO')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
module Generator
|
5
|
+
class Acknowledgements
|
6
|
+
def license_text(spec)
|
7
|
+
return nil unless spec.license
|
8
|
+
|
9
|
+
text = spec.license[:text]
|
10
|
+
unless text
|
11
|
+
if license_file = spec.license[:file]
|
12
|
+
license_path = file_accessor(spec).root + license_file
|
13
|
+
if File.exist?(license_path)
|
14
|
+
text = IO.read(license_path)
|
15
|
+
else
|
16
|
+
# UI.warn "Unable to read the license file `#{license_file}` " \
|
17
|
+
# "for the spec `#{spec}`"
|
18
|
+
end
|
19
|
+
elsif license_file = file_accessor(spec).license
|
20
|
+
text = IO.read(license_file)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
text
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require 'parallel'
|
4
|
+
require 'cocoapods'
|
5
|
+
|
6
|
+
module Pod
|
7
|
+
class Installer
|
8
|
+
class Analyzer
|
9
|
+
# > 1.6.0
|
10
|
+
# all_specs[dep.name] 为 nil 会崩溃
|
11
|
+
# 主要原因是 all_specs 分析错误
|
12
|
+
# 查看 source 是否正确
|
13
|
+
#
|
14
|
+
# def dependencies_for_specs(specs, platform, all_specs)
|
15
|
+
# return [] if specs.empty? || all_specs.empty?
|
16
|
+
|
17
|
+
# dependent_specs = Set.new
|
18
|
+
|
19
|
+
# specs.each do |s|
|
20
|
+
# s.dependencies(platform).each do |dep|
|
21
|
+
# all_specs[dep.name].each do |spec|
|
22
|
+
# dependent_specs << spec
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
|
27
|
+
# dependent_specs - specs
|
28
|
+
# end
|
29
|
+
|
30
|
+
# > 1.5.3 版本
|
31
|
+
# rewrite update_repositories
|
32
|
+
#
|
33
|
+
alias old_update_repositories update_repositories
|
34
|
+
def update_repositories
|
35
|
+
if installation_options.update_source_with_multi_processes
|
36
|
+
# 并发更新私有源
|
37
|
+
# 这里多线程会导致 pod update 额外输出 --verbose 的内容
|
38
|
+
# 不知道为什么?
|
39
|
+
Parallel.each(sources.uniq(&:url), in_processes: 4) do |source|
|
40
|
+
if source.git?
|
41
|
+
config.sources_manager.update(source.name, true)
|
42
|
+
else
|
43
|
+
UI.message "Skipping `#{source.name}` update because the repository is not a git source repository."
|
44
|
+
end
|
45
|
+
end
|
46
|
+
@specs_updated = true
|
47
|
+
else
|
48
|
+
old_update_repositories
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'macho'
|
2
|
+
require 'cocoapods'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
class Sandbox
|
6
|
+
class FileAccessor
|
7
|
+
|
8
|
+
# swift动态库 需要设置为true
|
9
|
+
def dynamic_binary?(binary)
|
10
|
+
@cached_dynamic_binary_results ||= {}
|
11
|
+
return @cached_dynamic_binary_results[binary] unless @cached_dynamic_binary_results[binary].nil?
|
12
|
+
return false unless binary.file?
|
13
|
+
|
14
|
+
@cached_dynamic_binary_results[binary] = MachO.open(binary).dylib?
|
15
|
+
rescue MachO::MachOError
|
16
|
+
@cached_dynamic_binary_results[binary] = true
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
# def expanded_paths(patterns, options = {})
|
21
|
+
# return [] if patterns.empty?
|
22
|
+
# path_list.glob(patterns, options).flatten.compact.uniq
|
23
|
+
# end
|
24
|
+
|
25
|
+
#-----------------------------------------------------------------------#
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
require 'cocoapods'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
class Installer
|
6
|
+
class InstallationOptions
|
7
|
+
def self.env_option(key, default = true)
|
8
|
+
option key, ENV[key.to_s].nil? ? default : ENV[key.to_s] == 'true'
|
9
|
+
end
|
10
|
+
|
11
|
+
# 不同 source 存在相同 spec 名时,默认不警告
|
12
|
+
defaults.delete('warn_for_multiple_pod_sources')
|
13
|
+
env_option :warn_for_multiple_pod_sources, false
|
14
|
+
|
15
|
+
# 是否警告不安全 source (如 http )
|
16
|
+
env_option :warn_for_unsecure_source, false
|
17
|
+
|
18
|
+
# 是否多线程执行 install_pod_sources
|
19
|
+
env_option :install_with_multi_threads, true
|
20
|
+
|
21
|
+
# 是否多进程执行 update_repositories
|
22
|
+
env_option :update_source_with_multi_processes, true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'cocoapods/installer/project_cache/target_metadata.rb'
|
2
|
+
require 'parallel'
|
3
|
+
require 'cocoapods'
|
4
|
+
require 'xcodeproj'
|
5
|
+
require 'swordfish/native/pod_source_installer'
|
6
|
+
|
7
|
+
module Pod
|
8
|
+
class Installer
|
9
|
+
alias old_create_pod_installer create_pod_installer
|
10
|
+
def create_pod_installer(pod_name)
|
11
|
+
installer = old_create_pod_installer(pod_name)
|
12
|
+
installer.installation_options = installation_options
|
13
|
+
installer
|
14
|
+
end
|
15
|
+
|
16
|
+
alias old_install_pod_sources install_pod_sources
|
17
|
+
def install_pod_sources
|
18
|
+
if installation_options.install_with_multi_threads
|
19
|
+
if Pod.match_version?('~> 1.4.0')
|
20
|
+
install_pod_sources_for_version_in_1_4_0
|
21
|
+
elsif Pod.match_version?('~> 1.5')
|
22
|
+
install_pod_sources_for_version_above_1_5_0
|
23
|
+
else
|
24
|
+
old_install_pod_sources
|
25
|
+
end
|
26
|
+
else
|
27
|
+
old_install_pod_sources
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# rewrite install_pod_sources
|
32
|
+
def install_pod_sources_for_version_in_1_4_0
|
33
|
+
@installed_specs = []
|
34
|
+
pods_to_install = sandbox_state.added | sandbox_state.changed
|
35
|
+
title_options = { verbose_prefix: '-> '.green }
|
36
|
+
Parallel.each(root_specs.sort_by(&:name), in_threads: 4) do |spec|
|
37
|
+
if pods_to_install.include?(spec.name)
|
38
|
+
if sandbox_state.changed.include?(spec.name) && sandbox.manifest
|
39
|
+
previous = sandbox.manifest.version(spec.name)
|
40
|
+
title = "Installing #{spec.name} #{spec.version} (was #{previous})"
|
41
|
+
else
|
42
|
+
title = "Installing #{spec}"
|
43
|
+
end
|
44
|
+
UI.titled_section(title.green, title_options) do
|
45
|
+
install_source_of_pod(spec.name)
|
46
|
+
end
|
47
|
+
else
|
48
|
+
UI.titled_section("Using #{spec}", title_options) do
|
49
|
+
create_pod_installer(spec.name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def install_pod_sources_for_version_above_1_5_0
|
56
|
+
@installed_specs = []
|
57
|
+
pods_to_install = sandbox_state.added | sandbox_state.changed
|
58
|
+
title_options = { verbose_prefix: '-> '.green }
|
59
|
+
# 多进程下载,多线程时 log 会显著交叉,多进程好点,但是多进程需要利用文件锁对 cache 进行保护
|
60
|
+
# in_processes: 10
|
61
|
+
Parallel.each(root_specs.sort_by(&:name), in_threads: 4) do |spec|
|
62
|
+
if pods_to_install.include?(spec.name)
|
63
|
+
if sandbox_state.changed.include?(spec.name) && sandbox.manifest
|
64
|
+
current_version = spec.version
|
65
|
+
previous_version = sandbox.manifest.version(spec.name)
|
66
|
+
has_changed_version = current_version != previous_version
|
67
|
+
current_repo = analysis_result.specs_by_source.detect do |key, values|
|
68
|
+
break key if values.map(&:name).include?(spec.name)
|
69
|
+
end
|
70
|
+
current_repo &&= current_repo.url || current_repo.name
|
71
|
+
previous_spec_repo = sandbox.manifest.spec_repo(spec.name)
|
72
|
+
has_changed_repo = !previous_spec_repo.nil? && current_repo && (current_repo != previous_spec_repo)
|
73
|
+
title = "Installing #{spec.name} #{spec.version}"
|
74
|
+
if has_changed_version && has_changed_repo
|
75
|
+
title += " (was #{previous_version} and source changed to `#{current_repo}` from `#{previous_spec_repo}`)"
|
76
|
+
end
|
77
|
+
if has_changed_version && !has_changed_repo
|
78
|
+
title += " (was #{previous_version})"
|
79
|
+
end
|
80
|
+
if !has_changed_version && has_changed_repo
|
81
|
+
title += " (source changed to `#{current_repo}` from `#{previous_spec_repo}`)"
|
82
|
+
end
|
83
|
+
else
|
84
|
+
title = "Installing #{spec}"
|
85
|
+
end
|
86
|
+
UI.titled_section(title.green, title_options) do
|
87
|
+
install_source_of_pod(spec.name)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
UI.titled_section("Using #{spec}", title_options) do
|
91
|
+
create_pod_installer(spec.name)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
alias old_write_lockfiles write_lockfiles
|
98
|
+
def write_lockfiles
|
99
|
+
old_write_lockfiles
|
100
|
+
if File.exist?('Podfile_local')
|
101
|
+
|
102
|
+
project = Xcodeproj::Project.open(config.sandbox.project_path)
|
103
|
+
#获取主group
|
104
|
+
group = project.main_group
|
105
|
+
group.set_source_tree('SOURCE_ROOT')
|
106
|
+
#向group中添加 文件引用
|
107
|
+
file_ref = group.new_reference(config.sandbox.root + '../Podfile_local')
|
108
|
+
#podfile_local排序
|
109
|
+
podfile_local_group = group.children.last
|
110
|
+
group.children.pop
|
111
|
+
group.children.unshift(podfile_local_group)
|
112
|
+
#保存
|
113
|
+
project.save
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
module Downloader
|
119
|
+
class Cache
|
120
|
+
# 多线程锁
|
121
|
+
@@lock = Mutex.new
|
122
|
+
|
123
|
+
# 后面如果要切到进程的话,可以在 cache root 里面新建一个文件
|
124
|
+
# 利用这个文件 lock
|
125
|
+
# https://stackoverflow.com/questions/23748648/using-fileflock-as-ruby-global-lock-mutex-for-processes
|
126
|
+
|
127
|
+
# rmtree 在多进程情况下可能 Directory not empty @ dir_s_rmdir 错误
|
128
|
+
# old_ensure_matching_version 会移除不是同一个 CocoaPods 版本的组件缓存
|
129
|
+
alias old_ensure_matching_version ensure_matching_version
|
130
|
+
def ensure_matching_version
|
131
|
+
@@lock.synchronize { old_ensure_matching_version }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
require 'swordfish/native/specification'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
class Specification
|
6
|
+
class Linter
|
7
|
+
# !@group Lint steps
|
8
|
+
|
9
|
+
# Checks that the spec's root name matches the filename.
|
10
|
+
#
|
11
|
+
# @return [void]
|
12
|
+
#
|
13
|
+
def validate_root_name
|
14
|
+
if spec.root.name && file
|
15
|
+
acceptable_names = Specification::VALID_EXTNAME.map { |extname| "#{spec.root.name}#{extname}" }
|
16
|
+
names_match = acceptable_names.include?(file.basename.to_s)
|
17
|
+
unless names_match
|
18
|
+
results.add_error('name', 'The name of the spec should match the ' \
|
19
|
+
'name of the file.')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require 'swordfish/native/specification'
|
4
|
+
|
5
|
+
module Pod
|
6
|
+
module ExternalSources
|
7
|
+
# Provides support for fetching a specification file from a path local to
|
8
|
+
# the machine running the installation.
|
9
|
+
#
|
10
|
+
class PathSource < AbstractExternalSource
|
11
|
+
def normalized_podspec_path(declared_path)
|
12
|
+
extension = File.extname(declared_path)
|
13
|
+
|
14
|
+
if extension == '.podspec' || extension == '.json'
|
15
|
+
path_with_ext = declared_path
|
16
|
+
else
|
17
|
+
# 默认先从 binary podspec 找起,因为 binary podspec 的 subspec 可能比 code podspec 多
|
18
|
+
# 这里可能出现 code subspec 和 binary subspec 对应不上的情况,导致 lint 失败
|
19
|
+
# 所以不要在 code podspec 同一目录下保留 binary podspec
|
20
|
+
path_with_ext = Specification::VALID_EXTNAME
|
21
|
+
.map { |extname| "#{declared_path}/#{name}#{extname}" }
|
22
|
+
.find { |file| File.exist?(file) } || "#{declared_path}/#{name}.podspec"
|
23
|
+
end
|
24
|
+
|
25
|
+
UI.message "获取的 podspec 路径为 `#{path_with_ext}`"
|
26
|
+
|
27
|
+
podfile_dir = File.dirname(podfile_path || '')
|
28
|
+
|
29
|
+
File.expand_path(path_with_ext, podfile_dir)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require 'swordfish/native/installation_options'
|
4
|
+
|
5
|
+
module Pod
|
6
|
+
class Installer
|
7
|
+
class PodSourceInstaller
|
8
|
+
attr_accessor :installation_options
|
9
|
+
|
10
|
+
alias old_verify_source_is_secure verify_source_is_secure
|
11
|
+
def verify_source_is_secure(root_spec)
|
12
|
+
# http source 默认不警告
|
13
|
+
if installation_options.warn_for_unsecure_source?
|
14
|
+
old_verify_source_is_secure(root_spec)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|