lib/nanoc/data_sources/filesystem.rb in nanoc-4.0.0a1 vs lib/nanoc/data_sources/filesystem.rb in nanoc-4.0.0a2

- old
+ new

@@ -31,19 +31,10 @@ load_objects(layouts_dir_name, 'layout', Nanoc::Int::Layout) end protected - # Creates a new object (item or layout) on disk in dir_name according to - # the given identifier. The file will have its attributes taken from the - # attributes hash argument and its content from the content argument. - def create_object(_dir_name, _content, _attributes, _identifier, _params = {}) - raise NotImplementedError.new( - "#{self.class} does not implement ##{name}" - ) - end - # Creates instances of klass corresponding to the files in dir_name. The # kind attribute indicates the kind of object that is being loaded and is # used solely for debugging purposes. # # This particular implementation loads objects from a filesystem-based @@ -52,99 +43,107 @@ # needs to be present, obviously) and the content file can start with a # metadata section. # # @see Nanoc::DataSources::Filesystem#load_objects def load_objects(dir_name, kind, klass) - all_split_files_in(dir_name).map do |base_filename, (meta_ext, content_ext)| - # Get filenames - meta_filename = filename_for(base_filename, meta_ext) - content_filename = filename_for(base_filename, content_ext) + res = [] - # Read content and metadata - is_binary = content_filename && !@site.config[:text_extensions].include?(File.extname(content_filename)[1..-1]) - if is_binary && klass == Nanoc::Int::Item - meta = (meta_filename && YAML.load_file(meta_filename)) || {} - content_or_filename = content_filename - elsif is_binary && klass == Nanoc::Int::Layout - raise "The layout file '#{content_filename}' is a binary file, but layouts can only be textual" - else - meta, content_or_filename = parse(content_filename, meta_filename, kind) - end + all_split_files_in(dir_name).each do |base_filename, (meta_ext, content_exts)| + content_exts.each do |content_ext| + # Get filenames + meta_filename = filename_for(base_filename, meta_ext) + content_filename = filename_for(base_filename, content_ext) - # Get attributes - attributes = { - filename: content_filename, - content_filename: content_filename, - meta_filename: meta_filename, - extension: content_filename ? ext_of(content_filename)[1..-1] : nil, - }.merge(meta) + # Read content and metadata + is_binary = content_filename && !@site.config[:text_extensions].include?(File.extname(content_filename)[1..-1]) + if is_binary && klass == Nanoc::Int::Item + meta = (meta_filename && YAML.load_file(meta_filename)) || {} + content_or_filename = content_filename + elsif is_binary && klass == Nanoc::Int::Layout + raise "The layout file '#{content_filename}' is a binary file, but layouts can only be textual" + else + meta, content_or_filename = parse(content_filename, meta_filename, kind) + end - # Get identifier - if meta_filename - identifier = identifier_for_filename(meta_filename[(dir_name.length + 1)..-1]) - elsif content_filename - identifier = identifier_for_filename(content_filename[(dir_name.length + 1)..-1]) - else - raise 'meta_filename and content_filename are both nil' - end + # Get attributes + attributes = { + filename: content_filename, + content_filename: content_filename, + meta_filename: meta_filename, + extension: content_filename ? ext_of(content_filename)[1..-1] : nil, + }.merge(meta) - # Get modification times - meta_mtime = meta_filename ? File.stat(meta_filename).mtime : nil - content_mtime = content_filename ? File.stat(content_filename).mtime : nil - if meta_mtime && content_mtime - mtime = meta_mtime > content_mtime ? meta_mtime : content_mtime - elsif meta_mtime - mtime = meta_mtime - elsif content_mtime - mtime = content_mtime - else - raise 'meta_mtime and content_mtime are both nil' - end + # Get identifier + if meta_filename + identifier = identifier_for_filename(meta_filename[dir_name.length..-1]) + elsif content_filename + identifier = identifier_for_filename(content_filename[dir_name.length..-1]) + else + raise 'meta_filename and content_filename are both nil' + end - # Create layout object - klass.new( - content_or_filename, attributes, identifier, - binary: is_binary, mtime: mtime - ) + # Get modification times + meta_mtime = meta_filename ? File.stat(meta_filename).mtime : nil + content_mtime = content_filename ? File.stat(content_filename).mtime : nil + if meta_mtime && content_mtime + mtime = meta_mtime > content_mtime ? meta_mtime : content_mtime + elsif meta_mtime + mtime = meta_mtime + elsif content_mtime + mtime = content_mtime + else + raise 'meta_mtime and content_mtime are both nil' + end + + # Create layout object + res << klass.new( + content_or_filename, attributes, identifier, + binary: is_binary, mtime: mtime + ) + end end + + res end - # Finds all items/layouts/... in the given base directory. Returns a hash - # in which the keys are the file's dirname + basenames, and the values a - # pair consisting of the metafile extension and the content file - # extension. The meta file extension or the content file extension can be - # nil, but not both. Backup files are ignored. For example: + # e.g. # # { - # 'content/foo' => [ 'yaml', 'html' ], - # 'content/bar' => [ 'yaml', nil ], - # 'content/qux' => [ nil, 'html' ] + # 'content/foo' => [ 'yaml', ['html', 'md'] ], + # 'content/bar' => [ 'yaml', [nil] ], + # 'content/qux' => [ nil, ['html'] ] # } def all_split_files_in(dir_name) - grouped_filenames = + by_basename = all_files_in(dir_name) .reject { |fn| fn =~ /(~|\.orig|\.rej|\.bak)$/ } .group_by { |fn| basename_of(fn) } - grouped_filenames.each_pair do |key, filenames| + all = {} + + by_basename.each_pair do |basename, filenames| # Divide meta_filenames = filenames.select { |fn| ext_of(fn) == '.yaml' } content_filenames = filenames.select { |fn| ext_of(fn) != '.yaml' } # Check number of files per type unless [0, 1].include?(meta_filenames.size) - raise "Found #{meta_filenames.size} meta files for #{key}; expected 0 or 1" + raise "Found #{meta_filenames.size} meta files for #{basename}; expected 0 or 1" end - unless [0, 1].include?(content_filenames.size) - raise "Found #{content_filenames.size} content files for #{key}; expected 0 or 1" + unless config[:identifier_style] == 'full' + unless [0, 1].include?(content_filenames.size) + raise "Found #{content_filenames.size} content files for #{basename}; expected 0 or 1" + end end - # Reorder elements and convert to extnames - filenames[0] = meta_filenames[0] ? 'yaml' : nil - filenames[1] = content_filenames[0] ? ext_of(content_filenames[0])[1..-1] || '' : nil + all[basename] = [] + all[basename][0] = + meta_filenames[0] ? 'yaml' : nil + all[basename][1] = + content_filenames.any? ? content_filenames.map { |fn| ext_of(fn)[1..-1] || '' } : [nil] end - grouped_filenames + all end # Returns all files in the given directory and directories below it. def all_files_in(dir_name) Nanoc::Extra::FilesystemTools.all_files_in(dir_name, config[:extra_files])