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