refinement 0.2.1 → 0.4.1
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 +4 -4
- data/CHANGELOG.md +20 -0
- data/VERSION +1 -1
- data/exe/refine +1 -0
- data/lib/cocoapods_plugin.rb +3 -3
- data/lib/refinement.rb +2 -0
- data/lib/refinement/analyzer.rb +46 -22
- data/lib/refinement/annotated_target.rb +10 -3
- data/lib/refinement/changeset.rb +15 -11
- data/lib/refinement/changeset/file_modification.rb +11 -4
- data/lib/refinement/cli.rb +3 -0
- data/lib/refinement/cocoapods_post_install_writer.rb +7 -0
- data/lib/refinement/used_path.rb +2 -0
- data/lib/refinement/version.rb +2 -0
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d250f8a41cab420b717380a1b0c713541ecda9d0a8439c596bd351c25631fbf
|
4
|
+
data.tar.gz: cc6635b7ebb6f797f7d5142f99a7a85b355d90a0a09b5af15f39a5a6450c389c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bebda46b92a0bc1eaa25d4852c674a697472caa89f67d9fd5e990d0fd16cd7bf594b0c19559d9a8b4a9de7f4fe7a91f08d6f825ab2116afbe3b6fe5525d42cd1
|
7
|
+
data.tar.gz: c86b9b7e206c8b201374817bc4c27b8e7b5372cec0e1a082f27e5c94d34245e50fb237cb5e22c6d3abadb33194ed90b7281d26a69b3484f470f477a47c20879e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Refinement Changes
|
2
2
|
|
3
|
+
## 0.3.1 (2019-08-09)
|
4
|
+
|
5
|
+
##### Bug Fixes
|
6
|
+
|
7
|
+
* Take into consideration product reference names when refinining.
|
8
|
+
|
9
|
+
|
10
|
+
## 0.3.0 (2019-08-09)
|
11
|
+
|
12
|
+
##### Bug Fixes
|
13
|
+
|
14
|
+
* Multiple YAML used keys paths for the same file will no longer cause the YAML
|
15
|
+
to be parsed multiple times.
|
16
|
+
|
17
|
+
|
18
|
+
## 0.2.2 (2019-04-08)
|
19
|
+
|
20
|
+
No changes.
|
21
|
+
|
22
|
+
|
3
23
|
## 0.2.1 (2019-04-08)
|
4
24
|
|
5
25
|
##### Bug Fixes
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.1
|
data/exe/refine
CHANGED
data/lib/cocoapods_plugin.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'cocoapods'
|
2
4
|
|
3
5
|
Pod::Installer
|
@@ -7,9 +9,7 @@ Pod::Installer
|
|
7
9
|
|
8
10
|
return unless plugins.key?('refinement')
|
9
11
|
|
10
|
-
unless Gem::Version.create(Pod::VERSION) >= Gem::Version.create('1.6.0')
|
11
|
-
raise Pod::Informative, 'Refinement requires a CocoaPods version >= 1.6.0'
|
12
|
-
end
|
12
|
+
raise Pod::Informative, 'Refinement requires a CocoaPods version >= 1.6.0' unless Gem::Version.create(Pod::VERSION) >= Gem::Version.create('1.6.0')
|
13
13
|
|
14
14
|
require 'refinement/cocoapods_post_install_writer'
|
15
15
|
Pod::UI.message 'Writing refinement file' do
|
data/lib/refinement.rb
CHANGED
data/lib/refinement/analyzer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Refinement
|
2
4
|
# Analyzes changes in a repository
|
3
5
|
# and determines how those changes impact the targets in Xcode projects in the workspace.
|
@@ -26,12 +28,12 @@ module Refinement
|
|
26
28
|
@changeset = changeset
|
27
29
|
|
28
30
|
raise ArgumentError, 'Can only specify one of workspace_path and projects' if workspace_path && projects
|
31
|
+
|
29
32
|
@workspace_path = workspace_path
|
30
33
|
@projects = projects
|
31
34
|
|
32
|
-
if augmenting_paths_yaml_files && augmenting_paths_by_target
|
33
|
-
|
34
|
-
end
|
35
|
+
raise ArgumentError, 'Can only specify one of augmenting_paths_yaml_files and augmenting_paths_by_target' if augmenting_paths_yaml_files && augmenting_paths_by_target
|
36
|
+
|
35
37
|
@augmenting_paths_yaml_files = augmenting_paths_yaml_files
|
36
38
|
@augmenting_paths_by_target = augmenting_paths_by_target
|
37
39
|
end
|
@@ -75,25 +77,38 @@ module Refinement
|
|
75
77
|
"Given: #{filter_scheme_for_build_action.inspect}."
|
76
78
|
end
|
77
79
|
|
78
|
-
if filter_when_scheme_has_changed
|
79
|
-
|
80
|
+
if !filter_when_scheme_has_changed &&
|
81
|
+
UsedPath.new(path: Pathname(scheme_path), inclusion_reason: 'scheme').find_in_changeset(changeset)
|
82
|
+
return scheme
|
83
|
+
end
|
84
|
+
|
85
|
+
changes_by_suite_name = Hash[annotate_targets!
|
86
|
+
.map { |at| [at.xcode_target.name, at.change_reason(level: change_level)] }]
|
80
87
|
|
81
|
-
|
82
|
-
.map { |at| [at.xcode_target.name, at.change_reason(level: change_level)] }]
|
88
|
+
doc = scheme.doc
|
83
89
|
|
84
|
-
|
90
|
+
xpaths = sections_to_filter.map { |section| "//*/#{section}/BuildableReference" }
|
91
|
+
xpaths.each do |xpath|
|
92
|
+
doc.get_elements(xpath).to_a.each do |buildable_reference|
|
93
|
+
suite_name = buildable_reference.attributes['BlueprintName']
|
94
|
+
if (change_reason = changes_by_suite_name[suite_name])
|
95
|
+
puts "#{suite_name} changed because #{change_reason}" if log_changes
|
96
|
+
next
|
97
|
+
end
|
98
|
+
puts "#{suite_name} did not change, removing from scheme" if log_changes
|
99
|
+
buildable_reference.parent.remove
|
100
|
+
end
|
101
|
+
end
|
85
102
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
next
|
93
|
-
end
|
94
|
-
puts "#{suite_name} did not change, removing from scheme" if log_changes
|
95
|
-
buildable_reference.parent.remove
|
103
|
+
if filter_scheme_for_build_action == :testing
|
104
|
+
doc.get_elements('//*/BuildActionEntry/BuildableReference').to_a.each do |buildable_reference|
|
105
|
+
suite_name = buildable_reference.attributes['BlueprintName']
|
106
|
+
if (change_reason = changes_by_suite_name[suite_name])
|
107
|
+
puts "#{suite_name} changed because #{change_reason}" if log_changes
|
108
|
+
next
|
96
109
|
end
|
110
|
+
puts "#{suite_name} did not change, setting to not build for testing" if log_changes
|
111
|
+
buildable_reference.parent.attributes['buildForTesting'] = 'NO'
|
97
112
|
end
|
98
113
|
end
|
99
114
|
|
@@ -110,6 +125,7 @@ module Refinement
|
|
110
125
|
.map do |annotated_target|
|
111
126
|
change_reason = annotated_target.change_reason(level: change_level)
|
112
127
|
next if !include_unchanged_targets && !change_reason
|
128
|
+
|
113
129
|
change_reason ||= 'did not change'
|
114
130
|
"\t#{annotated_target.xcode_target}: #{change_reason}"
|
115
131
|
end.compact
|
@@ -150,10 +166,11 @@ module Refinement
|
|
150
166
|
targets = projects.flat_map(&:targets)
|
151
167
|
targets_by_uuid = Hash[targets.map { |t| [t.uuid, t] }]
|
152
168
|
targets_by_name = Hash[targets.map { |t| [t.name, t] }]
|
153
|
-
targets_by_product_name =
|
169
|
+
targets_by_product_name = targets.each_with_object({}) do |t, h|
|
154
170
|
next unless t.respond_to?(:product_reference)
|
155
|
-
[File.basename(t.product_reference.path)
|
156
|
-
|
171
|
+
h[File.basename(t.product_reference.path)] = t
|
172
|
+
h[File.basename(t.product_reference.name)] = t if t.product_reference.name
|
173
|
+
end
|
157
174
|
|
158
175
|
find_dep = ->(td) { targets_by_uuid[td.native_target_uuid] || targets_by_name[td.name] }
|
159
176
|
target_deps = lambda do |target|
|
@@ -166,7 +183,7 @@ module Refinement
|
|
166
183
|
# yay auto-linking
|
167
184
|
if (phase = target.frameworks_build_phases)
|
168
185
|
phase.files_references.each do |fr|
|
169
|
-
if (dt = fr
|
186
|
+
if (dt = fr&.path && targets_by_product_name[File.basename(fr.path)])
|
170
187
|
target_dependencies << dt
|
171
188
|
end
|
172
189
|
end
|
@@ -232,6 +249,7 @@ module Refinement
|
|
232
249
|
|
233
250
|
expand_build_settings = lambda do |s|
|
234
251
|
return [s] unless s =~ /\$(?:\{([_a-zA-Z0-0]+?)\}|\(([_a-zA-Z0-0]+?)\))/
|
252
|
+
|
235
253
|
match, key = Regexp.last_match.values_at(0, 1, 2).compact
|
236
254
|
substitutions = target.resolved_build_setting(key, true).values.compact.uniq
|
237
255
|
substitutions.flat_map do |sub|
|
@@ -242,6 +260,7 @@ module Refinement
|
|
242
260
|
target.build_configuration_list.build_configurations.each do |build_configuration|
|
243
261
|
ref = build_configuration.base_configuration_reference
|
244
262
|
next unless ref
|
263
|
+
|
245
264
|
yield UsedPath.new(path: ref.real_path,
|
246
265
|
inclusion_reason: "base configuration reference for #{build_configuration}")
|
247
266
|
end
|
@@ -249,6 +268,7 @@ module Refinement
|
|
249
268
|
target.build_phases.each do |build_phase|
|
250
269
|
build_phase.files_references.each do |fr|
|
251
270
|
next unless fr
|
271
|
+
|
252
272
|
yield UsedPath.new(path: fr.real_path,
|
253
273
|
inclusion_reason: "#{build_phase.display_name.downcase.chomp('s')} file")
|
254
274
|
end
|
@@ -257,9 +277,11 @@ module Refinement
|
|
257
277
|
target.shell_script_build_phases.each do |shell_script_build_phase|
|
258
278
|
%w[input_file_list_paths output_file_list_paths input_paths output_paths].each do |method|
|
259
279
|
next unless (paths = shell_script_build_phase.public_send(method))
|
280
|
+
|
260
281
|
file_type = method.tr('_', ' ').chomp('s')
|
261
282
|
paths.each do |config_path|
|
262
283
|
next unless config_path
|
284
|
+
|
263
285
|
expand_build_settings[config_path].each do |path|
|
264
286
|
path = Pathname(path).expand_path(target.project.project_dir)
|
265
287
|
yield UsedPath.new(path: path,
|
@@ -273,6 +295,7 @@ module Refinement
|
|
273
295
|
target.resolved_build_setting(build_setting, true).each_value do |paths|
|
274
296
|
Array(paths).each do |path|
|
275
297
|
next unless path
|
298
|
+
|
276
299
|
path = Pathname(path).expand_path(target.project.project_dir)
|
277
300
|
yield UsedPath.new(path: path, inclusion_reason: "#{build_setting} value")
|
278
301
|
end
|
@@ -301,6 +324,7 @@ module Refinement
|
|
301
324
|
project.root_object.build_configuration_list.build_configurations.each do |build_configuration|
|
302
325
|
ref = build_configuration.base_configuration_reference
|
303
326
|
next unless ref
|
327
|
+
|
304
328
|
yield UsedPath.new(path: ref.real_path,
|
305
329
|
inclusion_reason: "base configuration reference for #{build_configuration}")
|
306
330
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Refinement
|
2
4
|
# A target, annotated with any changes
|
3
5
|
class AnnotatedTarget
|
@@ -45,15 +47,20 @@ module Refinement
|
|
45
47
|
when :full_transitive
|
46
48
|
direct_change_reason || Refinement.map_find(dependencies) do |dependency|
|
47
49
|
next unless (dependency_change_reason = dependency.change_reason(level: level))
|
50
|
+
|
48
51
|
"dependency #{dependency} changed because #{dependency_change_reason}"
|
49
52
|
end
|
50
53
|
when proc { |symbol, int| (symbol == :at_most_n_away) && int.is_a?(Integer) }
|
51
54
|
distance_from_target = level.last
|
52
|
-
raise ArgumentError, "level must be positive, not #{distance_from_target}" if distance_from_target
|
55
|
+
raise ArgumentError, "level must be positive, not #{distance_from_target}" if distance_from_target.negative?
|
56
|
+
|
53
57
|
change_reason = direct_change_reason
|
54
|
-
if distance_from_target
|
58
|
+
if distance_from_target.positive?
|
55
59
|
change_reason ||= Refinement.map_find(dependencies) do |dependency|
|
56
|
-
|
60
|
+
unless (dependency_change_reason = dependency.change_reason(level: [:at_most_n_away, level.last.pred]))
|
61
|
+
next
|
62
|
+
end
|
63
|
+
|
57
64
|
"dependency #{dependency} changed because #{dependency_change_reason}"
|
58
65
|
end
|
59
66
|
end
|
data/lib/refinement/changeset.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'cocoapods/executable'
|
2
4
|
require 'set'
|
3
5
|
|
@@ -43,6 +45,7 @@ module Refinement
|
|
43
45
|
dirs = Set.new
|
44
46
|
add = lambda { |path|
|
45
47
|
break unless dirs.add?(path)
|
48
|
+
|
46
49
|
add[path.dirname]
|
47
50
|
}
|
48
51
|
modifications.each do |mod|
|
@@ -124,8 +127,10 @@ module Refinement
|
|
124
127
|
# @param keypath [Array]
|
125
128
|
def find_modification_for_yaml_keypath(absolute_path:, keypath:)
|
126
129
|
return unless (file_modification = find_modification_for_path(absolute_path: absolute_path))
|
130
|
+
|
127
131
|
diff = file_modification.yaml_diff(keypath)
|
128
132
|
return unless diff
|
133
|
+
|
129
134
|
[file_modification, diff]
|
130
135
|
end
|
131
136
|
|
@@ -144,14 +149,14 @@ module Refinement
|
|
144
149
|
end
|
145
150
|
|
146
151
|
CHANGE_TYPES = {
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
152
|
+
'was added': 'A',
|
153
|
+
'was copied': 'C',
|
154
|
+
'was deleted': 'D',
|
155
|
+
'was modified': 'M',
|
156
|
+
'was renamed': 'R',
|
157
|
+
'changed type': 'T',
|
158
|
+
'is unmerged': 'U',
|
159
|
+
'changed in an unknown way': 'X'
|
155
160
|
}.freeze
|
156
161
|
private_constant :CHANGE_TYPES
|
157
162
|
|
@@ -206,9 +211,8 @@ module Refinement
|
|
206
211
|
def self.git!(command, *args, chdir:)
|
207
212
|
require 'open3'
|
208
213
|
out, err, status = Open3.capture3('git', command, *args, chdir: chdir.to_s)
|
209
|
-
unless status.success?
|
210
|
-
|
211
|
-
end
|
214
|
+
raise GitError, "Running git #{command} failed (#{status.to_s.gsub(/pid \d+\s*/, '')}):\n\n#{err}" unless status.success?
|
215
|
+
|
212
216
|
out
|
213
217
|
end
|
214
218
|
private_class_method :git!
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Refinement
|
2
4
|
class Changeset
|
3
5
|
# Represents a modification to a single file or directory on disk
|
@@ -51,12 +53,14 @@ module Refinement
|
|
51
53
|
# @visibility private
|
52
54
|
def ==(other)
|
53
55
|
return unless other.is_a?(FileModification)
|
56
|
+
|
54
57
|
(path == other.path) && (type == other.type) && prior_path == other.prior_path
|
55
58
|
end
|
56
59
|
|
57
60
|
# @visibility private
|
58
61
|
def eql?(other)
|
59
62
|
return unless other.is_a?(FileModification)
|
63
|
+
|
60
64
|
path.eql?(other.path) && type.eql?(other.type) && prior_path.eql?(other.prior_path)
|
61
65
|
end
|
62
66
|
|
@@ -68,9 +72,12 @@ module Refinement
|
|
68
72
|
def yaml_diff(keypath)
|
69
73
|
require 'yaml'
|
70
74
|
|
71
|
-
|
75
|
+
@cached_yaml ||= {}
|
76
|
+
|
77
|
+
dig_yaml = lambda do |yaml, path|
|
72
78
|
return yaml if DOES_NOT_EXIST == yaml
|
73
|
-
|
79
|
+
|
80
|
+
object = @cached_yaml[path] ||= YAML.safe_load(yaml, [Symbol])
|
74
81
|
if keypath.empty?
|
75
82
|
object
|
76
83
|
elsif object.respond_to?(:dig)
|
@@ -82,8 +89,8 @@ module Refinement
|
|
82
89
|
end
|
83
90
|
end
|
84
91
|
|
85
|
-
prior = dig_yaml[prior_contents]
|
86
|
-
current = dig_yaml[contents]
|
92
|
+
prior = dig_yaml[prior_contents, :prior]
|
93
|
+
current = dig_yaml[contents, :current]
|
87
94
|
|
88
95
|
require 'xcodeproj/differ'
|
89
96
|
|
data/lib/refinement/cli.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'claide'
|
2
4
|
|
3
5
|
module Refinement
|
@@ -48,6 +50,7 @@ module Refinement
|
|
48
50
|
puts analyzer.format_changes if @print_changes
|
49
51
|
|
50
52
|
return unless @scheme
|
53
|
+
|
51
54
|
analyzer.filtered_scheme(scheme_path: @scheme, log_changes: @print_scheme_changes, filter_scheme_for_build_action: @filter_scheme_for_build_action)
|
52
55
|
.save_as(@scheme.gsub(%r{\.(xcodeproj|xcworkspace)/.+}, '.\1'), File.basename(@scheme, '.xcscheme'), true)
|
53
56
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Refinement
|
2
4
|
# Called after CocoaPods installation to write an augmenting file that
|
3
5
|
# takes into account changes to Pod configuration,
|
@@ -9,6 +11,7 @@ module Refinement
|
|
9
11
|
# Initializes a post-install writer with CocoaPods target objects.
|
10
12
|
# @return [CocoaPodsPostInstallWriter] a new instance of CocoaPodsPostInstallWriter
|
11
13
|
# @param aggregate_targets [Array<Pod::AggregateTarget>]
|
14
|
+
# @param pod_targets [Array<Pod::PodTarget>]
|
12
15
|
# @param config [Pod::Config]
|
13
16
|
# @param options [Hash]
|
14
17
|
def initialize(aggregate_targets, pod_targets, config, options)
|
@@ -100,6 +103,10 @@ module Refinement
|
|
100
103
|
inclusion_reason: 'CocoaPods lockfile',
|
101
104
|
yaml_keypath: ['SPEC CHECKSUMS', pod_target.pod_name] }
|
102
105
|
]
|
106
|
+
if pod_target.sandbox.predownloaded?(pod_target.pod_name)
|
107
|
+
paths << { path: 'Podfile.lock', inclusion_reason: 'Dependency external source', yaml_keypath: ['EXTERNAL SOURCES', pod_target.pod_name] }
|
108
|
+
paths << { path: 'Podfile.lock', inclusion_reason: 'Pod checkout options', yaml_keypath: ['CHECKOUT OPTIONS', pod_target.pod_name] }
|
109
|
+
end
|
103
110
|
spec_paths.each { |path| paths << { path: path, inclusion_reason: 'podspec' } }
|
104
111
|
|
105
112
|
Pod::Validator::FILE_PATTERNS.each do |pattern|
|
data/lib/refinement/used_path.rb
CHANGED
data/lib/refinement/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: refinement
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Giddins
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: xcodeproj
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '10.0'
|
47
|
-
description:
|
47
|
+
description:
|
48
48
|
email:
|
49
49
|
- segiddins@squareup.com
|
50
50
|
executables:
|
@@ -70,7 +70,7 @@ files:
|
|
70
70
|
homepage: https://github.com/square/refinement
|
71
71
|
licenses: []
|
72
72
|
metadata: {}
|
73
|
-
post_install_message:
|
73
|
+
post_install_message:
|
74
74
|
rdoc_options: []
|
75
75
|
require_paths:
|
76
76
|
- lib
|
@@ -78,15 +78,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
78
78
|
requirements:
|
79
79
|
- - ">="
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: '2.
|
81
|
+
version: '2.3'
|
82
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
83
|
requirements:
|
84
84
|
- - ">="
|
85
85
|
- !ruby/object:Gem::Version
|
86
86
|
version: '0'
|
87
87
|
requirements: []
|
88
|
-
rubygems_version: 3.0.
|
89
|
-
signing_key:
|
88
|
+
rubygems_version: 3.0.1
|
89
|
+
signing_key:
|
90
90
|
specification_version: 4
|
91
91
|
summary: Generates a list of Xcode targets to build & test as a result of a git diff.
|
92
92
|
test_files: []
|