class Bundler::FileUtils::Entry_

:nodoc: internal use only

def blockdev?

def blockdev?
  s = lstat!
  s and s.blockdev?
end

def chardev?

def chardev?
  s = lstat!
  s and s.chardev?
end

def check_have_lchmod?

def check_have_lchmod?
  return false unless File.respond_to?(:lchmod)
  File.lchmod 0
  return true
rescue NotImplementedError
  return false
end

def check_have_lchown?

def check_have_lchown?
  return false unless File.respond_to?(:lchown)
  File.lchown nil, nil
  return true
rescue NotImplementedError
  return false
end

def chmod(mode)

def chmod(mode)
  if symlink?
    File.lchmod mode, path() if have_lchmod?
  else
    File.chmod mode, path()
  end
rescue Errno::EOPNOTSUPP
end

def chown(uid, gid)

def chown(uid, gid)
  if symlink?
    File.lchown uid, gid, path() if have_lchown?
  else
    File.chown uid, gid, path()
  end
end

def copy(dest)

def copy(dest)
  lstat
  case
  when file?
    copy_file dest
  when directory?
    if !File.exist?(dest) and descendant_directory?(dest, path)
      raise ArgumentError, "cannot copy directory %s to itself %s" % [path, dest]
    end
    begin
      Dir.mkdir dest
    rescue
      raise unless File.directory?(dest)
    end
  when symlink?
    File.symlink File.readlink(path()), dest
  when chardev?, blockdev?
    raise "cannot handle device file"
  when socket?
    begin
      require 'socket'
    rescue LoadError
      raise "cannot handle socket"
    else
      raise "cannot handle socket" unless defined?(UNIXServer)
    end
    UNIXServer.new(dest).close
    File.chmod lstat().mode, dest
  when pipe?
    raise "cannot handle FIFO" unless File.respond_to?(:mkfifo)
    File.mkfifo dest, lstat().mode
  when door?
    raise "cannot handle door: #{path()}"
  else
    raise "unknown file type: #{path()}"
  end
end

def copy_file(dest)

def copy_file(dest)
  File.open(path()) do |s|
    File.open(dest, 'wb', s.stat.mode) do |f|
      IO.copy_stream(s, f)
    end
  end
end

def copy_metadata(path)

def copy_metadata(path)
  st = lstat()
  if !st.symlink?
    File.utime st.atime, st.mtime, path
  end
  mode = st.mode
  begin
    if st.symlink?
      begin
        File.lchown st.uid, st.gid, path
      rescue NotImplementedError
      end
    else
      File.chown st.uid, st.gid, path
    end
  rescue Errno::EPERM, Errno::EACCES
    # clear setuid/setgid
    mode &= 01777
  end
  if st.symlink?
    begin
      File.lchmod mode, path
    rescue NotImplementedError, Errno::EOPNOTSUPP
    end
  else
    File.chmod mode, path
  end
end

def dereference?

def dereference?
  @deref
end

def descendant_directory?(descendant, ascendant)

def descendant_directory?(descendant, ascendant)
  if File::FNM_SYSCASE.nonzero?
    File.expand_path(File.dirname(descendant)).casecmp(File.expand_path(ascendant)) == 0
  else
    File.expand_path(File.dirname(descendant)) == File.expand_path(ascendant)
  end
end

def directory?

def directory?
  s = lstat!
  s and s.directory?
end

def door?

def door?
  s = lstat!
  s and (s.mode & 0xF000 == S_IF_DOOR)
end

def entries

def entries
  opts = {}
  opts[:encoding] = fu_windows? ? ::Encoding::UTF_8 : path.encoding
  files = Dir.children(path, **opts)
  untaint = RUBY_VERSION < '2.7'
  files.map {|n| Entry_.new(prefix(), join(rel(), untaint ? n.untaint : n)) }
end

def exist?

def exist?
  begin
    lstat
    true
  rescue Errno::ENOENT
    false
  end
end

def file?

def file?
  s = lstat!
  s and s.file?
end

def have_lchmod?

