cocoapods 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +329 -0
- data/lib/cocoapods/command/init.rb +6 -6
- data/lib/cocoapods/command/ipc/list.rb +40 -0
- data/lib/cocoapods/command/ipc/podfile.rb +31 -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/ipc.rb +18 -0
- data/lib/cocoapods/command/lib/create.rb +105 -0
- data/lib/cocoapods/command/lib/lint.rb +111 -0
- data/lib/cocoapods/command/lib.rb +3 -207
- data/lib/cocoapods/command/repo/push.rb +44 -20
- data/lib/cocoapods/command/setup.rb +2 -1
- data/lib/cocoapods/command/spec/lint.rb +4 -0
- data/lib/cocoapods/command.rb +2 -1
- data/lib/cocoapods/config.rb +4 -1
- data/lib/cocoapods/downloader/cache.rb +1 -0
- data/lib/cocoapods/downloader.rb +20 -0
- data/lib/cocoapods/executable.rb +1 -1
- data/lib/cocoapods/gem_version.rb +1 -1
- data/lib/cocoapods/generator/acknowledgements/plist.rb +4 -1
- data/lib/cocoapods/generator/copy_resources_script.rb +4 -10
- data/lib/cocoapods/generator/header.rb +2 -1
- data/lib/cocoapods/generator/prefix_header.rb +0 -12
- data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +38 -5
- data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +5 -4
- data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +5 -1
- data/lib/cocoapods/installer/analyzer/target_inspector.rb +24 -1
- data/lib/cocoapods/installer/analyzer.rb +161 -1
- data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +29 -9
- data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +204 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +314 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +401 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +214 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator.rb +265 -0
- data/lib/cocoapods/installer/xcode.rb +7 -0
- data/lib/cocoapods/installer.rb +50 -214
- data/lib/cocoapods/resolver.rb +15 -9
- data/lib/cocoapods/sandbox/headers_store.rb +4 -10
- data/lib/cocoapods/sandbox/path_list.rb +20 -9
- data/lib/cocoapods/sources_manager.rb +7 -10
- data/lib/cocoapods/target/aggregate_target.rb +20 -0
- data/lib/cocoapods/target/pod_target.rb +37 -7
- data/lib/cocoapods/user_interface/error_report.rb +7 -0
- data/lib/cocoapods/user_interface/inspector_reporter.rb +109 -0
- data/lib/cocoapods/user_interface.rb +7 -5
- data/lib/cocoapods/validator.rb +59 -11
- metadata +112 -83
- data/lib/cocoapods/command/inter_process_communication.rb +0 -177
- data/lib/cocoapods/installer/file_references_installer.rb +0 -310
- data/lib/cocoapods/installer/migrator.rb +0 -86
- data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +0 -191
- data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +0 -368
- data/lib/cocoapods/installer/target_installer.rb +0 -210
data/lib/cocoapods/resolver.rb
CHANGED
@@ -73,9 +73,10 @@ module Pod
|
|
73
73
|
def specs_by_target
|
74
74
|
@specs_by_target ||= {}.tap do |specs_by_target|
|
75
75
|
podfile.target_definition_list.each do |target|
|
76
|
+
dependencies = {}
|
76
77
|
specs = target.dependencies.map(&:name).flat_map do |name|
|
77
78
|
node = @activated.vertex_named(name)
|
78
|
-
valid_dependencies_for_target_from_node(target, node) << node
|
79
|
+
valid_dependencies_for_target_from_node(target, dependencies, node) << node
|
79
80
|
end
|
80
81
|
|
81
82
|
specs_by_target[target] = specs.
|
@@ -389,7 +390,6 @@ module Pod
|
|
389
390
|
error.conflicts.each do |name, conflict|
|
390
391
|
local_pod_parent = conflict.requirement_trees.flatten.reverse.find(&:local?)
|
391
392
|
lockfile_reqs = conflict.requirements[name_for_locking_dependency_source]
|
392
|
-
|
393
393
|
if lockfile_reqs && lockfile_reqs.last && lockfile_reqs.last.prerelease? && !conflict.existing
|
394
394
|
message = 'Due to the previous naïve CocoaPods resolver, ' \
|
395
395
|
"you were using a pre-release version of `#{name}`, " \
|
@@ -398,7 +398,7 @@ module Pod
|
|
398
398
|
'version requirement to your Podfile ' \
|
399
399
|
"(e.g. `pod '#{name}', '#{lockfile_reqs.map(&:requirement).join("', '")}'`) " \
|
400
400
|
"or revert to a stable version by running `pod update #{name}`."
|
401
|
-
elsif local_pod_parent && !specifications_for_dependency(conflict.requirement).empty?
|
401
|
+
elsif local_pod_parent && !specifications_for_dependency(conflict.requirement).empty? && !conflict.possibility
|
402
402
|
# Conflict was caused by a requirement from a local dependency.
|
403
403
|
# Tell user to use `pod update`.
|
404
404
|
message << "\n\nIt seems like you've changed the constraints of dependency `#{name}` " \
|
@@ -472,13 +472,19 @@ module Pod
|
|
472
472
|
# An array of target-appropriate nodes whose `payload`s are
|
473
473
|
# dependencies for `target`.
|
474
474
|
#
|
475
|
-
def valid_dependencies_for_target_from_node(target, node)
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
475
|
+
def valid_dependencies_for_target_from_node(target, dependencies, node)
|
476
|
+
dependencies[node.name] ||= begin
|
477
|
+
validate_platform(node.payload, target)
|
478
|
+
dependency_nodes = node.outgoing_edges.select do |edge|
|
479
|
+
edge_is_valid_for_target?(edge, target)
|
480
|
+
end.map(&:destination)
|
481
|
+
|
482
|
+
dependency_nodes + dependency_nodes.flat_map do |item|
|
483
|
+
node_result = valid_dependencies_for_target_from_node(target, dependencies, item)
|
480
484
|
|
481
|
-
|
485
|
+
node_result
|
486
|
+
end
|
487
|
+
end
|
482
488
|
end
|
483
489
|
|
484
490
|
# Whether the given `edge` should be followed to find dependencies for the
|
@@ -72,11 +72,11 @@ module Pod
|
|
72
72
|
#
|
73
73
|
def add_files(namespace, relative_header_paths)
|
74
74
|
relative_header_paths.map do |relative_header_path|
|
75
|
-
add_file(namespace, relative_header_path
|
75
|
+
add_file(namespace, relative_header_path)
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
# Adds a header to the directory
|
79
|
+
# Adds a header to the directory.
|
80
80
|
#
|
81
81
|
# @param [Pathname] namespace
|
82
82
|
# the path where the header file should be stored relative to the
|
@@ -86,23 +86,17 @@ module Pod
|
|
86
86
|
# the path of the header file relative to the Pods project
|
87
87
|
# (`PODS_ROOT` variable of the xcconfigs).
|
88
88
|
#
|
89
|
-
# @param [String] final_name
|
90
|
-
# the name under which the file should be available in the
|
91
|
-
# headers directory.
|
92
|
-
#
|
93
89
|
# @note This method does _not_ add the file to the search paths.
|
94
90
|
#
|
95
91
|
# @return [Pathname]
|
96
92
|
#
|
97
|
-
def add_file(namespace, relative_header_path
|
93
|
+
def add_file(namespace, relative_header_path)
|
98
94
|
namespaced_path = root + namespace
|
99
95
|
namespaced_path.mkpath unless File.exist?(namespaced_path)
|
100
96
|
|
101
97
|
absolute_source = (sandbox.root + relative_header_path)
|
102
98
|
source = absolute_source.relative_path_from(namespaced_path)
|
103
|
-
|
104
|
-
FileUtils.ln_sf(source, final_name)
|
105
|
-
end
|
99
|
+
FileUtils.ln_sf(source, namespaced_path)
|
106
100
|
namespaced_path + relative_header_path.basename
|
107
101
|
end
|
108
102
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/multibyte/unicode'
|
2
|
+
|
1
3
|
module Pod
|
2
4
|
class Sandbox
|
3
5
|
# The PathList class is designed to perform multiple glob matches against
|
@@ -20,7 +22,8 @@ module Pod
|
|
20
22
|
# @param [Pathname] root The root of the PathList.
|
21
23
|
#
|
22
24
|
def initialize(root)
|
23
|
-
|
25
|
+
root_dir = ActiveSupport::Multibyte::Unicode.normalize(root.to_s)
|
26
|
+
@root = Pathname.new(root_dir)
|
24
27
|
@glob_cache = {}
|
25
28
|
end
|
26
29
|
|
@@ -47,15 +50,23 @@ module Pod
|
|
47
50
|
unless root.exist?
|
48
51
|
raise Informative, "Attempt to read non existent folder `#{root}`."
|
49
52
|
end
|
50
|
-
root_length = root.to_s.length + 1
|
51
53
|
escaped_root = escape_path_for_glob(root)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
|
55
|
+
absolute_paths = Pathname.glob(escaped_root + '**/*', File::FNM_DOTMATCH).lazy
|
56
|
+
dirs_and_files = absolute_paths.reject { |path| path.basename.to_s =~ /^\.\.?$/ }
|
57
|
+
dirs, files = dirs_and_files.partition { |path| File.directory?(path) }
|
58
|
+
|
59
|
+
root_length = root.cleanpath.to_s.length + File::SEPARATOR.length
|
60
|
+
sorted_relative_paths_from_full_paths = lambda do |paths|
|
61
|
+
relative_paths = paths.lazy.map do |path|
|
62
|
+
path_string = path.to_s
|
63
|
+
path_string.slice(root_length, path_string.length - root_length)
|
64
|
+
end
|
65
|
+
relative_paths.sort_by(&:upcase)
|
66
|
+
end
|
67
|
+
|
68
|
+
@dirs = sorted_relative_paths_from_full_paths.call(dirs)
|
69
|
+
@files = sorted_relative_paths_from_full_paths.call(files)
|
59
70
|
@glob_cache = {}
|
60
71
|
end
|
61
72
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'cocoapods-core/source'
|
2
|
+
require 'set'
|
2
3
|
|
3
4
|
module Pod
|
4
5
|
class Source
|
@@ -102,24 +103,22 @@ module Pod
|
|
102
103
|
end
|
103
104
|
|
104
105
|
def update_git_repo(show_output = false)
|
105
|
-
ensure_in_repo!
|
106
106
|
Config.instance.with_changes(:verbose => show_output) do
|
107
|
-
git!(
|
107
|
+
git!(['-C', repo, 'pull', '--ff-only'])
|
108
108
|
end
|
109
109
|
rescue
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
110
|
+
raise Informative, 'CocoaPods was not able to update the ' \
|
111
|
+
"`#{name}` repo. If this is an unexpected issue " \
|
112
|
+
'and persists you can inspect it running ' \
|
113
|
+
'`pod repo update --verbose`'
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
117
|
class MasterSource
|
118
118
|
def update_git_repo(show_output = false)
|
119
|
-
ensure_in_repo!
|
120
119
|
if repo.join('.git', 'shallow').file?
|
121
120
|
UI.info "Performing a deep fetch of the `#{name}` specs repo to improve future performance" do
|
122
|
-
git!(
|
121
|
+
git!(['-C', repo, 'fetch', '--unshallow'])
|
123
122
|
end
|
124
123
|
end
|
125
124
|
super
|
@@ -141,8 +140,6 @@ module Pod
|
|
141
140
|
"CocoaPods #{latest_cocoapods_version} is available.".green,
|
142
141
|
"To update use: `#{install_message}`".green,
|
143
142
|
("[!] This is a test version we'd love you to try.".yellow if rc),
|
144
|
-
("Until we reach version 1.0 the features of CocoaPods can and will change.\n" \
|
145
|
-
'We strongly recommend that you use the latest version at all times.'.yellow unless rc),
|
146
143
|
'',
|
147
144
|
'For more information, see https://blog.cocoapods.org ' \
|
148
145
|
'and the CHANGELOG for this version at ' \
|
@@ -7,6 +7,10 @@ module Pod
|
|
7
7
|
# generated this target.
|
8
8
|
attr_reader :target_definition
|
9
9
|
|
10
|
+
# Product types where the product's frameworks must be embedded in a host target
|
11
|
+
#
|
12
|
+
EMBED_FRAMEWORKS_IN_HOST_TARGET_TYPES = [:app_extension, :framework, :messages_extension, :watch_extension, :xpc_service].freeze
|
13
|
+
|
10
14
|
# Initialize a new instance
|
11
15
|
#
|
12
16
|
# @param [TargetDefinition] target_definition @see target_definition
|
@@ -23,6 +27,22 @@ module Pod
|
|
23
27
|
@xcconfigs = {}
|
24
28
|
end
|
25
29
|
|
30
|
+
# @return [Boolean] True if the user_target's pods are
|
31
|
+
# for an extension and must be embedded in a host,
|
32
|
+
# target, otherwise false.
|
33
|
+
#
|
34
|
+
def requires_host_target?
|
35
|
+
# If we don't have a user_project, then we can't
|
36
|
+
# glean any info about how this target is going to
|
37
|
+
# be integrated, so return false since we can't know
|
38
|
+
# for sure that this target refers to an extension
|
39
|
+
# target that would require a host target
|
40
|
+
return false if user_project.nil?
|
41
|
+
symbol_types = user_targets.map(&:symbol_type).uniq
|
42
|
+
raise ArgumentError, "Expected single kind of user_target for #{name}. Found #{symbol_types.join(', ')}." unless symbol_types.count == 1
|
43
|
+
EMBED_FRAMEWORKS_IN_HOST_TARGET_TYPES.include?(symbol_types[0])
|
44
|
+
end
|
45
|
+
|
26
46
|
# @return [String] the label for the target.
|
27
47
|
#
|
28
48
|
def label
|
@@ -47,6 +47,7 @@ module Pod
|
|
47
47
|
@file_accessors = []
|
48
48
|
@resource_bundle_targets = []
|
49
49
|
@dependent_targets = []
|
50
|
+
@build_config_cache = {}
|
50
51
|
end
|
51
52
|
|
52
53
|
# @param [Hash{Array => PodTarget}] cache
|
@@ -65,6 +66,7 @@ module Pod
|
|
65
66
|
target.native_target = native_target
|
66
67
|
target.archs = archs
|
67
68
|
target.dependent_targets = dependent_targets.flat_map { |pt| pt.scoped(cache) }.select { |pt| pt.target_definitions == [target_definition] }
|
69
|
+
target.host_requires_frameworks = host_requires_frameworks
|
68
70
|
cache[cache_key] = target
|
69
71
|
end
|
70
72
|
end
|
@@ -80,6 +82,12 @@ module Pod
|
|
80
82
|
end
|
81
83
|
end
|
82
84
|
|
85
|
+
# @return [String] the Swift version for the target.
|
86
|
+
#
|
87
|
+
def swift_version
|
88
|
+
target_definitions.map(&:swift_version).compact.uniq.first
|
89
|
+
end
|
90
|
+
|
83
91
|
# @note The deployment target for the pod target is the maximum of all
|
84
92
|
# the deployment targets for the current platform of the target
|
85
93
|
# (or the minimum required to support the current installation
|
@@ -134,9 +142,12 @@ module Pod
|
|
134
142
|
# A target should not be build if it has no source files.
|
135
143
|
#
|
136
144
|
def should_build?
|
137
|
-
|
138
|
-
|
139
|
-
|
145
|
+
return @should_build if defined? @should_build
|
146
|
+
@should_build = begin
|
147
|
+
source_files = file_accessors.flat_map(&:source_files)
|
148
|
+
source_files -= file_accessors.flat_map(&:headers)
|
149
|
+
!source_files.empty?
|
150
|
+
end
|
140
151
|
end
|
141
152
|
|
142
153
|
# @return [Array<Specification::Consumer>] the specification consumers for
|
@@ -149,8 +160,11 @@ module Pod
|
|
149
160
|
# @return [Boolean] Whether the target uses Swift code
|
150
161
|
#
|
151
162
|
def uses_swift?
|
152
|
-
|
153
|
-
|
163
|
+
return @uses_swift if defined? @uses_swift
|
164
|
+
@uses_swift = begin
|
165
|
+
file_accessors.any? do |file_accessor|
|
166
|
+
file_accessor.source_files.any? { |sf| sf.extname == '.swift' }
|
167
|
+
end
|
154
168
|
end
|
155
169
|
end
|
156
170
|
|
@@ -188,8 +202,14 @@ module Pod
|
|
188
202
|
# dependency upon.
|
189
203
|
#
|
190
204
|
def recursive_dependent_targets
|
191
|
-
targets = dependent_targets
|
192
|
-
|
205
|
+
targets = dependent_targets.clone
|
206
|
+
|
207
|
+
targets.each do |target|
|
208
|
+
target.dependent_targets.each do |t|
|
209
|
+
targets.push(t) unless t == self || targets.include?(t)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
193
213
|
targets
|
194
214
|
end
|
195
215
|
|
@@ -203,13 +223,20 @@ module Pod
|
|
203
223
|
# The name of the build configuration.
|
204
224
|
#
|
205
225
|
def include_in_build_config?(target_definition, configuration_name)
|
226
|
+
key = [target_definition.label, configuration_name]
|
227
|
+
if @build_config_cache.key?(key)
|
228
|
+
return @build_config_cache[key]
|
229
|
+
end
|
230
|
+
|
206
231
|
whitelists = target_definition_dependencies(target_definition).map do |dependency|
|
207
232
|
target_definition.pod_whitelisted_for_configuration?(dependency.name, configuration_name)
|
208
233
|
end.uniq
|
209
234
|
|
210
235
|
if whitelists.empty?
|
236
|
+
@build_config_cache[key] = true
|
211
237
|
return true
|
212
238
|
elsif whitelists.count == 1
|
239
|
+
@build_config_cache[key] = whitelists.first
|
213
240
|
whitelists.first
|
214
241
|
else
|
215
242
|
raise Informative, "The subspecs of `#{pod_name}` are linked to " \
|
@@ -224,13 +251,16 @@ module Pod
|
|
224
251
|
# @return [Bool]
|
225
252
|
#
|
226
253
|
def inhibit_warnings?
|
254
|
+
return @inhibit_warnings if defined? @inhibit_warnings
|
227
255
|
whitelists = target_definitions.map do |target_definition|
|
228
256
|
target_definition.inhibits_warnings_for_pod?(root_spec.name)
|
229
257
|
end.uniq
|
230
258
|
|
231
259
|
if whitelists.empty?
|
260
|
+
@inhibit_warnings = false
|
232
261
|
return false
|
233
262
|
elsif whitelists.count == 1
|
263
|
+
@inhibit_warnings = whitelists.first
|
234
264
|
whitelists.first
|
235
265
|
else
|
236
266
|
UI.warn "The pod `#{pod_name}` is linked to different targets " \
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rbconfig'
|
4
4
|
require 'cgi'
|
5
|
+
require 'gh_inspector'
|
5
6
|
|
6
7
|
module Pod
|
7
8
|
module UserInterface
|
@@ -112,6 +113,12 @@ EOS
|
|
112
113
|
EOS
|
113
114
|
end
|
114
115
|
|
116
|
+
def search_for_exceptions(exception)
|
117
|
+
inspector = GhInspector::Inspector.new 'cocoapods', 'cocoapods'
|
118
|
+
message_delegate = UserInterface::InspectorReporter.new
|
119
|
+
inspector.search_exception exception, message_delegate
|
120
|
+
end
|
121
|
+
|
115
122
|
private
|
116
123
|
|
117
124
|
def `(other)
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
module UserInterface
|
5
|
+
# Redirects GH-issues delegate callbacks to CocoaPods UI methods.
|
6
|
+
#
|
7
|
+
class InspectorReporter
|
8
|
+
# Called just as the investigation has begun.
|
9
|
+
# Lets the user know that it's looking for an issue.
|
10
|
+
#
|
11
|
+
# @param [query] String unused
|
12
|
+
#
|
13
|
+
# @param [GhInspector::Inspector] inspector
|
14
|
+
# The current inspector
|
15
|
+
#
|
16
|
+
# @return [void]
|
17
|
+
#
|
18
|
+
def inspector_started_query(_, inspector)
|
19
|
+
UI.puts "Looking for related issues on #{inspector.repo_owner}/#{inspector.repo_name}..."
|
20
|
+
end
|
21
|
+
|
22
|
+
# Called once the inspector has recieved a report with more than one issue,
|
23
|
+
# showing the top 3 issues, and offering a link to see more.
|
24
|
+
#
|
25
|
+
# @param [GhInspector::InspectionReport] report
|
26
|
+
# Report a list of the issues
|
27
|
+
#
|
28
|
+
# @param [GhInspector::Inspector] inspector
|
29
|
+
# The current inspector
|
30
|
+
#
|
31
|
+
# @return [void]
|
32
|
+
#
|
33
|
+
def inspector_successfully_recieved_report(report, _)
|
34
|
+
report.issues[0..2].each { |issue| print_issue_full(issue) }
|
35
|
+
|
36
|
+
if report.issues.count > 3
|
37
|
+
UI.puts "and #{report.total_results - 3} more at:"
|
38
|
+
UI.puts report.url
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Called once the report has been recieved, but when there are no issues found.
|
43
|
+
#
|
44
|
+
# @param [GhInspector::InspectionReport] report
|
45
|
+
# An empty report
|
46
|
+
#
|
47
|
+
# @param [GhInspector::Inspector] inspector
|
48
|
+
# The current inspector
|
49
|
+
#
|
50
|
+
# @return [void]
|
51
|
+
#
|
52
|
+
def inspector_recieved_empty_report(_, inspector)
|
53
|
+
UI.puts 'Found no similar issues. To create a new issue, please visit:'
|
54
|
+
UI.puts "https://github.com/#{inspector.repo_owner}/#{inspector.repo_name}/issues/new"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Called when there have been networking issues in creating the report.
|
58
|
+
#
|
59
|
+
# @param [Error] error
|
60
|
+
# The error returned during networking
|
61
|
+
#
|
62
|
+
# @param [String] query
|
63
|
+
# The original search query
|
64
|
+
#
|
65
|
+
# @param [GhInspector::Inspector] inspector
|
66
|
+
# The current inspector
|
67
|
+
#
|
68
|
+
# @return [void]
|
69
|
+
#
|
70
|
+
def inspector_could_not_create_report(error, query, inspector)
|
71
|
+
safe_query = URI.escape query
|
72
|
+
UI.puts 'Could not access the GitHub API, you may have better luck via the website.'
|
73
|
+
UI.puts "https://github.com/#{inspector.repo_owner}/#{inspector.repo_name}/search?q=#{safe_query}&type=Issues&utf8=✓"
|
74
|
+
UI.puts "Error: #{error.name}"
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def print_issue_full(issue)
|
80
|
+
safe_url = URI.escape issue.html_url
|
81
|
+
UI.puts " - #{issue.title}"
|
82
|
+
UI.puts " #{safe_url} [#{issue.state}] [#{issue.comments} comment#{issue.comments == 1 ? '' : 's'}]"
|
83
|
+
UI.puts " #{pretty_date(issue.updated_at)}"
|
84
|
+
UI.puts ''
|
85
|
+
end
|
86
|
+
|
87
|
+
# Taken from http://stackoverflow.com/questions/195740/how-do-you-do-relative-time-in-rails
|
88
|
+
def pretty_date(date_string)
|
89
|
+
date = Time.parse(date_string)
|
90
|
+
a = (Time.now - date).to_i
|
91
|
+
|
92
|
+
case a
|
93
|
+
when 0 then 'just now'
|
94
|
+
when 1 then 'a second ago'
|
95
|
+
when 2..59 then a.to_s + ' seconds ago'
|
96
|
+
when 60..119 then 'a minute ago' # 120 = 2 minutes
|
97
|
+
when 120..3540 then (a / 60).to_i.to_s + ' minutes ago'
|
98
|
+
when 3541..7100 then 'an hour ago' # 3600 = 1 hour
|
99
|
+
when 7101..82_800 then ((a + 99) / 3600).to_i.to_s + ' hours ago'
|
100
|
+
when 82_801..172_000 then 'a day ago' # 86400 = 1 day
|
101
|
+
when 172_001..518_400 then ((a + 800) / (60 * 60 * 24)).to_i.to_s + ' days ago'
|
102
|
+
when 518_400..1_036_800 then 'a week ago'
|
103
|
+
when 1_036_801..4_147_204 then ((a + 180_000) / (60 * 60 * 24 * 7)).to_i.to_s + ' weeks ago'
|
104
|
+
else date.strftime('%d %b %Y')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'cocoapods/user_interface/error_report'
|
2
|
+
require 'cocoapods/user_interface/inspector_reporter'
|
2
3
|
|
3
4
|
module Pod
|
4
5
|
# Provides support for UI output. It provides support for nested sections of
|
@@ -7,7 +8,7 @@ module Pod
|
|
7
8
|
module UserInterface
|
8
9
|
require 'colored'
|
9
10
|
|
10
|
-
@title_colors = %w( yellow green
|
11
|
+
@title_colors = %w( yellow green )
|
11
12
|
@title_level = 0
|
12
13
|
@indentation_level = 2
|
13
14
|
@treat_titles_as_messages = false
|
@@ -117,9 +118,6 @@ module Pod
|
|
117
118
|
self.title_level -= 1
|
118
119
|
end
|
119
120
|
|
120
|
-
# def title(title, verbose_prefix = '', relative_indentation = 2)
|
121
|
-
# end
|
122
|
-
|
123
121
|
# Prints a verbose message taking an optional verbose prefix and
|
124
122
|
# a relative indentation valid for the UI action in the passed
|
125
123
|
# block.
|
@@ -187,7 +185,11 @@ module Pod
|
|
187
185
|
if pathname
|
188
186
|
from_path = config.podfile_path.dirname if config.podfile_path
|
189
187
|
from_path ||= Pathname.pwd
|
190
|
-
path =
|
188
|
+
path = begin
|
189
|
+
Pathname(pathname).relative_path_from(from_path)
|
190
|
+
rescue
|
191
|
+
pathname
|
192
|
+
end
|
191
193
|
"`#{path}`"
|
192
194
|
else
|
193
195
|
''
|
data/lib/cocoapods/validator.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/array'
|
2
2
|
require 'active_support/core_ext/string/inflections'
|
3
3
|
|
4
|
-
autoload :Fourflusher, 'fourflusher'
|
5
|
-
|
6
4
|
module Pod
|
7
5
|
# Validates a Specification.
|
8
6
|
#
|
@@ -144,7 +142,15 @@ module Pod
|
|
144
142
|
reasons << 'all results apply only to public specs, but you can use ' \
|
145
143
|
'`--private` to ignore them if linting the specification for a private pod'
|
146
144
|
end
|
147
|
-
|
145
|
+
if dot_swift_version.nil?
|
146
|
+
reasons.to_sentence + ".\n[!] The validator for Swift projects uses " \
|
147
|
+
'Swift 3.0 by default, if you are using a different version of ' \
|
148
|
+
'swift you can use a `.swift-version` file to set the version for ' \
|
149
|
+
"your Pod. For example to use Swift 2.3, run: \n" \
|
150
|
+
' `echo "2.3" > .swift-version`'
|
151
|
+
else
|
152
|
+
reasons.to_sentence
|
153
|
+
end
|
148
154
|
end
|
149
155
|
|
150
156
|
#-------------------------------------------------------------------------#
|
@@ -239,6 +245,30 @@ module Pod
|
|
239
245
|
Pathname(Dir.tmpdir) + 'CocoaPods/Lint'
|
240
246
|
end
|
241
247
|
|
248
|
+
# @return [String] the SWIFT_VERSION to use for validation.
|
249
|
+
#
|
250
|
+
def swift_version
|
251
|
+
@swift_version ||= dot_swift_version || '3.0'
|
252
|
+
end
|
253
|
+
|
254
|
+
# Set the SWIFT_VERSION that should be used to validate the pod.
|
255
|
+
#
|
256
|
+
attr_writer :swift_version
|
257
|
+
|
258
|
+
# @return [String] the SWIFT_VERSION in the .swift-version file or nil.
|
259
|
+
#
|
260
|
+
def dot_swift_version
|
261
|
+
swift_version_path = file.dirname + '.swift-version'
|
262
|
+
swift_version_path.read if swift_version_path.exist?
|
263
|
+
end
|
264
|
+
|
265
|
+
# @return [String] A string representing the Swift version used during linting
|
266
|
+
# or nil, if Swift was not used.
|
267
|
+
#
|
268
|
+
def used_swift_version
|
269
|
+
swift_version if @installer.pod_targets.any?(&:uses_swift?)
|
270
|
+
end
|
271
|
+
|
242
272
|
#-------------------------------------------------------------------------#
|
243
273
|
|
244
274
|
private
|
@@ -388,10 +418,26 @@ module Pod
|
|
388
418
|
|
389
419
|
source_file = write_app_import_source_file(pod_target)
|
390
420
|
source_file_ref = app_project.new_group('App', 'App').new_file(source_file)
|
391
|
-
app_project.targets.first
|
421
|
+
app_target = app_project.targets.first
|
422
|
+
app_target.add_file_references([source_file_ref])
|
423
|
+
add_swift_version(app_target)
|
424
|
+
add_xctest(app_target) if @installer.pod_targets.any? { |pt| pt.spec_consumers.any? { |c| c.frameworks.include?('XCTest') } }
|
392
425
|
app_project.save
|
393
426
|
end
|
394
427
|
|
428
|
+
def add_swift_version(app_target)
|
429
|
+
app_target.build_configurations.each do |configuration|
|
430
|
+
configuration.build_settings['SWIFT_VERSION'] = swift_version
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
def add_xctest(app_target)
|
435
|
+
app_target.build_configurations.each do |configuration|
|
436
|
+
search_paths = configuration.build_settings['FRAMEWORK_SEARCH_PATHS'] ||= '$(inherited)'
|
437
|
+
search_paths << ' "$(PLATFORM_DIR)/Developer/Library/Frameworks"'
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
395
441
|
def write_app_import_source_file(pod_target)
|
396
442
|
language = pod_target.uses_swift? ? :swift : :objc
|
397
443
|
|
@@ -427,7 +473,7 @@ module Pod
|
|
427
473
|
# for all available platforms with xcodebuild.
|
428
474
|
#
|
429
475
|
def install_pod
|
430
|
-
%i(
|
476
|
+
%i(verify_no_duplicate_framework_and_library_names
|
431
477
|
verify_no_static_framework_transitive_dependencies
|
432
478
|
verify_framework_usage generate_pods_project integrate_user_project
|
433
479
|
perform_post_install_actions).each { |m| @installer.send(m) }
|
@@ -438,6 +484,7 @@ module Pod
|
|
438
484
|
next unless native_target = pod_target.native_target
|
439
485
|
native_target.build_configuration_list.build_configurations.each do |build_configuration|
|
440
486
|
(build_configuration.build_settings['OTHER_CFLAGS'] ||= '$(inherited)') << ' -Wincomplete-umbrella'
|
487
|
+
build_configuration.build_settings['SWIFT_VERSION'] = swift_version if pod_target.uses_swift?
|
441
488
|
end
|
442
489
|
end
|
443
490
|
if target.pod_targets.any?(&:uses_swift?) && consumer.platform_name == :ios &&
|
@@ -575,7 +622,7 @@ module Pod
|
|
575
622
|
end
|
576
623
|
non_source_files = header_files - file_accessor.source_files
|
577
624
|
unless non_source_files.empty?
|
578
|
-
error(attr_name, 'The pattern includes header files that are not listed' \
|
625
|
+
error(attr_name, 'The pattern includes header files that are not listed ' \
|
579
626
|
"in source_files (#{non_source_files.join(', ')}).")
|
580
627
|
end
|
581
628
|
end
|
@@ -710,20 +757,21 @@ module Pod
|
|
710
757
|
# returns its output (both STDOUT and STDERR).
|
711
758
|
#
|
712
759
|
def xcodebuild
|
713
|
-
|
760
|
+
require 'fourflusher'
|
761
|
+
command = ['clean', 'build', '-workspace', File.join(validation_dir, 'App.xcworkspace'), '-scheme', 'App', '-configuration', 'Release']
|
714
762
|
case consumer.platform_name
|
715
763
|
when :ios
|
716
764
|
command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
|
717
|
-
command += Fourflusher::SimControl.new.destination(
|
765
|
+
command += Fourflusher::SimControl.new.destination(:oldest, 'iOS', deployment_target)
|
718
766
|
when :watchos
|
719
767
|
command += %w(CODE_SIGN_IDENTITY=- -sdk watchsimulator)
|
720
|
-
command += Fourflusher::SimControl.new.destination(
|
768
|
+
command += Fourflusher::SimControl.new.destination(:oldest, 'watchOS', deployment_target)
|
721
769
|
when :tvos
|
722
770
|
command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
|
723
|
-
command += Fourflusher::SimControl.new.destination(
|
771
|
+
command += Fourflusher::SimControl.new.destination(:oldest, 'tvOS', deployment_target)
|
724
772
|
end
|
725
773
|
|
726
|
-
output, status =
|
774
|
+
output, status = _xcodebuild(command)
|
727
775
|
|
728
776
|
unless status.success?
|
729
777
|
message = 'Returned an unsuccessful exit code.'
|