Class: File
- Defined in:
- lib/ruby_archive/handlers/rubyzip/zip/stdrubyext.rb,
lib/ruby_archive/patch/file.rb
Overview
:nodoc:all
Direct Known Subclasses
Constant Summary collapse
- @@ruby_archive_file_class_bind =
binding
Class Method Summary collapse
-
.forward_method_multi(method, min_arguments = 1, first_path_arg_index = 0) ⇒ Object
See
forward_method_single
. -
.forward_method_single(method, min_arguments = 1, path_arg_index = 0, on_load_error = nil) ⇒ Object
Automates creating class methods that operate on either normal files or files within archives, given a symbol with the name of the method and the index of the argument containing the file name.
-
.forward_method_unsupported(method, min_arguments = 1, path_args = [0], return_instead = :raise) ⇒ Object
Marks a function as unsupported by archives.
-
.in_archive?(path) ⇒ Boolean
Determines whether a specified location appears to be within an archive.
-
.open(path, mode = 'r', perm = 0666, &block) ⇒ Object
Open a file, either from the filesystem or from within an archive.
-
.read(fileName) ⇒ Object
singleton method read does not exist in 1.6.x.
Class Method Details
.forward_method_multi(method, min_arguments = 1, first_path_arg_index = 0) ⇒ Object
See forward_method_single
. Does nearly the same thing, but assumes the argument list ends with a list of files to operate on rather than a single file to operate on.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/ruby_archive/patch/file.rb', line 81 def forward_method_multi method, min_arguments=1, first_path_arg_index=0 alias_name = "ruby_archive_original_#{method}".intern eval_line = __LINE__; eval %{ unless File.respond_to?(:#{alias_name}) alias_method(:#{alias_name}, :#{method}) end protected(:#{alias_name}) define_method(:#{method}) do |*args| if (#{min_arguments} > 0 && args.size == 0) raise ArgumentError, "wrong number of arguments (0 for #{min_arguments})" end # grab args before the list of filepaths, and the list of filepaths args_before_path = nil if #{first_path_arg_index} == 0 args_before_path = [] else args_before_path = args[0..(#{first_path_arg_index - 1})] end path_list = args[#{first_path_arg_index}..(args.size - 1)] path_list.each do |path| location_info = File.in_archive?(path) if location_info == false args_to_send = args_before_path + [path] File.send(:#{alias_name},*args_to_send) next else begin file_handler = RubyArchive.get(location_info[0]).file raise NotImplementedError unless file_handler.respond_to?(:#{method}) args_to_send = args_before_path + [location_info[1]] file_handler.send(:#{method},*args_to_send) next rescue NotImplementedError raise NotImplementedError, "#{method} not implemented in handler for specified archive" end end end return path_list.size end }, @@ruby_archive_file_class_bind, __FILE__, eval_line end |
.forward_method_single(method, min_arguments = 1, path_arg_index = 0, on_load_error = nil) ⇒ Object
Automates creating class methods that operate on either normal files or files within archives, given a symbol with the name of the method and the index of the argument containing the file name.
It performs tasks in the following order:
-
alias the original method to ruby_archive_original_name, marks the alias as protected.
-
overrides the class method so that it tries, in order:
1. returns the result of the original class method if the given file exists 2. returns the result of the original class method if an archive is not specified 3. returns the result of the archive handler method if an archive is specified
The current method of doing this is kind of ugly and involves ‘eval’, but it works(tm). This method is definitely a candidate for improvement.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/ruby_archive/patch/file.rb', line 33 def forward_method_single method, min_arguments=1, path_arg_index=0, on_load_error=nil alias_name = "ruby_archive_original_#{method}".intern eval_line = __LINE__; eval %{ unless File.respond_to?(:#{alias_name}) alias_method(:#{alias_name}, :#{method}) end protected(:#{alias_name}) define_method(:#{method}) do |*args| if (#{min_arguments} > 0 && args.size == 0) raise ArgumentError, "wrong number of arguments (0 for #{min_arguments})" end # grab args before and after the filepath args_before_path = nil if #{path_arg_index} == 0 args_before_path = [] else args_before_path = args[0..(#{path_arg_index - 1})] end path = args[#{path_arg_index}] args_after_path = args[(#{path_arg_index + 1})..(args.size-1)] # get file location info and forward it to the appropriate method location_info = File.in_archive?(path) if location_info == false return File.send(:#{alias_name},*args) else begin file_handler = RubyArchive.get(location_info[0]).file raise NotImplementedError unless file_handler.respond_to?(:#{method}) args_to_send = args_before_path + [location_info[1]] + args_after_path return file_handler.send(:#{method},*args_to_send) rescue LoadError raise if #{on_load_error.inspect}.nil? return #{on_load_error.inspect} rescue NotImplementedError raise NotImplementedError, "#{method} not implemented in handler for specified archive" end end end }, @@ruby_archive_file_class_bind, __FILE__, eval_line end |
.forward_method_unsupported(method, min_arguments = 1, path_args = [0], return_instead = :raise) ⇒ Object
Marks a function as unsupported by archives. path_args should be an array of argument indices containing filepaths to check.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/ruby_archive/patch/file.rb', line 129 def forward_method_unsupported method, min_arguments=1, path_args=[0], return_instead=:raise alias_name = "ruby_archive_original_#{method}".intern eval_line = __LINE__; eval %{ unless File.respond_to?(:#{alias_name}) alias_method(:#{alias_name}, :#{method}) end protected(:#{alias_name}) define_method(:#{method}) do |*args| if (#{min_arguments} > 0 && args.size == 0) raise ArgumentError, "wrong number of arguments (0 for #{min_arguments})" end # grab args before the list of filepaths, and the list of filepaths #{path_args.inspect}.each do |i| if File.in_archive?(args[i]) != false unless #{return_instead.inspect} == :raise warn "Dir.#{method} is not supported for files within archives" return #{return_instead.inspect} end raise NotImplementedError, "File.#{method} is not supported for files within archives (yet)" end end File.send(:#{alias_name},*args) end }, @@ruby_archive_file_class_bind, __FILE__, eval_line end |
.in_archive?(path) ⇒ Boolean
Determines whether a specified location appears to be within an archive. It first checks if the given location exists on the filesystem, and if not check if there is an ‘!’ mark in the filename.
Returns an array of [archive_path, file_inside_archive] if location appears to be in an archive, false
otherwise.
11 12 13 14 15 16 17 |
# File 'lib/ruby_archive/patch/file.rb', line 11 def in_archive? path return false if File.ruby_archive_original_exist?(path) sp = path.split('!') return sp if sp.size == 2 raise ArgumentError, "only one archive deep supported (for now)" if sp.size > 2 return false end |
.open(path, mode = 'r', perm = 0666, &block) ⇒ Object
Open a file, either from the filesystem or from within an archive. If the given path exists on the filesystem, it will be opened from there. Otherwise the path will be split by delimiter ! and checked again.
TODO: ‘perm’ is currently ignored by anything sent to an archive, due to incompatibility with rubyzip.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/ruby_archive/patch/file.rb', line 172 def open path,mode='r',perm=0666,&block # 0666 from io.c in MRI if File.ruby_archive_original_exist?(path) return File.ruby_archive_original_open(path,mode,perm,&block) end location_info = File.in_archive?(path) if location_info == false return File.ruby_archive_original_open(path,mode,perm,&block) else f = RubyArchive.get(location_info[0]).file.open(location_info[1],mode) return f if block.nil? begin return yield(f) ensure f.close end end end |
.read(fileName) ⇒ Object
singleton method read does not exist in 1.6.x
192 193 194 195 196 197 198 199 |
# File 'lib/ruby_archive/patch/file.rb', line 192 def read name,length=nil,offset=nil ret = nil self.open(name) do |f| f.seek(offset) unless offset.nil? ret = f.read(length) end ret end |