kintsugi 0.5.0 → 0.5.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46711f40795142678185287c0035cb3ad3ebe304b418cf8add570c0e4f6db997
4
- data.tar.gz: b2c6fd04f472dca7ca3ca436140b0256264a221228a8ae2c086ff3cef9ac9dc4
3
+ metadata.gz: 563ca542b9548a7627fbed93666f74046bb2d58d172c8d8669e9450935391804
4
+ data.tar.gz: '0049c73e560aefe9d627ac32cb2834914611ad9f7944ba6cd99f9b07744d5b9b'
5
5
  SHA512:
6
- metadata.gz: 8b9a65bbd0796ce8e2f0da7fb50f772e753d03875fd79f5cc0816cd3197e049bc656cc14c2f521ab6c1a63b77b34290137d1b103dc5b51bc3e5b5daadac20b7f
7
- data.tar.gz: 143a7a9d17799dde48c845570084ec94b7ea00ee482cd6f50773055c71efdca5e8e82360130d43f64989a5a4c5d945b7b938d2458e91b3d745c6e4700932863f
6
+ metadata.gz: 420b46d20c19b8ed5596d1034a4791a054820e1ad550c28bf6cd18bbc92334b1f969f65b9b9384b1d824430d11f41cb48e9cabc09a2bb5aea0cb85f68d6d3fca
7
+ data.tar.gz: dc09f81c4d329a6e2ba93624a7caf2e54bc38a29752076ba56bb347d12fcb7ad49537c50d6ea42af17d92d55e46250582da71f1b8b946537f3193e0b1b58faba
@@ -0,0 +1,33 @@
1
+ name: Release
2
+
3
+ on: workflow_dispatch
4
+
5
+ jobs:
6
+ main-job:
7
+ name: Release
8
+ runs-on: ubuntu-latest
9
+ env:
10
+ GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}
11
+
12
+ steps:
13
+ - name: Checkout repo
14
+ uses: actions/checkout@v2
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: 2.5.8
20
+ rubygems: latest
21
+
22
+ - name: Draft a new release
23
+ run: |
24
+ echo ${{ secrets.GITHUB_TOKEN }} | gh auth login --with-token
25
+ version="v$(grep STRING lib/kintsugi/version.rb | cut -d \" -f 2)"
26
+ git tag $version
27
+ git push --tag
28
+ gh release create $version --generate-notes
29
+
30
+ - name: Publish to rubygems.org
31
+ run: |
32
+ gem build *.gemspec
33
+ gem push *.gem
@@ -1,4 +1,4 @@
1
- name: CI
1
+ name: Tests
2
2
 
3
3
  on:
4
4
  push:
@@ -19,6 +19,7 @@ jobs:
19
19
  uses: ruby/setup-ruby@v1
20
20
  with:
21
21
  ruby-version: 2.5.8
22
+ rubygems: latest
22
23
  bundler-cache: true
23
24
 
24
25
  - name: Run Rake
data/.rubocop.yml CHANGED
@@ -12,6 +12,9 @@ RSpec/MultipleExpectations:
12
12
  AllCops:
13
13
  DisplayCopNames: true
14
14
  TargetRubyVersion: 2.5
15
+ Exclude:
16
+ - 'lib/**/xcodeproj_extensions.rb'
17
+ - 'vendor/bundle/**/*'
15
18
  NewCops: enable
16
19
 
17
20
  Metrics/BlockLength:
data/Gemfile CHANGED
@@ -2,8 +2,3 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
  gemspec
5
-
6
- gem "ruby-debug-ide", "0.7.2"
7
- gem "debase", "0.2.5.beta2"
8
-
9
- gem "pry", "~> 0.14.1"
data/bin/kintsugi CHANGED
@@ -5,37 +5,9 @@
5
5
  # Created by Ben Yohay.
6
6
 
7
7
  require "kintsugi"
