kintsugi 0.5.4 → 0.6.2
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/lib/kintsugi/apply_change_to_project.rb +269 -65
- data/lib/kintsugi/cli.rb +7 -0
- data/lib/kintsugi/settings.rb +18 -0
- data/lib/kintsugi/version.rb +1 -1
- data/spec/kintsugi_apply_change_to_project_spec.rb +364 -111
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3cad34bb224a6760f052ff90ac433095e7fb071e7b59ca9018719e3c6a8f5c96
|
4
|
+
data.tar.gz: a0b9675697896041b08d60186804e3c112e51c0dd61d66d26ce9f9310c626f4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 359e1799a2f313daf547645342677eca83f58a76dc857d2f72b6f97b06318455385cec7b0145344c380ec659376ff3228add2f6c91499f1bef1cd20d63beae11
|
7
|
+
data.tar.gz: 04c9e862353bef092c14464de1e781c3d2168ad958fb8c5d08ed53f74e4090921023f674e6759eff997fbe2994af9514a0d546de4a8d652b19e5a37b32ce3970
|
@@ -6,8 +6,21 @@ require "xcodeproj"
|
|
6
6
|
|
7
7
|
require_relative "utils"
|
8
8
|
require_relative "error"
|
9
|
+
require_relative "settings"
|
9
10
|
require_relative "xcodeproj_extensions"
|
10
11
|
|
12
|
+
class Array
|
13
|
+
# Converts an array of arrays of size 2 into a multimap, mapping the first element of each
|
14
|
+
# subarray to an array of the last elements it appears with in the same subarray.
|
15
|
+
def to_multi_h
|
16
|
+
raise ArgumentError, "Not all elements are arrays of size 2" unless all? do |arr|
|
17
|
+
arr.is_a?(Array) && arr.count == 2
|
18
|
+
end
|
19
|
+
|
20
|
+
group_by(&:first).transform_values { |group| group.map(&:last) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
11
24
|
module Kintsugi
|
12
25
|
class << self
|
13
26
|
# Applies the change specified by `change` to `project`.
|
@@ -22,14 +35,15 @@ module Kintsugi
|
|
22
35
|
#
|
23
36
|
# @return [void]
|
24
37
|
def apply_change_to_project(project, change)
|
38
|
+
return unless change&.key?("rootObject")
|
39
|
+
|
25
40
|
# We iterate over the main group and project references first because they might create file
|
26
41
|
# or project references that are referenced in other parts.
|
27
42
|
unless change["rootObject"]["mainGroup"].nil?
|
28
43
|
if project.root_object.main_group.nil?
|
29
44
|
puts "Warning: Main group doesn't exist, ignoring changes to it."
|
30
45
|
else
|
31
|
-
|
32
|
-
change["rootObject"]["mainGroup"], "rootObject")
|
46
|
+
apply_main_group_change(project, change["rootObject"]["mainGroup"])
|
33
47
|
end
|
34
48
|
end
|
35
49
|
|
@@ -46,10 +60,159 @@ module Kintsugi
|
|
46
60
|
|
47
61
|
private
|
48
62
|
|
63
|
+
def apply_main_group_change(project, main_group_change)
|
64
|
+
additions, removals, diffs = classify_group_and_file_changes(main_group_change, "")
|
65
|
+
apply_group_additions(project, additions)
|
66
|
+
apply_file_changes(project, additions, removals)
|
67
|
+
apply_group_and_file_diffs(project, diffs)
|
68
|
+
apply_group_removals(project, removals)
|
69
|
+
end
|
70
|
+
|
71
|
+
def classify_group_and_file_changes(change, path)
|
72
|
+
children_changes = change["children"] || {}
|
73
|
+
removals = flatten_change(children_changes[:removed], path)
|
74
|
+
additions = flatten_change(children_changes[:added], path)
|
75
|
+
diffs = [[change, path]]
|
76
|
+
subchanges_of_change(children_changes).each do |key, subchange|
|
77
|
+
sub_additions, sub_removals, sub_diffs =
|
78
|
+
classify_group_and_file_changes(subchange, join_path(path, key))
|
79
|
+
removals += sub_removals
|
80
|
+
additions += sub_additions
|
81
|
+
diffs += sub_diffs
|
82
|
+
end
|
83
|
+
|
84
|
+
[additions, removals, diffs]
|
85
|
+
end
|
86
|
+
|
87
|
+
def flatten_change(change, path)
|
88
|
+
entries = (change || []).map do |child|
|
89
|
+
[child, path]
|
90
|
+
end
|
91
|
+
group_entries = entries.map do |group, _|
|
92
|
+
next if group["children"].nil?
|
93
|
+
|
94
|
+
flatten_change(group["children"], join_path(path, group["displayName"]))
|
95
|
+
end.compact.flatten(1)
|
96
|
+
entries + group_entries
|
97
|
+
end
|
98
|
+
|
99
|
+
def apply_group_additions(project, additions)
|
100
|
+
additions.each do |change, path|
|
101
|
+
next unless %w[PBXGroup PBXVariantGroup].include?(change["isa"])
|
102
|
+
|
103
|
+
group_type = Module.const_get("Xcodeproj::Project::#{change["isa"]}")
|
104
|
+
containing_group = path.empty? ? project.main_group : project[path]
|
105
|
+
|
106
|
+
next if !Settings.allow_duplicates &&
|
107
|
+
!find_group_in_group(containing_group, group_type, change).nil?
|
108
|
+
|
109
|
+
new_group = project.new(group_type)
|
110
|
+
containing_group.children << new_group
|
111
|
+
add_attributes_to_component(new_group, change, path, ignore_keys: ["children"])
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def find_group_in_group(group, instance_type, change)
|
116
|
+
group
|
117
|
+
.children
|
118
|
+
.select { |child| child.instance_of?(instance_type) }
|
119
|
+
.find do |child_group|
|
120
|
+
child_group.display_name == change["displayName"] && child_group.path == change["path"]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def apply_file_changes(project, additions, removals)
|
125
|
+
def file_reference_key(change)
|
126
|
+
[change["name"], change["path"], change["sourceTree"]]
|
127
|
+
end
|
128
|
+
|
129
|
+
file_additions = additions.select { |change, _| change["isa"] == "PBXFileReference" }
|
130
|
+
file_removals = removals.select { |change, _| change["isa"] == "PBXFileReference" }
|
131
|
+
|
132
|
+
addition_keys_to_paths = file_additions
|
133
|
+
.map { |change, path| [file_reference_key(change), path] }
|
134
|
+
.to_multi_h
|
135
|
+
removal_keys_to_references = file_removals.to_multi_h.map do |change, paths|
|
136
|
+
references = paths.map do |containing_path|
|
137
|
+
project[join_path(containing_path, change["displayName"])]
|
138
|
+
end
|
139
|
+
|
140
|
+
[file_reference_key(change), references]
|
141
|
+
end.to_h
|
142
|
+
|
143
|
+
file_additions.each do |change, path|
|
144
|
+
containing_group = path.empty? ? project.main_group : project[path]
|
145
|
+
change_key = file_reference_key(change)
|
146
|
+
|
147
|
+
if (removal_keys_to_references[change_key] || []).empty?
|
148
|
+
apply_file_addition(containing_group, change, "rootObject/mainGroup/#{path}")
|
149
|
+
elsif addition_keys_to_paths[change_key].length == 1 &&
|
150
|
+
removal_keys_to_references[change_key].length == 1 &&
|
151
|
+
!removal_keys_to_references[change_key].first.nil?
|
152
|
+
removal_keys_to_references[change_key].first.move(containing_group)
|
153
|
+
else
|
154
|
+
file_path = join_path(path, change["displayName"])
|
155
|
+
raise MergeError,
|
156
|
+
"Cannot deduce whether the file #{file_path} is new, or was moved to its new place"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
file_removals.each do |change, path|
|
161
|
+
next unless addition_keys_to_paths[file_reference_key(change)].nil?
|
162
|
+
|
163
|
+
file_reference = project[join_path(path, change["displayName"])]
|
164
|
+
remove_component(file_reference, change)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def apply_file_addition(containing_group, change, path)
|
169
|
+
return if !Settings.allow_duplicates &&
|
170
|
+
!find_file_in_group(containing_group, Xcodeproj::Project::PBXFileReference,
|
171
|
+
change["path"]).nil?
|
172
|
+
|
173
|
+
file_reference = containing_group.project.new(Xcodeproj::Project::PBXFileReference)
|
174
|
+
containing_group.children << file_reference
|
175
|
+
|
176
|
+
# For some reason, `include_in_index` is set to `1` and `source_tree` to `SDKROOT` by
|
177
|
+
# default.
|
178
|
+
file_reference.include_in_index = nil
|
179
|
+
file_reference.source_tree = nil
|
180
|
+
add_attributes_to_component(file_reference, change, path)
|
181
|
+
end
|
182
|
+
|
183
|
+
def apply_group_and_file_diffs(project, diffs)
|
184
|
+
diffs.each do |change, path|
|
185
|
+
component = project[path]
|
186
|
+
|
187
|
+
next if component.nil?
|
188
|
+
|
189
|
+
change.each do |subchange_name, subchange|
|
190
|
+
next if subchange_name == "children"
|
191
|
+
|
192
|
+
apply_change_to_component(component, subchange_name, subchange, path)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def apply_group_removals(project, removals)
|
198
|
+
removals.sort_by(&:last).reverse.each do |change, path|
|
199
|
+
next unless %w[PBXGroup PBXVariantGroup].include?(change["isa"])
|
200
|
+
|
201
|
+
group_path = join_path(path, change["displayName"])
|
202
|
+
|
203
|
+
# by now we've deleted all of this group's children in the project, so we need to adapt the
|
204
|
+
# change to the expected current state of the group, that is, without any children.
|
205
|
+
change_without_children = change.dup
|
206
|
+
change_without_children["children"] = []
|
207
|
+
|
208
|
+
remove_component(project[group_path], change_without_children)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
49
212
|
def apply_change_to_component(parent_component, change_name, change, parent_change_path)
|
50
213
|
return if change_name == "displayName"
|
51
214
|
|
52
|
-
change_path = parent_change_path
|
215
|
+
change_path = join_path(parent_change_path, change_name)
|
53
216
|
|
54
217
|
attribute_name = attribute_name_from_change_name(change_name)
|
55
218
|
if simple_attribute?(parent_component, attribute_name)
|
@@ -61,28 +224,40 @@ module Kintsugi
|
|
61
224
|
component = replace_component_with_new_type(parent_component, attribute_name, change)
|
62
225
|
change = change_for_component_of_new_type(component, change)
|
63
226
|
else
|
64
|
-
component = child_component(parent_component, change_name)
|
65
|
-
|
66
|
-
if component.nil?
|
67
|
-
add_missing_component_if_valid(parent_component, change_name, change, change_path)
|
68
|
-
return
|
69
|
-
end
|
227
|
+
component = child_component(parent_component, change, change_name)
|
70
228
|
end
|
71
229
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
230
|
+
if change[:removed].is_a?(Hash)
|
231
|
+
remove_component(component, change[:removed])
|
232
|
+
elsif change[:removed].is_a?(Array)
|
233
|
+
unless component.nil?
|
234
|
+
(change[:removed]).each do |removed_change|
|
235
|
+
child = child_component_of_object_list(component, removed_change,
|
236
|
+
removed_change["displayName"])
|
237
|
+
remove_component(child, removed_change)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
elsif !change[:removed].nil?
|
241
|
+
raise MergeError, "Unsupported removed change type for #{change[:removed]}"
|
77
242
|
end
|
78
243
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
244
|
+
if change[:added].is_a?(Hash)
|
245
|
+
add_child_to_component(parent_component, change[:added], change_path)
|
246
|
+
elsif change[:added].is_a?(Array)
|
247
|
+
(change[:added]).each do |added_change|
|
248
|
+
add_child_to_component(parent_component, added_change, change_path)
|
249
|
+
end
|
250
|
+
elsif !change[:added].nil?
|
251
|
+
raise MergeError, "Unsupported added change type for #{change[:added]}"
|
83
252
|
end
|
84
253
|
|
85
254
|
subchanges_of_change(change).each do |subchange_name, subchange|
|
255
|
+
if component.nil?
|
256
|
+
raise MergeError, "Trying to apply changes to a component that doesn't exist at path " \
|
257
|
+
"#{change_path}. It was probably removed in a previous commit. This is considered a " \
|
258
|
+
"conflict that should be resolved manually."
|
259
|
+
end
|
260
|
+
|
86
261
|
apply_change_to_component(component, subchange_name, subchange, change_path)
|
87
262
|
end
|
88
263
|
end
|
@@ -103,16 +278,6 @@ module Kintsugi
|
|
103
278
|
end
|
104
279
|
end
|
105
280
|
|
106
|
-
def add_missing_component_if_valid(parent_component, change_name, change, change_path)
|
107
|
-
if change[:added] && change.compact.count == 1
|
108
|
-
add_child_to_component(parent_component, change[:added], change_path)
|
109
|
-
return
|
110
|
-
end
|
111
|
-
|
112
|
-
puts "Warning: Detected change of an object named '#{change_name}' contained in " \
|
113
|
-
"'#{parent_component}' but the object doesn't exist. Ignoring this change."
|
114
|
-
end
|
115
|
-
|
116
281
|
def replace_component_with_new_type(parent_component, name_in_parent_component, change)
|
117
282
|
old_component = parent_component.send(name_in_parent_component)
|
118
283
|
new_component = component_of_new_type(parent_component, change, old_component)
|
@@ -164,15 +329,23 @@ module Kintsugi
|
|
164
329
|
end
|
165
330
|
end
|
166
331
|
|
167
|
-
def child_component(component, change_name)
|
332
|
+
def child_component(component, change, change_name)
|
168
333
|
if component.is_a?(Xcodeproj::Project::ObjectList)
|
169
|
-
component
|
334
|
+
child_component_of_object_list(component, change, change_name)
|
170
335
|
else
|
171
336
|
attribute_name = attribute_name_from_change_name(change_name)
|
172
337
|
component.send(attribute_name)
|
173
338
|
end
|
174
339
|
end
|
175
340
|
|
341
|
+
def child_component_of_object_list(component, change, change_name)
|
342
|
+
if change["isa"] == "PBXReferenceProxy"
|
343
|
+
find_reference_proxy_in_component(component, change["remoteRef"])
|
344
|
+
else
|
345
|
+
component.find { |child| child.display_name == change_name }
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
176
349
|
def simple_attribute?(component, attribute_name)
|
177
350
|
return false unless component.respond_to?("simple_attributes")
|
178
351
|
|
@@ -281,7 +454,14 @@ module Kintsugi
|
|
281
454
|
|
282
455
|
return added_change if ((old_value || []) - (removed_change || [])).empty?
|
283
456
|
|
284
|
-
|
457
|
+
new_value = (old_value || []) - (removed_change || [])
|
458
|
+
filtered_added_change = if Settings.allow_duplicates
|
459
|
+
(added_change || [])
|
460
|
+
else
|
461
|
+
(added_change || []).reject { |added| new_value.include?(added) }
|
462
|
+
end
|
463
|
+
|
464
|
+
new_value + filtered_added_change
|
285
465
|
end
|
286
466
|
|
287
467
|
def new_string_simple_attribute_value(old_value, removed_change, added_change)
|
@@ -294,10 +474,13 @@ module Kintsugi
|
|
294
474
|
end
|
295
475
|
|
296
476
|
def remove_component(component, change)
|
477
|
+
return if component.nil?
|
478
|
+
|
297
479
|
if component.to_tree_hash != change
|
298
480
|
raise MergeError, "Trying to remove an object that changed since then. This is " \
|
299
481
|
"considered a conflict that should be resolved manually. Name of the object is: " \
|
300
|
-
"'#{component.display_name}'"
|
482
|
+
"'#{component.display_name}'. Existing component: #{component.to_tree_hash}. " \
|
483
|
+
"Change: #{change}"
|
301
484
|
end
|
302
485
|
|
303
486
|
if change["isa"] == "PBXFileReference"
|
@@ -320,7 +503,7 @@ module Kintsugi
|
|
320
503
|
end
|
321
504
|
|
322
505
|
def add_child_to_component(component, change, component_change_path)
|
323
|
-
change_path =
|
506
|
+
change_path = join_path(component_change_path, change["displayName"])
|
324
507
|
|
325
508
|
if change["ProjectRef"] && change["ProductGroup"]
|
326
509
|
add_subproject_reference(component, change, change_path)
|
@@ -426,6 +609,10 @@ module Kintsugi
|
|
426
609
|
end
|
427
610
|
containing_component.file_ref = file_reference
|
428
611
|
when Xcodeproj::Project::PBXGroup
|
612
|
+
return if !Settings.allow_duplicates &&
|
613
|
+
!find_file_in_group(containing_component, Xcodeproj::Project::PBXReferenceProxy,
|
614
|
+
change["path"]).nil?
|
615
|
+
|
429
616
|
reference_proxy = containing_component.project.new(Xcodeproj::Project::PBXReferenceProxy)
|
430
617
|
containing_component << reference_proxy
|
431
618
|
add_attributes_to_component(reference_proxy, change, change_path)
|
@@ -441,13 +628,11 @@ module Kintsugi
|
|
441
628
|
containing_component.file_ref =
|
442
629
|
find_variant_group(containing_component.project, change["displayName"])
|
443
630
|
when Xcodeproj::Project::PBXGroup, Xcodeproj::Project::PBXVariantGroup
|
444
|
-
|
445
|
-
|
631
|
+
if find_group_in_group(containing_component, Xcodeproj::Project::PBXVariantGroup,
|
632
|
+
change).nil?
|
633
|
+
raise "Group should have been added already, so this is most likely a bug in Kintsugi" \
|
634
|
+
"Change is: #{change}. Change path: #{change_path}"
|
446
635
|
end
|
447
|
-
|
448
|
-
variant_group = containing_component.project.new(Xcodeproj::Project::PBXVariantGroup)
|
449
|
-
containing_component.children << variant_group
|
450
|
-
add_attributes_to_component(variant_group, change, change_path)
|
451
636
|
else
|
452
637
|
raise MergeError, "Trying to add variant group to an unsupported component type " \
|
453
638
|
"#{containing_component.isa}. Change is: #{change}"
|
@@ -506,6 +691,11 @@ module Kintsugi
|
|
506
691
|
return
|
507
692
|
end
|
508
693
|
|
694
|
+
existing_build_file = build_phase.files.find do |build_file|
|
695
|
+
build_file.file_ref && build_file.file_ref.path == change["fileRef"]["path"]
|
696
|
+
end
|
697
|
+
return if !Settings.allow_duplicates && !existing_build_file.nil?
|
698
|
+
|
509
699
|
build_file = build_phase.project.new(Xcodeproj::Project::PBXBuildFile)
|
510
700
|
build_phase.files << build_file
|
511
701
|
add_attributes_to_component(build_file, change, change_path)
|
@@ -581,6 +771,12 @@ module Kintsugi
|
|
581
771
|
end
|
582
772
|
|
583
773
|
def add_subproject_reference(root_object, project_reference_change, change_path)
|
774
|
+
existing_subproject =
|
775
|
+
root_object.project_references.find do |project_reference|
|
776
|
+
project_reference.project_ref.path == project_reference_change["ProjectRef"]["path"]
|
777
|
+
end
|
778
|
+
return if !Settings.allow_duplicates && !existing_subproject.nil?
|
779
|
+
|
584
780
|
filter_subproject_without_project_references = lambda do |file_reference|
|
585
781
|
root_object.project_references.find do |project_reference|
|
586
782
|
project_reference.project_ref.uuid == file_reference.uuid
|
@@ -645,48 +841,45 @@ module Kintsugi
|
|
645
841
|
when Xcodeproj::Project::PBXBuildFile
|
646
842
|
containing_component.file_ref = find_file(containing_component.project, change["path"])
|
647
843
|
when Xcodeproj::Project::PBXGroup, Xcodeproj::Project::PBXVariantGroup
|
648
|
-
|
649
|
-
|
844
|
+
if find_file_in_group(containing_component, Xcodeproj::Project::PBXFileReference,
|
845
|
+
change["path"]).nil?
|
846
|
+
raise "File should have been added already, so this is most likely a bug in Kintsugi" \
|
847
|
+
"Change is: #{change}. Change path: #{change_path}"
|
650
848
|
end
|
651
|
-
|
652
|
-
file_reference = containing_component.project.new(Xcodeproj::Project::PBXFileReference)
|
653
|
-
containing_component.children << file_reference
|
654
|
-
|
655
|
-
# For some reason, `include_in_index` is set to `1` and `source_tree` to `SDKROOT` by
|
656
|
-
# default.
|
657
|
-
file_reference.include_in_index = nil
|
658
|
-
file_reference.source_tree = nil
|
659
|
-
add_attributes_to_component(file_reference, change, change_path)
|
660
849
|
else
|
661
850
|
raise MergeError, "Trying to add file reference to an unsupported component type " \
|
662
851
|
"#{containing_component.isa}. Change is: #{change}"
|
663
852
|
end
|
664
853
|
end
|
665
854
|
|
855
|
+
def find_file_in_group(group, instance_type, filepath)
|
856
|
+
group
|
857
|
+
.children
|
858
|
+
.select { |child| child.instance_of?(instance_type) }
|
859
|
+
.find { |file| file.path == filepath }
|
860
|
+
end
|
861
|
+
|
666
862
|
def adding_files_and_groups_allowed?(change_path)
|
667
863
|
change_path.start_with?("rootObject/mainGroup") ||
|
668
864
|
change_path.start_with?("rootObject/projectReferences")
|
669
865
|
end
|
670
866
|
|
671
867
|
def add_group(containing_component, change, change_path)
|
672
|
-
unless adding_files_and_groups_allowed?(change_path)
|
673
|
-
return
|
674
|
-
end
|
675
|
-
|
676
868
|
case containing_component
|
677
869
|
when Xcodeproj::Project::ObjectDictionary
|
678
870
|
# It is assumed that an `ObjectDictionary` always represents a project reference.
|
679
871
|
new_group = containing_component[:project_ref].project.new(Xcodeproj::Project::PBXGroup)
|
680
872
|
containing_component[:product_group] = new_group
|
873
|
+
add_attributes_to_component(new_group, change, change_path)
|
681
874
|
when Xcodeproj::Project::PBXGroup
|
682
|
-
|
683
|
-
|
875
|
+
if find_group_in_group(containing_component, Xcodeproj::Project::PBXGroup, change).nil?
|
876
|
+
raise "Group should have been added already, so this is most likely a bug in Kintsugi" \
|
877
|
+
"Change is: #{change}. Change path: #{change_path}"
|
878
|
+
end
|
684
879
|
else
|
685
880
|
raise MergeError, "Trying to add group to an unsupported component type " \
|
686
|
-
"#{containing_component.isa}. Change is: #{change}"
|
881
|
+
"#{containing_component.isa}. Change is: #{change}. Change path: #{change_path}"
|
687
882
|
end
|
688
|
-
|
689
|
-
add_attributes_to_component(new_group, change, change_path)
|
690
883
|
end
|
691
884
|
|
692
885
|
def add_attributes_to_component(component, change, change_path, ignore_keys: [])
|
@@ -739,12 +932,9 @@ module Kintsugi
|
|
739
932
|
|
740
933
|
def find_reference_proxy(project, container_item_proxy_change, reference_filter: ->(_) { true })
|
741
934
|
reference_proxies = project.root_object.project_references.map do |project_ref_and_products|
|
742
|
-
project_ref_and_products[:product_group].children
|
743
|
-
|
744
|
-
|
745
|
-
product.remote_ref.remote_info == container_item_proxy_change["remoteInfo"] &&
|
746
|
-
reference_filter.call(product)
|
747
|
-
end
|
935
|
+
find_reference_proxy_in_component(project_ref_and_products[:product_group].children,
|
936
|
+
container_item_proxy_change,
|
937
|
+
reference_filter: reference_filter)
|
748
938
|
end.compact
|
749
939
|
|
750
940
|
if reference_proxies.length > 1
|
@@ -758,5 +948,19 @@ module Kintsugi
|
|
758
948
|
|
759
949
|
reference_proxies.first
|
760
950
|
end
|
951
|
+
|
952
|
+
def find_reference_proxy_in_component(component, container_item_proxy_change,
|
953
|
+
reference_filter: ->(_) { true })
|
954
|
+
component.find do |product|
|
955
|
+
product.remote_ref.remote_global_id_string ==
|
956
|
+
container_item_proxy_change["remoteGlobalIDString"] &&
|
957
|
+
product.remote_ref.remote_info == container_item_proxy_change["remoteInfo"] &&
|
958
|
+
reference_filter.call(product)
|
959
|
+
end
|
960
|
+
end
|
961
|
+
|
962
|
+
def join_path(left, right)
|
963
|
+
left.empty? ? right : "#{left}/#{right}"
|
964
|
+
end
|
761
965
|
end
|
762
966
|
end
|
data/lib/kintsugi/cli.rb
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
require "fileutils"
|
6
6
|
require "optparse"
|
7
7
|
|
8
|
+
require_relative "settings"
|
8
9
|
require_relative "version"
|
9
10
|
|
10
11
|
module Kintsugi
|
@@ -182,6 +183,8 @@ module Kintsugi
|
|
182
183
|
exit
|
183
184
|
end
|
184
185
|
|
186
|
+
opts.on("--allow-duplicates", "Allow to add duplicates of the same entity")
|
187
|
+
|
185
188
|
opts.on_tail("\nSUBCOMMANDS\n#{subcommands_descriptions(subcommands)}")
|
186
189
|
end
|
187
190
|
|
@@ -192,6 +195,10 @@ module Kintsugi
|
|
192
195
|
exit(1)
|
193
196
|
end
|
194
197
|
|
198
|
+
if options[:"allow-duplicates"]
|
199
|
+
Settings.allow_duplicates = true
|
200
|
+
end
|
201
|
+
|
195
202
|
project_file_path = File.expand_path(arguments[0])
|
196
203
|
Kintsugi.resolve_conflicts(project_file_path, options[:"changes-output-path"])
|
197
204
|
puts "Resolved conflicts successfully"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright (c) 2022 Lightricks. All rights reserved.
|
2
|
+
# Created by Ben Yohay.
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
module Kintsugi
|
6
|
+
# Kintsugi global settings.
|
7
|
+
class Settings
|
8
|
+
class << self
|
9
|
+
# `true` if Kintsugi can create entities that are identical to existing ones, `false`
|
10
|
+
# otherwise.
|
11
|
+
attr_writer :allow_duplicates
|
12
|
+
|
13
|
+
def allow_duplicates
|
14
|
+
@allow_duplicates || false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|