kintsugi 0.5.4 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|