8
- require_relative "../lib/kintsugi/cli"
9
- require_relative "../lib/kintsugi/error"
10
-
11
- def parse_options!(command, argv)
12
- options = {}
13
- command.option_parser.parse!(argv, into: options)
14
- options
15
- end
16
-
17
- def name_of_subcommand?(subcommands, argument)
18
- subcommands.include?(argument)
19
- end
20
-
21
- first_argument = ARGV[0]
22
- cli = Kintsugi::CLI.new
23
- command =
24
- if name_of_subcommand?(cli.subcommands, first_argument)
25
- ARGV.shift
26
- cli.subcommands[first_argument]
27
- else
28
- cli.root_command
29
- end
30
-
31
- options = parse_options!(command, ARGV)
32
8
 
33
9
  begin
34
- command.action.call(options, ARGV)
35
- rescue ArgumentError => e
36
- puts "#{e.class}: #{e}"
37
- exit(1)
38
- rescue Kintsugi::MergeError => e
39
- puts e
10
+ Kintsugi.run(ARGV)
11
+ rescue ArgumentError, Kintsugi::MergeError
40
12
  exit(1)
41
13
  end
data/kintsugi.gemspec CHANGED
@@ -22,8 +22,9 @@ Gem::Specification.new do |spec|
22
22
  spec.test_files = spec.files.grep(%r{^(spec)/})
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- spec.add_dependency "xcodeproj", ">= 1.19.0", "<= 1.21.0"
25
+ spec.add_dependency "xcodeproj", ">= 1.19.0", "<= 1.22.0"
26
26
 
27
+ spec.add_development_dependency "git", "~> 1.11"
27
28
  spec.add_development_dependency "rake", "~> 13.0"
28
29
  spec.add_development_dependency "rspec", "~> 3.9"
29
30
  spec.add_development_dependency "rubocop", "1.12.0"
@@ -29,26 +29,28 @@ module Kintsugi
29
29
  puts "Warning: Main group doesn't exist, ignoring changes to it."
30
30
  else
31
31
  apply_change_to_component(project.root_object, "mainGroup",
32
- change["rootObject"]["mainGroup"])
32
+ change["rootObject"]["mainGroup"], "rootObject")
33
33
  end
34
34
  end
35
35
 
36
36
  unless change["rootObject"]["projectReferences"].nil?
37
37
  apply_change_to_component(project.root_object, "projectReferences",
38
- change["rootObject"]["projectReferences"])
38
+ change["rootObject"]["projectReferences"], "rootObject")
39
39
  end
40
40
 
41
41
  apply_change_to_component(project, "rootObject",
42
42
  change["rootObject"].reject { |key|
43
43
  %w[mainGroup projectReferences].include?(key)
44
- })
44
+ }, "")
45
45
  end
46
46
 
47
47
  private
48
48
 
49
- def apply_change_to_component(parent_component, change_name, change)
49
+ def apply_change_to_component(parent_component, change_name, change, parent_change_path)
50
50
  return if change_name == "displayName"
51
51
 
52
+ change_path = parent_change_path.empty? ? change_name : "#{parent_change_path}/#{change_name}"
53
+
52
54
  attribute_name = attribute_name_from_change_name(change_name)
53
55
  if simple_attribute?(parent_component, attribute_name)
54
56
  apply_change_to_simple_attribute(parent_component, attribute_name, change)
@@ -62,7 +64,7 @@ module Kintsugi
62
64
  component = child_component(parent_component, change_name)
63
65
 
64
66
  if component.nil?
65
- add_missing_component_if_valid(parent_component, change_name, change)
67
+ add_missing_component_if_valid(parent_component, change_name, change, change_path)
66
68
  return
67
69
  end
68
70
  end
@@ -76,11 +78,12 @@ module Kintsugi
76
78
 
77
79
  (change[:added] || []).each do |added_change|
78
80
  is_object_list = component.is_a?(Xcodeproj::Project::ObjectList)
79
- add_child_to_component(is_object_list ? parent_component : component, added_change)
81
+ add_child_to_component(is_object_list ? parent_component : component, added_change,
82
+ change_path)
80
83
  end
