class FPM::Fry::Chroot

Helper class for filesystem operations inside staging directory. Resolves all symlinks relativ to a given base directory.

Constants

FOLLOW
FOLLOW_ALL_BUT_LAST

Attributes

base[R]

Public Class Methods

new(base) click to toggle source

@param [String] base filesystem base

# File lib/fpm/fry/chroot.rb, line 10
def initialize(base)
  raise ArgumentError, "Base #{base.inspect} is not a directory" unless File.directory? base
  @base = base
end

Public Instance Methods

entries(path) click to toggle source

Returns all directory entries like Dir.entries. @param [String] path @return [Array<String>] entries

# File lib/fpm/fry/chroot.rb, line 18
def entries(path)
  dir = rebase(path)
  return Dir.entries(dir)
rescue => ex
  raise Fry::WithData(ex, path: path)
end
find(path, &block) click to toggle source

Yields all entries recursively like Find.find. @param [String] path @yield entry @yieldparam [String] entry

# File lib/fpm/fry/chroot.rb, line 39
def find(path, &block)
  if stat(path).directory?
    catch(:prune) do
      block.call(path)
      entries(path).each do | e |
        next if e == "."
        next if e == ".."
        ep = File.join(path,e)
        find(ep, &block)
      end
    end
  else
    block.call(path)
  end
  return nil
end
lstat(file) click to toggle source

Stats a file without following the last symlink like File.lstat. @param [String] file @return [File::Stat] stat @see (File.lstat)

# File lib/fpm/fry/chroot.rb, line 60
def lstat(file)
  File.lstat(rebase(file, FOLLOW_ALL_BUT_LAST))
end
open(path,*args,&block) click to toggle source

Opens a file like File.open. @param [String] path @see (File.open)

# File lib/fpm/fry/chroot.rb, line 28
def open(path,*args,&block)
  file = rebase(path)
  return File.open(file,*args,&block)
rescue => ex
  raise Fry::WithData(ex, path: path)
end
stat(file) click to toggle source

Stats a file like File.stat. @param [String] file @return [File::Stat] stat @see (File.stat)

# File lib/fpm/fry/chroot.rb, line 68
def stat(file)
  File.stat(rebase(file))
end

Private Instance Methods

rebase(path, symlink_strategy = FOLLOW) click to toggle source
# File lib/fpm/fry/chroot.rb, line 91
def rebase(path, symlink_strategy = FOLLOW)
  segs = path.split('/')
  current = []
  while segs.any?
    seg = segs.shift
    case seg
    when '', '.' then next
    when '..' then
      # We don't check if anything was actually removed.
      # This is consistent with File/Dir behavior.
      current.pop
    else
      current << seg
      rl = symlink_strategy.call(base, current, segs)
      if rl
        if rl.start_with? '/'
          current = []
        else
          current.pop
        end
        segs.unshift *rl.split('/')
      end
    end
  end
  return [base,*current].join('/')
end