kintsugi 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,9 +6,11 @@ require "json"
6
6
  require "rspec"
7
7
  require "tempfile"
8
8
  require "tmpdir"
9
+ require "tty-prompt"
9
10
 
10
11
  require "kintsugi/apply_change_to_project"
11
12
  require "kintsugi/error"
13
+ require "tty/prompt/test"
12
14
 
13
15
  require_relative "be_equivalent_to_project"
14
16
 
@@ -18,6 +20,7 @@ describe Kintsugi, :apply_change_to_project do
18
20
  let(:base_project) { Xcodeproj::Project.new(base_project_path) }
19
21
 
20
22
  before do
23
+ Kintsugi::Settings.interactive_resolution = false
21
24
  base_project.save
22
25
  end
23
26
 
@@ -29,8 +32,9 @@ describe Kintsugi, :apply_change_to_project do
29
32
 
30
33
  it "not raises when change is nil or doesn't have root object" do
31
34
  expect {
32
- described_class.apply_change_to_project(base_project, nil)
33
- described_class.apply_change_to_project(base_project, {})
35
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
36
+ described_class.apply_change_to_project(base_project, nil, theirs_project)
37
+ described_class.apply_change_to_project(base_project, {}, theirs_project)
34
38
  }.not_to raise_error
35
39
  end
36
40
 
@@ -40,7 +44,7 @@ describe Kintsugi, :apply_change_to_project do
40
44
 
41
45
  changes_to_apply = get_diff(theirs_project, base_project)
42
46
 
43
- described_class.apply_change_to_project(base_project, changes_to_apply)
47
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
44
48
 
45
49
  expect(base_project).to be_equivalent_to_project(theirs_project)
46
50
  end
@@ -51,7 +55,7 @@ describe Kintsugi, :apply_change_to_project do
51
55
 
52
56
  changes_to_apply = get_diff(theirs_project, base_project)
53
57
 
54
- described_class.apply_change_to_project(base_project, changes_to_apply)
58
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
55
59
 
56
60
  expect(base_project).to be_equivalent_to_project(theirs_project)
57
61
  end
@@ -64,7 +68,7 @@ describe Kintsugi, :apply_change_to_project do
64
68
 
65
69
  changes_to_apply = get_diff(theirs_project, base_project)
66
70
 
67
- described_class.apply_change_to_project(base_project, changes_to_apply)
71
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
68
72
 
69
73
  expect(base_project).to be_equivalent_to_project(theirs_project)
70
74
  end
@@ -75,7 +79,7 @@ describe Kintsugi, :apply_change_to_project do
75
79
 
76
80
  changes_to_apply = get_diff(theirs_project, base_project)
77
81
 
78
- described_class.apply_change_to_project(base_project, changes_to_apply)
82
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
79
83
 
80
84
  expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
81
85
  end
@@ -96,7 +100,7 @@ describe Kintsugi, :apply_change_to_project do
96
100
 
97
101
  changes_to_apply = get_diff(theirs_project, base_project)
98
102
 
99
- described_class.apply_change_to_project(base_project, changes_to_apply)
103
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
100
104
 
101
105
  expect(base_project).to be_equivalent_to_project(theirs_project)
102
106
  end
@@ -113,7 +117,7 @@ describe Kintsugi, :apply_change_to_project do
113
117
 
114
118
  changes_to_apply = get_diff(theirs_project, base_project)
115
119
 
116
- described_class.apply_change_to_project(base_project, changes_to_apply)
120
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
117
121
 
118
122
  expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
119
123
  end
@@ -131,10 +135,27 @@ describe Kintsugi, :apply_change_to_project do
131
135
  changes_to_apply = get_diff(theirs_project, base_project)
132
136
 
133
137
  expect {
134
- described_class.apply_change_to_project(ours_project, changes_to_apply)
138
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
135
139
  }.to raise_error(Kintsugi::MergeError)
136
140
  end
137
141
 
142
+ it "ignores removal of a product reference that was already removed" do
143
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
144
+ base_project.save
145
+
146
+ ours_project = create_copy_of_project(base_project.path, "ours")
147
+ ours_project.targets[0].product_reference.remove_from_project
148
+
149
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
150
+ theirs_project.targets[0].product_reference.remove_from_project
151
+
152
+ changes_to_apply = get_diff(theirs_project, base_project)
153
+
154
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
155
+
156
+ expect(ours_project).to be_equivalent_to_project(theirs_project)
157
+ end
158
+
138
159
  describe "file related changes" do
139
160
  let(:filepath) { "foo" }
140
161
 
@@ -154,11 +175,64 @@ describe Kintsugi, :apply_change_to_project do
154
175
 
155
176
  changes_to_apply = get_diff(theirs_project, base_project)
156
177
 
157
- described_class.apply_change_to_project(base_project, changes_to_apply)
178
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
158
179
 
159
180
  expect(base_project).to be_equivalent_to_project(theirs_project)
160
181
  end
161
182
 
183
+ it "raises if trying to move file to another group that no longer exists" do
184
+ base_project.main_group.find_subpath("new_group", true)
185
+ base_project.save
186
+
187
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
188
+ new_group = theirs_project.main_group.find_subpath("new_group")
189
+ file_reference = theirs_project.main_group.find_file_by_path(filepath)
190
+ file_reference.move(new_group)
191
+
192
+ changes_to_apply = get_diff(theirs_project, base_project)
193
+
194
+ base_project.main_group.find_subpath("new_group").remove_from_project
195
+
196
+ expect {
197
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
198
+ }.to raise_error(Kintsugi::MergeError)
199
+ end
200
+
201
+ it "raises if trying to add file to a group that no longer exists" do
202
+ base_project.main_group.find_subpath("new_group", true)
203
+ base_project.save
204
+
205
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
206
+ theirs_project.main_group.find_subpath("new_group").new_reference("foo")
207
+
208
+ changes_to_apply = get_diff(theirs_project, base_project)
209
+
210
+ base_project.main_group.find_subpath("new_group").remove_from_project
211
+
212
+ expect {
213
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
214
+ }.to raise_error(Kintsugi::MergeError)
215
+ end
216
+
217
+ it "does nothing if trying to remove a file from a group that no longer exists" do
218
+ base_project.main_group.find_subpath("new_group", true).new_reference("foo")
219
+ base_project.save
220
+
221
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
222
+ theirs_project.main_group.find_subpath("new_group/foo").remove_from_project
223
+
224
+ changes_to_apply = get_diff(theirs_project, base_project)
225
+
226
+ base_project.main_group.find_subpath("new_group").remove_from_project
227
+
228
+ base_project.save
229
+ expected_project = create_copy_of_project(base_project.path, "expected")
230
+
231
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
232
+
233
+ expect(base_project).to be_equivalent_to_project(expected_project)
234
+ end
235
+
162
236
  it "raises when a file is split into two" do
163
237
  base_project.main_group.find_subpath("new_group", true)
164
238
  base_project.main_group.find_subpath("new_group2", true)
@@ -173,7 +247,7 @@ describe Kintsugi, :apply_change_to_project do
173
247
  changes_to_apply = get_diff(theirs_project, base_project)
174
248
 
175
249
  expect {
176
- described_class.apply_change_to_project(base_project, changes_to_apply)
250
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
177
251
  }.to raise_error(Kintsugi::MergeError)
178
252
  end
179
253
 
@@ -184,7 +258,7 @@ describe Kintsugi, :apply_change_to_project do
184
258
 
185
259
  changes_to_apply = get_diff(theirs_project, base_project)
186
260
 
187
- described_class.apply_change_to_project(base_project, changes_to_apply)
261
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
188
262
 
189
263
  expect(base_project).to be_equivalent_to_project(theirs_project)
190
264
  end
@@ -198,7 +272,7 @@ describe Kintsugi, :apply_change_to_project do
198
272
 
199
273
  changes_to_apply = get_diff(theirs_project, base_project)
200
274
 
201
- described_class.apply_change_to_project(base_project, changes_to_apply)
275
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
202
276
 
203
277
  expect(base_project).to be_equivalent_to_project(theirs_project)