81
84
 
82
85
  subchanges_of_change(change).each do |subchange_name, subchange|
83
- apply_change_to_component(component, subchange_name, subchange)
86
+ apply_change_to_component(component, subchange_name, subchange, change_path)
84
87
  end
85
88
  end
86
89
 
@@ -100,9 +103,9 @@ module Kintsugi
100
103
  end
101
104
  end
102
105
 
103
- def add_missing_component_if_valid(parent_component, change_name, change)
106
+ def add_missing_component_if_valid(parent_component, change_name, change, change_path)
104
107
  if change[:added] && change.compact.count == 1
105
- add_child_to_component(parent_component, change[:added])
108
+ add_child_to_component(parent_component, change[:added], change_path)
106
109
  return
107
110
  end
108
111
 
@@ -112,10 +115,7 @@ module Kintsugi
112
115
 
113
116
  def replace_component_with_new_type(parent_component, name_in_parent_component, change)
114
117
  old_component = parent_component.send(name_in_parent_component)
115
-
116
- new_component = parent_component.project.new(
117
- Module.const_get("Xcodeproj::Project::#{change["isa"][:added]}")
118
- )
118
+ new_component = component_of_new_type(parent_component, change, old_component)
119
119
 
120
120
  copy_attributes_to_new_component(old_component, new_component)
121
121
 
@@ -123,6 +123,27 @@ module Kintsugi
123
123
  new_component
124
124
  end
125
125
 
126
+ def component_of_new_type(parent_component, change, old_component)
127
+ if change["isa"][:added] == "PBXFileReference"
128
+ path = (change["path"] && change["path"][:added]) || old_component.path
129
+ case parent_component
130
+ when Xcodeproj::Project::XCBuildConfiguration
131
+ parent_component.base_configuration_reference = find_file(parent_component.project, path)
132
+ return parent_component.base_configuration_reference
133
+ when Xcodeproj::Project::PBXNativeTarget
134
+ parent_component.product_reference = find_file(parent_component.project, path)
135
+ return parent_component.product_reference
136
+ when Xcodeproj::Project::PBXBuildFile
137
+ parent_component.file_ref = find_file(parent_component.project, path)
138
+ return parent_component.file_ref
139
+ end
140
+ end
141
+
142
+ parent_component.project.new(
143
+ Module.const_get("Xcodeproj::Project::#{change["isa"][:added]}")
144
+ )
145
+ end
146
+
126
147
  def copy_attributes_to_new_component(old_component, new_component)
127
148
  # The change won't describe the attributes that haven't changed, therefore the attributes
128
149
  # are copied to the new component.
@@ -298,63 +319,65 @@ module Kintsugi
298
319
  end
299
320
  end
300
321
 
301
- def add_child_to_component(component, change)
322
+ def add_child_to_component(component, change, component_change_path)
323
+ change_path = "#{component_change_path}/#{change["displayName"]}"
324
+
302
325
  if change["ProjectRef"] && change["ProductGroup"]
303
- add_subproject_reference(component, change)
326
+ add_subproject_reference(component, change, change_path)
304
327
  return
305
328
  end
306
329
 
307
330
  case change["isa"]
308
331
  when "PBXNativeTarget"
309
- add_target(component, change)
332
+ add_target(component, change, change_path)
310
333
  when "PBXAggregateTarget"
311
- add_aggregate_target(component, change)
334
+ add_aggregate_target(component, change, change_path)
312
335
  when "PBXFileReference"
313
- add_file_reference(component, change)
336
+ add_file_reference(component, change, change_path)
314
337
  when "PBXGroup"
315
- add_group(component, change)
338
+ add_group(component, change, change_path)
316
339
  when "PBXContainerItemProxy"
317
- add_container_item_proxy(component, change)
340
+ add_container_item_proxy(component, change, change_path)
318
341
  when "PBXTargetDependency"
