lib/ole/storage/file_system.rb in ruby-ole-1.2.9 vs lib/ole/storage/file_system.rb in ruby-ole-1.2.10
- old
+ new
@@ -43,16 +43,17 @@
# tries to get a dirent for path. return nil if it doesn't exist
# (change it)
def dirent_from_path path
dirent = @root
- path = file.expand_path path
- path = path.sub(/^\/*/, '').sub(/\/*$/, '').split(/\/+/)
+ path = file.expand_path(path).split('/')
until path.empty?
+ part = path.shift
+ next if part.empty?
return nil if dirent.file?
- return nil unless dirent = dirent/path.shift
- end
+ return nil unless dirent = dirent/part
+ end
dirent
end
class FileClass
class Stat
@@ -105,26 +106,32 @@
def initialize ole
@ole = ole
end
def expand_path path
- # get the raw stored pwd value (its blank for root)
- pwd = @ole.dir.instance_variable_get :@pwd
- # its only absolute if it starts with a '/'
- path = "#{pwd}/#{path}" unless path =~ /^\//
+ # its already absolute if it starts with a '/'
+ unless path =~ /^\//
+ # get the raw stored pwd value (its blank for root)
+ pwd = @ole.dir.instance_variable_get :@pwd
+ path = "#{pwd}/#{path}"
+ end
# at this point its already absolute. we use File.expand_path
# just for the .. and . handling
# No longer use RUBY_PLATFORM =~ /win/ as it matches darwin. better way?
- File.expand_path(path)[File::ALT_SEPARATOR == "\\" ? (2..-1) : (0..-1)]
+ if File::ALT_SEPARATOR != "\\"
+ File.expand_path(path)
+ else
+ File.expand_path(path)[2..-1]
+ end
end
# +orig_path+ is just so that we can use the requested path
# in the error messages even if it has been already modified
def dirent_from_path path, orig_path=nil
orig_path ||= path
dirent = @ole.dirent_from_path path
- raise Errno::ENOENT, orig_path unless dirent
+ raise Errno::ENOENT, orig_path unless dirent
raise Errno::EISDIR, orig_path if dirent.dir?
dirent
end
private :dirent_from_path
@@ -150,11 +157,11 @@
rescue Errno::ENOENT
# maybe instead of repeating this everywhere, i should have
# a get_parent_dirent function.
parent_path, basename = File.split expand_path(path)
parent = @ole.dir.send :dirent_from_path, parent_path, path
- parent.children << dirent = Dirent.new(@ole, :type => :file, :name => basename)
+ parent << dirent = Dirent.new(@ole, :type => :file, :name => basename)
end
else
dirent = dirent_from_path path
end
dirent.open mode, &block
@@ -209,51 +216,42 @@
# we actually get here, but rcov doesn't think so. add 1 + 1 to
# keep rcov happy for now... :)
1 + 1
end
# reparent the dirent
- from_parent_path, from_basename = File.split expand_path(from_path)
to_parent_path, to_basename = File.split expand_path(to_path)
- from_parent = @ole.dir.send :dirent_from_path, from_parent_path, from_path
+ from_parent = dirent.parent
to_parent = @ole.dir.send :dirent_from_path, to_parent_path, to_path
- from_parent.children.delete dirent
+ from_parent.delete dirent, false
# and also change its name
dirent.name = to_basename
- to_parent.children << dirent
+ to_parent << dirent
0
end
- # crappy copy from Dir.
def unlink(*paths)
paths.each do |path|
- dirent = @ole.dirent_from_path path
- # i think we should free all of our blocks from the
- # allocation table.
- # i think if you run repack, all free blocks should get zeroed,
- # but currently the original data is there unmodified.
- open(path) { |f| f.truncate 0 }
- # remove ourself from our parent, so we won't be part of the dir
- # tree at save time.
- parent_path, basename = File.split expand_path(path)
- parent = @ole.dir.send :dirent_from_path, parent_path, path
- parent.children.delete dirent
+ dirent = dirent_from_path path
+ dirent.parent.delete dirent
end
paths.length # hmmm. as per ::File ?
end
alias delete :unlink
end
#
- # an *instance* of this class is supposed to provide similar methods
+ # An *instance* of this class is supposed to provide similar methods
# to the class methods of Dir itself.
#
- # pretty complete. like zip/zipfilesystem's implementation, i provide
+ # Fairly complete - like zip/zipfilesystem's implementation, i provide
# everything except chroot and glob. glob could be done with a glob
- # to regex regex, and then simply match in the entries array... although
- # recursive glob complicates that somewhat.
+ # to regex conversion, and then simply match in the entries array...
+ # although recursive glob complicates that somewhat.
#
- # Dir.chroot, Dir.glob, Dir.[], and Dir.tmpdir is the complete list.
+ # Dir.chroot, Dir.glob, Dir.[], and Dir.tmpdir is the complete list of
+ # methods still missing.
+ #
class DirClass
def initialize ole
@ole = ole
@pwd = ''
end
@@ -269,36 +267,30 @@
end
private :dirent_from_path
def open path
dir = Dir.new path, entries(path)
- if block_given?
- yield dir
- else
- dir
- end
+ return dir unless block_given?
+ yield dir
end
# as for file, explicit alias to inhibit block
def new path
open path
end
# pwd is always stored without the trailing slash. we handle
# the root case here
def pwd
- if @pwd.empty?
- '/'
- else
- @pwd
- end
+ return '/' if @pwd.empty?
+ @pwd
end
alias getwd :pwd
def chdir orig_path
# make path absolute, squeeze slashes, and remove trailing slash
- path = @ole.file.expand_path(orig_path).gsub(/\/+/, '/').sub(/\/$/, '')
+ path = @ole.file.expand_path(orig_path).squeeze('/').sub(/\/$/, '')
# this is just for the side effects of the exceptions if invalid
dirent_from_path path, orig_path
if block_given?
old_pwd = @pwd
begin
@@ -329,53 +321,34 @@
def foreach path, &block
entries(path).each(&block)
end
- # there are some other important ones, like:
- # chroot (!), glob etc etc. for now, i think
def mkdir path
- # as for rmdir below:
parent_path, basename = File.split @ole.file.expand_path(path)
# note that we will complain about the full path despite accessing
# the parent path. this is consistent with ::Dir
parent = dirent_from_path parent_path, path
# now, we first should ensure that it doesn't already exist
# either as a file or a directory.
raise Errno::EEXIST, path if parent/basename
- parent.children << Dirent.new(@ole, :type => :dir, :name => basename)
+ parent << Dirent.new(@ole, :type => :dir, :name => basename)
0
end
def rmdir path
dirent = dirent_from_path path
raise Errno::ENOTEMPTY, path unless dirent.children.empty?
-
- # now delete it, how to do that? the canonical representation that is
- # maintained is the root tree, and the children array. we must remove it
- # from the children array.
- # we need the parent then. this sucks but anyway:
- # we need to split the path. but before we can do that, we need
- # to expand it first. eg. say we need the parent to unlink
- # a/b/../c. the parent should be a, not a/b/.., or a/b.
- parent_path, basename = File.split @ole.file.expand_path(path)
- # this shouldn't be able to fail if the above didn't
- parent = dirent_from_path parent_path
- # note that the way this currently works, on save and repack time this will get
- # reflected. to work properly, ie to make a difference now it would have to re-write
- # the dirent. i think that Ole::Storage#close will handle that. and maybe include a
- # #repack.
- parent.children.delete dirent
+ dirent.parent.delete dirent
0 # hmmm. as per ::Dir ?
end
alias delete :rmdir
alias unlink :rmdir
# note that there is nothing remotely ole specific about
# this class. it simply provides the dir like sequential access
# methods on top of an array.
- # hmm, doesn't throw the IOError's on use of a closed directory...
class Dir
include Enumerable
attr_reader :path
def initialize path, entries
@@ -406,17 +379,15 @@
def pos= pos
raise IOError if @closed
@pos = [[0, pos].max, @entries.length].min
end
+ alias tell :pos
+ alias seek :pos=
def rewind
- raise IOError if @closed
- @pos = 0
+ seek 0
end
-
- alias tell :pos
- alias seek :pos=
end
end
end
end