204
278
  end
@@ -214,11 +288,44 @@ describe Kintsugi, :apply_change_to_project do
214
288
 
215
289
  changes_to_apply = get_diff(theirs_project, base_project)
216
290
 
217
- described_class.apply_change_to_project(base_project, changes_to_apply)
291
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
218
292
 
219
293
  expect(base_project).to be_equivalent_to_project(theirs_project)
220
294
  end
221
295
 
296
+ it "raises when trying to add a group to a group that no longer exists" do
297
+ base_project.main_group.find_subpath("new_group", true)
298
+ base_project.save
299
+
300
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
301
+ theirs_project["new_group"].find_subpath("sub_group", true)
302
+
303
+ changes_to_apply = get_diff(theirs_project, base_project)
304
+
305
+ base_project.main_group.find_subpath("new_group").remove_from_project
306
+
307
+ expect {
308
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
309
+ }.to raise_error(Kintsugi::MergeError)
310
+ end
311
+
312
+ it "raises when trying to move a group to a group that no longer exists" do
313
+ base_project.main_group.find_subpath("new_group", true)
314
+ base_project.main_group.find_subpath("other_group", true)
315
+ base_project.save
316
+
317
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
318
+ theirs_project["other_group"].move(theirs_project["new_group"])
319
+
320
+ changes_to_apply = get_diff(theirs_project, base_project)
321
+
322
+ base_project.main_group.find_subpath("new_group").remove_from_project
323
+
324
+ expect {
325
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
326
+ }.to raise_error(Kintsugi::MergeError)
327
+ end
328
+
222
329
  it "moves a group with a group in it" do
223
330
  new_group = base_project.main_group.find_subpath("new_group", true)
224
331
  new_group.find_subpath("sub_group", true)
@@ -230,7 +337,7 @@ describe Kintsugi, :apply_change_to_project do
230
337
 
231
338
  changes_to_apply = get_diff(theirs_project, base_project)
232
339
 
233
- described_class.apply_change_to_project(base_project, changes_to_apply)
340
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
234
341
 
235
342
  expect(base_project).to be_equivalent_to_project(theirs_project)
236
343
  end
@@ -247,7 +354,7 @@ describe Kintsugi, :apply_change_to_project do
247
354
 
248
355
  changes_to_apply = get_diff(theirs_project, base_project)
249
356
 
250
- described_class.apply_change_to_project(base_project, changes_to_apply)
357
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
251
358
 
252
359
  expect(base_project).to be_equivalent_to_project(theirs_project)
253
360
  end
@@ -260,7 +367,7 @@ describe Kintsugi, :apply_change_to_project do
260
367
 
261
368
  changes_to_apply = get_diff(theirs_project, base_project)
262
369
 
263
- described_class.apply_change_to_project(base_project, changes_to_apply)
370
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
264
371
 
265
372
  expect(base_project).to be_equivalent_to_project(theirs_project)
266
373
  end
@@ -272,7 +379,7 @@ describe Kintsugi, :apply_change_to_project do
272
379
 
273
380
  changes_to_apply = get_diff(theirs_project, base_project)
274
381
 
275
- described_class.apply_change_to_project(base_project, changes_to_apply)
382
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
276
383
 
277
384
  expect(base_project).to be_equivalent_to_project(theirs_project)
278
385
  end
@@ -283,7 +390,7 @@ describe Kintsugi, :apply_change_to_project do
283
390
 
284
391
  changes_to_apply = get_diff(theirs_project, base_project)
285
392
 
286
- described_class.apply_change_to_project(base_project, changes_to_apply)
393
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
287
394
 
288
395
  expect(base_project).to be_equivalent_to_project(theirs_project)
289
396
  end
@@ -300,7 +407,7 @@ describe Kintsugi, :apply_change_to_project do
300
407
 
301
408
  changes_to_apply = get_diff(theirs_project, base_project)
302
409
 
303
- described_class.apply_change_to_project(base_project, changes_to_apply)
410
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
304
411
 
305
412
  expect(base_project).to be_equivalent_to_project(theirs_project)
306
413
  end
@@ -316,7 +423,7 @@ describe Kintsugi, :apply_change_to_project do
316
423
 
317
424
  base_project.main_group.children.delete_at(-1)
318
425
 
319
- described_class.apply_change_to_project(base_project, changes_to_apply)
426
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
320
427
 
321
428
  expect(base_project).to be_equivalent_to_project(theirs_project)
322
429
  end
@@ -339,7 +446,7 @@ describe Kintsugi, :apply_change_to_project do
339
446
 
340
447
  changes_to_apply = get_diff(theirs_project, base_project)
341
448
 
342
- described_class.apply_change_to_project(base_project, changes_to_apply)
449
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
343
450
 
344
451
  expect(base_project).to be_equivalent_to_project(theirs_project)
345
452
  end
@@ -354,7 +461,7 @@ describe Kintsugi, :apply_change_to_project do
354
461
 
355
462
  changes_to_apply = get_diff(theirs_project, base_project)
356
463
 
357
- described_class.apply_change_to_project(base_project, changes_to_apply)
464
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
358
465
 
359
466
  expect(base_project).to be_equivalent_to_project(theirs_project)
360
467
  end
@@ -368,7 +475,7 @@ describe Kintsugi, :apply_change_to_project do
368
475
 
369
476
  changes_to_apply = get_diff(theirs_project, base_project)
370
477
 
371
- described_class.apply_change_to_project(base_project, changes_to_apply)
478
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
372
479
 
373
480
  expect(base_project).to be_equivalent_to_project(theirs_project)
374
481
  end
@@ -383,30 +490,31 @@ describe Kintsugi, :apply_change_to_project do
383
490
 
384
491
  changes_to_apply = get_diff(theirs_project, base_project)
385
492
 
386
- described_class.apply_change_to_project(base_project, changes_to_apply)
493
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
387
494
 
388
495
  expect(base_project).to be_equivalent_to_project(theirs_project)
389
496
  end
390
497
 
391
498
  describe "dealing with unexpected change" do
392
- it "ignores change to a file whose containing group doesn't exist" do
499
+ it "raises if applying change to a file whose containing group doesn't exist" do
393
500
  ours_project = create_copy_of_project(base_project.path, "ours")
394
- ours_project.main_group.remove_from_project
501
+ new_group = ours_project.main_group.find_subpath("new_group", true)
502
+ ours_project.main_group.find_file_by_path(filepath).move(new_group)
395
503
  ours_project.save
396
504
 
397
505
  theirs_project = create_copy_of_project(base_project.path, "theirs")
398
506
  theirs_project.main_group.find_file_by_path(filepath).explicit_file_type = "bar"
399
507
 
400
- changes_to_apply = get_diff(theirs_project, base_project)
508
+ ours_project.main_group.find_subpath("new_group").remove_from_project
401
509
 
402
- ours_project_before_applying_changes = create_copy_of_project(ours_project.path, "ours")
403
-
404
- described_class.apply_change_to_project(ours_project, changes_to_apply)
510
+ changes_to_apply = get_diff(theirs_project, base_project)
405
511
 
406
- expect(ours_project).to be_equivalent_to_project(ours_project_before_applying_changes)
512
+ expect {
513
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
514
+ }.to raise_error(Kintsugi::MergeError)
407
515
  end
408
516
 
409
- it "ignores change to a file that doesn't exist" do
517
+ it "raises if applying change to a file that doesn't exist" do
410
518
  ours_project = create_copy_of_project(base_project.path, "ours")
411
519
  ours_project.main_group.find_file_by_path(filepath).remove_from_project
412
520
  ours_project.save
@@ -416,11 +524,9 @@ describe Kintsugi, :apply_change_to_project do
416
524
 
417
525
  changes_to_apply = get_diff(theirs_project, base_project)
418
526
 
419
- ours_project_before_applying_changes = create_copy_of_project(ours_project.path, "ours")
420
-
421
- described_class.apply_change_to_project(ours_project, changes_to_apply)
422
-
423
- expect(ours_project).to be_equivalent_to_project(ours_project_before_applying_changes)
527
+ expect {
528
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
529
+ }.to raise_error(Kintsugi::MergeError)
424
530
  end
