lib/xcodeproj/plist.rb
module Xcodeproj # Provides support for loading and serializing property list files. # module Plist autoload :FFI, 'xcodeproj/plist/ffi' autoload :PlistGem, 'xcodeproj/plist/plist_gem' # @return [Hash] Returns the native objects loaded from a property list # file. # # @param [#to_s] path # The path of the file. # def self.read_from_path(path) path = path.to_s unless File.exist?(path) raise Informative, "The plist file at path `#{path}` doesn't exist." end if file_in_conflict?(path) raise Informative, "The file `#{path}` is in a merge conflict." end implementation.read_from_path(path) end # Serializes a hash as an XML property list file. # # @param [#to_hash] hash # The hash to store. # # @param [#to_s] path # The path of the file. # def self.write_to_path(hash, path) if hash.respond_to?(:to_hash) hash = hash.to_hash else raise TypeError, "The given `#{hash.inspect}` must respond " \ "to #to_hash'." end unless path.is_a?(String) || path.is_a?(Pathname) raise TypeError, "The given `#{path}` must be a string or 'pathname'." end path = path.to_s raise IOError, 'Empty path.' if path.empty? implementation.write_to_path(hash, path) end # The known modules that can serialize plists. # KNOWN_IMPLEMENTATIONS = [:FFI, :PlistGem] class << self # @return The module used to implement plist serialization. # attr_accessor :implementation def implementation @implementation ||= autoload_implementation end end # Attempts to autoload a known plist implementation. # # @return a successfully loaded plist serialization implementation. # def self.autoload_implementation failures = KNOWN_IMPLEMENTATIONS.map do |impl| begin impl = Plist.const_get(impl) failure = impl.attempt_to_load! return impl if failure.nil? failure rescue NameError, LoadError => e e.message end end.compact raise Informative, "Unable to load a plist implementation:\n\n#{failures.join("\n\n")}" end # @return [Bool] Checks whether there are merge conflicts in the file. # # @param [#to_s] path # The path of the file. # def self.file_in_conflict?(path) File.read(path).match(/^(<|=|>){7}/) end end end