319
- add_target_dependency(component, change)
342
+ add_target_dependency(component, change, change_path)
320
343
  when "PBXBuildFile"
321
- add_build_file(component, change)
344
+ add_build_file(component, change, change_path)
322
345
  when "XCConfigurationList"
323
- add_build_configuration_list(component, change)
346
+ add_build_configuration_list(component, change, change_path)
324
347
  when "XCBuildConfiguration"
325
- add_build_configuration(component, change)
348
+ add_build_configuration(component, change, change_path)
326
349
  when "PBXHeadersBuildPhase"
327
- add_headers_build_phase(component, change)
350
+ add_headers_build_phase(component, change, change_path)
328
351
  when "PBXSourcesBuildPhase"
329
- add_sources_build_phase(component, change)
352
+ add_sources_build_phase(component, change, change_path)
330
353
  when "PBXCopyFilesBuildPhase"
331
- add_copy_files_build_phase(component, change)
354
+ add_copy_files_build_phase(component, change, change_path)
332
355
  when "PBXShellScriptBuildPhase"
333
- add_shell_script_build_phase(component, change)
356
+ add_shell_script_build_phase(component, change, change_path)
334
357
  when "PBXFrameworksBuildPhase"
335
- add_frameworks_build_phase(component, change)
358
+ add_frameworks_build_phase(component, change, change_path)
336
359
  when "PBXResourcesBuildPhase"
337
- add_resources_build_phase(component, change)
360
+ add_resources_build_phase(component, change, change_path)
338
361
  when "PBXBuildRule"
339
- add_build_rule(component, change)
362
+ add_build_rule(component, change, change_path)
340
363
  when "PBXVariantGroup"
341
- add_variant_group(component, change)
364
+ add_variant_group(component, change, change_path)
342
365
  when "PBXReferenceProxy"
343
- add_reference_proxy(component, change)
366
+ add_reference_proxy(component, change, change_path)
344
367
  when "XCSwiftPackageProductDependency"
345
- add_swift_package_product_dependency(component, change)
368
+ add_swift_package_product_dependency(component, change, change_path)
346
369
  when "XCRemoteSwiftPackageReference"
347
- add_remote_swift_package_reference(component, change)
370
+ add_remote_swift_package_reference(component, change, change_path)
348
371
  else
349
372
  raise MergeError, "Trying to add unsupported component type #{change["isa"]}. Full " \
350
373
  "component change is: #{change}"
351
374
  end
352
375
  end
353
376
 
354
- def add_remote_swift_package_reference(containing_component, change)
377
+ def add_remote_swift_package_reference(containing_component, change, change_path)
355
378
  remote_swift_package_reference =
356
379
  containing_component.project.new(Xcodeproj::Project::XCRemoteSwiftPackageReference)
357
- add_attributes_to_component(remote_swift_package_reference, change)
380
+ add_attributes_to_component(remote_swift_package_reference, change, change_path)
358
381
 
359
382
  case containing_component
360
383
  when Xcodeproj::Project::XCSwiftPackageProductDependency
@@ -367,10 +390,10 @@ module Kintsugi
367
390
  end
368
391
  end
369
392
 
370
- def add_swift_package_product_dependency(containing_component, change)
393
+ def add_swift_package_product_dependency(containing_component, change, change_path)
371
394
  swift_package_product_dependency =
372
395
  containing_component.project.new(Xcodeproj::Project::XCSwiftPackageProductDependency)
373
- add_attributes_to_component(swift_package_product_dependency, change)
396
+ add_attributes_to_component(swift_package_product_dependency, change, change_path)
374
397
 
375
398
  case containing_component
376
399
  when Xcodeproj::Project::PBXBuildFile
@@ -383,7 +406,7 @@ module Kintsugi
383
406
  end
384
407
  end
385
408
 
386
- def add_reference_proxy(containing_component, change)
409
+ def add_reference_proxy(containing_component, change, change_path)
387
410
  case containing_component
388
411
  when Xcodeproj::Project::PBXBuildFile