425
531
 
426
532
  it "ignores removal of a file whose group doesn't exist" do
@@ -435,7 +541,7 @@ describe Kintsugi, :apply_change_to_project do
435
541
 
436
542
  ours_project_before_applying_changes = create_copy_of_project(ours_project.path, "ours")
437
543
 
438
- described_class.apply_change_to_project(ours_project, changes_to_apply)
544
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
439
545
 
440
546
  expect(ours_project).to be_equivalent_to_project(ours_project_before_applying_changes)
441
547
  end
@@ -449,7 +555,7 @@ describe Kintsugi, :apply_change_to_project do
449
555
 
450
556
  changes_to_apply = get_diff(theirs_project, base_project)
451
557
 
452
- described_class.apply_change_to_project(ours_project, changes_to_apply)
558
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
453
559
 
454
560
  expect(ours_project).to be_equivalent_to_project(theirs_project)
455
561
  end
@@ -474,7 +580,7 @@ describe Kintsugi, :apply_change_to_project do
474
580
  file_reference.move(new_group)
475
581
  changes_to_apply = get_diff(theirs_project, base_project)
476
582
 
477
- described_class.apply_change_to_project(base_project, changes_to_apply)
583
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
478
584
 
479
585
  expect(base_project).to be_equivalent_to_project(theirs_project)
480
586
  end
@@ -489,7 +595,7 @@ describe Kintsugi, :apply_change_to_project do
489
595
  file_reference.move(theirs_project.main_group)
490
596
  changes_to_apply = get_diff(theirs_project, base_project)
491
597
 
492
- described_class.apply_change_to_project(base_project, changes_to_apply)
598
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
493
599
 
494
600
  expect(base_project).to be_equivalent_to_project(theirs_project)
495
601
  end
@@ -506,7 +612,7 @@ describe Kintsugi, :apply_change_to_project do
506
612
 
507
613
  changes_to_apply = get_diff(theirs_project, base_project)
508
614
 
509
- described_class.apply_change_to_project(base_project, changes_to_apply)
615
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
510
616
 
511
617
  expect(base_project).to be_equivalent_to_project(theirs_project)
512
618
  end
@@ -518,6 +624,10 @@ describe Kintsugi, :apply_change_to_project do
518
624
  base_project.targets[0].frameworks_build_phase.add_file_reference(file_reference)
519
625
 
520
626
  add_new_subproject_to_project(base_project, "subproj", framework_filename)
627
+
628
+ # Removes the container item proxy to make sure the display name of the reference proxy is the
629
+ # same as the file reference.
630
+ base_project.root_object.project_references[-1][:product_group].children[0].remote_ref.remove_from_project
521
631
  base_project.save
522
632
 
523
633
  theirs_project = create_copy_of_project(base_project.path, "theirs")
@@ -530,7 +640,7 @@ describe Kintsugi, :apply_change_to_project do
530
640
 
531
641
  changes_to_apply = get_diff(theirs_project, base_project)
532
642
 
533
- described_class.apply_change_to_project(base_project, changes_to_apply)
643
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
534
644
 
535
645
  expect(base_project).to be_equivalent_to_project(theirs_project)
536
646
  end
@@ -542,7 +652,7 @@ describe Kintsugi, :apply_change_to_project do
542
652
 
543
653
  changes_to_apply = get_diff(theirs_project, base_project)
544
654
 
545
- described_class.apply_change_to_project(base_project, changes_to_apply)
655
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
546
656
 
547
657
  expect(base_project).to be_equivalent_to_project(theirs_project)
548
658
  end
@@ -551,9 +661,12 @@ describe Kintsugi, :apply_change_to_project do
551
661
  framework_filename = "baz"
552
662
 
553
663
  add_new_subproject_to_project(base_project, "subproj", framework_filename)
554
- base_project.targets[0].frameworks_build_phase.add_file_reference(
664
+ subproject_reference_proxy =
555
665
  base_project.root_object.project_references[0][:product_group].children[0]
556
- )
666
+ # Removes the container item proxy to make sure the display name of the reference proxy is the
667
+ # same as the file reference.
668
+ subproject_reference_proxy.remote_ref.remove_from_project
669
+ base_project.targets[0].frameworks_build_phase.add_file_reference(subproject_reference_proxy)
557
670
 
558
671
  base_project.save
559
672
 
@@ -567,7 +680,7 @@ describe Kintsugi, :apply_change_to_project do
567
680
 
568
681
  changes_to_apply = get_diff(theirs_project, base_project)
569
682
 
570
- described_class.apply_change_to_project(base_project, changes_to_apply)
683
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
571
684
  # This verifies we haven't created a new file reference instead of reusing the one in the
572
685
  # hierarchy.
573
686
  base_project.files[-1].name = "foo"
@@ -595,9 +708,7 @@ describe Kintsugi, :apply_change_to_project do
595
708
 
596
709
  changes_to_apply = get_diff(theirs_project, base_project)
597
710
 
598
- changes_to_apply["rootObject"].delete("projectReferences")
599
-
600
- described_class.apply_change_to_project(base_project, changes_to_apply)
711
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
601
712
 
602
713
  expect(base_project).to be_equivalent_to_project(theirs_project)
603
714
  end
@@ -623,7 +734,7 @@ describe Kintsugi, :apply_change_to_project do
623
734
 
624
735
  changes_to_apply = get_diff(theirs_project, base_project)
625
736
 
626
- described_class.apply_change_to_project(base_project, changes_to_apply)
737
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
627
738
 
628
739
  expect(base_project).to be_equivalent_to_project(theirs_project)
629
740
  end
@@ -639,7 +750,7 @@ describe Kintsugi, :apply_change_to_project do
639
750
 
640
751
  changes_to_apply = get_diff(theirs_project, base_project)
641
752
 
642
- described_class.apply_change_to_project(base_project, changes_to_apply)
753
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
643
754
 
644
755
  expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
645
756
  end
@@ -655,7 +766,7 @@ describe Kintsugi, :apply_change_to_project do
655
766
 
656
767
  changes_to_apply = get_diff(theirs_project, base_project)
657
768
  other_project = create_copy_of_project(base_project.path, "theirs")
658
- described_class.apply_change_to_project(other_project, changes_to_apply)
769
+ described_class.apply_change_to_project(other_project, changes_to_apply, theirs_project)
659
770
 
660
771
  expect(other_project).to be_equivalent_to_project(theirs_project)
661
772
  end
@@ -674,7 +785,7 @@ describe Kintsugi, :apply_change_to_project do
674
785
 
675
786
  changes_to_apply = get_diff(theirs_project, base_project)
676
787
 
677
- described_class.apply_change_to_project(base_project, changes_to_apply)
788
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
678
789
 
679
790
  expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
680
791
  end
@@ -694,7 +805,7 @@ describe Kintsugi, :apply_change_to_project do
694
805
 
695
806
  changes_to_apply = get_diff(theirs_project, base_project)
696
807
 
697
- described_class.apply_change_to_project(base_project, changes_to_apply)
808
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
698
809
 
699
810
  expect(base_project).to be_equivalent_to_project(theirs_project)
700
811
  end
@@ -712,7 +823,7 @@ describe Kintsugi, :apply_change_to_project do
712
823
 
713
824
  changes_to_apply = get_diff(theirs_project, base_project)
714
825
 
715
- described_class.apply_change_to_project(base_project, changes_to_apply)
826
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
716
827
 
717
828
  expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
718
829
  end
@@ -730,7 +841,7 @@ describe Kintsugi, :apply_change_to_project do
730
841
  changes_to_apply = get_diff(theirs_project, base_project)
731
842
 
732
843
  other_project = create_copy_of_project(base_project.path, "other")
733
- described_class.apply_change_to_project(other_project, changes_to_apply)
844
+ described_class.apply_change_to_project(other_project, changes_to_apply, theirs_project)
734
845
 
735
846
  expect(other_project).to be_equivalent_to_project(base_project)
736
847
  end
@@ -755,7 +866,7 @@ describe Kintsugi, :apply_change_to_project do
755
866
 
