diff --git a/bin/synx b/bin/synx index 2fb7b1c..0da71d6 100755 --- a/bin/synx +++ b/bin/synx @@ -6,6 +6,7 @@ require 'synx' Clamp do parameter "xcodeproj", "Path to the xcodeproj", :attribute_name => :xcodeproj_path + option ["--warn-type", "-w"], "warning|error", "show warnings or errors for files whose paths do not match the project structure. Using this option will not make any changes to the project. Use it as an Xcode build phase to alert the developer.", :attribute_name => :warn_type option ["--prune", "-p"], :flag, "remove source files and image resources that are not referenced by the the xcode project" option "--no-color", :flag, "removes all color from the output" option "--no-default-exclusions", :flag, "doesn't use the default exclusions of /Libraries, /Frameworks, and /Products" @@ -21,7 +22,7 @@ Clamp do puts "You cannot run Synx as root.".red else project = Synx::Project.open(xcodeproj_path) - project.sync(:prune => prune?, :quiet => quiet?, :no_color => no_color?, :no_default_exclusions => no_default_exclusions?, :group_exclusions => exclusion_list) + project.sync(:warn_type => warn_type, :prune => prune?, :quiet => quiet?, :no_color => no_color?, :no_default_exclusions => no_default_exclusions?, :group_exclusions => exclusion_list) end end diff --git a/lib/synx/project.rb b/lib/synx/project.rb index ce175cc..a5f765a 100644 --- a/lib/synx/project.rb +++ b/lib/synx/project.rb @@ -17,7 +17,13 @@ def sync(options={}) presync_check Synx::Tabber.increase Synx::Tabber.puts "Syncing files that are included in Xcode project...".bold.white - main_group.all_groups.each { |gr| gr.sync(main_group) } + warn_type = warn_type_from_options(options) + isError = false + main_group.all_groups.each do |gr| + isError = gr.sync(main_group, warn_type) || isError + end + exit -1 if isError + return if warn_type != nil Synx::Tabber.puts "\n\n" Synx::Tabber.puts "Syncing files that are not included in Xcode project..".bold.white main_group.all_groups.each(&:move_entries_not_in_xcodeproj) @@ -26,6 +32,16 @@ def sync(options={}) save end + def warn_type_from_options(options) + return nil if !options[:warn_type] + warn_type = options[:warn_type] + if warn_type != "warning" && warn_type != "error" + raise "Invalid warning type `#{warn_type}`" + end + return warn_type + end + private :warn_type_from_options + def presync_check forward_slash_groups = main_group.groups_containing_forward_slash unless forward_slash_groups.empty? diff --git a/lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb b/lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb index a95a6f4..5e370d4 100644 --- a/lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb +++ b/lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb @@ -3,23 +3,32 @@ class Project module Object class PBXFileReference - def sync(group) + def sync(group, warn_type) + isError = false if should_sync? if should_move? - FileUtils.mv(real_path.to_s, work_pathname.to_s) - # TODO: move out to abstract_object - self.source_tree = "" - self.path = work_pathname.relative_path_from(parent.work_pathname).to_s + if !warn_type + FileUtils.mv(real_path.to_s, work_pathname.to_s) + # TODO: move out to abstract_object + self.source_tree = "" + self.path = work_pathname.relative_path_from(parent.work_pathname).to_s + else + cmd = "echo '#{real_path.to_s}:1: #{warn_type}: Path on disk does not match project group structure.'" + warnings = `#{cmd}` + puts warnings + isError = (warnings.length > 0 && warn_type == "error") + end else # Don't move this file around -- it's not even inside the structure. Just fix the relative reference self.path = real_path.relative_path_from((project.work_pathname_to_pathname(group.work_pathname))).to_s end change_build_settings_reference - output + output if warn_type == nil else Synx::Tabber.puts "skipped #{basename}".red end + return isError end def output diff --git a/lib/synx/xcodeproj_ext/project/object/pbx_group.rb b/lib/synx/xcodeproj_ext/project/object/pbx_group.rb index 1eadaaa..4362fc4 100644 --- a/lib/synx/xcodeproj_ext/project/object/pbx_group.rb +++ b/lib/synx/xcodeproj_ext/project/object/pbx_group.rb @@ -3,8 +3,9 @@ class Project module Object class PBXGroup - def sync(group) + def sync(group, warn_type) ensure_internal_consistency(group) # Make sure we don't belong to any other groups + isError = false if excluded_from_sync? Synx::Tabber.puts "#{basename}/ (excluded)".yellow else @@ -17,16 +18,17 @@ def sync(group) # inside the loops. files.each do |pbx_file| pbx_file.work_pathname.dirname.mkpath - pbx_file.sync(self) + isError = pbx_file.sync(self, warn_type) || isError end all_groups.each do |group| group.work_pathname.dirname.mkpath - group.sync(self) + isError = group.sync(self, warn_type) || isError end sync_path Synx::Tabber.decrease end + return isError end def excluded_from_sync? diff --git a/spec/synx/original_file_structure.yml b/spec/synx/original_file_structure.yml new file mode 100644 index 0000000..f43eba0 --- /dev/null +++ b/spec/synx/original_file_structure.yml @@ -0,0 +1,44 @@ +dummy: + AlreadySynced: + Core Data.xcdatamodeld: + .xccurrentversion: + Core Data.xcdatamodel: + contents: + Core Data 2.xcdatamodel: + contents: + Core Data 3.xcdatamodel: + contents: + Core Data 4.xcdatamodel: + contents: + FolderNotInXcodeProj: + AnotherFileNotInXcodeProj.h: + NSObject+abc.h: + NSObject+abc.m: + Wowwww.h: + Wowwww.m: + Woot.h: + Woot.m: + stuff.xml: + FileNotInXcodeProj.h + ManyFiles.h + ManyFiles.m + Wow.h + Wow.m + data.json + dummy-Prefix.pch + dummy.h + dummy.m + en.lproj: + Localizable.strings: + de.lproj: + Localizable.strings: + folderWithGroupNotLinked: + data.json + image-not-in-xcodeproj.png: + image.png: +dummyTests: + dummyTests-Info.plist: + dummyTests-prefix.pch: + dummyTests.m: + en.lproj: + InfoPlist.strings: diff --git a/spec/synx/project_spec.rb b/spec/synx/project_spec.rb index 0a1cbad..6c3b414 100644 --- a/spec/synx/project_spec.rb +++ b/spec/synx/project_spec.rb @@ -92,6 +92,10 @@ def expected_group_structure YAML::load_file(File.expand_path("../expected_group_structure.yml", __FILE__)) end + def original_file_structure + YAML::load_file(File.expand_path("../original_file_structure.yml", __FILE__)) + end + describe "with no additional options" do before(:all) do @@ -121,6 +125,16 @@ def expected_group_structure end end + describe "with warnings only option enabled" do + before(:all) do + DUMMY_SYNX_TEST_PROJECT.sync(:prune => true, :output => StringIO.new) + end + + it "should not make any changes to file structure" do + verify_file_structure(Pathname(DUMMY_SYNX_TEST_PROJECT_PATH).parent, original_file_structure) + end + end + describe "with the prune option toggled" do before(:all) do @@ -235,4 +249,4 @@ def expected_group_structure expect(value).to eq(expected) end end -end \ No newline at end of file +end