389
412
  # If there are two file references that refer to the same file, one with a build file and
@@ -405,74 +428,78 @@ module Kintsugi
405
428
  when Xcodeproj::Project::PBXGroup
406
429
  reference_proxy = containing_component.project.new(Xcodeproj::Project::PBXReferenceProxy)
407
430
  containing_component << reference_proxy
408
- add_attributes_to_component(reference_proxy, change)
431
+ add_attributes_to_component(reference_proxy, change, change_path)
409
432
  else
410
433
  raise MergeError, "Trying to add reference proxy to an unsupported component type " \
411
434
  "#{containing_component.isa}. Change is: #{change}"
412
435
  end
413
436
  end
414
437
 
415
- def add_variant_group(containing_component, change)
438
+ def add_variant_group(containing_component, change, change_path)
416
439
  case containing_component
417
440
  when Xcodeproj::Project::PBXBuildFile
418
441
  containing_component.file_ref =
419
442
  find_variant_group(containing_component.project, change["displayName"])
420
443
  when Xcodeproj::Project::PBXGroup, Xcodeproj::Project::PBXVariantGroup
444
+ unless adding_files_and_groups_allowed?(change_path)
445
+ return
446
+ end
447
+
421
448
  variant_group = containing_component.project.new(Xcodeproj::Project::PBXVariantGroup)
422
449
  containing_component.children << variant_group
423
- add_attributes_to_component(variant_group, change)
450
+ add_attributes_to_component(variant_group, change, change_path)
424
451
  else
425
452
  raise MergeError, "Trying to add variant group to an unsupported component type " \
426
453
  "#{containing_component.isa}. Change is: #{change}"
427
454
  end
428
455
  end
429
456
 
430
- def add_build_rule(target, change)
457
+ def add_build_rule(target, change, change_path)
431
458
  build_rule = target.project.new(Xcodeproj::Project::PBXBuildRule)
432
459
  target.build_rules << build_rule
433
- add_attributes_to_component(build_rule, change)
460
+ add_attributes_to_component(build_rule, change, change_path)
434
461
  end
435
462
 
436
- def add_shell_script_build_phase(target, change)
463
+ def add_shell_script_build_phase(target, change, change_path)
437
464
  build_phase = target.new_shell_script_build_phase(change["displayName"])
438
- add_attributes_to_component(build_phase, change)
465
+ add_attributes_to_component(build_phase, change, change_path)
439
466
  end
440
467
 
441
- def add_headers_build_phase(target, change)
442
- add_attributes_to_component(target.headers_build_phase, change)
468
+ def add_headers_build_phase(target, change, change_path)
469
+ add_attributes_to_component(target.headers_build_phase, change, change_path)
443
470
  end
444
471
 
445
- def add_sources_build_phase(target, change)
446
- add_attributes_to_component(target.source_build_phase, change)
472
+ def add_sources_build_phase(target, change, change_path)
473
+ add_attributes_to_component(target.source_build_phase, change, change_path)
447
474
  end
448
475
 
449
- def add_frameworks_build_phase(target, change)
450
- add_attributes_to_component(target.frameworks_build_phase, change)
476
+ def add_frameworks_build_phase(target, change, change_path)
477
+ add_attributes_to_component(target.frameworks_build_phase, change, change_path)
451
478
  end
452
479
 
453
- def add_resources_build_phase(target, change)
454
- add_attributes_to_component(target.resources_build_phase, change)
480
+ def add_resources_build_phase(target, change, change_path)
481
+ add_attributes_to_component(target.resources_build_phase, change, change_path)
455
482
  end
456
483
 
457
- def add_copy_files_build_phase(target, change)
484
+ def add_copy_files_build_phase(target, change, change_path)
458
485
  copy_files_phase_name = change["displayName"] == "CopyFiles" ? nil : change["displayName"]
459
486
  copy_files_phase = target.new_copy_files_build_phase(copy_files_phase_name)
460
487
 