756
867
  changes_to_apply = get_diff(theirs_project, base_project)
757
868
 
758
- described_class.apply_change_to_project(base_project, changes_to_apply)
869
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
759
870
 
760
871
  expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
761
872
  end
@@ -770,7 +881,7 @@ describe Kintsugi, :apply_change_to_project do
770
881
 
771
882
  changes_to_apply = get_diff(theirs_project, base_project)
772
883
 
773
- described_class.apply_change_to_project(base_project, changes_to_apply)
884
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
774
885
 
775
886
  expect(base_project).to be_equivalent_to_project(theirs_project)
776
887
  end
@@ -790,7 +901,7 @@ describe Kintsugi, :apply_change_to_project do
790
901
 
791
902
  changes_to_apply = get_diff(theirs_project, base_project)
792
903
 
793
- described_class.apply_change_to_project(base_project, changes_to_apply)
904
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
794
905
 
795
906
  expect(base_project).to be_equivalent_to_project(theirs_project)
796
907
  end
@@ -807,7 +918,7 @@ describe Kintsugi, :apply_change_to_project do
807
918
 
808
919
  changes_to_apply = get_diff(theirs_project, base_project)
809
920
 
810
- described_class.apply_change_to_project(base_project, changes_to_apply)
921
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
811
922
 
812
923
  expect(base_project).to be_equivalent_to_project(theirs_project)
813
924
  end
@@ -830,7 +941,7 @@ describe Kintsugi, :apply_change_to_project do
830
941
 
831
942
  changes_to_apply = get_diff(theirs_project, base_project)
832
943
 
833
- described_class.apply_change_to_project(base_project, changes_to_apply)
944
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
834
945
 
835
946
  expect(base_project).to be_equivalent_to_project(theirs_project)
836
947
  end
@@ -848,7 +959,7 @@ describe Kintsugi, :apply_change_to_project do
848
959
  configuration.build_settings["HEADER_SEARCH_PATHS"] = "baz"
849
960
  end
850
961
 
851
- described_class.apply_change_to_project(ours_project, changes_to_apply)
962
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
852
963
 
853
964
  expected_project = create_copy_of_project(base_project.path, "expected")
854
965
  expected_project.targets[0].build_configurations.each do |configuration|
@@ -870,7 +981,7 @@ describe Kintsugi, :apply_change_to_project do
870
981
  configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[bar foo]
871
982
  end
872
983
 
873
- described_class.apply_change_to_project(ours_project, changes_to_apply)
984
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
874
985
 
875
986
  expected_project = create_copy_of_project(base_project.path, "expected")
876
987
  expected_project.targets[0].build_configurations.each do |configuration|
@@ -895,7 +1006,7 @@ describe Kintsugi, :apply_change_to_project do
895
1006
 
896
1007
  changes_to_apply = get_diff(theirs_project, base_project)
897
1008
 
898
- described_class.apply_change_to_project(base_project, changes_to_apply)
1009
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
899
1010
 
900
1011
  expect(base_project).to be_equivalent_to_project(theirs_project)
901
1012
  end
@@ -914,7 +1025,7 @@ describe Kintsugi, :apply_change_to_project do
914
1025
 
915
1026
  changes_to_apply = get_diff(theirs_project, base_project)
916
1027
 
917
- described_class.apply_change_to_project(base_project, changes_to_apply)
1028
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
918
1029
 
919
1030
  expect(base_project).to be_equivalent_to_project(theirs_project)
920
1031
  end
@@ -932,7 +1043,7 @@ describe Kintsugi, :apply_change_to_project do
932
1043
 
933
1044
  changes_to_apply = get_diff(theirs_project, base_project)
934
1045
 
935
- described_class.apply_change_to_project(base_project, changes_to_apply)
1046
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
936
1047
 
937
1048
  expect(base_project).to be_equivalent_to_project(theirs_project)
938
1049
  end
@@ -956,7 +1067,7 @@ describe Kintsugi, :apply_change_to_project do
956
1067
 
957
1068
  changes_to_apply = get_diff(theirs_project, base_project)
958
1069
 
959
- described_class.apply_change_to_project(base_project, changes_to_apply)
1070
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
960
1071
 
961
1072
  expect(base_project).to be_equivalent_to_project(theirs_project)
962
1073
  end
@@ -976,7 +1087,7 @@ describe Kintsugi, :apply_change_to_project do
976
1087
 
977
1088
  changes_to_apply = get_diff(theirs_project, before_theirs_project)
978
1089
 
979
- described_class.apply_change_to_project(base_project, changes_to_apply)
1090
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
980
1091
 
981
1092
  expect(base_project).to be_equivalent_to_project(theirs_project)
982
1093
  end
@@ -996,7 +1107,7 @@ describe Kintsugi, :apply_change_to_project do
996
1107
 
997
1108
  changes_to_apply = get_diff(theirs_project, before_theirs_project)
998
1109
 
999
- described_class.apply_change_to_project(base_project, changes_to_apply)
1110
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1000
1111
 
1001
1112
  expect(base_project).to be_equivalent_to_project(theirs_project)
1002
1113
  end
@@ -1017,7 +1128,7 @@ describe Kintsugi, :apply_change_to_project do
1017
1128
 
1018
1129
  changes_to_apply = get_diff(theirs_project, before_theirs_project)
1019
1130
 
1020
- described_class.apply_change_to_project(base_project, changes_to_apply)
1131
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1021
1132
  base_project.save
1022
1133
 
1023
1134
  expected_project = create_copy_of_project(base_project.path, "expected")
@@ -1043,7 +1154,7 @@ describe Kintsugi, :apply_change_to_project do
1043
1154
 
1044
1155
  changes_to_apply = get_diff(theirs_project, before_theirs_project)
1045
1156
 
1046
- described_class.apply_change_to_project(base_project, changes_to_apply)
1157
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1047
1158
  base_project.save
1048
1159
 
1049
1160
  expected_project = create_copy_of_project(base_project.path, "expected")
@@ -1066,7 +1177,7 @@ describe Kintsugi, :apply_change_to_project do
1066
1177
 
1067
1178
  changes_to_apply = get_diff(theirs_project, base_project)
1068
1179
 
1069
- described_class.apply_change_to_project(base_project, changes_to_apply)
1180
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1070
1181
 
1071
1182
  expect(base_project).to be_equivalent_to_project(theirs_project)
1072
1183
  end
@@ -1084,7 +1195,7 @@ describe Kintsugi, :apply_change_to_project do
1084
1195
 
1085
1196
  changes_to_apply = get_diff(theirs_project, base_project)
1086
1197
 
1087
- described_class.apply_change_to_project(base_project, changes_to_apply)
1198
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1088
1199
 
1089
1200
  expect(base_project).to be_equivalent_to_project(theirs_project)
1090
1201
  end
@@ -1110,7 +1221,7 @@ describe Kintsugi, :apply_change_to_project do
1110
1221
 
1111
1222
  changes_to_apply = get_diff(theirs_project, before_theirs_project)
1112
1223
 
1113
- described_class.apply_change_to_project(base_project, changes_to_apply)
1224
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1114
1225
 
1115
1226
  expect(base_project).to be_equivalent_to_project(expected_project)
1116
1227
  end
@@ -1132,7 +1243,7 @@ describe Kintsugi, :apply_change_to_project do
1132
1243
  changes_to_apply = get_diff(theirs_project, before_theirs_project)
1133
1244
 
1134
1245
  expect {
1135
- described_class.apply_change_to_project(base_project, changes_to_apply)
1246
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1136
1247
  }.to raise_error(Kintsugi::MergeError)
1137
1248
  end
1138
1249
 
@@ -1156,7 +1267,7 @@ describe Kintsugi, :apply_change_to_project do
1156
1267
  changes_to_apply = get_diff(theirs_project, before_theirs_project)
1157
1268
 
1158
1269
  expect {
1159
- described_class.apply_change_to_project(base_project, changes_to_apply)
1270
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1160
1271
  }.to raise_error(Kintsugi::MergeError)
1161
1272
  end
