diff --git a/lib/nanoc/data_sources/filesystem.rb b/lib/nanoc/data_sources/filesystem.rb index c697fc8ee2..5fdce86dfc 100644 --- a/lib/nanoc/data_sources/filesystem.rb +++ b/lib/nanoc/data_sources/filesystem.rb @@ -117,7 +117,7 @@ def read_proto_document(content_filename, meta_filename, klass) ProtoDocument.new(is_binary: true, filename: content_filename, attributes: meta) elsif is_binary && klass == Nanoc::Int::Layout - raise "The layout file '#{content_filename}' is a binary file, but layouts can only be textual" + raise Errors::BinaryLayout.new(content_filename) else parse_result = parse(content_filename, meta_filename) @@ -239,11 +239,11 @@ def all_split_files_in(dir_name) # Check number of files per type unless [0, 1].include?(meta_filenames.size) - raise "Found #{meta_filenames.size} meta files for #{basename}; expected 0 or 1" + raise Errors::MultipleMetaFiles.new(meta_filenames, basename) end unless config[:identifier_type] == 'full' unless [0, 1].include?(content_filenames.size) - raise "Found #{content_filenames.size} content files for #{basename}; expected 0 or 1" + raise Errors::MultipleContentFiles.new(meta_filenames, basename) end end @@ -352,7 +352,7 @@ def parse_with_frontmatter(content_filename) pieces = data.split(/^(-{5}|-{3})[ \t]*\r?\n?/, 3) if pieces.size < 4 - raise "The file '#{content_filename}' appears to start with a metadata section (three or five dashes at the top) but it does not seem to be in the correct format." + raise Errors::InvalidFormat.new(content_filename) end meta = parse_metadata(pieces[2], content_filename) @@ -366,7 +366,7 @@ def parse_metadata(data, filename) begin meta = YAML.load(data) || {} rescue => e - raise "Could not parse YAML for #{filename}: #{e.message}" + raise Errors::UnparseableMetadata.new(filename, e) end verify_meta(meta, filename) @@ -386,16 +386,10 @@ def initialize(content:, attributes:, attributes_data:) end end - class InvalidMetadataError < Nanoc::Error - def initialize(filename, klass) - super("The file #{filename} has invalid metadata (expected key-value pairs, found #{klass} instead)") - end - end - def verify_meta(meta, filename) return if meta.is_a?(Hash) - raise InvalidMetadataError.new(filename, meta.class) + raise Errors::InvalidMetadata.new(filename, meta.class) end # Reads the content of the file with the given name and returns a string @@ -407,7 +401,7 @@ def read(filename) begin data = File.read(filename) rescue => e - raise "Could not read #{filename}: #{e.inspect}" + raise Errors::FileUnreadable.new(filename, e) end # Fix @@ -422,11 +416,11 @@ def read(filename) begin data.encode!('UTF-8') rescue - raise_encoding_error(filename, original_encoding) + raise Errors::InvalidEncoding.new(filename, original_encoding) end unless data.valid_encoding? - raise_encoding_error(filename, original_encoding) + raise Errors::InvalidEncoding.new(filename, original_encoding) end end @@ -435,12 +429,8 @@ def read(filename) data end - - # Raises an invalid encoding error for the given filename and encoding. - def raise_encoding_error(filename, encoding) - raise "Could not read #{filename} because the file is not valid #{encoding}." - end end end require_relative 'filesystem/tools' +require_relative 'filesystem/errors' diff --git a/lib/nanoc/data_sources/filesystem/errors.rb b/lib/nanoc/data_sources/filesystem/errors.rb new file mode 100644 index 0000000000..99e3ed6957 --- /dev/null +++ b/lib/nanoc/data_sources/filesystem/errors.rb @@ -0,0 +1,55 @@ +class Nanoc::DataSources::Filesystem < Nanoc::DataSource + # @api private + module Errors + class Generic < ::Nanoc::Error + end + + class BinaryLayout < Generic + def initialize(content_filename) + super("The layout file '#{content_filename}' is a binary file, but layouts can only be textual") + end + end + + class MultipleMetaFiles < Generic + def initialize(meta_filenames, basename) + super("Found #{meta_filenames.size} meta files for #{basename}; expected 0 or 1") + end + end + + class MultipleContentFiles < Generic + def initialize(content_filenames, basename) + super("Found #{content_filenames.size} content files for #{basename}; expected 0 or 1") + end + end + + class InvalidFormat < Generic + def initialize(content_filename) + super("The file '#{content_filename}' appears to start with a metadata section (three or five dashes at the top) but it does not seem to be in the correct format.") + end + end + + class UnparseableMetadata < Generic + def initialize(filename, error) + super("Could not parse metadata for #{filename}: #{error.message}") + end + end + + class InvalidMetadata < Generic + def initialize(filename, klass) + super("The file #{filename} has invalid metadata (expected key-value pairs, found #{klass} instead)") + end + end + + class InvalidEncoding < Generic + def initialize(filename, encoding) + super("Could not read #{filename} because the file is not valid #{encoding}.") + end + end + + class FileUnreadable < Generic + def initialize(filename, error) + super("Could not read #{filename}: #{error.inspect}") + end + end + end +end diff --git a/test/cli/commands/test_create_site.rb b/test/cli/commands/test_create_site.rb index 255f4ad71a..3d4c3f3235 100644 --- a/test/cli/commands/test_create_site.rb +++ b/test/cli/commands/test_create_site.rb @@ -75,7 +75,7 @@ def test_default_encoding FileUtils.cd('foo') do # Try with encoding = default encoding = utf-8 File.open('content/index.html', 'w') { |io| io.write('Hello ' + 0xD6.chr + "!\n") } - exception = assert_raises(RuntimeError) do + exception = assert_raises(Nanoc::DataSources::Filesystem::Errors::InvalidEncoding) do Nanoc::Int::SiteLoader.new.new_from_cwd end assert_equal 'Could not read content/index.html because the file is not valid UTF-8.', exception.message diff --git a/test/data_sources/test_filesystem.rb b/test/data_sources/test_filesystem.rb index f55e326355..d1f9077ac9 100644 --- a/test/data_sources/test_filesystem.rb +++ b/test/data_sources/test_filesystem.rb @@ -135,7 +135,7 @@ def test_load_binary_layouts File.open('foo/stuff.dat', 'w') { |io| io.write('random binary data') } # Load - assert_raises(RuntimeError) do + assert_raises(Nanoc::DataSources::Filesystem::Errors::BinaryLayout) do data_source.send(:load_objects, 'foo', Nanoc::Int::Layout) end end @@ -642,7 +642,7 @@ def test_all_split_files_in_with_multiple_content_files end # Check - assert_raises RuntimeError do + assert_raises(Nanoc::DataSources::Filesystem::Errors::MultipleContentFiles) do data_source.send(:all_split_files_in, '.') end end @@ -829,7 +829,7 @@ def test_parse_embedded_invalid_2 data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil) # Parse it - assert_raises(RuntimeError) do + assert_raises(Nanoc::DataSources::Filesystem::Errors::InvalidFormat) do data_source.instance_eval { parse('test.html', nil) } end end @@ -981,7 +981,7 @@ def test_parse_internal_bad_metadata data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil) - assert_raises(Nanoc::DataSources::Filesystem::InvalidMetadataError) do + assert_raises(Nanoc::DataSources::Filesystem::Errors::InvalidMetadata) do data_source.instance_eval { parse('test.html', nil) } end end @@ -992,7 +992,7 @@ def test_parse_external_bad_metadata data_source = Nanoc::DataSources::Filesystem.new(nil, nil, nil, nil) - assert_raises(Nanoc::DataSources::Filesystem::InvalidMetadataError) do + assert_raises(Nanoc::DataSources::Filesystem::Errors::InvalidMetadata) do data_source.instance_eval { parse('test.html', 'test.yaml') } end end