461
- add_attributes_to_component(copy_files_phase, change)
488
+ add_attributes_to_component(copy_files_phase, change, change_path)
462
489
  end
463
490
 
464
- def add_build_configuration_list(target, change)
491
+ def add_build_configuration_list(target, change, change_path)
465
492
  target.build_configuration_list = target.project.new(Xcodeproj::Project::XCConfigurationList)
466
- add_attributes_to_component(target.build_configuration_list, change)
493
+ add_attributes_to_component(target.build_configuration_list, change, change_path)
467
494
  end
468
495
 
469
- def add_build_configuration(configuration_list, change)
496
+ def add_build_configuration(configuration_list, change, change_path)
470
497
  build_configuration = configuration_list.project.new(Xcodeproj::Project::XCBuildConfiguration)
471
498
  configuration_list.build_configurations << build_configuration
472
- add_attributes_to_component(build_configuration, change)
499
+ add_attributes_to_component(build_configuration, change, change_path)
473
500
  end
474
501
 
475
- def add_build_file(build_phase, change)
502
+ def add_build_file(build_phase, change, change_path)
476
503
  if change["fileRef"].nil?
477
504
  puts "Warning: Trying to add a build file without any file reference to build phase " \
478
505
  "'#{build_phase}'"
@@ -481,7 +508,7 @@ module Kintsugi
481
508
 
482
509
  build_file = build_phase.project.new(Xcodeproj::Project::PBXBuildFile)
483
510
  build_phase.files << build_file
484
- add_attributes_to_component(build_file, change)
511
+ add_attributes_to_component(build_file, change, change_path)
485
512
  end
486
513
 
487
514
  def find_variant_group(project, display_name)
@@ -490,7 +517,7 @@ module Kintsugi
490
517
  end
491
518
  end
492
519
 
493
- def add_target_dependency(target, change)
520
+ def add_target_dependency(target, change, change_path)
494
521
  target_dependency = find_target(target.project, change["displayName"])
495
522
 
496
523
  if target_dependency
@@ -501,14 +528,14 @@ module Kintsugi
501
528
  target_dependency = target.project.new(Xcodeproj::Project::PBXTargetDependency)
502
529
 
503
530
  target.dependencies << target_dependency
504
- add_attributes_to_component(target_dependency, change)
531
+ add_attributes_to_component(target_dependency, change, change_path)
505
532
  end
506
533
 
507
534
  def find_target(project, display_name)
508
535
  project.targets.find { |target| target.display_name == display_name }
509
536
  end
510
537
 
511
- def add_container_item_proxy(component, change)
538
+ def add_container_item_proxy(component, change, change_path)
512
539
  container_proxy = component.project.new(Xcodeproj::Project::PBXContainerItemProxy)
513
540
  container_proxy.container_portal = find_containing_project_uuid(component.project, change)
514
541
 
@@ -521,7 +548,8 @@ module Kintsugi
521
548
  raise MergeError, "Trying to add container item proxy to an unsupported component type " \
522
549
  "#{containing_component.isa}. Change is: #{change}"
523
550
  end
524
- add_attributes_to_component(container_proxy, change, ignore_keys: ["containerPortal"])
551
+ add_attributes_to_component(container_proxy, change, change_path,
552
+ ignore_keys: ["containerPortal"])
525
553
  end
526
554
 
527
555
  def find_containing_project_uuid(project, container_item_proxy_change)
@@ -552,14 +580,14 @@ module Kintsugi
552
580
  container_item_proxies.first.container_portal
553
581
  end
554
582
 
555
- def add_subproject_reference(root_object, project_reference_change)
583
+ def add_subproject_reference(root_object, project_reference_change, change_path)
556
584
  filter_subproject_without_project_references = lambda do |file_reference|
557
585
  root_object.project_references.find do |project_reference|
558
586
  project_reference.project_ref.uuid == file_reference.uuid
559
587
  end.nil?
560
588
  end
561
589
  subproject_reference =