1162
1273
  end
@@ -1173,7 +1284,7 @@ describe Kintsugi, :apply_change_to_project do
1173
1284
 
1174
1285
  changes_to_apply = get_diff(theirs_project, base_project)
1175
1286
 
1176
- described_class.apply_change_to_project(base_project, changes_to_apply)
1287
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1177
1288
 
1178
1289
  expect(base_project).to be_equivalent_to_project(theirs_project)
1179
1290
  end
@@ -1185,7 +1296,7 @@ describe Kintsugi, :apply_change_to_project do
1185
1296
 
1186
1297
  changes_to_apply = get_diff(theirs_project, base_project)
1187
1298
 
1188
- described_class.apply_change_to_project(base_project, changes_to_apply)
1299
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1189
1300
 
1190
1301
  expect(base_project).to be_equivalent_to_project(theirs_project)
1191
1302
  end
@@ -1199,7 +1310,7 @@ describe Kintsugi, :apply_change_to_project do
1199
1310
 
1200
1311
  changes_to_apply = get_diff(theirs_project, base_project)
1201
1312
 
1202
- described_class.apply_change_to_project(base_project, changes_to_apply)
1313
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1203
1314
 
1204
1315
  expect(base_project).to be_equivalent_to_project(theirs_project)
1205
1316
  end
@@ -1217,7 +1328,7 @@ describe Kintsugi, :apply_change_to_project do
1217
1328
 
1218
1329
  changes_to_apply = get_diff(theirs_project, base_project)
1219
1330
 
1220
- described_class.apply_change_to_project(base_project, changes_to_apply)
1331
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1221
1332
 
1222
1333
  expect(base_project).to be_equivalent_to_project(theirs_project)
1223
1334
  end
@@ -1231,7 +1342,7 @@ describe Kintsugi, :apply_change_to_project do
1231
1342
 
1232
1343
  changes_to_apply = get_diff(theirs_project, base_project)
1233
1344
 
1234
- described_class.apply_change_to_project(base_project, changes_to_apply)
1345
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1235
1346
 
1236
1347
  expect(base_project).to be_equivalent_to_project(theirs_project)
1237
1348
  end
@@ -1249,7 +1360,7 @@ describe Kintsugi, :apply_change_to_project do
1249
1360
 
1250
1361
  changes_to_apply = get_diff(theirs_project, base_project)
1251
1362
 
1252
- described_class.apply_change_to_project(base_project, changes_to_apply)
1363
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1253
1364
 
1254
1365
  expect(base_project).to be_equivalent_to_project(theirs_project)
1255
1366
  end
@@ -1263,7 +1374,7 @@ describe Kintsugi, :apply_change_to_project do
1263
1374
 
1264
1375
  changes_to_apply = get_diff(theirs_project, base_project)
1265
1376
 
1266
- described_class.apply_change_to_project(base_project, changes_to_apply)
1377
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1267
1378
 
1268
1379
  expect(base_project).to be_equivalent_to_project(theirs_project)
1269
1380
  end
@@ -1279,7 +1390,7 @@ describe Kintsugi, :apply_change_to_project do
1279
1390
 
1280
1391
  changes_to_apply = get_diff(theirs_project, base_project)
1281
1392
 
1282
- described_class.apply_change_to_project(base_project, changes_to_apply)
1393
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1283
1394
 
1284
1395
  expect(base_project).to be_equivalent_to_project(theirs_project)
1285
1396
  end
@@ -1291,7 +1402,7 @@ describe Kintsugi, :apply_change_to_project do
1291
1402
 
1292
1403
  changes_to_apply = get_diff(theirs_project, base_project)
1293
1404
 
1294
- described_class.apply_change_to_project(base_project, changes_to_apply)
1405
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1295
1406
 
1296
1407
  expect(base_project).to be_equivalent_to_project(theirs_project)
1297
1408
  end
@@ -1302,7 +1413,7 @@ describe Kintsugi, :apply_change_to_project do
1302
1413
 
1303
1414
  changes_to_apply = get_diff(theirs_project, base_project)
1304
1415
 
1305
- described_class.apply_change_to_project(base_project, changes_to_apply)
1416
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1306
1417
 
1307
1418
  expect(base_project).to be_equivalent_to_project(theirs_project)
1308
1419
  end
@@ -1315,7 +1426,7 @@ describe Kintsugi, :apply_change_to_project do
1315
1426
 
1316
1427
  changes_to_apply = get_diff(theirs_project, base_project)
1317
1428
 
1318
- described_class.apply_change_to_project(base_project, changes_to_apply)
1429
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1319
1430
 
1320
1431
  expect(base_project).to be_equivalent_to_project(theirs_project)
1321
1432
  end
@@ -1330,7 +1441,7 @@ describe Kintsugi, :apply_change_to_project do
1330
1441
 
1331
1442
  changes_to_apply = get_diff(theirs_project, base_project)
1332
1443
 
1333
- described_class.apply_change_to_project(base_project, changes_to_apply)
1444
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1334
1445
 
1335
1446
  expect(base_project).to be_equivalent_to_project(theirs_project)
1336
1447
  end
@@ -1345,7 +1456,7 @@ describe Kintsugi, :apply_change_to_project do
1345
1456
 
1346
1457
  changes_to_apply = get_diff(theirs_project, base_project)
1347
1458
 
1348
- described_class.apply_change_to_project(base_project, changes_to_apply)
1459
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1349
1460
 
1350
1461
  expect(base_project).to be_equivalent_to_project(theirs_project)
1351
1462
  end
@@ -1360,7 +1471,7 @@ describe Kintsugi, :apply_change_to_project do
1360
1471
 
1361
1472
  changes_to_apply = get_diff(theirs_project, base_project)
1362
1473
 
1363
- described_class.apply_change_to_project(base_project, changes_to_apply)
1474
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1364
1475
 
1365
1476
  expect(base_project).to be_equivalent_to_project(theirs_project)
1366
1477
  end
@@ -1378,7 +1489,7 @@ describe Kintsugi, :apply_change_to_project do
1378
1489
 
1379
1490
  changes_to_apply = get_diff(theirs_project, base_project)
1380
1491
 
1381
- described_class.apply_change_to_project(ours_project, changes_to_apply)
1492
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1382
1493
 
1383
1494
  expect(ours_project).to be_equivalent_to_project(theirs_project)
1384
1495
  end
@@ -1395,7 +1506,7 @@ describe Kintsugi, :apply_change_to_project do
1395
1506
 
1396
1507
  changes_to_apply = get_diff(theirs_project, base_project)
1397
1508
 
1398
- described_class.apply_change_to_project(ours_project, changes_to_apply)
1509
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1399
1510
 
1400
1511
  expect(ours_project).to be_equivalent_to_project(theirs_project)
1401
1512
  end
@@ -1422,7 +1533,7 @@ describe Kintsugi, :apply_change_to_project do
1422
1533
 
1423
1534
  changes_to_apply = get_diff(ours_project, theirs_project)
1424
1535
 
1425
- described_class.apply_change_to_project(base_project, changes_to_apply)
1536
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1426
1537
 
1427
1538
  expect(base_project).to be_equivalent_to_project(ours_project, ignore_keys: ["containerPortal"])
1428
1539
  end
@@ -1441,7 +1552,7 @@ describe Kintsugi, :apply_change_to_project do
1441
1552
 
1442
1553
  changes_to_apply = get_diff(theirs_project, base_project)
1443
1554
 
1444
- described_class.apply_change_to_project(base_project, changes_to_apply)
1555
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1445
1556
 
1446
1557
  expect(base_project).to be_equivalent_to_project(theirs_project)
1447
1558
  end
@@ -1456,7 +1567,7 @@ describe Kintsugi, :apply_change_to_project do
1456
1567
 
1457
1568
  changes_to_apply = get_diff(theirs_project, base_project)
1458
1569
 
1459
- described_class.apply_change_to_project(base_project, changes_to_apply)
1570
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1460
1571
  expect(base_project).to be_equivalent_to_project(theirs_project)
1461
1572
  end
1462
1573
 
