class Path

Constants

EMPTY

Empty path.

@return [Path] Empty path.

Public Class Methods

default_glob_flags(flags) click to toggle source

@!visibility private

# File lib/rubypath/dir_operations.rb, line 26
def default_glob_flags(flags)
  if flags.nil? && defined?(::File::FNM_EXTGLOB)
    ::File::FNM_EXTGLOB
  else
    flags.to_i
  end
end
getwd() click to toggle source

Returns the current working directory.

@return [Path] Current working directory. @see ::Dir.getwd

# File lib/rubypath/dir_operations.rb, line 10
def getwd
  new Backend.instance.getwd
end
glob(pattern, flags = nil) { |Path path| ... } click to toggle source
# File lib/rubypath/dir_operations.rb, line 14
def glob(pattern, flags = nil)
  flags = default_glob_flags(flags)

  if block_given?
    Backend.instance.glob(pattern, flags) {|path| yield Path path }
  else
    Backend.instance.glob(pattern, flags).map(&Path)
  end
end
like?(obj) click to toggle source

Check if given object is like a path.

An object is like a path if

  1. It is a {Path} object.

  2. It is a string.

  3. It responds to {#to_path} and {#to_path} returns a string.

  4. It responds to {#path} and {#path} returns a string.

If no rule matches it is not considered to be like a path.

@return [Boolean] True if object is path like, false otherwise.

rubocop:disable Metrics/CyclomaticComplexity

# File lib/rubypath/construction.rb, line 36
def like?(obj)
  return true if obj.is_a?(self)
  return true if obj.is_a?(String)
  return true if obj.respond_to?(:to_path) && obj.to_path.is_a?(String)
  return true if obj.respond_to?(:path) && obj.path.is_a?(String)
  false
end
like_path(obj) click to toggle source

Convert given object to path string using {::Path.like?} rules.

@note Should not be used directly.

@return [String] @raise [ArgumentError] If given object is not {::Path.like?}. @see ::Path.like?

rubocop:disable Metrics/MethodLength

# File lib/rubypath/construction.rb, line 54
def like_path(obj)
  case obj
    when String
      return obj
    else
      %i[to_path path to_str to_s].each do |mth|
        if obj.respond_to?(mth) && obj.send(mth).is_a?(String)
          return obj.send(mth)
        end
      end
  end

  raise ArgumentError.new \
    "Argument #{obj.inspect} cannot be converted to path string."
end
mock(_opts = {}) { |Path('/'), instance.backend| ... } click to toggle source

Configure current path backend. Can be used to configure specified test scenario. If no virtual or scoped path backend is set the default one will be used.

Do not forget to use mock file system in your specs: See more {Backend.mock}.

around do |example|
  Path::Backend.mock &example
end

Note: Not all operations are supported.

@example

Path.mock do |root|
  root.mkpath '/a/b/c/d/e'
  root.touch '/a/b/test.txt'
  root.join('/a/c/lorem.yaml').write YAML.dump({'lorem' => 'ipsum'})
  #...
end

@example Configure backend (only with virtual file system)

Path.mock do |root, backend|
  backend.current_user = 'test'
  backend.homes = {'test' => '/path/to/test/home'}
  #...
end

@yield |root, backend| Yield file system root path and current backend. @yieldparam root [Path] Root path of current packend. @yieldparam backend [Backend] Current backend.

# File lib/rubypath/mock.rb, line 39
def mock(_opts = {})
  yield Path('/'), Backend.instance.backend if block_given?
  nil
end
new(*args) click to toggle source

Create new {Path}.

If single argument is a path object it will be returned and no new one will be created. If not arguments are given {Path::EMPTY} will be returned.

@see initialize

Calls superclass method
# File lib/rubypath/construction.rb, line 15
def new(*args)
  args.flatten!
  return Path::EMPTY if args.empty?
  return args.first if args.size == 1 && args.first.is_a?(self)
  super
end
new(*args) click to toggle source

Initialize new {Path} object.

Given arguments will be converted to String using `#to_path`, `#path` or `#to_s` in this order if they return a String object.

@overload initialize([[String, to_path, path, to_s], …]

# File lib/rubypath/construction.rb, line 99
def initialize(*args)
  parts = args.flatten
  @path = if parts.size > 1
            ::File.join(*parts.map {|p| Path.like_path p })
          elsif parts.size == 1
            Path.like_path(parts.first).dup
          else
            ''
          end
end
separator() click to toggle source

Return system file path separator.

@return [String] File separator. @see ::File::SEPARATOR

# File lib/rubypath/construction.rb, line 76
def separator
  ::File::SEPARATOR
end
to_proc() click to toggle source

Allow class object to be used as a bock.

@example

%w(path/to/fileA path/to/fileB).map(&Path)
# File lib/rubypath/construction.rb, line 85
def to_proc
  proc {|*args| Path.new(*args) }
end
umask(mask = nil) click to toggle source

Read or set process umask.

@overload umask

Read process umask.

@return [Integer] Process umask.

@overload umask(mask)

Set process umask.

@param mask [Integer] New process umask.

@see File.umask

# File lib/rubypath/file_operations.rb, line 184
def umask(mask = nil)
  if mask
    invoke_backend :umask=, mask
  else
    invoke_backend :umask
  end
end
Also aliased as: umask=
umask=(mask = nil)
Alias for: umask

Private Class Methods

invoke_backend(mth, *args) click to toggle source
# File lib/rubypath/backend.rb, line 89
def invoke_backend(mth, *args)
  Backend.instance.send mth, *args
end

Public Instance Methods

==(other)
Alias for: eql?
absolute(*args)
Alias for: expand
absolute?() click to toggle source

Check if path is an absolute path.

An absolute path is a path with a leading slash.

@return [Boolean] True if path is absolute. @see relative?

# File lib/rubypath/path_predicates.rb, line 13
def absolute?
  internal_path[0] == '/'
end
absolute_path(*args)
Alias for: expand
ancestors() click to toggle source

Return an array of all ancestors.

@example

Path('/path/to/file').ancestors
# => [<Path:/path/to/file.txt>, <Path:/path/to>, <Path:/path>, <Path:/>]

@return [Array<Path>] All ancestors.

# File lib/rubypath/path_operations.rb, line 220
def ancestors
  each_ancestors.to_a
end
as_absolute() click to toggle source

Return given path as a absolute path by just prepending a leading slash.

@example

Path.new('path/to/file').as_absolute
#=> <Path '/path/to/file'>

@return [Path] Path transformed to absolute path.

# File lib/rubypath/path_operations.rb, line 248
def as_absolute
  if internal_path[0] != '/'
    Path "/#{internal_path}"
  else
    self
  end
end
as_relative() click to toggle source

Return given path as a relative path by just striping leading slashes.

@example

Path.new('/path/to/file').as_relative
#=> <Path 'path/to/file'>

@return [Path] Path transformed to relative path.

# File lib/rubypath/path_operations.rb, line 232
def as_relative
  if (rel_path = internal_path.gsub(%r{^/+}, '')) != internal_path
    Path rel_path
  else
    self
  end
end
ascend() { |path| ... } click to toggle source

Yield given block for path and each ancestor.

@example

Path('/path/to/file.txt').ascend{|path| p path}
#<Path:/path/to/file.txt>
#<Path:/path/to>
#<Path:/path>
#<Path:/>
#=> <Path:/path/to/file.txt>

@example

Path('path/to/file.txt').ascend{|path| p path}
#<Path:path/to/file.txt>
#<Path:path/to>
#<Path:path>
#<Path:.>
#=> <Path:path/to/file.txt>

@yield |path| Yield path and ancestors. @yieldparam path [Path] Path or ancestor. @return [Path] Self.

# File lib/rubypath/path_operations.rb, line 198
def ascend
  return to_enum(:ascend) unless block_given?

  path = self
  loop do
    yield path
    break unless (path = path.parent)
  end

  self
end
Also aliased as: each_ancestors
atime() click to toggle source

Return file access time.

@return [Time] Time of last access.

# File lib/rubypath/file_operations.rb, line 149
def atime
  invoke_backend :atime
end
atime=(time) click to toggle source

Set last access time.

@param [Time] Time of last access.

# File lib/rubypath/file_operations.rb, line 157
def atime=(time)
  invoke_backend :atime=, internal_path, time
end
basename()
Alias for: name
chmod(mode) click to toggle source
# File lib/rubypath/file_operations.rb, line 165
def chmod(mode)
  invoke_backend :chmod, internal_path, mode
end
cleanpath() click to toggle source

Return cleaned path with all dot components removed.

No file system will accessed and not symlinks will be resolved.

@example

Path('./file.txt').cleanpath
#=> <Path file.txt>

@example

Path('path/to/another/../file/../../txt').cleanpath
#=> <Path path/txt>

@return [Path] Cleaned path.

# File lib/rubypath/path_operations.rb, line 310
def cleanpath
  path = Pathname.new(self).cleanpath
  if path == internal_path
    self
  elsif internal_path[-1] == Path.separator
    Path path, ''
  else
    Path path
  end
end
components(*args) click to toggle source

Return an array with all path components.

@example

Path('path/to/file').components
# => ["path", "to", "file"]

@example

Path('/path/to/file').components
# => ["path", "to", "file"]

@return [Array<String>] File names.

# File lib/rubypath/path_operations.rb, line 87
def components(*args)
  each_component(*args).to_a
end
directory?() click to toggle source

Check if path points to a directory.

@return [Boolean] True if path is a directory. @see ::File.directory?

# File lib/rubypath/file_predicates.rb, line 31
def directory?
  invoke_backend :directory?
end
dirname() click to toggle source

Return path to parent directory. If path is already an absolute or relative root nil will be returned.

@example Get parent directory:

Path.new('/path/to/file').dir.path
#=> '/path/to'

@example Try to get parent of absolute root:

Path.new('/').dir
#=> nil

@example Try to get parent of relative root:

Path.new('.').dir
#=> nil

@return [Path] Parent path or nil if path already points to an absolute

or relative root.
# File lib/rubypath/path_operations.rb, line 167
def dirname
  return nil if %w[. /].include? internal_path

  dir = ::File.dirname internal_path
  dir.empty? ? nil : self.class.new(dir)
end
Also aliased as: parent
dotfile?() click to toggle source

Check if file or directory is a dot file.

@example

Path("~/.gitconfig").dotfile?
#=> true

@return [Boolean] True if file is a dot file otherwise false.

# File lib/rubypath/path_predicates.rb, line 60
def dotfile?
  name[0] == '.'
end
each_ancestors()
Alias for: ascend
each_component(opts = {}, &block) click to toggle source

Iterate over all path components.

@overload each_component

Return a enumerator to iterate over all path components.

@example Iterate over path components using a enumerator
  enum = Path('/path/to/file.txt').each_component
  enum.each{|fn| puts fn}
  # => "path"
  # => "to"
  # => "file.txt"

@example Map each path component and create a new path
  path = Path('/path/to/file.txt')
  Path path.each_component.map{|fn| fn.length}
  # => <Path:"/4/2/8">

@return [Enumerator] Return a enumerator for all path components.

@overload each_component(&block)

Yield given block for each path components.

@example Print each file name
  Path('/path/to/file.txt').each_component{|fn| puts fn}
  # => "path"
  # => "to"
  # => "file.txt"

@param block [Proc] Block to invoke with each path component.
  If no block is given an enumerator will returned.
@return [self] Self.
# File lib/rubypath/path_operations.rb, line 62
def each_component(opts = {}, &block)
  rv = if opts[:empty]
         # split eats leading slashes
         ary = path.split(Path.separator)
         # so add an empty string if path ends with slash
         ary << '' if path[-1] == Path.separator
         ary.each(&block)
       else
         Pathname(path).each_filename(&block)
       end
  block ? self : rv
end
entries(*_args) click to toggle source

Return list of entries in directory. That includes special directories (`.`, `..`).

Given arguments will be joined before children are listed for directory.

@return [Array<Path>] Entries in directory.

# File lib/rubypath/dir_operations.rb, line 77
def entries(*_args)
  invoke_backend(:entries, internal_path).map(&Path)
end
eql?(other) click to toggle source

Compare path to given object. If object is a string, Path or #{Path.like?} they will be compared using the string paths. Otherwise they are assumed as not equal.

@param other [Object] Object to compare path with. @return [Boolean] True if object represents same path.

# File lib/rubypath/comparison.rb, line 13
def eql?(other)
  if other.is_a?(Path)
    cleanpath.internal_path == other.cleanpath.internal_path
  elsif Path.like?(other)
    Path.new(other).eql?(self)
  end
end
Also aliased as: ==
exist?()
Alias for: exists?
existent?()
Alias for: exists?
exists?() click to toggle source

Check if path points to an existing location.

@return [Boolean] True if path exists. @see ::File.exists?

# File lib/rubypath/file_predicates.rb, line 20
def exists?
  invoke_backend :exists?
end
Also aliased as: exist?, existent?
expand(*args) click to toggle source

Converts a pathname to an absolute pathname. Given arguments will be joined to current path before expanding path. Relative paths are referenced from the current working directory of the process unless the `:base` option is set, which will be used as the starting point.

The given pathname may start with a “~”, which expands to the process owner's home directory (the environment variable HOME must be set correctly). “~user” expands to the named user's home directory.

@example

Path('path/to/../tmp').expand
#=> <Path:"path/tmp">

@example

Path('~/tmp').expand
#=> <Path:"/home/user/tmp">

@example

Path('~oma/tmp').expand
#=> <Path:"/home/oma/tmp">

@example

Path('~/tmp').expand('../file.txt')
#=> <Path:"/home/user/file.txt">

@return [Path] Expanded path. @see ::File#expand_path

# File lib/rubypath/path_operations.rb, line 119
def expand(*args)
  opts = args.last.is_a?(Hash) ? args.pop : {}

  with_path(*args) do |path|
    base          = Path.like_path(opts[:base] || Backend.instance.getwd)
    expanded_path = Backend.instance.expand_path(path, base)
    if expanded_path != internal_path
      Path expanded_path
    else
      self
    end
  end
end
Also aliased as: expand_path, absolute, absolute_path
expand_path(*args)
Alias for: expand
ext()
Alias for: extension
extension() click to toggle source

Return last file extension.

@example

Path.new('/path/to/template.de.html.erb').extension
#=> 'erb'

@return [String] Last file extensions.

# File lib/rubypath/extensions.rb, line 31
def extension
  extensions.last
end
Also aliased as: ext
extensions() click to toggle source

Return list of all file extensions.

@example

Path.new('/path/to/template.de.html.erb').extensions
#=> ['de', 'html', 'erb']

@return [Array<String>] List of file extensions.

# File lib/rubypath/extensions.rb, line 14
def extensions
  if dotfile?
    name.split('.')[2..-1]
  else
    name.split('.')[1..-1]
  end
end
Also aliased as: exts
extname() click to toggle source

Return last file extension include dot character.

@return [String] Ext name. @see ::File.extname

# File lib/rubypath/extensions.rb, line 41
def extname
  ::File.extname name
end
exts()
Alias for: extensions
file?() click to toggle source

Check if path points to file.

@return [Boolean] True if path is a file. @see ::File.file?

# File lib/rubypath/file_predicates.rb, line 11
def file?
  invoke_backend :file?
end
glob(pattern, flags = nil, &block) click to toggle source
# File lib/rubypath/dir_operations.rb, line 82
def glob(pattern, flags = nil, &block)
  Path.glob(::File.join(escaped_glob_path, pattern), flags, &block)
end
inspect() click to toggle source

Return a useful object string representation.

@return [String] Useful object representation

# File lib/rubypath/identity.rb, line 20
def inspect
  "<#{self.class.name}:#{internal_path}>"
end
join(*args) click to toggle source

Join path with given arguments.

@overload initialize([[Path, String, to_path, path, to_s], …]

Join all given arguments to build a new path.

@example
  Path('/').join('test', %w(a b), 5, Pathname.new('file'))
  # => <Path:"/test/a/b/5/file">

@return [Path]

# File lib/rubypath/path_operations.rb, line 17
def join(*args)
  parts = args.flatten
  case parts.size
    when 0
      self
    when 1
      join = Path parts.shift
      join.absolute? ? join : Path(::File.join(path, join.path))
    else
      join(parts.shift).join(*parts)
  end
end
lookup(pattern, flags = nil) click to toggle source

Search for a file in current directory or parent directories.

Given search pattern can either be a regular expression or a shell glob expression.

@example

Path.cwd.lookup('project.{yml,yaml}')
#=> <Path:"/path/config.yml">

@example

Path.cwd.lookup(/config(_\d+).ya?ml/)
#=> <Path:"/path/config_354.yaml">

@example

Path('~').lookup('*config', ::File::FNM_DOTMATCH)
#=> <Path:"/gome/user/.gitconfig">

@param pattern [String|RegExp] Expression file name must match. @param flags [Integer] Additional flags. See {::File.fnmatch}.

Defaults to `File::FNM_EXTGLOB`.

@return [Path] Path to found file or nil.

# File lib/rubypath/file_operations.rb, line 108
def lookup(pattern, flags = nil) # rubocop:disable MethodLength
  flags = self.class.default_glob_flags(flags)

  expand.ascend do |path|
    case pattern
      when String
        path.entries.each do |c|
          return path.join(c) if ::File.fnmatch?(pattern, c.name, flags)
        end
      when Regexp
        path.entries.each do |c|
          # rubocop:disable RegexpMatch
          return path.join(c) if pattern =~ c.name
        end
    end
  end

  nil
end
mkdir(*args) click to toggle source

Create directory.

Given arguments will be joined with current path before directory is created.

@raise [Errno::ENOENT] If parent directory could not created. @return [Path] Path to created directory. @see mkpath

# File lib/rubypath/dir_operations.rb, line 46
def mkdir(*args)
  with_path(*args) do |path|
    Backend.instance.mkdir path
    Path path
  end
end
mkdir_p(*args)
Alias for: mkpath
mkfile(*args) click to toggle source

Create a file at pointed location and all missing parent directories.

Given arguments will be joined with current path before directories and file is created.

If file already exists nothing will be done.

@example

Path('/path/to/file.txt').mkfile
#=> <Path:"/path/to/file.txt">

@example

Path('/').mkfile('path', 'to', 'file.txt')
#=> <Path:"/path/to/file.txt">

@return [Path] Path to created or existent file.

# File lib/rubypath/file_operations.rb, line 74
def mkfile(*args) # rubocop:disable AbcSize
  with_path(*args) do |path|
    path.parent.mkpath if !path.exists? && path.parent && !path.parent.exists?

    if path.exists?
      raise Errno::ENOENT.new path.to_s unless path.file?
    else
      path.touch
    end
  end
end
mkpath(*args) click to toggle source

Create directory and all missing parent directories.

Given arguments will be joined with current path before directories are created.

@return [Path] Path to created directory. @see mkdir @see ::FileUtils.mkdir_p

# File lib/rubypath/dir_operations.rb, line 62
def mkpath(*args)
  with_path(*args) do |path|
    Backend.instance.mkpath path
    Path path
  end
end
Also aliased as: mkdir_p
mode() click to toggle source
# File lib/rubypath/file_operations.rb, line 161
def mode
  invoke_backend :mode
end
mountpoint?(*args) click to toggle source

@overload mountpoint?([Path, String], …)

Join current and given paths and check if resulting
path points to a mountpoint.

@example
  Path('/').mountpoint?('tmp')
  #=> true

@overload mountpoint?

Check if current path is a mountpoint.

@example
  Path('/tmp').mountpoint?
  #=> true

@return [Boolean] True if path is a mountpoint, false otherwise. @see Pathname#mountpoint?

# File lib/rubypath/path_predicates.rb, line 46
def mountpoint?(*args)
  with_path(*args) do |path|
    Backend.instance.mountpoint? path
  end
end
mtime() click to toggle source

Return file modification time.

@return [Time] Time of last modification.

# File lib/rubypath/file_operations.rb, line 133
def mtime
  invoke_backend :mtime
end
mtime=(time) click to toggle source

Set last modification time.

@param [Time] Time of last modification.

# File lib/rubypath/file_operations.rb, line 141
def mtime=(time)
  invoke_backend :mtime=, internal_path, time
end
name() click to toggle source

Return base name without path.

@return [String] Base name.

# File lib/rubypath/file_operations.rb, line 10
def name
  ::File.basename internal_path
end
Also aliased as: basename
only_filename?() click to toggle source

Check if path consists of only a filename.

@example

Path('file.txt').only_filename?
#=> true

@return [Boolean] True if path consists of only a filename.

# File lib/rubypath/path_operations.rb, line 145
def only_filename?
  internal_path.index(Path.separator).nil?
end
parent()
Alias for: dirname
path() click to toggle source

Return path as string. String will be duped before it gets returned and cannot be used to modify the path object.

@return [String] Path as string.

# File lib/rubypath/identity.rb, line 10
def path
  internal_path.dup
end
Also aliased as: to_path, to_str, to_s
pure_name() click to toggle source

Return the file name without any extensions.

@example

Path("template.de.html.slim").pure_name
#=> "template"

@example

Path("~/.gitconfig").pure_name
#=> ".gitconfig"

@return [String] File name without extensions.

# File lib/rubypath/extensions.rb, line 57
def pure_name
  if dotfile?
    name.split('.', 3)[0..1].join('.')
  else
    name.split('.', 2)[0]
  end
end
read(*args) click to toggle source

Read file content from disk.

@overload read()

Read all content from file.

Additional arguments will be passed to {::IO.read}.

@example
  Path('file.txt').read
  #=> "CONTENT"

@overload read(length, [..])

Read given amount of bytes from file.

Additional arguments will be passed to {::IO.read}.

@example
  Path('file.txt').read(4)
  #=> "CONT"

@param length [Integer] Number of bytes to read.

@overload read(length, offset, [..])

Read given amount of bytes from file starting at given offset.

Additional arguments will be passed to {::IO.read}.

@example
  Path('file.txt').read(4, 2)
  #=> "NTEN"

@param length [Integer] Number of bytes to read.
@param offset [Integer] Where to start reading.

@see IO.read @return [String] Read content.

# File lib/rubypath/io_operations.rb, line 81
def read(*args)
  invoke_backend :read, self, *args
end
relative?() click to toggle source

Check if path is a relative path.

A relative path does not start with a slash.

@return [Boolean] True if path is relative. @see absolute?

# File lib/rubypath/path_predicates.rb, line 24
def relative?
  !absolute?
end
relative_from(base) click to toggle source

Return a relative path from the given base path to the receiver path.

Both paths need to be either absolute or relative otherwise an error will be raised. The file system will not be accessed and no symlinks are assumed.

@example

relative = Path('src/lib/module1/class.rb')
  .relative_from('src/lib/module2')
#=> <Path '../module1/class.rb'>

@return [Path] Relative path from argument to receiver. @see Pathname#relative_path_from

rubocop:disable AbcSize rubocop:disable CyclomaticComplexity rubocop:disable MethodLength rubocop:disable PerceivedComplexity rubocop:disable LineLength

# File lib/rubypath/path_operations.rb, line 276
def relative_from(base)
  base = Path(base).cleanpath
  path = cleanpath

  return Path '.' if base == path

  if (base.relative? && path.absolute?) || (base.absolute? && path.relative?)
    raise ArgumentError.new \
      "Different prefix: #{base.inspect} and #{path.inspect}"
  end

  base = base.components(empty: true)
  path = path.components(empty: true)
  base.shift && path.shift while base.first == path.first && !(base.empty? || path.empty?)

  Path(*((['..'] * base.size) + path))
end
Also aliased as: relative_path_from
relative_path_from(base)
Alias for: relative_from
replace_extension(*args) click to toggle source

Replace last extension with one or multiple new extensions.

@example

Path('file.de.txt').replace_extension('html')
#=> <Path "file.de.html">

@example

Path('file.de.txt').replace_extension('html', 'erb')
#=> <Path "file.de.html.erb">

@return [Path] Path to new filename.

# File lib/rubypath/extensions.rb, line 155
def replace_extension(*args)
  extensions = self.extensions
  extensions.pop
  extensions += args.flatten

  replace_extensions extensions
end
replace_extensions(*args) click to toggle source

Replace file extensions with given new ones or by a given translation map.

@overload replace_extensions(exts)

Replace all extensions with given new ones. Number of given extensions
does not need to match number of existing extensions.

@example
  Path('file.de.txt').replace_extensions(%w(en html))
  #=> <Path "file.en.html">

@example
  Path('file.de.mobile.html.haml').replace_extensions(%w(int txt))
  #=> <Path "file.int.txt">

@param exts [Array<String>] New extensions.

@overload replace_extensions(ext, [ext, [..]])

Replace all extensions with given new ones. Number of given extensions
does not need to match number of existing extensions.

@example
  Path('file.de.txt').replace_extensions('en', 'html')
  #=> <Path "file.en.html">

@example
  Path('file.de.mobile.html.haml').replace_extensions('en', 'html')
  #=> <Path "file.en.html">

@example
  Path('file.de.txt').replace_extensions('html')
  #=> <Path "file.html">

@param ext [String] New extensions.

@overload replace_extensions(map)

Replace all matching extensions.

@example
  Path('file.de.html.haml').replace_extensions('de'=>'en', 'haml'=>'slim')
  #=> <Path "file.en.html.slim">

@param map [Hash<String, String>] Translation map as hash.

@return [Path] Path to new filename.

rubocop:disable AbcSize rubocop:disable CyclomaticComplexity rubocop:disable MethodLength rubocop:disable PerceivedComplexity

# File lib/rubypath/extensions.rb, line 116
def replace_extensions(*args)
  args.flatten!
  extensions = self.extensions

  if (replace = (args.last.is_a?(Hash) ? args.pop : nil))
    if args.empty?
      extensions.map! do |ext|
        replace[ext] ? replace[ext].to_s : ext
      end
    else
      raise ArgumentError.new 'Cannot replace extensions with array ' \
                              'and hash at the same time.'
    end
  else
    extensions = args.map(&:to_s)
  end

  if extensions == self.extensions
    self
  elsif only_filename?
    Path "#{pure_name}.#{extensions.join('.')}"
  else
    dirname.join "#{pure_name}.#{extensions.join('.')}"
  end
end
rm_r(*args)
Alias for: rmtree!
rm_rf(*args)
Alias for: rmtree
rmtree(*args) click to toggle source

Removes file or directory. If it's a directory it will be removed recursively.

WARNING: This method causes local vulnerability if one of parent directories or removing directory tree are world writable (including `/tmp`, whose permission is 1777), and the current process has strong privilege such as Unix super user (root), and the system has symbolic link. For secure removing see {#safe_rmtree}.

@return [Path] Path to removed file or directory.

# File lib/rubypath/dir_operations.rb, line 97
def rmtree(*args)
  with_path(*args) do |path|
    invoke_backend :rmtree, internal_path
    Path path
  end
end
Also aliased as: rm_rf
rmtree!(*args) click to toggle source

Removes file or directory. If it's a directory it will be removed recursively.

This method behaves exactly like {#rmtree} but will raise exceptions e.g. when file does not exist.

@return [Path] Path to removed file or directory.

# File lib/rubypath/dir_operations.rb, line 133
def rmtree!(*args)
  with_path(*args) do |path|
    invoke_backend :rmtree!, internal_path
    Path path
  end
end
Also aliased as: rm_r
safe_rmtree(*args) click to toggle source

Removes file or directory. If it's a directory it will be removed recursively.

This method uses #{FileUtils#remove_entry_secure} to avoid TOCTTOU (time-of-check-to-time-of-use) local security vulnerability of {#rmtree}. {#rmtree} causes security hole when:

  • Parent directory is world writable (including `/tmp`).

  • Removing directory tree includes world writable directory.

  • The system has symbolic link.

@return [Path] Path to removed file or directory.

# File lib/rubypath/dir_operations.rb, line 118
def safe_rmtree(*args)
  with_path(*args) do |path|
    invoke_backend :safe_rmtree, internal_path
    Path path
  end
end
safe_rmtree!(*args) click to toggle source

Removes file or directory. If it's a directory it will be removed recursively.

This method behaves exactly like {#safe_rmtree} but will raise exceptions e.g. when file does not exist.

@return [Path] Path to removed file or directory.

# File lib/rubypath/dir_operations.rb, line 149
def safe_rmtree!(*args)
  with_path(*args) do |path|
    invoke_backend :safe_rmtree!, internal_path
    Path path
  end
end
to_path()
Alias for: path
to_s()
Alias for: path
to_str()
Alias for: path
touch(*args) click to toggle source

Create new file at pointed location or update modification time if file exists.

@example

Path('/path/to/file.txt').touch
#=> <Path:"/path/to/file.txt">

@example

Path('/path/to').touch('file.txt')
#=> <Path:"/path/to/file.txt">

@return [Path] Path to touched file.

# File lib/rubypath/file_operations.rb, line 28
def touch(*args)
  with_path(*args) do |path|
    invoke_backend :touch, path
    Path path
  end
end
write(content, *args) click to toggle source

Write given content to file.

@overload write(content, [..])

Write given content to file. An existing file will be truncated otherwise
a file will be created.

Additional arguments will be passed to {::IO.write}.

@example
  Path('/path/to/file.txt').write('CONTENT')
  #=> 7

@param content [String] Content to write to file.

@overload write(content, offset, [..])

Write content at specific position in file. Content will be replaced
starting at given offset.

Additional arguments will be passed to {::IO.write}.

@example
  path.write('CONTENT', 4)
  #=> 7
  path.read
  #=> "1234CONTENT2345678"

@param content [String] Content to write to file.
@param offset [Integer] Offset where to start writing. If nil file will
  be truncated.

@see IO.write @return [Path] Self.

# File lib/rubypath/io_operations.rb, line 39
def write(content, *args)
  invoke_backend :write, self, content, *args
  self
end

Protected Instance Methods

internal_path() click to toggle source

Return internal path object without duping.

Must not be modified to not change internal state.

@return [String] Internal path. @see path

# File lib/rubypath/identity.rb, line 33
def internal_path
  @path
end
with_path(*args) { |join(*args)| ... } click to toggle source

If arguments are provided the current path will be joined with given arguments to the result will be yielded. If no arguments are given the current path will be yielded.

Internal helper method.

@example

def handle_both(*args)
  with_path(*args) do |path|
    # do something
  end
end

Returns whatever the block returns.

# File lib/rubypath/identity.rb, line 52
def with_path(*args)
  if args.any?
    yield join(*args)
  else
    yield self
  end
end

Private Instance Methods

escaped_glob_path() click to toggle source
# File lib/rubypath/dir_operations.rb, line 158
def escaped_glob_path
  internal_path.gsub(/[\[\]\*\?\{\}]/, '\\\\\0')
end
invoke_backend(mth, *args) click to toggle source
# File lib/rubypath/backend.rb, line 81
def invoke_backend(mth, *args)
  args << self if args.empty?
  self.class.send :invoke_backend, mth, *args
end