def have_lchmod?
  # This is not MT-safe, but it does not matter.
  if @@fileutils_rb_have_lchmod == nil
    @@fileutils_rb_have_lchmod = check_have_lchmod?
  end
  @@fileutils_rb_have_lchmod
end

def have_lchown?

def have_lchown?
  # This is not MT-safe, but it does not matter.
  if @@fileutils_rb_have_lchown == nil
    @@fileutils_rb_have_lchown = check_have_lchown?
  end
  @@fileutils_rb_have_lchown
end

def initialize(a, b = nil, deref = false)

def initialize(a, b = nil, deref = false)
  @prefix = @rel = @path = nil
  if b
    @prefix = a
    @rel = b
  else
    @path = a
  end
  @deref = deref
  @stat = nil
  @lstat = nil
end

def inspect

def inspect
  "\#<#{self.class} #{path()}>"
end

def join(dir, base)

def join(dir, base)
  return File.path(dir) if not base or base == '.'
  return File.path(base) if not dir or dir == '.'
  begin
    File.join(dir, base)
  rescue EncodingError
    if fu_windows?
      File.join(dir.encode(::Encoding::UTF_8), base.encode(::Encoding::UTF_8))
    else
      raise
    end
  end
end

def link(dest)

def link(dest)
  case
  when directory?
    if !File.exist?(dest) and descendant_directory?(dest, path)
      raise ArgumentError, "cannot link directory %s to itself %s" % [path, dest]
    end
    begin
      Dir.mkdir dest
    rescue
      raise unless File.directory?(dest)
    end
  else
    File.link path(), dest
  end
end

def lstat

def lstat
  if dereference?
    @lstat ||= File.stat(path())
  else
    @lstat ||= File.lstat(path())
  end
end

def lstat!

def lstat!
  lstat()
rescue SystemCallError
  nil
end

def path

def path
  if @path
    File.path(@path)
  else
    join(@prefix, @rel)
  end
end

def pipe?

def pipe?
  s = lstat!
  s and s.pipe?
end

def platform_support

def platform_support
  return yield unless fu_windows?
  first_time_p = true
  begin
    yield
  rescue Errno::ENOENT
    raise
  rescue => err
    if first_time_p
      first_time_p = false
      begin
        File.chmod 0700, path()   # Windows does not have symlink
        retry
      rescue SystemCallError
      end
    end
    raise err
  end
end

def postorder_traverse

def postorder_traverse
  if directory?
    begin
      children = entries()
    rescue Errno::EACCES
      # Failed to get the list of children.
      # Assuming there is no children, try to process the parent directory.
      yield self
      return
    end
    children.each do |ent|
      ent.postorder_traverse do |e|
        yield e
      end
    end
  end
  yield self
end

def prefix

def prefix
  @prefix || @path
end

def preorder_traverse

def preorder_traverse
  stack = [self]
  while ent = stack.pop
    yield ent
    stack.concat ent.entries.reverse if ent.directory?
  end
end

def rel

def rel
  @rel
end

def remove

def remove
  if directory?
    remove_dir1
  else
    remove_file
  end
end

def remove_dir1

def remove_dir1
  platform_support {
    Dir.rmdir path().chomp(?/)
  }
end

def remove_file

def remove_file
  platform_support {
    File.unlink path
  }
end

def socket?

def socket?
  s = lstat!
  s and s.socket?
end

def stat

def stat
  return @stat if @stat
  if lstat() and lstat().symlink?
    @stat = File.stat(path())
  else
    @stat = lstat()
  end
  @stat
end

def stat!

def stat!
  return @stat if @stat
  if lstat! and lstat!.symlink?
    @stat = File.stat(path())
  else
    @stat = lstat!
  end
  @stat
rescue SystemCallError
  nil
end

def symlink?

def symlink?
  s = lstat!
  s and s.symlink?
end

def wrap_traverse(pre, post)

def wrap_traverse(pre, post)
  pre.call self
  if directory?
    entries.each do |ent|
      ent.wrap_traverse pre, post
    end
  end
  post.call self
end