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,220 @@
|
|
|
1
|
+
require 'active_support/multibyte/unicode'
|
|
2
|
+
require 'find'
|
|
3
|
+
|
|
4
|
+
module Pod
|
|
5
|
+
class Sandbox
|
|
6
|
+
# The PathList class is designed to perform multiple glob matches against
|
|
7
|
+
# a given directory. Basically, it generates a list of all the children
|
|
8
|
+
# paths and matches the globs patterns against them, resulting in just one
|
|
9
|
+
# access to the file system.
|
|
10
|
+
#
|
|
11
|
+
# @note A PathList once it has generated the list of the paths this is
|
|
12
|
+
# updated only if explicitly requested by calling
|
|
13
|
+
# {#read_file_system}
|
|
14
|
+
#
|
|
15
|
+
class PathList
|
|
16
|
+
# @return [Pathname] The root of the list whose files and directories
|
|
17
|
+
# are used to perform the matching operations.
|
|
18
|
+
#
|
|
19
|
+
attr_reader :root
|
|
20
|
+
|
|
21
|
+
# Initialize a new instance
|
|
22
|
+
#
|
|
23
|
+
# @param [Pathname] root @see #root
|
|
24
|
+
#
|
|
25
|
+
def initialize(root)
|
|
26
|
+
root_dir = ActiveSupport::Multibyte::Unicode.normalize(root.to_s)
|
|
27
|
+
@root = Pathname.new(root_dir)
|
|
28
|
+
@glob_cache = {}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Array<String>] The list of absolute the path of all the files
|
|
32
|
+
# contained in {root}.
|
|
33
|
+
#
|
|
34
|
+
def files
|
|
35
|
+
read_file_system unless @files
|
|
36
|
+
@files
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @return [Array<String>] The list of absolute the path of all the
|
|
40
|
+
# directories contained in {root}.
|
|
41
|
+
#
|
|
42
|
+
def dirs
|
|
43
|
+
read_file_system unless @dirs
|
|
44
|
+
@dirs
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @return [void] Reads the file system and populates the files and paths
|
|
48
|
+
# lists.
|
|
49
|
+
#
|
|
50
|
+
def read_file_system
|
|
51
|
+
unless root.exist?
|
|
52
|
+
raise Informative, "Attempt to read non existent folder `#{root}`."
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
dirs = []
|
|
56
|
+
files = []
|
|
57
|
+
root_length = root.cleanpath.to_s.length + File::SEPARATOR.length
|
|
58
|
+
Find.find(root.to_s) do |f|
|
|
59
|
+
directory = File.directory?(f)
|
|
60
|
+
f = f.slice(root_length, f.length - root_length)
|
|
61
|
+
next if f.nil?
|
|
62
|
+
|
|
63
|
+
(directory ? dirs : files) << f
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
dirs.sort_by!(&:upcase)
|
|
67
|
+
files.sort_by!(&:upcase)
|
|
68
|
+
|
|
69
|
+
@dirs = dirs
|
|
70
|
+
@files = files
|
|
71
|
+
@glob_cache = {}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#-----------------------------------------------------------------------#
|
|
75
|
+
|
|
76
|
+
public
|
|
77
|
+
|
|
78
|
+
# @!group Globbing
|
|
79
|
+
|
|
80
|
+
# Similar to {glob} but returns the absolute paths.
|
|
81
|
+
#
|
|
82
|
+
# @param [String,Array<String>] patterns
|
|
83
|
+
# @see #relative_glob
|
|
84
|
+
#
|
|
85
|
+
# @param [Hash] options
|
|
86
|
+
# @see #relative_glob
|
|
87
|
+
#
|
|
88
|
+
# @return [Array<Pathname>]
|
|
89
|
+
#
|
|
90
|
+
def glob(patterns, options = {})
|
|
91
|
+
cache_key = options.merge(:patterns => patterns)
|
|
92
|
+
@glob_cache[cache_key] ||= relative_glob(patterns, options).map { |p| root.join(p) }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# The list of relative paths that are case insensitively matched by a
|
|
96
|
+
# given pattern. This method emulates {Dir#glob} with the
|
|
97
|
+
# {File::FNM_CASEFOLD} option.
|
|
98
|
+
#
|
|
99
|
+
# @param [String,Array<String>] patterns
|
|
100
|
+
# A single {Dir#glob} like pattern, or a list of patterns.
|
|
101
|
+
#
|
|
102
|
+
# @param [Hash] options
|
|
103
|
+
#
|
|
104
|
+
# @option options [String] :dir_pattern
|
|
105
|
+
# An optional pattern to append to a pattern, if it is the path
|
|
106
|
+
# to a directory.
|
|
107
|
+
#
|
|
108
|
+
# @option options [Array<String>] :exclude_patterns
|
|
109
|
+
# Exclude specific paths given by those patterns.
|
|
110
|
+
#
|
|
111
|
+
# @option options [Array<String>] :include_dirs
|
|
112
|
+
# Additional paths to take into account for matching.
|
|
113
|
+
#
|
|
114
|
+
# @return [Array<Pathname>]
|
|
115
|
+
#
|
|
116
|
+
def relative_glob(patterns, options = {})
|
|
117
|
+
return [] if patterns.empty?
|
|
118
|
+
|
|
119
|
+
dir_pattern = options[:dir_pattern]
|
|
120
|
+
exclude_patterns = options[:exclude_patterns]
|
|
121
|
+
include_dirs = options[:include_dirs]
|
|
122
|
+
|
|
123
|
+
if include_dirs
|
|
124
|
+
full_list = files + dirs
|
|
125
|
+
else
|
|
126
|
+
full_list = files
|
|
127
|
+
end
|
|
128
|
+
patterns_array = Array(patterns)
|
|
129
|
+
exact_matches = (full_list & patterns_array).to_set
|
|
130
|
+
|
|
131
|
+
unless patterns_array.empty?
|
|
132
|
+
list = patterns_array.flat_map do |pattern|
|
|
133
|
+
if exact_matches.include?(pattern)
|
|
134
|
+
pattern
|
|
135
|
+
else
|
|
136
|
+
if directory?(pattern) && dir_pattern
|
|
137
|
+
pattern += '/' unless pattern.end_with?('/')
|
|
138
|
+
pattern += dir_pattern
|
|
139
|
+
end
|
|
140
|
+
expanded_patterns = dir_glob_equivalent_patterns(pattern)
|
|
141
|
+
full_list.select do |path|
|
|
142
|
+
expanded_patterns.any? do |p|
|
|
143
|
+
File.fnmatch(p, path, File::FNM_CASEFOLD | File::FNM_PATHNAME)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
list = list.map { |path| Pathname.new(path) }
|
|
151
|
+
if exclude_patterns
|
|
152
|
+
exclude_options = { :dir_pattern => '**/*', :include_dirs => include_dirs }
|
|
153
|
+
list -= relative_glob(exclude_patterns, exclude_options)
|
|
154
|
+
end
|
|
155
|
+
list
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
#-----------------------------------------------------------------------#
|
|
159
|
+
|
|
160
|
+
private
|
|
161
|
+
|
|
162
|
+
# @!group Private helpers
|
|
163
|
+
|
|
164
|
+
# @return [Bool] Wether a path is a directory. The result of this method
|
|
165
|
+
# computed without accessing the file system and is case
|
|
166
|
+
# insensitive.
|
|
167
|
+
#
|
|
168
|
+
# @param [String, Pathname] sub_path The path that could be a directory.
|
|
169
|
+
#
|
|
170
|
+
def directory?(sub_path)
|
|
171
|
+
sub_path = sub_path.to_s.downcase.sub(/\/$/, '')
|
|
172
|
+
dirs.any? { |dir| dir.downcase == sub_path }
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# @return [Array<String>] An array of patterns converted from a
|
|
176
|
+
# {Dir.glob} pattern to patterns that {File.fnmatch} can handle.
|
|
177
|
+
# This is used by the {#relative_glob} method to emulate
|
|
178
|
+
# {Dir.glob}.
|
|
179
|
+
#
|
|
180
|
+
# The expansion provides support for:
|
|
181
|
+
#
|
|
182
|
+
# - Literals
|
|
183
|
+
#
|
|
184
|
+
# dir_glob_equivalent_patterns('{file1,file2}.{h,m}')
|
|
185
|
+
# => ["file1.h", "file1.m", "file2.h", "file2.m"]
|
|
186
|
+
#
|
|
187
|
+
# - Matching the direct children of a directory with `**`
|
|
188
|
+
#
|
|
189
|
+
# dir_glob_equivalent_patterns('Classes/**/file.m')
|
|
190
|
+
# => ["Classes/**/file.m", "Classes/file.m"]
|
|
191
|
+
#
|
|
192
|
+
# @param [String] pattern A {Dir#glob} like pattern.
|
|
193
|
+
#
|
|
194
|
+
def dir_glob_equivalent_patterns(pattern)
|
|
195
|
+
pattern = pattern.gsub('/**/', '{/**/,/}')
|
|
196
|
+
values_by_set = {}
|
|
197
|
+
pattern.scan(/\{[^}]*\}/) do |set|
|
|
198
|
+
values = set.gsub(/[{}]/, '').split(',')
|
|
199
|
+
values_by_set[set] = values
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
if values_by_set.empty?
|
|
203
|
+
[pattern]
|
|
204
|
+
else
|
|
205
|
+
patterns = [pattern]
|
|
206
|
+
values_by_set.each do |set, values|
|
|
207
|
+
patterns = patterns.flat_map do |old_pattern|
|
|
208
|
+
values.map do |value|
|
|
209
|
+
old_pattern.gsub(set, value)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
patterns
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
#-----------------------------------------------------------------------#
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Pod
|
|
2
|
+
class Sandbox
|
|
3
|
+
class PodDirCleaner
|
|
4
|
+
attr_reader :root
|
|
5
|
+
attr_reader :specs_by_platform
|
|
6
|
+
|
|
7
|
+
def initialize(root, specs_by_platform)
|
|
8
|
+
@root = root
|
|
9
|
+
@specs_by_platform = specs_by_platform
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Removes all the files not needed for the installation according to the
|
|
13
|
+
# specs by platform.
|
|
14
|
+
#
|
|
15
|
+
# @return [void]
|
|
16
|
+
#
|
|
17
|
+
def clean!
|
|
18
|
+
clean_paths.each { |path| FileUtils.rm_rf(path) } if root.exist?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# @return [Array<Sandbox::FileAccessor>] the file accessors for all the
|
|
24
|
+
# specifications on their respective platform.
|
|
25
|
+
#
|
|
26
|
+
def file_accessors
|
|
27
|
+
@file_accessors ||= specs_by_platform.flat_map do |platform, specs|
|
|
28
|
+
specs.flat_map { |spec| Sandbox::FileAccessor.new(path_list, spec.consumer(platform)) }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @return [Sandbox::PathList] The path list for this Pod.
|
|
33
|
+
#
|
|
34
|
+
def path_list
|
|
35
|
+
@path_list ||= Sandbox::PathList.new(root)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Finds the absolute paths, including hidden ones, of the files
|
|
39
|
+
# that are not used by the pod and thus can be safely deleted.
|
|
40
|
+
#
|
|
41
|
+
# @note Implementation detail: Don't use `Dir#glob` as there is an
|
|
42
|
+
# unexplained issue (#568, #572 and #602).
|
|
43
|
+
#
|
|
44
|
+
# @todo The paths are down-cased for the comparison as issues similar
|
|
45
|
+
# to #602 lead the files not being matched and so cleaning all
|
|
46
|
+
# the files. This solution might create side effects.
|
|
47
|
+
#
|
|
48
|
+
# @return [Array<Strings>] The paths that can be deleted.
|
|
49
|
+
#
|
|
50
|
+
def clean_paths
|
|
51
|
+
cached_used = used_files
|
|
52
|
+
glob_options = File::FNM_DOTMATCH | File::FNM_CASEFOLD
|
|
53
|
+
files = Pathname.glob(root + '**/*', glob_options).map(&:to_s)
|
|
54
|
+
|
|
55
|
+
files.reject do |candidate|
|
|
56
|
+
candidate = candidate.downcase
|
|
57
|
+
candidate.end_with?('.', '..') || cached_used.any? do |path|
|
|
58
|
+
path = path.downcase
|
|
59
|
+
path.include?(candidate) || candidate.include?(path)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [Array<String>] The absolute path of all the files used by the
|
|
65
|
+
# specifications (according to their platform) of this Pod.
|
|
66
|
+
#
|
|
67
|
+
def used_files
|
|
68
|
+
files = [
|
|
69
|
+
file_accessors.map(&:vendored_frameworks),
|
|
70
|
+
file_accessors.map(&:vendored_libraries),
|
|
71
|
+
file_accessors.map(&:resource_bundle_files),
|
|
72
|
+
file_accessors.map(&:license),
|
|
73
|
+
file_accessors.map(&:prefix_header),
|
|
74
|
+
file_accessors.map(&:preserve_paths),
|
|
75
|
+
file_accessors.map(&:readme),
|
|
76
|
+
file_accessors.map(&:resources),
|
|
77
|
+
file_accessors.map(&:source_files),
|
|
78
|
+
file_accessors.map(&:module_map),
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
files.flatten.compact.map(&:to_s).uniq
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Pod
|
|
2
|
+
class Sandbox
|
|
3
|
+
class PodspecFinder
|
|
4
|
+
attr_reader :root
|
|
5
|
+
|
|
6
|
+
def initialize(root)
|
|
7
|
+
@root = root
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def podspecs
|
|
11
|
+
return @specs_by_name if @specs_by_name
|
|
12
|
+
@specs_by_name = {}
|
|
13
|
+
spec_files = Pathname.glob(root + '{,*}.podspec{,.json}')
|
|
14
|
+
spec_files.sort_by { |p| -p.to_path.split(File::SEPARATOR).size }.each do |file|
|
|
15
|
+
spec = Specification.from_file(file)
|
|
16
|
+
spec.validate_cocoapods_version
|
|
17
|
+
@specs_by_name[spec.name] = spec
|
|
18
|
+
end
|
|
19
|
+
@specs_by_name
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
require 'cocoapods-core/source'
|
|
2
|
+
require 'set'
|
|
3
|
+
|
|
4
|
+
module Pod
|
|
5
|
+
class Source
|
|
6
|
+
class Manager
|
|
7
|
+
# Returns the source whose {Source#url} is equal to `url`, adding the repo
|
|
8
|
+
# in a manner similarly to `pod repo add` if it is not found.
|
|
9
|
+
#
|
|
10
|
+
# @raise If no source with the given `url` could be created,
|
|
11
|
+
#
|
|
12
|
+
# @return [Source] The source whose {Source#url} is equal to `url`,
|
|
13
|
+
#
|
|
14
|
+
# @param [String] url
|
|
15
|
+
# The URL of the source.
|
|
16
|
+
#
|
|
17
|
+
def find_or_create_source_with_url(url)
|
|
18
|
+
unless source = source_with_url(url)
|
|
19
|
+
name = name_for_url(url)
|
|
20
|
+
# Hack to ensure that `repo add` output is shown.
|
|
21
|
+
previous_title_level = UI.title_level
|
|
22
|
+
UI.title_level = 0
|
|
23
|
+
begin
|
|
24
|
+
if name =~ /^master(-\d+)?$/
|
|
25
|
+
Command::Setup.parse([]).run
|
|
26
|
+
else
|
|
27
|
+
Command::Repo::Add.parse([name, url]).run
|
|
28
|
+
end
|
|
29
|
+
rescue Informative => e
|
|
30
|
+
message = "Unable to add a source with url `#{url}` " \
|
|
31
|
+
"named `#{name}`.\n"
|
|
32
|
+
message << "(#{e})\n" if Config.instance.verbose?
|
|
33
|
+
message << 'You can try adding it manually in ' \
|
|
34
|
+
"`#{Config.instance.repos_dir}` or via `pod repo add`."
|
|
35
|
+
raise Informative, message
|
|
36
|
+
ensure
|
|
37
|
+
UI.title_level = previous_title_level
|
|
38
|
+
end
|
|
39
|
+
source = source_with_url(url)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
raise "Unable to create a source with URL #{url}" unless source
|
|
43
|
+
|
|
44
|
+
source
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Returns the source whose {Source#name} or {Source#url} is equal to the
|
|
48
|
+
# given `name_or_url`.
|
|
49
|
+
#
|
|
50
|
+
# @return [Source] The source whose {Source#name} or {Source#url} is equal to the
|
|
51
|
+
# given `name_or_url`.
|
|
52
|
+
#
|
|
53
|
+
# @param [String] name_or_url
|
|
54
|
+
# The name or the URL of the source.
|
|
55
|
+
#
|
|
56
|
+
def source_with_name_or_url(name_or_url)
|
|
57
|
+
all.find { |s| s.name == name_or_url } ||
|
|
58
|
+
find_or_create_source_with_url(name_or_url)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @return [Pathname] The path where the search index should be stored.
|
|
62
|
+
#
|
|
63
|
+
def search_index_path
|
|
64
|
+
@search_index_path ||= Config.instance.search_index_file
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @!group Updating Sources
|
|
68
|
+
|
|
69
|
+
# Updates the local clone of the spec-repo with the given name or of all
|
|
70
|
+
# the git repos if the name is omitted.
|
|
71
|
+
#
|
|
72
|
+
# @param [String] source_name
|
|
73
|
+
#
|
|
74
|
+
# @param [Bool] show_output
|
|
75
|
+
#
|
|
76
|
+
# @return [void]
|
|
77
|
+
#
|
|
78
|
+
def update(source_name = nil, show_output = false)
|
|
79
|
+
if source_name
|
|
80
|
+
sources = [git_source_named(source_name)]
|
|
81
|
+
else
|
|
82
|
+
sources = git_sources
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
changed_spec_paths = {}
|
|
86
|
+
sources.each do |source|
|
|
87
|
+
UI.section "Updating spec repo `#{source.name}`" do
|
|
88
|
+
changed_source_paths = source.update(show_output)
|
|
89
|
+
changed_spec_paths[source] = changed_source_paths if changed_source_paths.count > 0
|
|
90
|
+
source.verify_compatibility!
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
# Perform search index update operation in background.
|
|
94
|
+
update_search_index_if_needed_in_background(changed_spec_paths)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
extend Executable
|
|
99
|
+
executable :git
|
|
100
|
+
|
|
101
|
+
def git(args, include_error: false)
|
|
102
|
+
Executable.capture_command('git', args, :capture => include_error ? :merge : :out).first.strip
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def update_git_repo(show_output = false)
|
|
106
|
+
Config.instance.with_changes(:verbose => show_output) do
|
|
107
|
+
args = %W(-C #{repo} fetch origin)
|
|
108
|
+
args.push('--progress') if show_output
|
|
109
|
+
git!(args)
|
|
110
|
+
current_branch = git!(%W(-C #{repo} rev-parse --abbrev-ref HEAD)).strip
|
|
111
|
+
git!(%W(-C #{repo} reset --hard origin/#{current_branch}))
|
|
112
|
+
end
|
|
113
|
+
rescue
|
|
114
|
+
raise Informative, 'CocoaPods was not able to update the ' \
|
|
115
|
+
"`#{name}` repo. If this is an unexpected issue " \
|
|
116
|
+
'and persists you can inspect it running ' \
|
|
117
|
+
'`pod repo update --verbose`'
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class MasterSource
|
|
122
|
+
def update_git_repo(show_output = false)
|
|
123
|
+
if repo.join('.git', 'shallow').file?
|
|
124
|
+
UI.info "Performing a deep fetch of the `#{name}` specs repo to improve future performance" do
|
|
125
|
+
git!(%W(-C #{repo} fetch --unshallow))
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
super
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def verify_compatibility!
|
|
132
|
+
super
|
|
133
|
+
latest_cocoapods_version = metadata.latest_cocoapods_version && Gem::Version.create(metadata.latest_cocoapods_version)
|
|
134
|
+
return unless Config.instance.new_version_message? &&
|
|
135
|
+
latest_cocoapods_version &&
|
|
136
|
+
latest_cocoapods_version > Gem::Version.new(Pod::VERSION)
|
|
137
|
+
|
|
138
|
+
rc = latest_cocoapods_version.prerelease?
|
|
139
|
+
install_message = !Pathname(__FILE__).dirname.writable? ? 'sudo ' : ''
|
|
140
|
+
install_message << 'gem install cocoapods'
|
|
141
|
+
install_message << ' --pre' if rc
|
|
142
|
+
message = [
|
|
143
|
+
'',
|
|
144
|
+
"CocoaPods #{latest_cocoapods_version} is available.".green,
|
|
145
|
+
"To update use: `#{install_message}`".green,
|
|
146
|
+
("[!] This is a test version we'd love you to try.".yellow if rc),
|
|
147
|
+
'',
|
|
148
|
+
'For more information, see https://blog.cocoapods.org ' \
|
|
149
|
+
'and the CHANGELOG for this version at ' \
|
|
150
|
+
"https://github.com/CocoaPods/CocoaPods/releases/tag/#{latest_cocoapods_version}".green,
|
|
151
|
+
'',
|
|
152
|
+
'',
|
|
153
|
+
].compact.join("\n")
|
|
154
|
+
UI.puts(message)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|