@@ -1466,7 +1577,7 @@ describe Kintsugi, :apply_change_to_project do
1466
1577
 
1467
1578
  changes_to_apply = get_diff(theirs_project, base_project)
1468
1579
 
1469
- described_class.apply_change_to_project(base_project, changes_to_apply)
1580
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1470
1581
  expect(base_project).to be_equivalent_to_project(theirs_project)
1471
1582
  end
1472
1583
 
@@ -1482,7 +1593,7 @@ describe Kintsugi, :apply_change_to_project do
1482
1593
 
1483
1594
  changes_to_apply = get_diff(theirs_project, base_project)
1484
1595
 
1485
- described_class.apply_change_to_project(base_project, changes_to_apply)
1596
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1486
1597
 
1487
1598
  expect(base_project).to be_equivalent_to_project(theirs_project)
1488
1599
  end
@@ -1500,7 +1611,7 @@ describe Kintsugi, :apply_change_to_project do
1500
1611
 
1501
1612
  changes_to_apply = get_diff(theirs_project, base_project)
1502
1613
 
1503
- described_class.apply_change_to_project(base_project, changes_to_apply)
1614
+ described_class.apply_change_to_project(base_project, changes_to_apply, theirs_project)
1504
1615
 
1505
1616
  expect(base_project).to be_equivalent_to_project(theirs_project)
1506
1617
  end
@@ -1515,7 +1626,7 @@ describe Kintsugi, :apply_change_to_project do
1515
1626
 
1516
1627
  changes_to_apply = get_diff(theirs_project, base_project)
1517
1628
  other_project = create_copy_of_project(base_project.path, "theirs")
1518
- described_class.apply_change_to_project(other_project, changes_to_apply)
1629
+ described_class.apply_change_to_project(other_project, changes_to_apply, theirs_project)
1519
1630
 
1520
1631
  expect(other_project).to be_equivalent_to_project(base_project)
1521
1632
  end
@@ -1529,7 +1640,7 @@ describe Kintsugi, :apply_change_to_project do
1529
1640
 
1530
1641
  changes_to_apply = get_diff(theirs_project, base_project)
1531
1642
  other_project = create_copy_of_project(base_project.path, "theirs")
1532
- described_class.apply_change_to_project(other_project, changes_to_apply)
1643
+ described_class.apply_change_to_project(other_project, changes_to_apply, theirs_project)
1533
1644
 
1534
1645
  expect(other_project).to be_equivalent_to_project(base_project)
1535
1646
  end
@@ -1543,7 +1654,7 @@ describe Kintsugi, :apply_change_to_project do
1543
1654
 
1544
1655
  changes_to_apply = get_diff(theirs_project, base_project)
1545
1656
  other_project = create_copy_of_project(base_project.path, "theirs")
1546
- described_class.apply_change_to_project(other_project, changes_to_apply)
1657
+ described_class.apply_change_to_project(other_project, changes_to_apply, theirs_project)
1547
1658
 
1548
1659
  expect(other_project).to be_equivalent_to_project(base_project)
1549
1660
  end
@@ -1558,7 +1669,7 @@ describe Kintsugi, :apply_change_to_project do
1558
1669
 
1559
1670
  changes_to_apply = get_diff(theirs_project, base_project)
1560
1671
 
1561
- described_class.apply_change_to_project(ours_project, changes_to_apply)
1672
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1562
1673
 
1563
1674
  expect(ours_project.root_object.project_references.count).to equal(1)
1564
1675
  end
@@ -1575,7 +1686,7 @@ describe Kintsugi, :apply_change_to_project do
1575
1686
 
1576
1687
  changes_to_apply = get_diff(theirs_project, base_project)
1577
1688
  other_project = create_copy_of_project(base_project.path, "theirs")
1578
- described_class.apply_change_to_project(other_project, changes_to_apply)
1689
+ described_class.apply_change_to_project(other_project, changes_to_apply, theirs_project)
1579
1690
 
1580
1691
  expect(other_project).to be_equivalent_to_project(base_project)
1581
1692
  end
@@ -1596,7 +1707,7 @@ describe Kintsugi, :apply_change_to_project do
1596
1707
  changes_to_apply = get_diff(theirs_project, base_project)
1597
1708
 
1598
1709
  other_project = create_copy_of_project(base_project.path, "theirs")
1599
- described_class.apply_change_to_project(other_project, changes_to_apply)
1710
+ described_class.apply_change_to_project(other_project, changes_to_apply, theirs_project)
1600
1711
 
1601
1712
  expect(other_project).to be_equivalent_to_project(base_project)
1602
1713
  end
@@ -1619,7 +1730,7 @@ describe Kintsugi, :apply_change_to_project do
1619
1730
 
1620
1731
  expected_project = create_copy_of_project(ours_project.path, "expected")
1621
1732
 
1622
- described_class.apply_change_to_project(ours_project, changes_to_apply)
1733
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1623
1734
 
1624
1735
  expect(ours_project).to be_equivalent_to_project(expected_project)
1625
1736
  end
@@ -1644,7 +1755,7 @@ describe Kintsugi, :apply_change_to_project do
1644
1755
 
1645
1756
  changes_to_apply = get_diff(theirs_project, base_project)
1646
1757
 
1647
- described_class.apply_change_to_project(ours_project, changes_to_apply)
1758
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1648
1759
 
1649
1760
  expect(ours_project.root_object.project_references[0][:project_ref].uuid)
1650
1761
  .not_to equal(ours_project.root_object.project_references[1][:project_ref].uuid)
@@ -1653,6 +1764,456 @@ describe Kintsugi, :apply_change_to_project do
1653
1764
  end
1654
1765
  end
1655
1766
 
