diff --git a/kintsugi.gemspec b/kintsugi.gemspec index 89c89d4..97e7360 100644 --- a/kintsugi.gemspec +++ b/kintsugi.gemspec @@ -23,7 +23,7 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "tty-prompt", "~> 0" - spec.add_dependency "xcodeproj", ">= 1.26.0", "<= 1.27.0" + spec.add_dependency "xcodeproj", ">= 1.26.0", "<= 1.28.1" spec.add_development_dependency "git", "~> 1.11" spec.add_development_dependency "rake", "~> 13.0" diff --git a/spec/kintsugi_integration_spec.rb b/spec/kintsugi_integration_spec.rb index a769df3..fb859a5 100644 --- a/spec/kintsugi_integration_spec.rb +++ b/spec/kintsugi_integration_spec.rb @@ -185,10 +185,100 @@ def create_new_project_at_path(path) project end +def find_exception_set_hash(plist) + plist["objects"].values.find do |object| + object["isa"] == "PBXFileSystemSynchronizedBuildFileExceptionSet" + end +end + +def write_exception_set_asset_tags(project_path, asset_tags) + pbxproj_path = File.join(project_path, "project.pbxproj") + plist = Xcodeproj::Plist.read_from_path(pbxproj_path) + find_exception_set_hash(plist)["assetTagsByRelativePath"] = asset_tags + File.open(pbxproj_path, "w") do |file| + Nanaimo::Writer::PBXProjWriter + .new(Nanaimo::Plist.new(plist, :ascii), pretty: true, output: file, strict: false).write + end +end + +def read_exception_set_asset_tags(project_path) + plist = Xcodeproj::Plist.read_from_path(File.join(project_path, "project.pbxproj")) + exception_set = find_exception_set_hash(plist) + exception_set && exception_set["assetTagsByRelativePath"] +end + describe Kintsugi, :kintsugi do %w[rebase cherry-pick merge].each do |git_command| ["foo.xcodeproj", "foo with space.xcodeproj"].each do |project_name| it_behaves_like("tests", git_command, project_name) end end + + context "when merging a project with on-demand resource asset tags" do + let(:temporary_directories_paths) { [] } + let(:git_directory_path) { Dir.mktmpdir.tap { |path| temporary_directories_paths << path } } + let(:git) { Git.init(git_directory_path) } + + before do + git.config("user.email", "you@example.com") + git.config("user.name", "Your Name") + end + + after do + temporary_directories_paths.each do |directory_path| + FileUtils.remove_entry(directory_path) + end + end + + it "keeps 'assetTagsByRelativePath' of an exception set when resolving with driver" do + git.config("merge.kintsugi.name", "Kintsugi driver") + git.config("merge.kintsugi.driver", "#{__dir__}/../bin/kintsugi driver %O %A %B %P") + File.write(File.join(git_directory_path, ".gitattributes"), "*.pbxproj merge=kintsugi") + + asset_tags = {"OnDemandAssets/Level1.imageset" => ["level1"]} + + project = create_new_project_at_path(File.join(git_directory_path, "foo.xcodeproj")) + target = project.new_target("com.apple.product-type.library.static", "foo", :ios) + group = project.new(Xcodeproj::Project::PBXFileSystemSynchronizedRootGroup) + group.source_tree = "" + group.path = "SyncedSources" + exception_set = + project.new(Xcodeproj::Project::PBXFileSystemSynchronizedBuildFileExceptionSet) + exception_set.target = target + exception_set.membership_exceptions = ["Excluded.swift"] + group.exceptions << exception_set + project.main_group.children << group + target.file_system_synchronized_groups << group + project.save + # `assetTagsByRelativePath` is written to the file directly because not all xcodeproj + # versions in the supported range model this attribute, and those that don't drop it when + # a project is saved, which is exactly what this test guards against. + write_exception_set_asset_tags(project.path, asset_tags) + + git.add(all: true) + git.commit("Initial project") + + project = Xcodeproj::Project.open(project.path) + project.new_target("com.apple.product-type.library.static", "bar", :ios) + project.save + write_exception_set_asset_tags(project.path, asset_tags) + git.add(all: true) + git.commit("Add target bar") + first_commit_hash = git.revparse("HEAD") + + git.checkout("HEAD^") + project = Xcodeproj::Project.open(project.path) + project.new_target("com.apple.product-type.library.static", "baz", :ios) + project.save + write_exception_set_asset_tags(project.path, asset_tags) + git.add(all: true) + git.commit("Add target baz") + + `git -C #{git_directory_path} merge #{first_commit_hash} &> /dev/null` + + project = Xcodeproj::Project.open(project.path) + expect(project.targets.map(&:display_name)).to contain_exactly("foo", "bar", "baz") + expect(read_exception_set_asset_tags(project.path)).to eq(asset_tags) + end + end end