kintsugi 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -5
- data/bin/kintsugi +9 -1
- data/lib/kintsugi/apply_change_to_project.rb +22 -20
- data/lib/kintsugi/cli.rb +106 -8
- data/lib/kintsugi/error.rb +9 -0
- data/lib/kintsugi/version.rb +1 -1
- data/lib/kintsugi.rb +8 -7
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e2593fa95851c928b7ad943430c1db40d4c21831e24bd16f371f24298714c99
|
4
|
+
data.tar.gz: dca49c53301790803690ad5aa81dcf59b2f9036402a713b63b9093130994fe51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa8c40252da2e56f9753fd143e1b100599c31737badcb5c16906e5883008b6344a5e44c09f2619f90045b0c987971f0248f2400d5f95acd20dac7c810b061a05
|
7
|
+
data.tar.gz: 15da61db3bea0d5d3c9528ba93b087ae67956eb58f4d846639936fcf682ac5f7cc5f6d2ec8eb87cc41673b960978e245b3eaf33d21b31c1e5a0ebadf46780d07
|
data/README.md
CHANGED
@@ -40,15 +40,22 @@ And see the magic happen! :sparkles:
|
|
40
40
|
|
41
41
|
### Git merge driver
|
42
42
|
|
43
|
-
|
43
|
+
You can setup Kintsugi to automatically resolve conflicts that occur in `pbxproj` files when such conflicts occur.
|
44
44
|
|
45
|
-
|
45
|
+
#### Automatic install
|
46
|
+
|
47
|
+
Run `kintsugi install-driver`. This will install Kintsugi as a merge driver globally. Note that Kintsugi needs to be in your `PATH`.
|
48
|
+
|
49
|
+
❗ Do not install with bundler because the installation might succeed even if Kintsugi is not in `PATH`.
|
50
|
+
|
51
|
+
#### Manual install
|
52
|
+
|
53
|
+
- Add Kintsugi as driver to Git config file by running the following:
|
46
54
|
```sh
|
47
55
|
git config merge.kintsugi.name "Kintsugi driver" # Or any other name you prefer
|
48
|
-
git config merge.kintsugi.driver "
|
56
|
+
git config merge.kintsugi.driver "<path_to_kintsugi> driver %O %A %B %P"
|
49
57
|
```
|
50
58
|
|
51
|
-
`kintsugi` should be in your `PATH`.
|
52
59
|
Run `git config` with `--global` to add this to the global config file.
|
53
60
|
|
54
61
|
- Add the following line to the `.gitattributes` file at the root of the repository:
|
@@ -65,7 +72,11 @@ See our [Contribution guidelines](./CONTRIBUTING.md).
|
|
65
72
|
|
66
73
|
## Alternatives
|
67
74
|
|
68
|
-
|
75
|
+
All of the alternatives below allow you to generate your Xcode projects based on a spec or manifest. You commit these files to git, and can even remove the `.xcodeproj` files from git.
|
76
|
+
|
77
|
+
- [XcodeGen](https://github.com/yonaskolb/XcodeGen)
|
78
|
+
- [Tuist](https://github.com/tuist)
|
79
|
+
- [Xcake](https://github.com/igor-makarov/xcake)
|
69
80
|
|
70
81
|
## Copyright
|
71
82
|
|
data/bin/kintsugi
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
|
7
7
|
require "kintsugi"
|
8
8
|
require_relative "../lib/kintsugi/cli"
|
9
|
+
require_relative "../lib/kintsugi/error"
|
9
10
|
|
10
11
|
def parse_options!(command, argv)
|
11
12
|
options = {}
|
@@ -28,4 +29,11 @@ command =
|
|
28
29
|
end
|
29
30
|
|
30
31
|
options = parse_options!(command, ARGV)
|
31
|
-
|
32
|
+
|
33
|
+
begin
|
34
|
+
command.action.call(options, ARGV)
|
35
|
+
rescue ArgumentError => e
|
36
|
+
puts "#{e.class}: #{e}"
|
37
|
+
rescue Kintsugi::MergeError => e
|
38
|
+
puts e
|
39
|
+
end
|
@@ -190,24 +190,24 @@ module Kintsugi
|
|
190
190
|
when Hash
|
191
191
|
(old_value || {}).reject do |key, value|
|
192
192
|
if value != removed_change[key] && added_change[key] != value
|
193
|
-
raise "Trying to remove value '#{removed_change[key]}' of hash with key
|
194
|
-
"it changed to #{value}. This is considered a conflict that should be
|
195
|
-
"manually."
|
193
|
+
raise MergeError, "Trying to remove value '#{removed_change[key]}' of hash with key " \
|
194
|
+
"'#{key}' but it changed to #{value}. This is considered a conflict that should be " \
|
195
|
+
"resolved manually."
|
196
196
|
end
|
197
197
|
|
198
198
|
removed_change.key?(key)
|
199
199
|
end
|
200
200
|
when String
|
201
201
|
if old_value != removed_change && !old_value.nil? && added_change != old_value
|
202
|
-
raise "Trying to remove value '#{removed_change}', but the existing value
|
203
|
-
"'#{old_value}'. This is considered a conflict that should be resolved manually."
|
202
|
+
raise MergeError, "Trying to remove value '#{removed_change}', but the existing value " \
|
203
|
+
"is '#{old_value}'. This is considered a conflict that should be resolved manually."
|
204
204
|
end
|
205
205
|
|
206
206
|
nil
|
207
207
|
when nil
|
208
208
|
nil
|
209
209
|
else
|
210
|
-
raise "Unsupported change #{removed_change} of type #{removed_change.class}"
|
210
|
+
raise MergeError, "Unsupported change #{removed_change} of type #{removed_change.class}"
|
211
211
|
end
|
212
212
|
end
|
213
213
|
|
@@ -220,7 +220,8 @@ module Kintsugi
|
|
220
220
|
new_value = old_value.merge(change)
|
221
221
|
|
222
222
|
unless (old_value.to_a - new_value.to_a).empty?
|
223
|
-
raise "New hash #{change} contains values that conflict with old hash
|
223
|
+
raise MergeError, "New hash #{change} contains values that conflict with old hash " \
|
224
|
+
"#{old_value}"
|
224
225
|
end
|
225
226
|
|
226
227
|
new_value
|
@@ -229,14 +230,15 @@ module Kintsugi
|
|
229
230
|
when nil
|
230
231
|
nil
|
231
232
|
else
|
232
|
-
raise "Unsupported change #{change} of type #{change.class}"
|
233
|
+
raise MergeError, "Unsupported change #{change} of type #{change.class}"
|
233
234
|
end
|
234
235
|
end
|
235
236
|
|
236
237
|
def remove_component(component, change)
|
237
238
|
if component.to_tree_hash != change
|
238
|
-
raise "Trying to remove an object that changed since then. This is
|
239
|
-
"that should be resolved manually. Name of the object is:
|
239
|
+
raise MergeError, "Trying to remove an object that changed since then. This is " \
|
240
|
+
"considered a conflict that should be resolved manually. Name of the object is: " \
|
241
|
+
"'#{component.display_name}'"
|
240
242
|
end
|
241
243
|
|
242
244
|
if change["isa"] == "PBXFileReference"
|
@@ -302,8 +304,8 @@ module Kintsugi
|
|
302
304
|
when "PBXReferenceProxy"
|
303
305
|
add_reference_proxy(component, change)
|
304
306
|
else
|
305
|
-
raise "Trying to add unsupported component type #{change["isa"]}. Full
|
306
|
-
"is: #{change}"
|
307
|
+
raise MergeError, "Trying to add unsupported component type #{change["isa"]}. Full " \
|
308
|
+
"component change is: #{change}"
|
307
309
|
end
|
308
310
|
end
|
309
311
|
|
@@ -331,7 +333,7 @@ module Kintsugi
|
|
331
333
|
containing_component << reference_proxy
|
332
334
|
add_attributes_to_component(reference_proxy, change)
|
333
335
|
else
|
334
|
-
raise "Trying to add reference proxy to an unsupported component type " \
|
336
|
+
raise MergeError, "Trying to add reference proxy to an unsupported component type " \
|
335
337
|
"#{containing_component.isa}. Change is: #{change}"
|
336
338
|
end
|
337
339
|
end
|
@@ -346,7 +348,7 @@ module Kintsugi
|
|
346
348
|
containing_component.children << variant_group
|
347
349
|
add_attributes_to_component(variant_group, change)
|
348
350
|
else
|
349
|
-
raise "Trying to add variant group to an unsupported component type " \
|
351
|
+
raise MergeError, "Trying to add variant group to an unsupported component type " \
|
350
352
|
"#{containing_component.isa}. Change is: #{change}"
|
351
353
|
end
|
352
354
|
end
|
@@ -442,7 +444,7 @@ module Kintsugi
|
|
442
444
|
when "PBXReferenceProxy"
|
443
445
|
component.remote_ref = container_proxy
|
444
446
|
else
|
445
|
-
raise "Trying to add container item proxy to an unsupported component type " \
|
447
|
+
raise MergeError, "Trying to add container item proxy to an unsupported component type " \
|
446
448
|
"#{containing_component.isa}. Change is: #{change}"
|
447
449
|
end
|
448
450
|
add_attributes_to_component(container_proxy, change, ignore_keys: ["containerPortal"])
|
@@ -541,7 +543,7 @@ module Kintsugi
|
|
541
543
|
file_reference.include_in_index = nil
|
542
544
|
add_attributes_to_component(file_reference, change)
|
543
545
|
else
|
544
|
-
raise "Trying to add file reference to an unsupported component type " \
|
546
|
+
raise MergeError, "Trying to add file reference to an unsupported component type " \
|
545
547
|
"#{containing_component.isa}. Change is: #{change}"
|
546
548
|
end
|
547
549
|
end
|
@@ -556,8 +558,8 @@ module Kintsugi
|
|
556
558
|
new_group = containing_component.project.new(Xcodeproj::Project::PBXGroup)
|
557
559
|
containing_component.children << new_group
|
558
560
|
else
|
559
|
-
raise "Trying to add group to an unsupported component type
|
560
|
-
"Change is: #{change}"
|
561
|
+
raise MergeError, "Trying to add group to an unsupported component type " \
|
562
|
+
"#{containing_component.isa}. Change is: #{change}"
|
561
563
|
end
|
562
564
|
|
563
565
|
add_attributes_to_component(new_group, change)
|
@@ -581,8 +583,8 @@ module Kintsugi
|
|
581
583
|
add_child_to_component(component, added_attribute_element)
|
582
584
|
end
|
583
585
|
else
|
584
|
-
raise "Trying to add attribute of unsupported type '#{change_value.class}'
|
585
|
-
"object #{component}. Attribute name is '#{change_name}'"
|
586
|
+
raise MergeError, "Trying to add attribute of unsupported type '#{change_value.class}' " \
|
587
|
+
"to object #{component}. Attribute name is '#{change_name}'"
|
586
588
|
end
|
587
589
|
end
|
588
590
|
end
|
data/lib/kintsugi/cli.rb
CHANGED
@@ -12,12 +12,14 @@ module Kintsugi
|
|
12
12
|
# Subcommands of Kintsugi CLI.
|
13
13
|
attr_reader :subcommands
|
14
14
|
|
15
|
-
# Root command Kintsugi CLI.
|
15
|
+
# Root command of Kintsugi CLI.
|
16
16
|
attr_reader :root_command
|
17
17
|
|
18
18
|
def initialize
|
19
19
|
@subcommands = {
|
20
|
-
"driver" => create_driver_subcommand
|
20
|
+
"driver" => create_driver_subcommand,
|
21
|
+
"install-driver" => create_install_driver_subcommand,
|
22
|
+
"uninstall-driver" => create_uninstall_driver_subcommand
|
21
23
|
}.freeze
|
22
24
|
@root_command = create_root_command
|
23
25
|
end
|
@@ -27,7 +29,7 @@ module Kintsugi
|
|
27
29
|
Command = Struct.new(:option_parser, :action, :description, keyword_init: true)
|
28
30
|
|
29
31
|
def create_driver_subcommand
|
30
|
-
|
32
|
+
option_parser =
|
31
33
|
OptionParser.new do |opts|
|
32
34
|
opts.banner = "Usage: kintsugi driver BASE OURS THEIRS ORIGINAL_FILE_PATH\n" \
|
33
35
|
"Uses Kintsugi as a Git merge driver. Parameters " \
|
@@ -40,7 +42,7 @@ module Kintsugi
|
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
|
-
driver_action = lambda { |_, arguments
|
45
|
+
driver_action = lambda { |_, arguments|
|
44
46
|
if arguments.count != 4
|
45
47
|
puts "Incorrect number of arguments to 'driver' subcommand\n\n"
|
46
48
|
puts option_parser
|
@@ -50,14 +52,110 @@ module Kintsugi
|
|
50
52
|
}
|
51
53
|
|
52
54
|
Command.new(
|
53
|
-
option_parser:
|
55
|
+
option_parser: option_parser,
|
54
56
|
action: driver_action,
|
55
57
|
description: "3-way merge compatible with Git merge driver"
|
56
58
|
)
|
57
59
|
end
|
58
60
|
|
61
|
+
def create_install_driver_subcommand
|
62
|
+
option_parser =
|
63
|
+
OptionParser.new do |opts|
|
64
|
+
opts.banner = "Usage: kintsugi install-driver\n" \
|
65
|
+
"Installs Kintsugi as a Git merge driver globally. "
|
66
|
+
|
67
|
+
opts.on("-h", "--help", "Prints this help") do
|
68
|
+
puts opts
|
69
|
+
exit
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
action = lambda { |_, arguments|
|
74
|
+
if arguments.count != 0
|
75
|
+
puts "Incorrect number of arguments to 'install-driver' subcommand\n\n"
|
76
|
+
puts option_parser
|
77
|
+
exit(1)
|
78
|
+
end
|
79
|
+
|
80
|
+
if `which kintsugi`.chomp.empty?
|
81
|
+
puts "Can only install Kintsugi globally if Kintsugi is in your PATH"
|
82
|
+
exit(1)
|
83
|
+
end
|
84
|
+
|
85
|
+
install_kintsugi_driver_globally
|
86
|
+
puts "Done! 🪄"
|
87
|
+
}
|
88
|
+
|
89
|
+
Command.new(
|
90
|
+
option_parser: option_parser,
|
91
|
+
action: action,
|
92
|
+
description: "Installs Kintsugi as a Git merge driver globally"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
def install_kintsugi_driver_globally
|
97
|
+
`git config --global merge.kintsugi.name "Kintsugi driver"`
|
98
|
+
`git config --global merge.kintsugi.driver "kintsugi driver %O %A %B %P"`
|
99
|
+
|
100
|
+
attributes_file_path = global_attributes_file_path
|
101
|
+
merge_using_kintsugi_line = "'*.pbxproj merge=kintsugi'"
|
102
|
+
`grep -sqxF #{merge_using_kintsugi_line} "#{attributes_file_path}" \
|
103
|
+
|| echo #{merge_using_kintsugi_line} >> "#{attributes_file_path}"`
|
104
|
+
end
|
105
|
+
|
106
|
+
def global_attributes_file_path
|
107
|
+
# The logic to decide the path to the global attributes file is described at:
|
108
|
+
# https://git-scm.com/docs/gitattributes.
|
109
|
+
config_attributes_file_path = `git config --global core.attributesfile`
|
110
|
+
return config_attributes_file_path unless config_attributes_file_path.empty?
|
111
|
+
|
112
|
+
if ENV["XDG_CONFIG_HOME"].nil? || ENV["XDG_CONFIG_HOME"].empty?
|
113
|
+
File.join(ENV["HOME"], ".config/git/attributes")
|
114
|
+
else
|
115
|
+
File.join(ENV["XDG_CONFIG_HOME"], "git/attributes")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def create_uninstall_driver_subcommand
|
120
|
+
option_parser =
|
121
|
+
OptionParser.new do |opts|
|
122
|
+
opts.banner = "Usage: kintsugi uninstall-driver\n" \
|
123
|
+
"Uninstalls Kintsugi as a Git merge driver that was previously installed globally."
|
124
|
+
|
125
|
+
opts.on("-h", "--help", "Prints this help") do
|
126
|
+
puts opts
|
127
|
+
exit
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
action = lambda { |_, arguments|
|
132
|
+
if arguments.count != 0
|
133
|
+
puts "Incorrect number of arguments to 'uninstall-driver' subcommand\n\n"
|
134
|
+
puts option_parser
|
135
|
+
exit(1)
|
136
|
+
end
|
137
|
+
|
138
|
+
uninstall_kintsugi_driver_globally
|
139
|
+
puts "Done!"
|
140
|
+
}
|
141
|
+
|
142
|
+
Command.new(
|
143
|
+
option_parser: option_parser,
|
144
|
+
action: action,
|
145
|
+
description: "Uninstalls Kintsugi as a Git merge driver that was previously installed " \
|
146
|
+
"globally."
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
def uninstall_kintsugi_driver_globally
|
151
|
+
`git config --global --unset merge.kintsugi.name`
|
152
|
+
`git config --global --unset merge.kintsugi.driver`
|
153
|
+
|
154
|
+
`sed -i '' '/\*.pbxproj\ merge=kintsugi/d' "#{global_attributes_file_path}"`
|
155
|
+
end
|
156
|
+
|
59
157
|
def create_root_command
|
60
|
-
|
158
|
+
option_parser = OptionParser.new do |opts|
|
61
159
|
opts.banner = "Kintsugi, version #{Version::STRING}\n" \
|
62
160
|
"Copyright (c) 2021 Lightricks\n\n" \
|
63
161
|
"Usage: kintsugi <pbxproj_filepath> [options]\n" \
|
@@ -83,7 +181,7 @@ module Kintsugi
|
|
83
181
|
opts.on_tail("\nSUBCOMMANDS\n#{subcommands_descriptions}")
|
84
182
|
end
|
85
183
|
|
86
|
-
root_action = lambda { |options, arguments
|
184
|
+
root_action = lambda { |options, arguments|
|
87
185
|
if arguments.count != 1
|
88
186
|
puts "Incorrect number of arguments\n\n"
|
89
187
|
puts option_parser
|
@@ -96,7 +194,7 @@ module Kintsugi
|
|
96
194
|
}
|
97
195
|
|
98
196
|
Command.new(
|
99
|
-
option_parser:
|
197
|
+
option_parser: option_parser,
|
100
198
|
action: root_action,
|
101
199
|
description: nil
|
102
200
|
)
|
data/lib/kintsugi/version.rb
CHANGED
data/lib/kintsugi.rb
CHANGED
@@ -9,6 +9,7 @@ require "xcodeproj"
|
|
9
9
|
|
10
10
|
require_relative "kintsugi/xcodeproj_extensions"
|
11
11
|
require_relative "kintsugi/apply_change_to_project"
|
12
|
+
require_relative "kintsugi/error"
|
12
13
|
|
13
14
|
module Kintsugi
|
14
15
|
class << self
|
@@ -21,11 +22,11 @@ module Kintsugi
|
|
21
22
|
# Path to where the changes to apply to the project are written in JSON format.
|
22
23
|
#
|
23
24
|
# @raise [ArgumentError]
|
24
|
-
# If the file extension is not `pbxproj
|
25
|
+
# If the file extension is not `pbxproj`, or the file doesn't exist, or if no rebase,
|
26
|
+
# cherry-pick, or merge is in progress
|
25
27
|
#
|
26
|
-
# @raise [
|
27
|
-
# If
|
28
|
-
# opened, or there was an error applying the change to the project.
|
28
|
+
# @raise [MergeError]
|
29
|
+
# If there was an error applying the change to the project.
|
29
30
|
#
|
30
31
|
# @return [void]
|
31
32
|
def resolve_conflicts(project_file_path, changes_output_path)
|
@@ -59,7 +60,7 @@ module Kintsugi
|
|
59
60
|
# @param [String] original_project_path
|
60
61
|
# Path to the original path of the file.
|
61
62
|
#
|
62
|
-
# @raise [
|
63
|
+
# @raise [MergeError]
|
63
64
|
# If there was an error applying the change to the project.
|
64
65
|
#
|
65
66
|
# @return [void]
|
@@ -104,8 +105,8 @@ module Kintsugi
|
|
104
105
|
|
105
106
|
Dir.chdir(File.dirname(project_file_path)) do
|
106
107
|
unless file_has_base_ours_and_theirs_versions?(project_file_path)
|
107
|
-
raise ArgumentError, "File '#{project_file_path}' doesn't have conflicts,
|
108
|
-
"merge is not possible."
|
108
|
+
raise ArgumentError, "File '#{project_file_path}' doesn't have conflicts, " \
|
109
|
+
"or a 3-way merge is not possible."
|
109
110
|
end
|
110
111
|
end
|
111
112
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kintsugi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Yohay
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: xcodeproj
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- lib/kintsugi.rb
|
124
124
|
- lib/kintsugi/apply_change_to_project.rb
|
125
125
|
- lib/kintsugi/cli.rb
|
126
|
+
- lib/kintsugi/error.rb
|
126
127
|
- lib/kintsugi/utils.rb
|
127
128
|
- lib/kintsugi/version.rb
|
128
129
|
- lib/kintsugi/xcodeproj_extensions.rb
|
@@ -150,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
151
|
version: '0'
|
151
152
|
requirements: []
|
152
153
|
rubyforge_project:
|
153
|
-
rubygems_version: 2.7.3
|
154
|
+
rubygems_version: 2.7.6.3
|
154
155
|
signing_key:
|
155
156
|
specification_version: 4
|
156
157
|
summary: pbxproj files git conflicts solver
|