1767
+ describe "resovling conflicts interactively" do
1768
+ let(:test_prompt) { TTY::Prompt::Test.new }
1769
+
1770
+ before do
1771
+ Kintsugi::Settings.interactive_resolution = true
1772
+ allow(TTY::Prompt).to receive(:new).and_return(test_prompt)
1773
+ test_prompt.setup
1774
+ end
1775
+
1776
+ after do
1777
+ Kintsugi::Settings.interactive_resolution = false
1778
+ end
1779
+
1780
+ describe "adding group to a non existent group" do
1781
+ it "creates the non existent group" do
1782
+ test_prompt.choose_option(0)
1783
+
1784
+ base_project.main_group.find_subpath("new_group", true)
1785
+ base_project.save
1786
+
1787
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1788
+ theirs_project["new_group"].find_subpath("sub_group", true)
1789
+
1790
+ changes_to_apply = get_diff(theirs_project, base_project)
1791
+
1792
+ ours_project = create_copy_of_project(base_project.path, "ours")
1793
+ ours_project.main_group.find_subpath("new_group").remove_from_project
1794
+
1795
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1796
+ expect(ours_project).to be_equivalent_to_project(theirs_project)
1797
+ end
1798
+
1799
+ it "ignores adding the group" do
1800
+ test_prompt.choose_option(1)
1801
+
1802
+ base_project.main_group.find_subpath("new_group", true)
1803
+ base_project.save
1804
+
1805
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1806
+ theirs_project["new_group"].find_subpath("sub_group", true)
1807
+
1808
+ changes_to_apply = get_diff(theirs_project, base_project)
1809
+
1810
+ ours_project = create_copy_of_project(base_project.path, "ours")
1811
+ ours_project.main_group.find_subpath("new_group").remove_from_project
1812
+ ours_project.save
1813
+ expected_project = create_copy_of_project(ours_project.path, "expected")
1814
+
1815
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1816
+ expect(ours_project).to be_equivalent_to_project(expected_project)
1817
+ end
1818
+ end
1819
+
1820
+ describe "adding file to a non existent group" do
1821
+ it "creates the non existent group" do
1822
+ test_prompt.choose_option(0)
1823
+
1824
+ base_project.main_group.find_subpath("new_group", true)
1825
+ base_project.save
1826
+
1827
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1828
+ theirs_project["new_group"].new_reference("foo/bar")
1829
+
1830
+ changes_to_apply = get_diff(theirs_project, base_project)
1831
+
1832
+ ours_project = create_copy_of_project(base_project.path, "ours")
1833
+ ours_project.main_group.find_subpath("new_group").remove_from_project
1834
+
1835
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1836
+ expect(ours_project).to be_equivalent_to_project(theirs_project)
1837
+ end
1838
+
1839
+ it "ignores adding the file" do
1840
+ test_prompt.choose_option(1)
1841
+
1842
+ base_project.main_group.find_subpath("new_group", true)
1843
+ base_project.save
1844
+
1845
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1846
+ theirs_project["new_group"].new_reference("foo/bar")
1847
+
1848
+ changes_to_apply = get_diff(theirs_project, base_project)
1849
+
1850
+ ours_project = create_copy_of_project(base_project.path, "ours")
1851
+ ours_project.main_group.find_subpath("new_group").remove_from_project
1852
+ ours_project.save
1853
+ expected_project = create_copy_of_project(ours_project.path, "expected")
1854
+
1855
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1856
+ expect(ours_project).to be_equivalent_to_project(expected_project)
1857
+ end
1858
+ end
1859
+
1860
+ describe "changing a group that was already removed" do
1861
+ it "creates the group and applies changes to it" do
1862
+ test_prompt.choose_option(0)
1863
+
1864
+ base_project.main_group.find_subpath("some_group", true)
1865
+ base_project.save
1866
+
1867
+ ours_project = create_copy_of_project(base_project.path, "ours")
1868
+ ours_project.main_group.find_subpath("some_group").remove_from_project
1869
+
1870
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1871
+ theirs_project.main_group.find_subpath("some_group").source_tree = "SDKROOT"
1872
+
1873
+ changes_to_apply = get_diff(theirs_project, base_project)
1874
+
1875
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1876
+
1877
+ expect(ours_project).to be_equivalent_to_project(theirs_project)
1878
+ end
1879
+
1880
+ it "ignores changes to group" do
1881
+ test_prompt.choose_option(1)
1882
+
1883
+ base_project.main_group.find_subpath("some_group", true)
1884
+ base_project.save
1885
+
1886
+ ours_project = create_copy_of_project(base_project.path, "ours")
1887
+ ours_project.main_group.find_subpath("some_group").remove_from_project
1888
+
1889
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1890
+ theirs_project.main_group.find_subpath("some_group").source_tree = "SDKROOT"
1891
+
1892
+ changes_to_apply = get_diff(theirs_project, base_project)
1893
+
1894
+ ours_project.save
1895
+ expected_project = create_copy_of_project(ours_project.path, "expected")
1896
+
1897
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1898
+
1899
+ expect(ours_project).to be_equivalent_to_project(expected_project)
1900
+ end
1901
+ end
1902
+
1903
+ describe "changing a component that was already removed" do
1904
+ it "creates the component and applies changes to it" do
1905
+ test_prompt.choose_option(0)
1906
+
1907
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
1908
+ base_project.save
1909
+
1910
+ ours_project = create_copy_of_project(base_project.path, "ours")
1911
+ ours_project.targets[0].product_reference.remove_from_project
1912
+
1913
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1914
+ theirs_project.targets[0].product_reference.source_tree = "SDKROOT"
1915
+
1916
+ changes_to_apply = get_diff(theirs_project, base_project)
1917
+
1918
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1919
+
1920
+ expect(ours_project).to be_equivalent_to_project(theirs_project)
1921
+ end
1922
+
1923
+ it "ignores changes to component" do
1924
+ test_prompt.choose_option(1)
1925
+
1926
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
1927
+ base_project.save
1928
+
1929
+ ours_project = create_copy_of_project(base_project.path, "ours")
1930
+ ours_project.targets[0].product_reference.remove_from_project
1931
+
1932
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1933
+ theirs_project.targets[0].product_reference.source_tree = "SDKROOT"
1934
+
1935
+ changes_to_apply = get_diff(theirs_project, base_project)
1936
+
1937
+ ours_project.save
1938
+ expected_project = create_copy_of_project(ours_project.path, "expected")
1939
+
1940
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1941
+
1942
+ expect(ours_project).to be_equivalent_to_project(expected_project)
1943
+ end
1944
+ end
1945
+
1946
+ describe "changing a file reference that has a build file and both were already removed" do
1947
+ it "creates the component and its build file and applies changes to it" do
1948
+ test_prompt.choose_option(0)
1949
+
1950
+ file_reference_name = "bar"
1951
+
1952
+ file_reference = base_project.main_group.new_reference(file_reference_name)
1953
+ target = base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
1954
+ target.source_build_phase.add_file_reference(file_reference)
1955
+ base_project.save
1956
+
1957
+ ours_project = create_copy_of_project(base_project.path, "ours")
1958
+ build_file = ours_project.targets[0].source_build_phase.files[-1]
1959
+ # Removing the build file first is done because prior to xcodeproj 1.22, the build file was
1960
+ # not removed when its file reference was removed.
1961
+ build_file.remove_from_project
1962
+ ours_project.main_group.find_subpath(file_reference_name).remove_from_project
1963
+
1964
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1965
+ theirs_project.main_group.find_subpath(file_reference_name).source_tree = "SDKROOT"
1966
+
1967
+ changes_to_apply = get_diff(theirs_project, base_project)
1968
+
1969
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1970
+
1971
+ expect(ours_project).to be_equivalent_to_project(theirs_project)
1972
+ end
1973
+
1974
+ it "ignores changes to component and to its build file" do
1975
+ test_prompt.choose_option(1)
1976
+
1977
+ file_reference_name = "bar"
1978
+
1979
+ file_reference = base_project.main_group.new_reference(file_reference_name)
1980
+ target = base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
1981
+ target.source_build_phase.add_file_reference(file_reference)
1982
+ base_project.save
1983
+
1984
+ ours_project = create_copy_of_project(base_project.path, "ours")
1985
+ ours_project.main_group.find_subpath(file_reference_name).remove_from_project
1986
+
1987
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
1988
+ theirs_project.main_group.find_subpath(file_reference_name).source_tree = "SDKROOT"
1989
+
1990
+ changes_to_apply = get_diff(theirs_project, base_project)
1991
+
1992
+ ours_project.save
1993
+ expected_project = create_copy_of_project(ours_project.path, "expected")
1994
+
1995
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
1996
+
1997
+ expect(ours_project).to be_equivalent_to_project(expected_project)
1998
+ end
1999
+ end
2000
+
2001
+ describe "adding entry to a hash that has another value for the same key" do
2002
+ it "overrides values from new hash" do
2003
+ # There will be two conflicts, one for each configuration.
2004
+ test_prompt.choose_option(0, repeating: 2)
2005
+
2006
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
2007
+ base_project.targets[0].build_configurations.each do |configuration|
2008
+ configuration.build_settings = nil
2009
+ end
2010
+ base_project.save
2011
+
2012
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
2013
+ theirs_project.targets[0].build_configurations.each do |configuration|
2014
+ configuration.build_settings = {"HEADER_SEARCH_PATHS" => "bar"}
2015
+ end
2016
+
2017
+ ours_project = create_copy_of_project(base_project.path, "ours")
2018
+ ours_project.targets[0].build_configurations.each do |configuration|
2019
+ configuration.build_settings = {"HEADER_SEARCH_PATHS" => "baz"}
2020
+ end
2021
+
2022
+ changes_to_apply = get_diff(theirs_project, base_project)
2023
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
2024
+
2025
+ expect(ours_project).to be_equivalent_to_project(theirs_project)
2026
+ end
2027
+
2028
+ it "keeps values from old hash" do
2029
+ # There will be two conflicts, one for each configuration.
2030
+ test_prompt.choose_option(1, repeating: 2)
2031
+
2032
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
2033
+ base_project.targets[0].build_configurations.each do |configuration|
2034
+ configuration.build_settings = nil
2035
+ end
2036
+ base_project.save
2037
+
2038
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
2039
+ theirs_project.targets[0].build_configurations.each do |configuration|
2040
+ configuration.build_settings = {"HEADER_SEARCH_PATHS" => "bar"}
2041
+ end
2042
+
2043
+ ours_project = create_copy_of_project(base_project.path, "ours")
2044
+ ours_project.targets[0].build_configurations.each do |configuration|
2045
+ configuration.build_settings = {"HEADER_SEARCH_PATHS" => "baz"}
2046
+ end
2047
+ ours_project.save
2048
+ expected_project = create_copy_of_project(ours_project.path, "expected")
2049
+
2050
+ changes_to_apply = get_diff(theirs_project, base_project)
2051
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
2052
+
2053
+ expect(ours_project).to be_equivalent_to_project(expected_project)
2054
+ end
2055
+ end
2056
+
2057
+ describe "trying to remove entry from a hash that has another value for the same key" do
2058
+ it "removes the key" do
2059
+ # There will be two conflicts, one for each configuration.
2060
+ test_prompt.choose_option(0, repeating: 2)
2061
+
2062
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
2063
+ base_project.targets[0].build_configurations.each do |configuration|
2064
+ configuration.build_settings = {"HEADER_SEARCH_PATHS" => "bar"}
2065
+ end
2066
+ base_project.save
2067
+
2068
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
2069
+ theirs_project.targets[0].build_configurations.each do |configuration|
2070
+ configuration.build_settings = nil
2071
+ end
2072
+
2073
+ ours_project = create_copy_of_project(base_project.path, "ours")
2074
+ ours_project.targets[0].build_configurations.each do |configuration|
2075
+ configuration.build_settings = {"HEADER_SEARCH_PATHS" => "baz"}
2076
+ end
2077
+
2078
+ changes_to_apply = get_diff(theirs_project, base_project)
2079
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
2080
+
2081
+ expected_project = create_copy_of_project(base_project.path, "expected")
2082
+ expected_project.targets[0].build_configurations.each do |configuration|
2083
+ configuration.build_settings = {}
2084
+ end
2085
+ expect(ours_project).to be_equivalent_to_project(expected_project)
2086
+ end
2087
+
2088
+ it "keeps the key" do
2089
+ # There will be two conflicts, one for each configuration.
2090
+ test_prompt.choose_option(1, repeating: 2)
2091
+
2092
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
2093
+ base_project.targets[0].build_configurations.each do |configuration|
2094
+ configuration.build_settings = {"HEADER_SEARCH_PATHS" => "bar"}
2095
+ end
2096
+ base_project.save
2097
+
2098
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
2099
+ theirs_project.targets[0].build_configurations.each do |configuration|
2100
+ configuration.build_settings = nil
2101
+ end
2102
+
2103
+ ours_project = create_copy_of_project(base_project.path, "ours")
2104
+ ours_project.targets[0].build_configurations.each do |configuration|
2105
+ configuration.build_settings = {"HEADER_SEARCH_PATHS" => "baz"}
2106
+ end
2107
+ ours_project.save
2108
+ expected_project = create_copy_of_project(ours_project.path, "expected")
2109
+
2110
+ changes_to_apply = get_diff(theirs_project, base_project)
2111
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
2112
+
2113
+ expect(ours_project).to be_equivalent_to_project(expected_project)
2114
+ end
2115
+ end
2116
+
2117
+ describe "trying to change string value that has another existing value" do
2118
+ it "replaces the string with the new value" do
2119
+ # There will be two conflicts, one for each configuration.
2120
+ test_prompt.choose_option(0, repeating: 2)
2121
+
2122
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
2123
+ base_project.targets[0].build_configurations.each do |configuration|
2124
+ configuration.build_settings["PRODUCT_NAME"] = "old"
2125
+ end
2126
+ base_project.save
2127
+
2128
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
2129
+ theirs_project.targets[0].build_configurations.each do |configuration|
2130
+ configuration.build_settings["PRODUCT_NAME"] = "new"
2131
+ end
2132
+
2133
+ ours_project = create_copy_of_project(base_project.path, "ours")
2134
+ ours_project.targets[0].build_configurations.each do |configuration|
2135
+ configuration.build_settings["PRODUCT_NAME"] = "existing"
2136
+ end
2137
+
2138
+ changes_to_apply = get_diff(theirs_project, base_project)
2139
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
2140
+
2141
+ expect(ours_project).to be_equivalent_to_project(theirs_project)
2142
+ end
2143
+
2144
+ it "keeps the existing value" do
2145
+ # There will be two conflicts, one for each configuration.
2146
+ test_prompt.choose_option(1, repeating: 2)
2147
+
2148
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
2149
+ base_project.targets[0].build_configurations.each do |configuration|
2150
+ configuration.build_settings["PRODUCT_NAME"] = "old"
2151
+ end
2152
+ base_project.save
2153
+
2154
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
2155
+ theirs_project.targets[0].build_configurations.each do |configuration|
2156
+ configuration.build_settings["PRODUCT_NAME"] = "new"
2157
+ end
2158
+
2159
+ ours_project = create_copy_of_project(base_project.path, "ours")
2160
+ ours_project.targets[0].build_configurations.each do |configuration|
2161
+ configuration.build_settings["PRODUCT_NAME"] = "existing"
2162
+ end
2163
+ ours_project.save
2164
+ expected_project = create_copy_of_project(ours_project.path, "expected")
2165
+
2166
+ changes_to_apply = get_diff(theirs_project, base_project)
2167
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
2168
+
2169
+ expect(ours_project).to be_equivalent_to_project(expected_project)
2170
+ end
2171
+ end
2172
+
2173
+ describe "trying to remove a component with different attributes" do
2174
+ it "removes the component anyway" do
2175
+ test_prompt.choose_option(0)
2176
+
2177
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
2178
+ base_project.targets[0].new_shell_script_build_phase("bar")
2179
+ base_project.save
2180
+
2181
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
2182
+ theirs_project.targets[0].shell_script_build_phases[0].remove_from_project
2183
+
2184
+ ours_project = create_copy_of_project(base_project.path, "ours")
2185
+ ours_project.targets[0].shell_script_build_phases[0].shell_script = "foo"
2186
+
2187
+ changes_to_apply = get_diff(theirs_project, base_project)
2188
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
2189
+
2190
+ expect(ours_project).to be_equivalent_to_project(theirs_project)
2191
+ end
2192
+
2193
+ it "keeps the component" do
2194
+ test_prompt.choose_option(1)
2195
+
2196
+ base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
2197
+ base_project.targets[0].new_shell_script_build_phase("bar")
2198
+ base_project.save
2199
+
2200
+ theirs_project = create_copy_of_project(base_project.path, "theirs")
2201
+ theirs_project.targets[0].shell_script_build_phases[0].remove_from_project
2202
+
2203
+ ours_project = create_copy_of_project(base_project.path, "ours")
2204
+ ours_project.targets[0].shell_script_build_phases[0].shell_script = "foo"
2205
+
2206
+ ours_project.save
2207
+ expected_project = create_copy_of_project(ours_project.path, "expected")
2208
+
2209
+ changes_to_apply = get_diff(theirs_project, base_project)
2210
+ described_class.apply_change_to_project(ours_project, changes_to_apply, theirs_project)
2211
+
2212
+ expect(ours_project).to be_equivalent_to_project(expected_project)
2213
+ end
2214
+ end
2215
+ end
2216
+
1656
2217
  def create_copy_of_project(project_path, new_project_prefix)
1657
2218
  copied_project_path = make_temp_directory(new_project_prefix, ".xcodeproj")
1658
2219
  FileUtils.cp(File.join(project_path, "project.pbxproj"), copied_project_path)
@@ -1743,3 +2304,20 @@ describe Kintsugi, :apply_change_to_project do
1743
2304
  directory_path
1744
2305
  end
1745
2306
  end
2307
+
2308
+ module TTY
2309
+ class Prompt
2310
+ class Test
2311
+ def choose_option(index, repeating: 1)
2312
+ input << "#{"j" * index}\n" * repeating
2313
+ input.rewind
2314
+ end
2315
+
2316
+ def setup
2317
+ on(:keypress) do |event|
2318
+ trigger(:keydown) if event.value == "j"
2319
+ end
2320
+ end
2321
+ end
2322
+ end
2323
+ end