Module: Nanoc::DataSources::Filesystem::Tools Private

Defined in:
lib/nanoc/data_sources/filesystem/tools.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Contains useful functions for managing the filesystem.

Defined Under Namespace

Classes: MaxSymlinkDepthExceededError, UnsupportedFileTypeError

Class Method Summary collapse

Class Method Details

.all_files_and_dirs_in(dir_name, extra_files) ⇒ Array<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns all files and directories in the given directory and directories below it.

Parameters:

  • dir_name (String)

    The name of the directory whose contents to fetch

  • extra_files (String, Array, nil)

    The list of extra patterns to extend the file search for files not found by default, example “**/.htaccess,htpasswd”

Returns:

  • (Array<String>)

    A list of files and directories

Raises:

  • (Nanoc::Core::TrivialError)

    when pattern can not be handled



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/nanoc/data_sources/filesystem/tools.rb', line 106

def all_files_and_dirs_in(dir_name, extra_files)
  base_patterns = ["#{dir_name}/**/*"]

  extra_patterns =
    case extra_files
    when nil
      []
    when String
      ["#{dir_name}/#{extra_files.dup.delete_prefix('/')}"]
    when Array
      extra_files.map { |extra_file| "#{dir_name}/#{extra_file.dup.delete_prefix('/')}" }
    else
      raise(
        Nanoc::Core::TrivialError,
        "Do not know how to handle extra_files: #{extra_files.inspect}",
      )
    end

  patterns = base_patterns + extra_patterns
  Dir.glob(patterns)
end

.all_files_in(dir_name, extra_files, recursion_limit = 10) ⇒ Array<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns all files in the given directory and directories below it, following symlinks up to a maximum of ‘recursion_limit` times.

Parameters:

  • dir_name (String)

    The name of the directory whose contents to fetch

  • extra_files (String, Array, nil)

    The list of extra patterns to extend the file search for files not found by default, example “**/.htaccess,htpasswd”

  • recursion_limit (Integer) (defaults to: 10)

    The maximum number of times to recurse into a symlink to a directory

Returns:

  • (Array<String>)

    A list of file names

Raises:



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/nanoc/data_sources/filesystem/tools.rb', line 58

def all_files_in(dir_name, extra_files, recursion_limit = 10)
  all_files_and_dirs_in(dir_name, extra_files).map do |fn|
    case File.ftype(fn)
    when 'link'
      if recursion_limit.zero?
        raise MaxSymlinkDepthExceededError.new(fn)
      else
        absolute_target = resolve_symlink(fn)
        if File.file?(absolute_target)
          fn
        else
          all_files_in(absolute_target, extra_files, recursion_limit - 1).map do |sfn|
            fn + sfn[absolute_target.size..]
          end
        end
      end
    when 'file'
      fn
    when 'directory'
      nil
    else
      raise UnsupportedFileTypeError.new(fn)
    end
  end.compact.flatten
end

.expand_and_relativize_path(path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Expands the path (including resolving ~ for home directory) and returns a relative path to the expanded path.



86
87
88
89
90
91
# File 'lib/nanoc/data_sources/filesystem/tools.rb', line 86

def expand_and_relativize_path(path)
  from = Pathname.new(Dir.getwd)
  to = Pathname.new(File.expand_path(path))

  to.relative_path_from(from).to_s
end

.read_file(filename, config:) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads the content of the file with the given name and returns a string in UTF-8 encoding. The original encoding of the string is derived from the default external encoding, but this can be overridden by the “encoding” configuration attribute in the data source configuration.



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/nanoc/data_sources/filesystem/tools.rb', line 164

def read_file(filename, config:)
  # Read
  begin
    data = File.read(filename)
  rescue => e
    raise Errors::FileUnreadable.new(filename, e)
  end

  # Set original encoding, if any
  if config && config[:encoding]
    original_encoding = Encoding.find(config[:encoding])
    data.force_encoding(config[:encoding])
  else
    original_encoding = data.encoding
  end

  # Set encoding to UTF-8
  begin
    data.encode!('UTF-8')
  rescue
    raise Errors::InvalidEncoding.new(filename, original_encoding)
  end

  # Verify
  unless data.valid_encoding?
    raise Errors::InvalidEncoding.new(filename, original_encoding)
  end

  # Remove UTF-8 BOM (ugly)
  data.delete!("\xEF\xBB\xBF")

  data
end

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resolves the given symlink into an absolute path.

Parameters:

  • filename (String)

    The filename of the symlink to resolve

  • recursion_limit (Integer) (defaults to: 5)

    The maximum number of times to recurse into a symlink

Returns:

  • (String)

    The absolute resolved filename of the symlink target

Raises:



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/nanoc/data_sources/filesystem/tools.rb', line 142

def resolve_symlink(filename, recursion_limit = 5)
  target = File.readlink(filename)
  absolute_target = Nanoc::Core::Utils.expand_path_without_drive_identifier(target, File.dirname(filename))

  case File.ftype(absolute_target)
  when 'link'
    if recursion_limit.zero?
      raise MaxSymlinkDepthExceededError.new(absolute_target)
    else
      resolve_symlink(absolute_target, recursion_limit - 1)
    end
  when 'file', 'directory'
    absolute_target
  else
    raise UnsupportedFileTypeError.new(absolute_target)
  end
end