xcocoapods 1.5.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 +7 -0
- data/CHANGELOG.md +6303 -0
- data/LICENSE +28 -0
- data/README.md +80 -0
- data/bin/pod +56 -0
- data/bin/sandbox-pod +168 -0
- data/lib/cocoapods.rb +73 -0
- data/lib/cocoapods/command.rb +175 -0
- data/lib/cocoapods/command/cache.rb +28 -0
- data/lib/cocoapods/command/cache/clean.rb +90 -0
- data/lib/cocoapods/command/cache/list.rb +69 -0
- data/lib/cocoapods/command/env.rb +66 -0
- data/lib/cocoapods/command/init.rb +128 -0
- data/lib/cocoapods/command/install.rb +45 -0
- data/lib/cocoapods/command/ipc.rb +19 -0
- data/lib/cocoapods/command/ipc/list.rb +40 -0
- data/lib/cocoapods/command/ipc/podfile.rb +31 -0
- data/lib/cocoapods/command/ipc/podfile_json.rb +30 -0
- data/lib/cocoapods/command/ipc/repl.rb +51 -0
- data/lib/cocoapods/command/ipc/spec.rb +29 -0
- data/lib/cocoapods/command/ipc/update_search_index.rb +24 -0
- data/lib/cocoapods/command/lib.rb +11 -0
- data/lib/cocoapods/command/lib/create.rb +105 -0
- data/lib/cocoapods/command/lib/lint.rb +121 -0
- data/lib/cocoapods/command/list.rb +39 -0
- data/lib/cocoapods/command/options/project_directory.rb +36 -0
- data/lib/cocoapods/command/options/repo_update.rb +34 -0
- data/lib/cocoapods/command/outdated.rb +140 -0
- data/lib/cocoapods/command/repo.rb +29 -0
- data/lib/cocoapods/command/repo/add.rb +103 -0
- data/lib/cocoapods/command/repo/lint.rb +82 -0
- data/lib/cocoapods/command/repo/list.rb +93 -0
- data/lib/cocoapods/command/repo/push.rb +281 -0
- data/lib/cocoapods/command/repo/remove.rb +36 -0
- data/lib/cocoapods/command/repo/update.rb +28 -0
- data/lib/cocoapods/command/setup.rb +103 -0
- data/lib/cocoapods/command/spec.rb +112 -0
- data/lib/cocoapods/command/spec/cat.rb +51 -0
- data/lib/cocoapods/command/spec/create.rb +283 -0
- data/lib/cocoapods/command/spec/edit.rb +87 -0
- data/lib/cocoapods/command/spec/env_spec.rb +53 -0
- data/lib/cocoapods/command/spec/lint.rb +137 -0
- data/lib/cocoapods/command/spec/which.rb +43 -0
- data/lib/cocoapods/command/update.rb +101 -0
- data/lib/cocoapods/config.rb +347 -0
- data/lib/cocoapods/core_overrides.rb +1 -0
- data/lib/cocoapods/downloader.rb +190 -0
- data/lib/cocoapods/downloader/cache.rb +233 -0
- data/lib/cocoapods/downloader/request.rb +86 -0
- data/lib/cocoapods/downloader/response.rb +16 -0
- data/lib/cocoapods/executable.rb +222 -0
- data/lib/cocoapods/external_sources.rb +57 -0
- data/lib/cocoapods/external_sources/abstract_external_source.rb +205 -0
- data/lib/cocoapods/external_sources/downloader_source.rb +30 -0
- data/lib/cocoapods/external_sources/path_source.rb +55 -0
- data/lib/cocoapods/external_sources/podspec_source.rb +54 -0
- data/lib/cocoapods/gem_version.rb +5 -0
- data/lib/cocoapods/generator/acknowledgements.rb +107 -0
- data/lib/cocoapods/generator/acknowledgements/markdown.rb +44 -0
- data/lib/cocoapods/generator/acknowledgements/plist.rb +94 -0
- data/lib/cocoapods/generator/app_target_helper.rb +244 -0
- data/lib/cocoapods/generator/bridge_support.rb +22 -0
- data/lib/cocoapods/generator/constant.rb +19 -0
- data/lib/cocoapods/generator/copy_resources_script.rb +230 -0
- data/lib/cocoapods/generator/dummy_source.rb +31 -0
- data/lib/cocoapods/generator/embed_frameworks_script.rb +215 -0
- data/lib/cocoapods/generator/header.rb +103 -0
- data/lib/cocoapods/generator/info_plist_file.rb +116 -0
- data/lib/cocoapods/generator/module_map.rb +99 -0
- data/lib/cocoapods/generator/prefix_header.rb +60 -0
- data/lib/cocoapods/generator/umbrella_header.rb +46 -0
- data/lib/cocoapods/hooks_manager.rb +132 -0
- data/lib/cocoapods/installer.rb +703 -0
- data/lib/cocoapods/installer/analyzer.rb +972 -0
- data/lib/cocoapods/installer/analyzer/analysis_result.rb +87 -0
- data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +98 -0
- data/lib/cocoapods/installer/analyzer/pod_variant.rb +67 -0
- data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +157 -0
- data/lib/cocoapods/installer/analyzer/podfile_dependency_cache.rb +54 -0
- data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +240 -0
- data/lib/cocoapods/installer/analyzer/specs_state.rb +84 -0
- data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +53 -0
- data/lib/cocoapods/installer/analyzer/target_inspector.rb +260 -0
- data/lib/cocoapods/installer/installation_options.rb +158 -0
- data/lib/cocoapods/installer/pod_source_installer.rb +202 -0
- data/lib/cocoapods/installer/pod_source_preparer.rb +77 -0
- data/lib/cocoapods/installer/podfile_validator.rb +139 -0
- data/lib/cocoapods/installer/post_install_hooks_context.rb +132 -0
- data/lib/cocoapods/installer/pre_install_hooks_context.rb +51 -0
- data/lib/cocoapods/installer/source_provider_hooks_context.rb +34 -0
- data/lib/cocoapods/installer/user_project_integrator.rb +250 -0
- data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +463 -0
- data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +146 -0
- data/lib/cocoapods/installer/xcode.rb +8 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator.rb +416 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +181 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +84 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +334 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +777 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +116 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +86 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +256 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +68 -0
- data/lib/cocoapods/installer/xcode/target_validator.rb +147 -0
- data/lib/cocoapods/open-uri.rb +33 -0
- data/lib/cocoapods/project.rb +414 -0
- data/lib/cocoapods/resolver.rb +585 -0
- data/lib/cocoapods/resolver/lazy_specification.rb +79 -0
- data/lib/cocoapods/sandbox.rb +404 -0
- data/lib/cocoapods/sandbox/file_accessor.rb +444 -0
- data/lib/cocoapods/sandbox/headers_store.rb +146 -0
- data/lib/cocoapods/sandbox/path_list.rb +220 -0
- data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +85 -0
- data/lib/cocoapods/sandbox/podspec_finder.rb +23 -0
- data/lib/cocoapods/sources_manager.rb +157 -0
- data/lib/cocoapods/target.rb +261 -0
- data/lib/cocoapods/target/aggregate_target.rb +338 -0
- data/lib/cocoapods/target/build_settings.rb +1075 -0
- data/lib/cocoapods/target/pod_target.rb +559 -0
- data/lib/cocoapods/user_interface.rb +459 -0
- data/lib/cocoapods/user_interface/error_report.rb +187 -0
- data/lib/cocoapods/user_interface/inspector_reporter.rb +109 -0
- data/lib/cocoapods/validator.rb +981 -0
- metadata +533 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
module Pod
|
|
4
|
+
describe Command::Env do
|
|
5
|
+
describe 'In general' do
|
|
6
|
+
before do
|
|
7
|
+
@report = Command::Env
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'returns a well-structured environment report' do
|
|
11
|
+
expected = <<-EOS
|
|
12
|
+
|
|
13
|
+
### Stack
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
CocoaPods : #{Pod::VERSION}
|
|
17
|
+
Ruby : #{RUBY_DESCRIPTION}
|
|
18
|
+
RubyGems : #{Gem::VERSION}
|
|
19
|
+
Host : :host_information
|
|
20
|
+
Xcode : :xcode_information
|
|
21
|
+
Git : :git_information
|
|
22
|
+
Ruby lib dir : #{RbConfig::CONFIG['libdir']}
|
|
23
|
+
Repositories : repo_1
|
|
24
|
+
repo_2
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Installation Source
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
Executable Path: /usr/bin/command
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Plugins
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
cocoapods : #{Pod::VERSION}
|
|
37
|
+
cocoapods-core : #{Pod::VERSION}
|
|
38
|
+
cocoapods-plugins : 1.2.3
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Podfile
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
EOS
|
|
47
|
+
|
|
48
|
+
@report.stubs(:actual_path).returns('/usr/bin/command')
|
|
49
|
+
report.should == expected
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
module Pod
|
|
2
|
+
class Command
|
|
3
|
+
class Spec < Command
|
|
4
|
+
class Lint < Spec
|
|
5
|
+
self.summary = 'Validates a spec file'
|
|
6
|
+
|
|
7
|
+
self.description = <<-DESC
|
|
8
|
+
Validates `NAME.podspec`. If a `DIRECTORY` is provided, it validates
|
|
9
|
+
the podspec files found, including subfolders. In case
|
|
10
|
+
the argument is omitted, it defaults to the current working dir.
|
|
11
|
+
DESC
|
|
12
|
+
|
|
13
|
+
self.arguments = [
|
|
14
|
+
CLAide::Argument.new(%w(NAME.podspec DIRECTORY http://PATH/NAME.podspec), false, true),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
def self.options
|
|
18
|
+
[
|
|
19
|
+
['--quick', 'Lint skips checks that would require to download and build the spec'],
|
|
20
|
+
['--allow-warnings', 'Lint validates even if warnings are present'],
|
|
21
|
+
['--subspec=NAME', 'Lint validates only the given subspec'],
|
|
22
|
+
['--no-subspecs', 'Lint skips validation of subspecs'],
|
|
23
|
+
['--no-clean', 'Lint leaves the build directory intact for inspection'],
|
|
24
|
+
['--fail-fast', 'Lint stops on the first failing platform or subspec'],
|
|
25
|
+
['--use-libraries', 'Lint uses static libraries to install the spec'],
|
|
26
|
+
['--sources=https://github.com/artsy/Specs,master', 'The sources from which to pull dependent pods ' \
|
|
27
|
+
'(defaults to https://github.com/CocoaPods/Specs.git). ' \
|
|
28
|
+
'Multiple sources must be comma-delimited.'],
|
|
29
|
+
['--platforms=ios,macos', 'Lint against specific platforms' \
|
|
30
|
+
'(defaults to all platforms supported by the podspec).' \
|
|
31
|
+
'Multiple platforms must be comma-delimited'],
|
|
32
|
+
['--private', 'Lint skips checks that apply only to public specs'],
|
|
33
|
+
['--swift-version=VERSION', 'The SWIFT_VERSION that should be used to lint the spec. ' \
|
|
34
|
+
'This takes precedence over a .swift-version file.'],
|
|
35
|
+
['--skip-import-validation', 'Lint skips validating that the pod can be imported'],
|
|
36
|
+
['--skip-tests', 'Lint skips building and running tests during validation'],
|
|
37
|
+
].concat(super)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def initialize(argv)
|
|
41
|
+
@quick = argv.flag?('quick')
|
|
42
|
+
@allow_warnings = argv.flag?('allow-warnings')
|
|
43
|
+
@clean = argv.flag?('clean', true)
|
|
44
|
+
@fail_fast = argv.flag?('fail-fast', false)
|
|
45
|
+
@subspecs = argv.flag?('subspecs', true)
|
|
46
|
+
@only_subspec = argv.option('subspec')
|
|
47
|
+
@use_frameworks = !argv.flag?('use-libraries')
|
|
48
|
+
@source_urls = argv.option('sources', 'https://github.com/CocoaPods/Specs.git').split(',')
|
|
49
|
+
@platforms = argv.option('platforms', '').split(',')
|
|
50
|
+
@private = argv.flag?('private', false)
|
|
51
|
+
@swift_version = argv.option('swift-version', nil)
|
|
52
|
+
@skip_import_validation = argv.flag?('skip-import-validation', false)
|
|
53
|
+
@skip_tests = argv.flag?('skip-tests', false)
|
|
54
|
+
@podspecs_paths = argv.arguments!
|
|
55
|
+
super
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def run
|
|
59
|
+
UI.puts
|
|
60
|
+
failure_reasons = []
|
|
61
|
+
podspecs_to_lint.each do |podspec|
|
|
62
|
+
validator = Validator.new(podspec, @source_urls, @platforms)
|
|
63
|
+
validator.quick = @quick
|
|
64
|
+
validator.no_clean = !@clean
|
|
65
|
+
validator.fail_fast = @fail_fast
|
|
66
|
+
validator.allow_warnings = @allow_warnings
|
|
67
|
+
validator.no_subspecs = !@subspecs || @only_subspec
|
|
68
|
+
validator.only_subspec = @only_subspec
|
|
69
|
+
validator.use_frameworks = @use_frameworks
|
|
70
|
+
validator.ignore_public_only_results = @private
|
|
71
|
+
validator.swift_version = @swift_version
|
|
72
|
+
validator.skip_import_validation = @skip_import_validation
|
|
73
|
+
validator.skip_tests = @skip_tests
|
|
74
|
+
validator.validate
|
|
75
|
+
failure_reasons << validator.failure_reason
|
|
76
|
+
|
|
77
|
+
unless @clean
|
|
78
|
+
UI.puts "Pods workspace available at `#{validator.validation_dir}/App.xcworkspace` for inspection."
|
|
79
|
+
UI.puts
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
count = podspecs_to_lint.count
|
|
84
|
+
UI.puts "Analyzed #{count} #{'podspec'.pluralize(count)}.\n\n"
|
|
85
|
+
|
|
86
|
+
failure_reasons.compact!
|
|
87
|
+
if failure_reasons.empty?
|
|
88
|
+
lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : 'All the specs passed validation.'
|
|
89
|
+
UI.puts lint_passed_message.green << "\n\n"
|
|
90
|
+
else
|
|
91
|
+
raise Informative, if count == 1
|
|
92
|
+
"The spec did not pass validation, due to #{failure_reasons.first}."
|
|
93
|
+
else
|
|
94
|
+
"#{failure_reasons.count} out of #{count} specs failed validation."
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
podspecs_tmp_dir.rmtree if podspecs_tmp_dir.exist?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
def podspecs_to_lint
|
|
103
|
+
@podspecs_to_lint ||= begin
|
|
104
|
+
files = []
|
|
105
|
+
@podspecs_paths << '.' if @podspecs_paths.empty?
|
|
106
|
+
@podspecs_paths.each do |path|
|
|
107
|
+
if path =~ %r{https?://}
|
|
108
|
+
require 'cocoapods/open-uri'
|
|
109
|
+
output_path = podspecs_tmp_dir + File.basename(path)
|
|
110
|
+
output_path.dirname.mkpath
|
|
111
|
+
begin
|
|
112
|
+
open(path) do |io|
|
|
113
|
+
output_path.open('w') { |f| f << io.read }
|
|
114
|
+
end
|
|
115
|
+
rescue => e
|
|
116
|
+
raise Informative, "Downloading a podspec from `#{path}` failed: #{e}"
|
|
117
|
+
end
|
|
118
|
+
files << output_path
|
|
119
|
+
elsif (pathname = Pathname.new(path)).directory?
|
|
120
|
+
files += Pathname.glob(pathname + '*.podspec{.json,}')
|
|
121
|
+
raise Informative, 'No specs found in the current directory.' if files.empty?
|
|
122
|
+
else
|
|
123
|
+
files << (pathname = Pathname.new(path))
|
|
124
|
+
raise Informative, "Unable to find a spec named `#{path}'." unless pathname.exist? && path.include?('.podspec')
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
files
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def podspecs_tmp_dir
|
|
132
|
+
Pathname.new(Dir.tmpdir) + 'CocoaPods/Lint_podspec'
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Pod
|
|
2
|
+
class Command
|
|
3
|
+
class Spec < Command
|
|
4
|
+
class Which < Spec
|
|
5
|
+
self.summary = 'Prints the path of the given spec'
|
|
6
|
+
|
|
7
|
+
self.description = <<-DESC
|
|
8
|
+
Prints the path of the .podspec file(s) whose name matches `QUERY`
|
|
9
|
+
DESC
|
|
10
|
+
|
|
11
|
+
self.arguments = [
|
|
12
|
+
CLAide::Argument.new('QUERY', false),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
def self.options
|
|
16
|
+
[
|
|
17
|
+
['--regex', 'Interpret the `QUERY` as a regular expression'],
|
|
18
|
+
['--show-all', 'Print all versions of the given podspec'],
|
|
19
|
+
].concat(super)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize(argv)
|
|
23
|
+
@use_regex = argv.flag?('regex')
|
|
24
|
+
@show_all = argv.flag?('show-all')
|
|
25
|
+
@query = argv.shift_argument
|
|
26
|
+
@query = @query.gsub('.podspec', '') unless @query.nil?
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def validate!
|
|
31
|
+
super
|
|
32
|
+
help! 'A podspec name is required.' unless @query
|
|
33
|
+
validate_regex!(@query) if @use_regex
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def run
|
|
37
|
+
query = @use_regex ? @query : Regexp.escape(@query)
|
|
38
|
+
UI.puts get_path_of_spec(query, @show_all)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module Pod
|
|
2
|
+
class Command
|
|
3
|
+
class Update < Command
|
|
4
|
+
include RepoUpdate
|
|
5
|
+
include ProjectDirectory
|
|
6
|
+
|
|
7
|
+
self.summary = 'Update outdated project dependencies and create new ' \
|
|
8
|
+
'Podfile.lock'
|
|
9
|
+
|
|
10
|
+
self.description = <<-DESC
|
|
11
|
+
Updates the Pods identified by the specified `POD_NAMES`, which is a
|
|
12
|
+
space-delimited list of pod names. If no `POD_NAMES` are specified, it
|
|
13
|
+
updates all the Pods, ignoring the contents of the Podfile.lock. This
|
|
14
|
+
command is reserved for the update of dependencies; pod install should
|
|
15
|
+
be used to install changes to the Podfile.
|
|
16
|
+
DESC
|
|
17
|
+
|
|
18
|
+
self.arguments = [
|
|
19
|
+
CLAide::Argument.new('POD_NAMES', false, true),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
def self.options
|
|
23
|
+
[
|
|
24
|
+
['--sources=https://github.com/artsy/Specs,master', 'The sources from which to update dependent pods. ' \
|
|
25
|
+
'Multiple sources must be comma-delimited. The master repo will not be included by default with this option.'],
|
|
26
|
+
['--exclude-pods=podName', 'Pods to exclude during update. Multiple pods must be comma-delimited.'],
|
|
27
|
+
].concat(super)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(argv)
|
|
31
|
+
@pods = argv.arguments! unless argv.arguments.empty?
|
|
32
|
+
|
|
33
|
+
source_urls = argv.option('sources', '').split(',')
|
|
34
|
+
excluded_pods = argv.option('exclude-pods', '').split(',')
|
|
35
|
+
unless source_urls.empty?
|
|
36
|
+
source_pods = source_urls.flat_map { |url| config.sources_manager.source_with_name_or_url(url).pods }
|
|
37
|
+
unless source_pods.empty?
|
|
38
|
+
source_pods = source_pods.select { |pod| config.lockfile.pod_names.include?(pod) }
|
|
39
|
+
if @pods
|
|
40
|
+
@pods += source_pods
|
|
41
|
+
else
|
|
42
|
+
@pods = source_pods unless source_pods.empty?
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
unless excluded_pods.empty?
|
|
48
|
+
@pods ||= config.lockfile.pod_names.dup
|
|
49
|
+
|
|
50
|
+
non_installed_pods = (excluded_pods - @pods)
|
|
51
|
+
unless non_installed_pods.empty?
|
|
52
|
+
pluralized_words = non_installed_pods.length > 1 ? %w(Pods are) : %w(Pod is)
|
|
53
|
+
message = "Trying to skip `#{non_installed_pods.join('`, `')}` #{pluralized_words.first} " \
|
|
54
|
+
"which #{pluralized_words.last} not installed"
|
|
55
|
+
raise Informative, message
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
@pods.delete_if { |pod| excluded_pods.include?(pod) }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
super
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Check if all given pods are installed
|
|
65
|
+
#
|
|
66
|
+
def verify_pods_are_installed!
|
|
67
|
+
lockfile_roots = config.lockfile.pod_names.map { |p| Specification.root_name(p) }
|
|
68
|
+
missing_pods = @pods.map { |p| Specification.root_name(p) }.select do |pod|
|
|
69
|
+
!lockfile_roots.include?(pod)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
unless missing_pods.empty?
|
|
73
|
+
message = if missing_pods.length > 1
|
|
74
|
+
"Pods `#{missing_pods.join('`, `')}` are not " \
|
|
75
|
+
'installed and cannot be updated'
|
|
76
|
+
else
|
|
77
|
+
"The `#{missing_pods.first}` Pod is not installed " \
|
|
78
|
+
'and cannot be updated'
|
|
79
|
+
end
|
|
80
|
+
raise Informative, message
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def run
|
|
85
|
+
verify_podfile_exists!
|
|
86
|
+
|
|
87
|
+
installer = installer_for_config
|
|
88
|
+
installer.repo_update = repo_update?(:default => true)
|
|
89
|
+
if @pods
|
|
90
|
+
verify_lockfile_exists!
|
|
91
|
+
verify_pods_are_installed!
|
|
92
|
+
installer.update = { :pods => @pods }
|
|
93
|
+
else
|
|
94
|
+
UI.puts 'Update all pods'.yellow
|
|
95
|
+
installer.update = true
|
|
96
|
+
end
|
|
97
|
+
installer.install!
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
require 'active_support/multibyte/unicode'
|
|
2
|
+
|
|
3
|
+
module Pod
|
|
4
|
+
# Stores the global configuration of CocoaPods.
|
|
5
|
+
#
|
|
6
|
+
class Config
|
|
7
|
+
# The default settings for the configuration.
|
|
8
|
+
#
|
|
9
|
+
# Users can specify custom settings in `~/.cocoapods/config.yaml`.
|
|
10
|
+
# An example of the contents of this file might look like:
|
|
11
|
+
#
|
|
12
|
+
# ---
|
|
13
|
+
# skip_repo_update: true
|
|
14
|
+
# new_version_message: false
|
|
15
|
+
#
|
|
16
|
+
DEFAULTS = {
|
|
17
|
+
:verbose => false,
|
|
18
|
+
:silent => false,
|
|
19
|
+
:skip_download_cache => !ENV['COCOAPODS_SKIP_CACHE'].nil?,
|
|
20
|
+
|
|
21
|
+
:new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?,
|
|
22
|
+
|
|
23
|
+
:cache_root => Pathname.new(Dir.home) + 'Library/Caches/CocoaPods',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# Applies the given changes to the config for the duration of the given
|
|
27
|
+
# block.
|
|
28
|
+
#
|
|
29
|
+
# @param [Hash<#to_sym,Object>] changes
|
|
30
|
+
# the changes to merge temporarily with the current config
|
|
31
|
+
#
|
|
32
|
+
# @yield [] is called while the changes are applied
|
|
33
|
+
#
|
|
34
|
+
def with_changes(changes)
|
|
35
|
+
old = {}
|
|
36
|
+
changes.keys.each do |key|
|
|
37
|
+
key = key.to_sym
|
|
38
|
+
old[key] = send(key) if respond_to?(key)
|
|
39
|
+
end
|
|
40
|
+
configure_with(changes)
|
|
41
|
+
yield if block_given?
|
|
42
|
+
ensure
|
|
43
|
+
configure_with(old)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
public
|
|
47
|
+
|
|
48
|
+
#-------------------------------------------------------------------------#
|
|
49
|
+
|
|
50
|
+
# @!group UI
|
|
51
|
+
|
|
52
|
+
# @return [Bool] Whether CocoaPods should provide detailed output about the
|
|
53
|
+
# performed actions.
|
|
54
|
+
#
|
|
55
|
+
attr_accessor :verbose
|
|
56
|
+
alias_method :verbose?, :verbose
|
|
57
|
+
|
|
58
|
+
# @return [Bool] Whether CocoaPods should produce not output.
|
|
59
|
+
#
|
|
60
|
+
attr_accessor :silent
|
|
61
|
+
alias_method :silent?, :silent
|
|
62
|
+
|
|
63
|
+
# @return [Bool] Whether a message should be printed when a new version of
|
|
64
|
+
# CocoaPods is available.
|
|
65
|
+
#
|
|
66
|
+
attr_accessor :new_version_message
|
|
67
|
+
alias_method :new_version_message?, :new_version_message
|
|
68
|
+
|
|
69
|
+
#-------------------------------------------------------------------------#
|
|
70
|
+
|
|
71
|
+
# @!group Installation
|
|
72
|
+
|
|
73
|
+
# @return [Bool] Whether the installer should skip the download cache.
|
|
74
|
+
#
|
|
75
|
+
attr_accessor :skip_download_cache
|
|
76
|
+
alias_method :skip_download_cache?, :skip_download_cache
|
|
77
|
+
|
|
78
|
+
public
|
|
79
|
+
|
|
80
|
+
#-------------------------------------------------------------------------#
|
|
81
|
+
|
|
82
|
+
# @!group Cache
|
|
83
|
+
|
|
84
|
+
# @return [Pathname] The directory where CocoaPods should cache remote data
|
|
85
|
+
# and other expensive to compute information.
|
|
86
|
+
#
|
|
87
|
+
attr_accessor :cache_root
|
|
88
|
+
|
|
89
|
+
def cache_root
|
|
90
|
+
@cache_root.mkpath unless @cache_root.exist?
|
|
91
|
+
@cache_root
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
public
|
|
95
|
+
|
|
96
|
+
#-------------------------------------------------------------------------#
|
|
97
|
+
|
|
98
|
+
# @!group Initialization
|
|
99
|
+
|
|
100
|
+
def initialize(use_user_settings = true)
|
|
101
|
+
configure_with(DEFAULTS)
|
|
102
|
+
|
|
103
|
+
unless ENV['CP_HOME_DIR'].nil?
|
|
104
|
+
@cache_root = home_dir + 'cache'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
if use_user_settings && user_settings_file.exist?
|
|
108
|
+
require 'yaml'
|
|
109
|
+
user_settings = YAML.load_file(user_settings_file)
|
|
110
|
+
configure_with(user_settings)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
unless ENV['CP_CACHE_DIR'].nil?
|
|
114
|
+
@cache_root = Pathname.new(ENV['CP_CACHE_DIR']).expand_path
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def verbose
|
|
119
|
+
@verbose && !silent
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
public
|
|
123
|
+
|
|
124
|
+
#-------------------------------------------------------------------------#
|
|
125
|
+
|
|
126
|
+
# @!group Paths
|
|
127
|
+
|
|
128
|
+
# @return [Pathname] the directory where repos, templates and configuration
|
|
129
|
+
# files are stored.
|
|
130
|
+
#
|
|
131
|
+
def home_dir
|
|
132
|
+
@home_dir ||= Pathname.new(ENV['CP_HOME_DIR'] || '~/.cocoapods').expand_path
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# @return [Pathname] the directory where the CocoaPods sources are stored.
|
|
136
|
+
#
|
|
137
|
+
def repos_dir
|
|
138
|
+
@repos_dir ||= Pathname.new(ENV['CP_REPOS_DIR'] || (home_dir + 'repos')).expand_path
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
attr_writer :repos_dir
|
|
142
|
+
|
|
143
|
+
def sources_manager
|
|
144
|
+
return @sources_manager if @sources_manager && @sources_manager.repos_dir == repos_dir
|
|
145
|
+
@sources_manager = Source::Manager.new(repos_dir)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# @return [Pathname] the directory where the CocoaPods templates are stored.
|
|
149
|
+
#
|
|
150
|
+
def templates_dir
|
|
151
|
+
@templates_dir ||= Pathname.new(ENV['CP_TEMPLATES_DIR'] || (home_dir + 'templates')).expand_path
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# @return [Pathname] the root of the CocoaPods installation where the
|
|
155
|
+
# Podfile is located.
|
|
156
|
+
#
|
|
157
|
+
def installation_root
|
|
158
|
+
current_dir = ActiveSupport::Multibyte::Unicode.normalize(Dir.pwd)
|
|
159
|
+
current_path = Pathname.new(current_dir)
|
|
160
|
+
unless @installation_root
|
|
161
|
+
until current_path.root?
|
|
162
|
+
if podfile_path_in_dir(current_path)
|
|
163
|
+
@installation_root = current_path
|
|
164
|
+
unless current_path == Pathname.pwd
|
|
165
|
+
UI.puts("[in #{current_path}]")
|
|
166
|
+
end
|
|
167
|
+
break
|
|
168
|
+
else
|
|
169
|
+
current_path = current_path.parent
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
@installation_root ||= Pathname.pwd
|
|
173
|
+
end
|
|
174
|
+
@installation_root
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
attr_writer :installation_root
|
|
178
|
+
alias_method :project_root, :installation_root
|
|
179
|
+
|
|
180
|
+
# @return [Pathname] The root of the sandbox.
|
|
181
|
+
#
|
|
182
|
+
def sandbox_root
|
|
183
|
+
@sandbox_root ||= installation_root + 'Pods'
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
attr_writer :sandbox_root
|
|
187
|
+
alias_method :project_pods_root, :sandbox_root
|
|
188
|
+
|
|
189
|
+
# @return [Sandbox] The sandbox of the current project.
|
|
190
|
+
#
|
|
191
|
+
def sandbox
|
|
192
|
+
@sandbox ||= Sandbox.new(sandbox_root)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# @return [Podfile] The Podfile to use for the current execution.
|
|
196
|
+
# @return [Nil] If no Podfile is available.
|
|
197
|
+
#
|
|
198
|
+
def podfile
|
|
199
|
+
@podfile ||= Podfile.from_file(podfile_path) if podfile_path
|
|
200
|
+
end
|
|
201
|
+
attr_writer :podfile
|
|
202
|
+
|
|
203
|
+
# @return [Lockfile] The Lockfile to use for the current execution.
|
|
204
|
+
# @return [Nil] If no Lockfile is available.
|
|
205
|
+
#
|
|
206
|
+
def lockfile
|
|
207
|
+
@lockfile ||= Lockfile.from_file(lockfile_path) if lockfile_path
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Returns the path of the Podfile.
|
|
211
|
+
#
|
|
212
|
+
# @note The Podfile can be named either `CocoaPods.podfile.yaml`,
|
|
213
|
+
# `CocoaPods.podfile` or `Podfile`. The first two are preferred as
|
|
214
|
+
# they allow to specify an OS X UTI.
|
|
215
|
+
#
|
|
216
|
+
# @return [Pathname]
|
|
217
|
+
# @return [Nil]
|
|
218
|
+
#
|
|
219
|
+
def podfile_path
|
|
220
|
+
@podfile_path ||= podfile_path_in_dir(installation_root)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Returns the path of the Lockfile.
|
|
224
|
+
#
|
|
225
|
+
# @note The Lockfile is named `Podfile.lock`.
|
|
226
|
+
#
|
|
227
|
+
def lockfile_path
|
|
228
|
+
@lockfile_path ||= installation_root + 'Podfile.lock'
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Returns the path of the default Podfile pods.
|
|
232
|
+
#
|
|
233
|
+
# @note The file is expected to be named Podfile.default
|
|
234
|
+
#
|
|
235
|
+
# @return [Pathname]
|
|
236
|
+
#
|
|
237
|
+
def default_podfile_path
|
|
238
|
+
@default_podfile_path ||= templates_dir + 'Podfile.default'
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Returns the path of the default Podfile test pods.
|
|
242
|
+
#
|
|
243
|
+
# @note The file is expected to be named Podfile.test
|
|
244
|
+
#
|
|
245
|
+
# @return [Pathname]
|
|
246
|
+
#
|
|
247
|
+
def default_test_podfile_path
|
|
248
|
+
@default_test_podfile_path ||= templates_dir + 'Podfile.test'
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# @return [Pathname] The file to use to cache the search data.
|
|
252
|
+
#
|
|
253
|
+
def search_index_file
|
|
254
|
+
cache_root + 'search_index.json'
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
private
|
|
258
|
+
|
|
259
|
+
#-------------------------------------------------------------------------#
|
|
260
|
+
|
|
261
|
+
# @!group Private helpers
|
|
262
|
+
|
|
263
|
+
# @return [Pathname] The path of the file which contains the user settings.
|
|
264
|
+
#
|
|
265
|
+
def user_settings_file
|
|
266
|
+
home_dir + 'config.yaml'
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Sets the values of the attributes with the given hash.
|
|
270
|
+
#
|
|
271
|
+
# @param [Hash{String,Symbol => Object}] values_by_key
|
|
272
|
+
# The values of the attributes grouped by key.
|
|
273
|
+
#
|
|
274
|
+
# @return [void]
|
|
275
|
+
#
|
|
276
|
+
def configure_with(values_by_key)
|
|
277
|
+
return unless values_by_key
|
|
278
|
+
values_by_key.each do |key, value|
|
|
279
|
+
if key == :cache_root
|
|
280
|
+
value = Pathname.new(value).expand_path
|
|
281
|
+
end
|
|
282
|
+
instance_variable_set("@#{key}", value)
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# @return [Array<String>] The filenames that the Podfile can have ordered
|
|
287
|
+
# by priority.
|
|
288
|
+
#
|
|
289
|
+
PODFILE_NAMES = [
|
|
290
|
+
'CocoaPods.podfile.yaml',
|
|
291
|
+
'CocoaPods.podfile',
|
|
292
|
+
'Podfile',
|
|
293
|
+
].freeze
|
|
294
|
+
|
|
295
|
+
public
|
|
296
|
+
|
|
297
|
+
# Returns the path of the Podfile in the given dir if any exists.
|
|
298
|
+
#
|
|
299
|
+
# @param [Pathname] dir
|
|
300
|
+
# The directory where to look for the Podfile.
|
|
301
|
+
#
|
|
302
|
+
# @return [Pathname] The path of the Podfile.
|
|
303
|
+
# @return [Nil] If not Podfile was found in the given dir
|
|
304
|
+
#
|
|
305
|
+
def podfile_path_in_dir(dir)
|
|
306
|
+
PODFILE_NAMES.each do |filename|
|
|
307
|
+
candidate = dir + filename
|
|
308
|
+
if candidate.exist?
|
|
309
|
+
return candidate
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
nil
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
public
|
|
316
|
+
|
|
317
|
+
#-------------------------------------------------------------------------#
|
|
318
|
+
|
|
319
|
+
# @!group Singleton
|
|
320
|
+
|
|
321
|
+
# @return [Config] the current config instance creating one if needed.
|
|
322
|
+
#
|
|
323
|
+
def self.instance
|
|
324
|
+
@instance ||= new
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
# Sets the current config instance. If set to nil the config will be
|
|
328
|
+
# recreated when needed.
|
|
329
|
+
#
|
|
330
|
+
# @param [Config, Nil] the instance.
|
|
331
|
+
#
|
|
332
|
+
# @return [void]
|
|
333
|
+
#
|
|
334
|
+
class << self
|
|
335
|
+
attr_writer :instance
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# Provides support for accessing the configuration instance in other
|
|
339
|
+
# scopes.
|
|
340
|
+
#
|
|
341
|
+
module Mixin
|
|
342
|
+
def config
|
|
343
|
+
Config.instance
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|