562
- find_file(root_object.project, project_reference_change["ProjectRef"],
590
+ find_file(root_object.project, project_reference_change["ProjectRef"]["path"],
563
591
  file_filter: filter_subproject_without_project_references)
564
592
 
565
593
  unless subproject_reference
@@ -578,7 +606,7 @@ module Kintsugi
578
606
  updated_project_reference_change =
579
607
  change_with_updated_subproject_uuid(project_reference_change, subproject_reference.uuid)
580
608
  add_attributes_to_component(project_reference, updated_project_reference_change,
581
- ignore_keys: ["ProjectRef"])
609
+ change_path, ignore_keys: ["ProjectRef"])
582
610
  end
583
611
 
584
612
  def change_with_updated_subproject_uuid(change, subproject_reference_uuid)
@@ -590,19 +618,19 @@ module Kintsugi
590
618
  new_change
591
619
  end
592
620
 
593
- def add_target(root_object, change)
621
+ def add_target(root_object, change, change_path)
594
622
  target = root_object.project.new(Xcodeproj::Project::PBXNativeTarget)
595
623
  root_object.project.targets << target
596
- add_attributes_to_component(target, change)
624
+ add_attributes_to_component(target, change, change_path)
597
625
  end
598
626
 
599
- def add_aggregate_target(root_object, change)
627
+ def add_aggregate_target(root_object, change, change_path)
600
628
  target = root_object.project.new(Xcodeproj::Project::PBXAggregateTarget)
601
629
  root_object.project.targets << target
602
- add_attributes_to_component(target, change)
630
+ add_attributes_to_component(target, change, change_path)
603
631
  end
604
632
 
605
- def add_file_reference(containing_component, change)
633
+ def add_file_reference(containing_component, change, change_path)
606
634
  # base configuration reference and product reference always reference a file that exists
607
635
  # inside a group, therefore in these cases the file is searched for.
608
636
  # In the case of group and variant group, the file can't exist in another group, therefore a
@@ -610,12 +638,17 @@ module Kintsugi
610
638
  case containing_component
611
639
  when Xcodeproj::Project::XCBuildConfiguration
612
640
  containing_component.base_configuration_reference =
613
- find_file(containing_component.project, change)
641
+ find_file(containing_component.project, change["path"])
614
642
  when Xcodeproj::Project::PBXNativeTarget
615
- containing_component.product_reference = find_file(containing_component.project, change)
643
+ containing_component.product_reference =
644
+ find_file(containing_component.project, change["path"])
616
645
  when Xcodeproj::Project::PBXBuildFile
617
- containing_component.file_ref = find_file(containing_component.project, change)
646
+ containing_component.file_ref = find_file(containing_component.project, change["path"])
618
647
  when Xcodeproj::Project::PBXGroup, Xcodeproj::Project::PBXVariantGroup
648
+ unless adding_files_and_groups_allowed?(change_path)
649
+ return
650
+ end
651
+
619
652
  file_reference = containing_component.project.new(Xcodeproj::Project::PBXFileReference)
620
653
  containing_component.children << file_reference
621
654
 
@@ -623,14 +656,23 @@ module Kintsugi
623
656
  # default.
624
657
  file_reference.include_in_index = nil
625
658
  file_reference.source_tree = nil
626
- add_attributes_to_component(file_reference, change)
659
+ add_attributes_to_component(file_reference, change, change_path)
627
660
  else
628
661
  raise MergeError, "Trying to add file reference to an unsupported component type " \
629
662
  "#{containing_component.isa}. Change is: #{change}"
630
663
  end
631
664
  end
632
665
 
633
- def add_group(containing_component, change)
666
+ def adding_files_and_groups_allowed?(change_path)
667
+ change_path.start_with?("rootObject/mainGroup") ||
668
+ change_path.start_with?("rootObject/projectReferences")
669
+ end
670
+
671
+ def add_group(containing_component, change, change_path)
672
+ unless adding_files_and_groups_allowed?(change_path)
673
+ return
674
+ end
675
+
634
676
  case containing_component
