kintsugi 0.4.3 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +33 -0
- data/.github/workflows/{ci.yml → tests.yml} +2 -1
- data/.rubocop.yml +3 -0
- data/bin/kintsugi +3 -29
- data/kintsugi.gemspec +1 -0
- data/lib/kintsugi/apply_change_to_project.rb +264 -132
- data/lib/kintsugi/cli.rb +2 -1
- data/lib/kintsugi/merge.rb +146 -0
- data/lib/kintsugi/version.rb +1 -1
- data/lib/kintsugi/xcodeproj_extensions.rb +122 -0
- data/lib/kintsugi.rb +29 -148
- data/spec/kintsugi_apply_change_to_project_spec.rb +549 -52
- data/spec/kintsugi_integration_spec.rb +148 -0
- data/spec/spec_helper.rb +3 -0
- metadata +22 -5
@@ -8,6 +8,7 @@ require "tempfile"
|
|
8
8
|
require "tmpdir"
|
9
9
|
|
10
10
|
require "kintsugi/apply_change_to_project"
|
11
|
+
require "kintsugi/error"
|
11
12
|
|
12
13
|
require_relative "be_equivalent_to_project"
|
13
14
|
|
@@ -50,6 +51,20 @@ describe Kintsugi, :apply_change_to_project do
|
|
50
51
|
expect(base_project).to be_equivalent_to_project(theirs_project)
|
51
52
|
end
|
52
53
|
|
54
|
+
it "adds package reference" do
|
55
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
56
|
+
|
57
|
+
theirs_project.root_object.package_references <<
|
58
|
+
create_remote_swift_package_reference(theirs_project)
|
59
|
+
|
60
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
61
|
+
|
62
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
63
|
+
base_project.save
|
64
|
+
|
65
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
66
|
+
end
|
67
|
+
|
53
68
|
it "adds new subproject" do
|
54
69
|
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
55
70
|
add_new_subproject_to_project(theirs_project, "foo", "foo")
|
@@ -100,6 +115,23 @@ describe Kintsugi, :apply_change_to_project do
|
|
100
115
|
expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
|
101
116
|
end
|
102
117
|
|
118
|
+
it "raises if adding subproject whose file reference isn't found" do
|
119
|
+
ours_project = create_copy_of_project(base_project.path, "ours")
|
120
|
+
|
121
|
+
add_new_subproject_to_project(base_project, "foo", "foo")
|
122
|
+
base_project.save
|
123
|
+
|
124
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
125
|
+
|
126
|
+
base_project.root_object.project_references.pop
|
127
|
+
|
128
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
129
|
+
|
130
|
+
expect {
|
131
|
+
described_class.apply_change_to_project(ours_project, changes_to_apply)
|
132
|
+
}.to raise_error(Kintsugi::MergeError)
|
133
|
+
end
|
134
|
+
|
103
135
|
describe "file related changes" do
|
104
136
|
let(:filepath) { "foo" }
|
105
137
|
|
@@ -370,6 +402,19 @@ describe Kintsugi, :apply_change_to_project do
|
|
370
402
|
expect(base_project).to be_equivalent_to_project(theirs_project)
|
371
403
|
end
|
372
404
|
|
405
|
+
it "adds package product dependency to target" do
|
406
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
407
|
+
theirs_project.targets[0].package_product_dependencies <<
|
408
|
+
create_swift_package_product_dependency(theirs_project)
|
409
|
+
|
410
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
411
|
+
|
412
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
413
|
+
base_project.save
|
414
|
+
|
415
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
416
|
+
end
|
417
|
+
|
373
418
|
it "changes framework from reference proxy to file reference" do
|
374
419
|
framework_filename = "baz"
|
375
420
|
|
@@ -382,7 +427,8 @@ describe Kintsugi, :apply_change_to_project do
|
|
382
427
|
|
383
428
|
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
384
429
|
|
385
|
-
file_reference = theirs_project.main_group.new_reference(
|
430
|
+
file_reference = theirs_project.main_group.new_reference("bar")
|
431
|
+
file_reference.name = framework_filename
|
386
432
|
build_phase = theirs_project.targets[0].frameworks_build_phase
|
387
433
|
build_phase.files[-1].remove_from_project
|
388
434
|
theirs_project.targets[0].frameworks_build_phase.add_file_reference(file_reference)
|
@@ -390,6 +436,10 @@ describe Kintsugi, :apply_change_to_project do
|
|
390
436
|
changes_to_apply = get_diff(theirs_project, base_project)
|
391
437
|
|
392
438
|
described_class.apply_change_to_project(base_project, changes_to_apply)
|
439
|
+
# This verifies we haven't created a new file reference instead of reusing the one in the
|
440
|
+
# hierarchy.
|
441
|
+
base_project.files[-1].name = "foo"
|
442
|
+
theirs_project.files[-1].name = "foo"
|
393
443
|
base_project.save
|
394
444
|
|
395
445
|
expect(base_project).to be_equivalent_to_project(theirs_project)
|
@@ -466,9 +516,28 @@ describe Kintsugi, :apply_change_to_project do
|
|
466
516
|
expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
|
467
517
|
end
|
468
518
|
|
469
|
-
it "adds
|
470
|
-
|
471
|
-
base_project.
|
519
|
+
it "adds product ref to build file" do
|
520
|
+
base_project.main_group.new_reference("bar")
|
521
|
+
base_project.save
|
522
|
+
|
523
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
524
|
+
|
525
|
+
file_reference = theirs_project.main_group.files.find { |file| file.display_name == "bar" }
|
526
|
+
build_file =
|
527
|
+
theirs_project.targets[0].frameworks_build_phase.add_file_reference(file_reference)
|
528
|
+
build_file.product_ref =
|
529
|
+
create_swift_package_product_dependency(theirs_project)
|
530
|
+
|
531
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
532
|
+
|
533
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
534
|
+
base_project.save
|
535
|
+
|
536
|
+
expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
|
537
|
+
end
|
538
|
+
|
539
|
+
it "adds build file to a file reference that already exists" do
|
540
|
+
base_project.main_group.new_reference("bar")
|
472
541
|
|
473
542
|
base_project.main_group.new_reference("bar")
|
474
543
|
|
@@ -557,69 +626,427 @@ describe Kintsugi, :apply_change_to_project do
|
|
557
626
|
expect(base_project).to be_equivalent_to_project(theirs_project, ignore_keys: ["containerPortal"])
|
558
627
|
end
|
559
628
|
|
560
|
-
|
561
|
-
|
629
|
+
describe "build settings" do
|
630
|
+
it "adds new string build setting" do
|
631
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
562
632
|
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
633
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
634
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "$(SRCROOT)/../Bar"
|
635
|
+
end
|
636
|
+
|
637
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
638
|
+
|
639
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
640
|
+
base_project.save
|
641
|
+
|
642
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
568
643
|
end
|
569
644
|
|
570
|
-
|
645
|
+
it "adds new array build setting" do
|
646
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
647
|
+
configuration.build_settings = {}
|
648
|
+
end
|
571
649
|
|
572
|
-
|
573
|
-
base_project.save
|
650
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
574
651
|
|
575
|
-
|
576
|
-
|
652
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
653
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = [
|
654
|
+
"$(SRCROOT)/../Foo",
|
655
|
+
"$(SRCROOT)/../Bar"
|
656
|
+
]
|
657
|
+
end
|
577
658
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
659
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
660
|
+
|
661
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
662
|
+
base_project.save
|
663
|
+
|
664
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
583
665
|
end
|
584
666
|
|
585
|
-
|
667
|
+
it "adds new hash build setting" do
|
668
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
586
669
|
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
670
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
671
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = [
|
672
|
+
"$(SRCROOT)/../Foo",
|
673
|
+
"$(SRCROOT)/../Bar"
|
674
|
+
]
|
675
|
+
end
|
676
|
+
|
677
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
678
|
+
|
679
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
680
|
+
base_project.save
|
681
|
+
|
682
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
592
683
|
end
|
593
684
|
|
594
|
-
|
685
|
+
it "adds values to existing array build setting" do
|
686
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
687
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = [
|
688
|
+
"$(SRCROOT)/../Foo"
|
689
|
+
]
|
690
|
+
end
|
595
691
|
|
596
|
-
|
597
|
-
base_project.save
|
692
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
598
693
|
|
599
|
-
|
600
|
-
|
694
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
695
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = [
|
696
|
+
"$(SRCROOT)/../Foo",
|
697
|
+
"$(SRCROOT)/../Bar"
|
698
|
+
]
|
699
|
+
end
|
601
700
|
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
701
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
702
|
+
|
703
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
704
|
+
base_project.save
|
705
|
+
|
706
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
608
707
|
end
|
609
708
|
|
610
|
-
|
611
|
-
|
709
|
+
it "adds array value to an existing string if no removed value" do
|
710
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
612
711
|
|
613
|
-
|
614
|
-
|
712
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
713
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[bar foo]
|
714
|
+
end
|
715
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
716
|
+
|
717
|
+
ours_project = create_copy_of_project(base_project.path, "ours")
|
718
|
+
ours_project.targets[0].build_configurations.each do |configuration|
|
719
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "baz"
|
720
|
+
end
|
721
|
+
ours_project.save
|
722
|
+
|
723
|
+
described_class.apply_change_to_project(ours_project, changes_to_apply)
|
724
|
+
ours_project.save
|
725
|
+
|
726
|
+
expected_project = create_copy_of_project(base_project.path, "expected")
|
727
|
+
expected_project.targets[0].build_configurations.each do |configuration|
|
728
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[bar foo baz]
|
729
|
+
end
|
730
|
+
expect(ours_project).to be_equivalent_to_project(expected_project)
|
615
731
|
end
|
616
732
|
|
617
|
-
|
733
|
+
it "adds string value to existing array value if no removed value" do
|
734
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
618
735
|
|
619
|
-
|
620
|
-
|
736
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
737
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "baz"
|
738
|
+
end
|
739
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
621
740
|
|
622
|
-
|
741
|
+
ours_project = create_copy_of_project(base_project.path, "ours")
|
742
|
+
ours_project.targets[0].build_configurations.each do |configuration|
|
743
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[bar foo]
|
744
|
+
end
|
745
|
+
ours_project.save
|
746
|
+
|
747
|
+
described_class.apply_change_to_project(ours_project, changes_to_apply)
|
748
|
+
ours_project.save
|
749
|
+
|
750
|
+
expected_project = create_copy_of_project(base_project.path, "expected")
|
751
|
+
expected_project.targets[0].build_configurations.each do |configuration|
|
752
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[bar foo baz]
|
753
|
+
end
|
754
|
+
expect(ours_project).to be_equivalent_to_project(expected_project)
|
755
|
+
end
|
756
|
+
|
757
|
+
it "removes array build setting" do
|
758
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
759
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = [
|
760
|
+
"$(SRCROOT)/../Foo",
|
761
|
+
"$(SRCROOT)/../Bar"
|
762
|
+
]
|
763
|
+
end
|
764
|
+
|
765
|
+
base_project.save
|
766
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
767
|
+
|
768
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
769
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = nil
|
770
|
+
end
|
771
|
+
|
772
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
773
|
+
|
774
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
775
|
+
base_project.save
|
776
|
+
|
777
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
778
|
+
end
|
779
|
+
|
780
|
+
it "removes string build setting" do
|
781
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
782
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
783
|
+
end
|
784
|
+
|
785
|
+
base_project.save
|
786
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
787
|
+
|
788
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
789
|
+
configuration.build_settings =
|
790
|
+
configuration.build_settings.reject { |key, _| key == "HEADER_SEARCH_PATHS" }
|
791
|
+
end
|
792
|
+
|
793
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
794
|
+
|
795
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
796
|
+
base_project.save
|
797
|
+
|
798
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
799
|
+
end
|
800
|
+
|
801
|
+
it "removes hash build setting" do
|
802
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
803
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
804
|
+
end
|
805
|
+
|
806
|
+
base_project.save
|
807
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
808
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
809
|
+
configuration.build_settings = nil
|
810
|
+
end
|
811
|
+
|
812
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
813
|
+
|
814
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
815
|
+
base_project.save
|
816
|
+
|
817
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
818
|
+
end
|
819
|
+
|
820
|
+
it "removes hash build setting if removed hash contains the existing hash" do
|
821
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
822
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
823
|
+
configuration.build_settings["foo"] = "baz"
|
824
|
+
end
|
825
|
+
|
826
|
+
base_project.save
|
827
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
828
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
829
|
+
configuration.build_settings = nil
|
830
|
+
end
|
831
|
+
|
832
|
+
ours_project = create_copy_of_project(base_project.path, "theirs")
|
833
|
+
ours_project.targets[0].build_configurations.each do |configuration|
|
834
|
+
configuration.build_settings["foo"] = nil
|
835
|
+
end
|
836
|
+
|
837
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
838
|
+
|
839
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
840
|
+
base_project.save
|
841
|
+
|
842
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
843
|
+
end
|
844
|
+
|
845
|
+
it "removes value if existing is string and removed is array that contains it" do
|
846
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
847
|
+
|
848
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
849
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
850
|
+
end
|
851
|
+
base_project.save
|
852
|
+
|
853
|
+
before_theirs_project = create_copy_of_project(base_project.path, "before_theirs")
|
854
|
+
before_theirs_project.targets[0].build_configurations.each do |configuration|
|
855
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = ["bar"]
|
856
|
+
end
|
857
|
+
|
858
|
+
changes_to_apply = get_diff(theirs_project, before_theirs_project)
|
859
|
+
|
860
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
861
|
+
base_project.save
|
862
|
+
|
863
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
864
|
+
end
|
865
|
+
|
866
|
+
it "removes value if removed value is string and existing is array that contains it" do
|
867
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
868
|
+
|
869
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
870
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = ["bar"]
|
871
|
+
end
|
872
|
+
base_project.save
|
873
|
+
|
874
|
+
before_theirs_project = create_copy_of_project(base_project.path, "before_theirs")
|
875
|
+
before_theirs_project.targets[0].build_configurations.each do |configuration|
|
876
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
877
|
+
end
|
878
|
+
|
879
|
+
changes_to_apply = get_diff(theirs_project, before_theirs_project)
|
880
|
+
|
881
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
882
|
+
base_project.save
|
883
|
+
|
884
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
885
|
+
end
|
886
|
+
|
887
|
+
it "removes value if existing is string and removed is array that contains it among other " \
|
888
|
+
"values" do
|
889
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
890
|
+
|
891
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
892
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
893
|
+
end
|
894
|
+
base_project.save
|
895
|
+
|
896
|
+
before_theirs_project = create_copy_of_project(base_project.path, "before_theirs")
|
897
|
+
before_theirs_project.targets[0].build_configurations.each do |configuration|
|
898
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[bar baz]
|
899
|
+
end
|
900
|
+
|
901
|
+
changes_to_apply = get_diff(theirs_project, before_theirs_project)
|
902
|
+
|
903
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
904
|
+
base_project.save
|
905
|
+
|
906
|
+
expected_project = create_copy_of_project(base_project.path, "expected")
|
907
|
+
expected_project.targets[0].build_configurations.each do |configuration|
|
908
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = nil
|
909
|
+
end
|
910
|
+
expect(base_project).to be_equivalent_to_project(expected_project)
|
911
|
+
end
|
912
|
+
|
913
|
+
it "changes to a single string value if removed is string and existing is array that " \
|
914
|
+
"contains it among another value" do
|
915
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
916
|
+
|
917
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
918
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[bar baz]
|
919
|
+
end
|
920
|
+
base_project.save
|
921
|
+
|
922
|
+
before_theirs_project = create_copy_of_project(base_project.path, "before_theirs")
|
923
|
+
before_theirs_project.targets[0].build_configurations.each do |configuration|
|
924
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
925
|
+
end
|
926
|
+
|
927
|
+
changes_to_apply = get_diff(theirs_project, before_theirs_project)
|
928
|
+
|
929
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
930
|
+
base_project.save
|
931
|
+
|
932
|
+
expected_project = create_copy_of_project(base_project.path, "expected")
|
933
|
+
expected_project.targets[0].build_configurations.each do |configuration|
|
934
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "baz"
|
935
|
+
end
|
936
|
+
expect(base_project).to be_equivalent_to_project(expected_project)
|
937
|
+
end
|
938
|
+
|
939
|
+
it "changes to string value if change contains removal of existing array" do
|
940
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
941
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[bar foo]
|
942
|
+
end
|
943
|
+
|
944
|
+
base_project.save
|
945
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
946
|
+
|
947
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
948
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "baz"
|
949
|
+
end
|
950
|
+
|
951
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
952
|
+
|
953
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
954
|
+
base_project.save
|
955
|
+
|
956
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
957
|
+
end
|
958
|
+
|
959
|
+
it "changes to array value if change contains removal of existing string" do
|
960
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
961
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
962
|
+
end
|
963
|
+
|
964
|
+
base_project.save
|
965
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
966
|
+
|
967
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
968
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[baz foo]
|
969
|
+
end
|
970
|
+
|
971
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
972
|
+
|
973
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
974
|
+
base_project.save
|
975
|
+
|
976
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
977
|
+
end
|
978
|
+
|
979
|
+
it "changes to array if added value is string and existing is another string and removal is" \
|
980
|
+
"nil for an array build setting" do
|
981
|
+
before_theirs_project = create_copy_of_project(base_project.path, "theirs")
|
982
|
+
|
983
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
984
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
985
|
+
end
|
986
|
+
base_project.save
|
987
|
+
|
988
|
+
theirs_project = create_copy_of_project(base_project.path, "before_theirs")
|
989
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
990
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "baz"
|
991
|
+
end
|
992
|
+
|
993
|
+
expected_project = create_copy_of_project(base_project.path, "expected")
|
994
|
+
expected_project.targets[0].build_configurations.each do |configuration|
|
995
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = %w[bar baz]
|
996
|
+
end
|
997
|
+
|
998
|
+
changes_to_apply = get_diff(theirs_project, before_theirs_project)
|
999
|
+
|
1000
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
1001
|
+
base_project.save
|
1002
|
+
|
1003
|
+
expect(base_project).to be_equivalent_to_project(expected_project)
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
it "raises if added value is string and existing is another string and removal is nil for a " \
|
1007
|
+
"string build setting" do
|
1008
|
+
before_theirs_project = create_copy_of_project(base_project.path, "theirs")
|
1009
|
+
|
1010
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
1011
|
+
configuration.build_settings["PRODUCT_NAME"] = "bar"
|
1012
|
+
end
|
1013
|
+
base_project.save
|
1014
|
+
|
1015
|
+
theirs_project = create_copy_of_project(base_project.path, "before_theirs")
|
1016
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
1017
|
+
configuration.build_settings["PRODUCT_NAME"] = "baz"
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
changes_to_apply = get_diff(theirs_project, before_theirs_project)
|
1021
|
+
|
1022
|
+
expect {
|
1023
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
1024
|
+
}.to raise_error(Kintsugi::MergeError)
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
it "raises if trying to remove hash entry whose value changed" do
|
1028
|
+
base_project.targets[0].build_configurations.each do |configuration|
|
1029
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "bar"
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
base_project.save
|
1033
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
1034
|
+
theirs_project.targets[0].build_configurations.each do |configuration|
|
1035
|
+
configuration.build_settings = nil
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
base_project.save
|
1039
|
+
before_theirs_project = create_copy_of_project(base_project.path, "theirs")
|
1040
|
+
before_theirs_project.targets[0].build_configurations.each do |configuration|
|
1041
|
+
configuration.build_settings["HEADER_SEARCH_PATHS"] = "baz"
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
changes_to_apply = get_diff(theirs_project, before_theirs_project)
|
1045
|
+
|
1046
|
+
expect {
|
1047
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
1048
|
+
}.to raise_error(Kintsugi::MergeError)
|
1049
|
+
end
|
623
1050
|
end
|
624
1051
|
|
625
1052
|
it "adds build phases" do
|
@@ -640,6 +1067,20 @@ describe Kintsugi, :apply_change_to_project do
|
|
640
1067
|
expect(base_project).to be_equivalent_to_project(theirs_project)
|
641
1068
|
end
|
642
1069
|
|
1070
|
+
it "adds build phase with a simple attribute value that has non nil default" do
|
1071
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
1072
|
+
|
1073
|
+
theirs_project.targets[0].new_shell_script_build_phase("bar")
|
1074
|
+
theirs_project.targets[0].build_phases.last.shell_script = "Other value"
|
1075
|
+
|
1076
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
1077
|
+
|
1078
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
1079
|
+
base_project.save
|
1080
|
+
|
1081
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
1082
|
+
end
|
1083
|
+
|
643
1084
|
it "removes build phase" do
|
644
1085
|
base_project.targets[0].new_shell_script_build_phase("bar")
|
645
1086
|
|
@@ -752,7 +1193,7 @@ describe Kintsugi, :apply_change_to_project do
|
|
752
1193
|
base_project.save
|
753
1194
|
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
754
1195
|
|
755
|
-
theirs_project.root_object.known_regions += ["
|
1196
|
+
theirs_project.root_object.known_regions += ["fr"]
|
756
1197
|
|
757
1198
|
changes_to_apply = get_diff(theirs_project, base_project)
|
758
1199
|
|
@@ -763,12 +1204,9 @@ describe Kintsugi, :apply_change_to_project do
|
|
763
1204
|
end
|
764
1205
|
|
765
1206
|
it "removes known regions" do
|
766
|
-
base_project.root_object.known_regions += ["en"]
|
767
|
-
|
768
|
-
base_project.save
|
769
1207
|
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
770
1208
|
|
771
|
-
theirs_project.root_object.known_regions =
|
1209
|
+
theirs_project.root_object.known_regions = nil
|
772
1210
|
|
773
1211
|
changes_to_apply = get_diff(theirs_project, base_project)
|
774
1212
|
|
@@ -927,6 +1365,41 @@ describe Kintsugi, :apply_change_to_project do
|
|
927
1365
|
expect(base_project).to be_equivalent_to_project(theirs_project)
|
928
1366
|
end
|
929
1367
|
|
1368
|
+
it "adds group to product group" do
|
1369
|
+
base_project_path = make_temp_directory("base", ".xcodeproj")
|
1370
|
+
base_project = Xcodeproj::Project.new(base_project_path)
|
1371
|
+
base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
|
1372
|
+
|
1373
|
+
base_project.save
|
1374
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
1375
|
+
|
1376
|
+
theirs_project.root_object.product_ref_group.new_group("foo")
|
1377
|
+
|
1378
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
1379
|
+
|
1380
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
1381
|
+
|
1382
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
it "adds localization files to product group" do
|
1386
|
+
base_project_path = make_temp_directory("base", ".xcodeproj")
|
1387
|
+
base_project = Xcodeproj::Project.new(base_project_path)
|
1388
|
+
base_project.new_target("com.apple.product-type.library.static", "foo", :ios)
|
1389
|
+
|
1390
|
+
base_project.save
|
1391
|
+
theirs_project = create_copy_of_project(base_project.path, "theirs")
|
1392
|
+
|
1393
|
+
variant_group = theirs_project.root_object.product_ref_group.new_variant_group("foo.strings")
|
1394
|
+
variant_group.new_reference("Base").last_known_file_type = "text.plist.strings"
|
1395
|
+
|
1396
|
+
changes_to_apply = get_diff(theirs_project, base_project)
|
1397
|
+
|
1398
|
+
described_class.apply_change_to_project(base_project, changes_to_apply)
|
1399
|
+
|
1400
|
+
expect(base_project).to be_equivalent_to_project(theirs_project)
|
1401
|
+
end
|
1402
|
+
|
930
1403
|
def create_copy_of_project(project_path, new_project_prefix)
|
931
1404
|
copied_project_path = make_temp_directory(new_project_prefix, ".xcodeproj")
|
932
1405
|
FileUtils.cp(File.join(project_path, "project.pbxproj"), copied_project_path)
|
@@ -934,7 +1407,15 @@ describe Kintsugi, :apply_change_to_project do
|
|
934
1407
|
end
|
935
1408
|
|
936
1409
|
def get_diff(first_project, second_project)
|
937
|
-
Xcodeproj::Differ.project_diff(first_project, second_project, :added, :removed)
|
1410
|
+
diff = Xcodeproj::Differ.project_diff(first_project, second_project, :added, :removed)
|
1411
|
+
|
1412
|
+
diff_without_display_name =
|
1413
|
+
diff.merge("rootObject" => diff["rootObject"].reject { |key, _| key == "displayName" })
|
1414
|
+
if diff_without_display_name == {"rootObject" => {}}
|
1415
|
+
raise "Diff contains no changes. This probably means the test doesn't check anything."
|
1416
|
+
end
|
1417
|
+
|
1418
|
+
diff
|
938
1419
|
end
|
939
1420
|
|
940
1421
|
def add_new_subproject_to_project(project, subproject_name, subproject_product_name)
|
@@ -987,6 +1468,22 @@ describe Kintsugi, :apply_change_to_project do
|
|
987
1468
|
reference_proxy
|
988
1469
|
end
|
989
1470
|
|
1471
|
+
def create_swift_package_product_dependency(project)
|
1472
|
+
product_dependency = project.new(Xcodeproj::Project::XCSwiftPackageProductDependency)
|
1473
|
+
product_dependency.product_name = "foo"
|
1474
|
+
product_dependency.package = create_remote_swift_package_reference(project)
|
1475
|
+
|
1476
|
+
product_dependency
|
1477
|
+
end
|
1478
|
+
|
1479
|
+
def create_remote_swift_package_reference(project)
|
1480
|
+
package_reference = project.new(Xcodeproj::Project::XCRemoteSwiftPackageReference)
|
1481
|
+
package_reference.repositoryURL = "http://foo"
|
1482
|
+
package_reference.requirement = {"foo" => "bar"}
|
1483
|
+
|
1484
|
+
package_reference
|
1485
|
+
end
|
1486
|
+
|
990
1487
|
def make_temp_directory(directory_prefix, directory_extension)
|
991
1488
|
directory_path = Dir.mktmpdir([directory_prefix, directory_extension])
|
992
1489
|
temporary_directories_paths << directory_path
|