635
677
  when Xcodeproj::Project::ObjectDictionary
636
678
  # It is assumed that an `ObjectDictionary` always represents a project reference.
@@ -644,25 +686,29 @@ module Kintsugi
644
686
  "#{containing_component.isa}. Change is: #{change}"
645
687
  end
646
688
 
647
- add_attributes_to_component(new_group, change)
689
+ add_attributes_to_component(new_group, change, change_path)
648
690
  end
649
691
 
650
- def add_attributes_to_component(component, change, ignore_keys: [])
692
+ def add_attributes_to_component(component, change, change_path, ignore_keys: [])
651
693
  change.each do |change_name, change_value|
652
694
  next if (%w[isa displayName] + ignore_keys).include?(change_name)
653
695
 
654
696
  attribute_name = attribute_name_from_change_name(change_name)
655
697
  if simple_attribute?(component, attribute_name)
656
- apply_change_to_simple_attribute(component, attribute_name, {added: change_value})
698
+ simple_attribute_change = {
699
+ added: change_value,
700
+ removed: simple_attribute_default_value(component, attribute_name)
701
+ }
702
+ apply_change_to_simple_attribute(component, attribute_name, simple_attribute_change)
657
703
  next
658
704
  end
659
705
 
660
706
  case change_value
661
707
  when Hash
662
- add_child_to_component(component, change_value)
708
+ add_child_to_component(component, change_value, change_path)
663
709
  when Array
664
710
  change_value.each do |added_attribute_element|
665
- add_child_to_component(component, added_attribute_element)
711
+ add_child_to_component(component, added_attribute_element, change_path)
666
712
  end
667
713
  else
668
714
  raise MergeError, "Trying to add attribute of unsupported type '#{change_value.class}' " \
@@ -671,16 +717,20 @@ module Kintsugi
671
717
  end
672
718
  end
673
719
 
674
- def find_file(project, file_reference_change, file_filter: ->(_) { true })
720
+ def simple_attribute_default_value(component, attribute_name)
721
+ component.simple_attributes.find do |attribute|
722
+ attribute.name == attribute_name
723
+ end.default_value
724
+ end
725
+
726
+ def find_file(project, path, file_filter: ->(_) { true })
675
727
  file_references = project.files.select do |file_reference|
676
- file_reference.path == file_reference_change["path"] && file_filter.call(file_reference)
728
+ file_reference.path == path && file_filter.call(file_reference)
677
729
  end
678
730
  if file_references.length > 1
679
- puts "Debug: Found more than one matching file with path " \
680
- "'#{file_reference_change["path"]}'. Using the first one."
731
+ puts "Debug: Found more than one matching file with path '#{path}'. Using the first one."
681
732
  elsif file_references.empty?
682
- puts "Debug: No file reference found for file with path " \
683
- "'#{file_reference_change["path"]}'."
733
+ puts "Debug: No file reference found for file with path '#{path}'."
684
734
  return
685
735
  end
686
736
 
data/lib/kintsugi/cli.rb CHANGED
@@ -50,6 +50,7 @@ module Kintsugi
50
50
  exit(1)
51
51
  end
52
52
  Kintsugi.three_way_merge(arguments[0], arguments[1], arguments[2], arguments[3])
53
+ warn "\e[32mKintsugi auto-merged #{arguments[3]}\e[0m"
53
54
  }
54
55
 
55
56
  Command.new(
@@ -109,7 +110,7 @@ module Kintsugi
109
110
  def global_attributes_file_path
110
111
  # The logic to decide the path to the global attributes file is described at:
111
112
  # https://git-scm.com/docs/gitattributes.
112
- config_attributes_file_path = `git config --global core.attributesfile`
113
+ config_attributes_file_path = `git config --global core.attributesfile`.chomp
113
114
  return config_attributes_file_path unless config_attributes_file_path.empty?
114
115
 
115
116
  if ENV["XDG_CONFIG_HOME"].nil? || ENV["XDG_CONFIG_HOME"].empty?