filesystem 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/filesystem.rb +351 -0
  2. data/lib/filesystem.rb~ +343 -0
  3. metadata +49 -0
@@ -0,0 +1,351 @@
1
+ # FileSystem is a test-obsessed library for mocking out the entire file system.
2
+ # It provides mock objects that clone the functionality of File, FileUtils,
3
+ # Dir, and other in-Ruby file-access libraries.
4
+ #
5
+ # To use FileSystem in your production code, call FileSystem.get_[ class ].
6
+ #
7
+ # FileSystem.get_file => File
8
+ # FileSystem.get_file_utils => FileUtils
9
+ # FileSystem.get_dir => Dir
10
+ # FileSystem.get_dir.entries( '.' ) => [".", "..", ...]
11
+ #
12
+ # Then, to turn these into mock instances for a test case, simply call
13
+ #
14
+ # FileSystem.mock = true
15
+ #
16
+ # When you've done this, the normal calls will actually return adapters that
17
+ # pretend to be the class in question:
18
+ #
19
+ # FileSystem.get_file => FileSystem::FileAdapter
20
+ # FileSystem.get_file_utils => FileSystem::FileUtilsAdapter
21
+ # FileSystem.get_dir => FileSystem::DirAdapter
22
+ # FileSystem.get_dir.entries( '.' ) => [".", "..", ...]
23
+ #
24
+ # You can get direct access to the enclosed MockFileSystem by calling
25
+ # FileSystem.mock_file_system.
26
+ #
27
+ # You can view the Rubyforge project page at
28
+ # http://rubyforge.org/projects/filesystem.
29
+
30
+ require 'delegate'
31
+ require 'extensions/all'
32
+ require 'fileutils'
33
+ require 'singleton'
34
+
35
+ module FileSystem
36
+ Version = '0.1.0'
37
+
38
+ @@mock = false
39
+
40
+ def self.method_missing( symbol, *args ) #:nodoc:
41
+ class_name = nil
42
+ if symbol.id2name =~ /^get_(.*)/
43
+ class_name = $1.capitalize
44
+ class_name.gsub!( /_(\w)/ ) { |s| $1.capitalize }
45
+ unless %w( Dir File FileUtils ).include?( class_name )
46
+ class_name = nil
47
+ end
48
+ end
49
+ if class_name
50
+ if @@mock
51
+ return_class = Class.by_name( 'FileSystem::' + class_name + 'Adapter' )
52
+ else
53
+ return_class = Class.by_name( class_name )
54
+ end
55
+ return_class || super
56
+ elsif @@mock
57
+ mock_file_system.send( symbol, *args )
58
+ else
59
+ super
60
+ end
61
+ end
62
+
63
+ # Tell FileSystem whether to offer interfaces to the real or mock file system.
64
+ # +is_mock+ should be a Boolean.
65
+ def self.mock= ( is_mock ); @@mock = is_mock; end
66
+
67
+ # If we're in mock mode, this will return the MockFileSystem; otherwise it
68
+ # will raise a RuntimeError.
69
+ def self.mock_file_system
70
+ @@mock ? MockFileSystem.instance : ( raise RuntimeError )
71
+ end
72
+
73
+ module Adapter #:nodoc:
74
+ @@delegated_methods = [ :delete, :entries, :mtime ]
75
+
76
+ def get_node( nodename ); MockFileSystem.instance.get_node( nodename ); end
77
+
78
+ def method_missing( sym, *args )
79
+ if @@delegated_methods.include?( sym )
80
+ get_node( args.first ).send( sym )
81
+ else
82
+ super
83
+ end
84
+ end
85
+
86
+ def respond_to?( sym )
87
+ @@delegated_methods.include?( sym ) ? true : super
88
+ end
89
+ end
90
+
91
+ class DirAdapter #:nodoc:
92
+ extend Adapter
93
+ include Adapter
94
+
95
+ def self.mkdir( dirname )
96
+ path = Path.new( dirname ).absolute
97
+ get_node( path.parent ).mkdir( path.node )
98
+ end
99
+
100
+ def initialize( dirname )
101
+ unless get_node( dirname ).class == MockFileSystem::MockDir
102
+ raise Errno::ENOTDIR
103
+ end
104
+ end
105
+ end
106
+
107
+ class FileAdapter #:nodoc:
108
+ extend Adapter
109
+
110
+ def self.chmod( perms, *filenames )
111
+ get_node( filenames.first ).permissions = perms
112
+ end
113
+
114
+ class << self
115
+ def exist?( filename )
116
+ begin
117
+ get_node( filename )
118
+ true
119
+ rescue Errno::ENOENT
120
+ false
121
+ end
122
+ end
123
+
124
+ alias_method :exists?, :exist?
125
+ end
126
+
127
+ def self.open( fd, mode_string = File::RDONLY, &action )
128
+ if mode_string.class == String
129
+ if mode_string == 'w'
130
+ mode_string = File::WRONLY
131
+ end
132
+ end
133
+ if mode_string == File::RDONLY
134
+ node = get_node( fd )
135
+ if node && node.permissions && node.permissions[0] == 0
136
+ raise Errno::EACCES
137
+ end
138
+ result = action.call( node )
139
+ node.rewind
140
+ result
141
+ else
142
+ path = Path.new( fd ).absolute
143
+ dir = get_node( path.parent )
144
+ if ( mode_string & File::APPEND > 0 )
145
+ mock_file = get_node( fd )
146
+ else
147
+ mock_file = MockFileSystem::MockFile.new( dir, path.node, '' )
148
+ end
149
+ if ( mode_string & File::APPEND == File::APPEND )
150
+ mock_file.pos = mock_file.size
151
+ end
152
+ action.call( mock_file )
153
+ mock_file.rewind
154
+ if ( mode_string & File::APPEND == 0 )
155
+ dir[path.node] = mock_file
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ class FileUtilsAdapter #:nodoc:
162
+ extend Adapter
163
+
164
+ def self.cp( src, dest, options = {} )
165
+ file = get_node( src ).clone
166
+ dest_path = Path.new( dest ).absolute
167
+ dest_dir = get_node( dest_path.parent )
168
+ dest_dir[dest_path.node] = file
169
+ file.name = dest_path.node
170
+ file.parent = dest_dir
171
+ end
172
+
173
+ def self.mv( src, dest, options = {} )
174
+ cp( src, dest, options )
175
+ FileSystem.get_file.delete( src )
176
+ end
177
+
178
+ def self.touch( file )
179
+ begin
180
+ get_node( file ).mtime = Time.now
181
+ rescue Errno::ENOENT
182
+ path = Path.new( file ).absolute
183
+ parent_dir = get_node( path.parent )
184
+ file = MockFileSystem::MockFile.new( parent_dir, path.node, nil )
185
+ parent_dir[path.node] = file
186
+ end
187
+ end
188
+ end
189
+
190
+ # The MockFileSystem is the singleton class that pretends to be the file system in mock mode. When it's first created, it fills in one path up to your real directory location; other paths will have to be filled by hand using +fill_path+.
191
+ class MockFileSystem
192
+ include Singleton
193
+
194
+ # Flushes all file information out of the MockFileSystem.
195
+ def self.flush; instance.flush; end
196
+
197
+ def initialize #:nodoc:
198
+ flush
199
+ end
200
+
201
+ # Flushes all file information out of the MockFileSystem.
202
+ def flush; @root = MockRoot.new( '' ); fill_path( '.' ); end
203
+
204
+ def get_node( dirname ) #:nodoc:
205
+ @root.get_node( dirname )
206
+ end
207
+
208
+ # Use this method to fill in directory paths. This is the same as calling mkdir a bunch of times.
209
+ #
210
+ # FileSystem.mock_file_system.fill_path '/usr/local/bin'
211
+ # FileSystem.mock_file_system.fill_path '/home/francis/Desktop/myproject/'
212
+ def fill_path( dirname )
213
+ @root.fill_path( Path.new( dirname ).absolute.strip )
214
+ end
215
+
216
+ module Node #:nodoc:
217
+ attr_accessor :mtime, :name, :parent, :permissions
218
+ end
219
+
220
+ class MockDir < DelegateClass( Hash ) #:nodoc:
221
+ include Node
222
+
223
+ def initialize( name, parent = nil )
224
+ super( {} )
225
+ @name, @parent = name, parent
226
+ @mtime = Time.now
227
+ end
228
+
229
+ def []= ( name, child )
230
+ super
231
+ @mtime = child.mtime
232
+ end
233
+
234
+ def delete( child = nil )
235
+ child ? super( child.name ) : parent.delete( self )
236
+ end
237
+
238
+ def entries; %w( . .. ).concat( keys ); end
239
+
240
+ def get_node( dirname )
241
+ if dirname.first == '..'
242
+ self.parent.get_node( dirname[1..-1] )
243
+ elsif dirname.first == '.'
244
+ self.get_node( dirname[1..-1] )
245
+ elsif dirname.size > 1
246
+ subdir = self[dirname.first]
247
+ subdir ? subdir.get_node( dirname[1..-1] ) : ( raise Errno::ENOENT )
248
+ elsif dirname == ''
249
+ self
250
+ else
251
+ self[dirname.strip] or ( raise Errno::ENOENT )
252
+ end
253
+ end
254
+
255
+ def fill_dir( dirname )
256
+ dir = self[dirname]
257
+ if dir.nil?
258
+ dir = MockDir.new( dirname, self )
259
+ self[dirname] = dir
260
+ @mtime = dir.mtime
261
+ end
262
+ dir
263
+ end
264
+
265
+ def fill_path( dirname )
266
+ if dirname.size > 1
267
+ dir = fill_dir( dirname.first )
268
+ dir.fill_path( dirname[1..-1] )
269
+ else
270
+ fill_dir( dirname )
271
+ end
272
+ end
273
+
274
+ def mkdir( dirname ); fill_path( Path.new( dirname ) ); end
275
+ end
276
+
277
+ class MockFile < DelegateClass( StringIO ) #:nodoc:
278
+ include Node
279
+
280
+ attr_writer :contents
281
+
282
+ def initialize( parent, name, contents )
283
+ @name = name; @parent = parent; @mtime = Time.now; @contents = contents
284
+ super( StringIO.new( contents ) ) if contents
285
+ end
286
+
287
+ def clone
288
+ rewind
289
+ clone = self.class.new( @parent, @name, gets( nil ) )
290
+ clone.mtime = @mtime
291
+ clone
292
+ end
293
+
294
+ def delete; parent.delete( self ); end
295
+
296
+ def gets( sep_string = $/ )
297
+ @contents ? super( sep_string ) : nil
298
+ end
299
+
300
+ def rewind; @contents ? super : nil; end
301
+ end
302
+
303
+ class MockRoot < MockDir #:nodoc:
304
+ def get_node( dirname )
305
+ begin
306
+ super( Path.new( dirname ).absolute.strip )
307
+ rescue Errno::ENOENT
308
+ raise Errno::ENOENT.new( dirname )
309
+ end
310
+ end
311
+ end
312
+ end
313
+
314
+ class Path < String #:nodoc:
315
+ @@getwd = nil
316
+
317
+ def self.getwd
318
+ @@getwd = Dir.getwd if @@getwd.nil?
319
+ @@getwd
320
+ end
321
+
322
+ def []( *args ); Path.new( self.split( "/" )[*args].join( "/" ) ); end
323
+
324
+ def absolute
325
+ if self =~ %r{^\w}
326
+ Path.new( File.join( self.class.getwd, self ) )
327
+ else
328
+ new_str = self.to_s
329
+ new_str.gsub!( %r{^\.\.}, self.class.getwd + '/..' )
330
+ new_str.gsub!( %r{^\.}, self.class.getwd )
331
+ Path.new( new_str )
332
+ end
333
+ end
334
+
335
+ def first; self.split( "/" ).first; end
336
+
337
+ def parent
338
+ self =~ %r{^(.*)/(.*?)$}
339
+ $1
340
+ end
341
+
342
+ def node
343
+ self =~ %r{^(.*)/(.*?)$}
344
+ $2
345
+ end
346
+
347
+ def size; self.split( '/' ).size; end
348
+
349
+ def strip; self.gsub( %r{^/+}, '' ).gsub( %r{/+$}, '' ); end
350
+ end
351
+ end
@@ -0,0 +1,343 @@
1
+ require 'delegate'
2
+ require 'extensions/all'
3
+ require 'fileutils'
4
+ require 'singleton'
5
+
6
+ # FileSystem is a test-obsessed library for mocking out the entire file system.
7
+ # It provides mock objects that clone the functionality of File, FileUtils,
8
+ # Dir, and other in-Ruby file-access libraries.
9
+ #
10
+ # To use FileSystem in your production code, call FileSystem.get_[ class ].
11
+ #
12
+ # FileSystem.get_file => File
13
+ # FileSystem.get_file_utils => FileUtils
14
+ # FileSystem.get_dir => Dir
15
+ # FileSystem.get_dir.entries( '.' ) => [".", "..", ...]
16
+ #
17
+ # Then, to turn these into mock instances for a test case, simply call
18
+ #
19
+ # FileSystem.mock = true
20
+ #
21
+ # When you've done this, the normal calls will actually return adapters that
22
+ # pretend to be the class in question:
23
+ #
24
+ # FileSystem.get_file => FileSystem::FileAdapter
25
+ # FileSystem.get_file_utils => FileSystem::FileUtilsAdapter
26
+ # FileSystem.get_dir => FileSystem::DirAdapter
27
+ # FileSystem.get_dir.entries( '.' ) => [".", "..", ...]
28
+ #
29
+ # You can get direct access to the enclosed MockFileSystem by calling
30
+ # FileSystem.mock_file_system.
31
+ module FileSystem
32
+ Version = '0.1'
33
+
34
+ @@mock = false
35
+
36
+ def self.method_missing( symbol, *args ) #:nodoc:
37
+ class_name = nil
38
+ if symbol.id2name =~ /^get_(.*)/
39
+ class_name = $1.capitalize
40
+ class_name.gsub!( /_(\w)/ ) { |s| $1.capitalize }
41
+ unless %w( Dir File FileUtils ).include?( class_name )
42
+ class_name = nil
43
+ end
44
+ end
45
+ if class_name
46
+ if @@mock
47
+ return_class = Class.by_name( 'FileSystem::' + class_name + 'Adapter' )
48
+ else
49
+ return_class = Class.by_name( class_name )
50
+ end
51
+ return_class || super
52
+ elsif @@mock
53
+ mock_file_system.send( symbol, *args )
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ # Tell FileSystem whether to offer interfaces to the real or mock file system.
60
+ # +is_mock+ should be a Boolean.
61
+ def self.mock= ( is_mock ); @@mock = is_mock; end
62
+
63
+ # If we're in mock mode, this will return the MockFileSystem; otherwise it will raise a RuntimeError.
64
+ def self.mock_file_system
65
+ @@mock ? MockFileSystem.instance : ( raise RuntimeError )
66
+ end
67
+
68
+ module Adapter #:nodoc:
69
+ @@delegated_methods = [ :delete, :entries, :mtime ]
70
+
71
+ def get_node( nodename ); MockFileSystem.instance.get_node( nodename ); end
72
+
73
+ def method_missing( sym, *args )
74
+ if @@delegated_methods.include?( sym )
75
+ get_node( args.first ).send( sym )
76
+ else
77
+ super
78
+ end
79
+ end
80
+
81
+ def respond_to?( sym )
82
+ @@delegated_methods.include?( sym ) ? true : super
83
+ end
84
+ end
85
+
86
+ class DirAdapter #:nodoc:
87
+ extend Adapter
88
+ include Adapter
89
+
90
+ def self.mkdir( dirname )
91
+ path = Path.new( dirname ).absolute
92
+ get_node( path.parent ).mkdir( path.node )
93
+ end
94
+
95
+ def initialize( dirname )
96
+ unless get_node( dirname ).class == MockFileSystem::MockDir
97
+ raise Errno::ENOTDIR
98
+ end
99
+ end
100
+ end
101
+
102
+ class FileAdapter #:nodoc:
103
+ extend Adapter
104
+
105
+ def self.chmod( perms, *filenames )
106
+ get_node( filenames.first ).permissions = perms
107
+ end
108
+
109
+ class << self
110
+ def exist?( filename )
111
+ begin
112
+ get_node( filename )
113
+ true
114
+ rescue Errno::ENOENT
115
+ false
116
+ end
117
+ end
118
+
119
+ alias_method :exists?, :exist?
120
+ end
121
+
122
+ def self.open( fd, mode_string = File::RDONLY, &action )
123
+ if mode_string.class == String
124
+ if mode_string == 'w'
125
+ mode_string = File::WRONLY
126
+ end
127
+ end
128
+ if mode_string == File::RDONLY
129
+ node = get_node( fd )
130
+ if node && node.permissions && node.permissions[0] == 0
131
+ raise Errno::EACCES
132
+ end
133
+ result = action.call( node )
134
+ node.rewind
135
+ result
136
+ else
137
+ path = Path.new( fd ).absolute
138
+ dir = get_node( path.parent )
139
+ if ( mode_string & File::APPEND > 0 )
140
+ mock_file = get_node( fd )
141
+ else
142
+ mock_file = MockFileSystem::MockFile.new( dir, path.node, '' )
143
+ end
144
+ if ( mode_string & File::APPEND == File::APPEND )
145
+ mock_file.pos = mock_file.size
146
+ end
147
+ action.call( mock_file )
148
+ mock_file.rewind
149
+ if ( mode_string & File::APPEND == 0 )
150
+ dir[path.node] = mock_file
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ class FileUtilsAdapter #:nodoc:
157
+ extend Adapter
158
+
159
+ def self.cp( src, dest, options = {} )
160
+ file = get_node( src ).clone
161
+ dest_path = Path.new( dest ).absolute
162
+ dest_dir = get_node( dest_path.parent )
163
+ dest_dir[dest_path.node] = file
164
+ file.name = dest_path.node
165
+ file.parent = dest_dir
166
+ end
167
+
168
+ def self.mv( src, dest, options = {} )
169
+ cp( src, dest, options )
170
+ FileSystem.get_file.delete( src )
171
+ end
172
+
173
+ def self.touch( file )
174
+ begin
175
+ get_node( file ).mtime = Time.now
176
+ rescue Errno::ENOENT
177
+ path = Path.new( file ).absolute
178
+ parent_dir = get_node( path.parent )
179
+ file = MockFileSystem::MockFile.new( parent_dir, path.node, '' )
180
+ parent_dir[path.node] = file
181
+ end
182
+ end
183
+ end
184
+
185
+ # The MockFileSystem is the singleton class that pretends to be the file system in mock mode. When it's first created, it fills in one path up to your real directory location; other paths will have to be filled by hand using +fill_path+.
186
+ class MockFileSystem
187
+ include Singleton
188
+
189
+ # Flushes all file information out of the MockFileSystem.
190
+ def self.flush; instance.flush; end
191
+
192
+ def initialize #:nodoc:
193
+ flush
194
+ end
195
+
196
+ # Flushes all file information out of the MockFileSystem.
197
+ def flush; @root = MockRoot.new( '' ); fill_path( '.' ); end
198
+
199
+ def get_node( dirname ) #:nodoc:
200
+ @root.get_node( dirname )
201
+ end
202
+
203
+ # Use this method to fill in directory paths. This is the same as calling mkdir a bunch of times.
204
+ #
205
+ # FileSystem.mock_file_system.fill_path '/usr/local/bin'
206
+ # FileSystem.mock_file_system.fill_path '/home/francis/Desktop/myproject/'
207
+ def fill_path( dirname )
208
+ @root.fill_path( Path.new( dirname ).absolute.strip )
209
+ end
210
+
211
+ module Node #:nodoc:
212
+ attr_accessor :mtime, :name, :parent, :permissions
213
+ end
214
+
215
+ class MockDir < DelegateClass( Hash ) #:nodoc:
216
+ include Node
217
+
218
+ def initialize( name, parent = nil )
219
+ super( {} )
220
+ @name, @parent = name, parent
221
+ @mtime = Time.now
222
+ end
223
+
224
+ def []= ( name, child )
225
+ super
226
+ @mtime = child.mtime
227
+ end
228
+
229
+ def delete( child = nil )
230
+ child ? super( child.name ) : parent.delete( self )
231
+ end
232
+
233
+ def entries; %w( . .. ).concat( keys ); end
234
+
235
+ def get_node( dirname )
236
+ if dirname.first == '..'
237
+ self.parent.get_node( dirname[1..-1] )
238
+ elsif dirname.first == '.'
239
+ self.get_node( dirname[1..-1] )
240
+ elsif dirname.size > 1
241
+ subdir = self[dirname.first]
242
+ subdir ? subdir.get_node( dirname[1..-1] ) : ( raise Errno::ENOENT )
243
+ elsif dirname == ''
244
+ self
245
+ else
246
+ self[dirname.strip] or ( raise Errno::ENOENT )
247
+ end
248
+ end
249
+
250
+ def fill_dir( dirname )
251
+ dir = self[dirname]
252
+ if dir.nil?
253
+ dir = MockDir.new( dirname, self )
254
+ self[dirname] = dir
255
+ @mtime = dir.mtime
256
+ end
257
+ dir
258
+ end
259
+
260
+ def fill_path( dirname )
261
+ if dirname.size > 1
262
+ dir = fill_dir( dirname.first )
263
+ dir.fill_path( dirname[1..-1] )
264
+ else
265
+ fill_dir( dirname )
266
+ end
267
+ end
268
+
269
+ def mkdir( dirname ); fill_path( Path.new( dirname ) ); end
270
+ end
271
+
272
+ class MockFile < DelegateClass( StringIO ) #:nodoc:
273
+ include Node
274
+
275
+ attr_writer :contents
276
+
277
+ def initialize( parent, name, contents )
278
+ @name = name; @parent = parent; @mtime = Time.now
279
+ contents = contents || ''
280
+ super( StringIO.new( contents ) )
281
+ end
282
+
283
+ def clone
284
+ rewind
285
+ clone = self.class.new( @parent, @name, gets( nil ) )
286
+ clone.mtime = @mtime
287
+ clone
288
+ end
289
+
290
+ def delete; parent.delete( self ); end
291
+
292
+ def gets( sep_string = $/ ); super( sep_string ) || ''; end
293
+ end
294
+
295
+ class MockRoot < MockDir #:nodoc:
296
+ def get_node( dirname )
297
+ begin
298
+ super( Path.new( dirname ).absolute.strip )
299
+ rescue Errno::ENOENT
300
+ raise Errno::ENOENT.new( dirname )
301
+ end
302
+ end
303
+ end
304
+ end
305
+
306
+ class Path < String #:nodoc:
307
+ @@getwd = nil
308
+
309
+ def self.getwd
310
+ @@getwd = Dir.getwd if @@getwd.nil?
311
+ @@getwd
312
+ end
313
+
314
+ def []( *args ); Path.new( self.split( "/" )[*args].join( "/" ) ); end
315
+
316
+ def absolute
317
+ if self =~ %r{^\w}
318
+ Path.new( File.join( self.class.getwd, self ) )
319
+ else
320
+ new_str = self.to_s
321
+ new_str.gsub!( %r{^\.\.}, self.class.getwd + '/..' )
322
+ new_str.gsub!( %r{^\.}, self.class.getwd )
323
+ Path.new( new_str )
324
+ end
325
+ end
326
+
327
+ def first; self.split( "/" ).first; end
328
+
329
+ def parent
330
+ self =~ %r{^(.*)/(.*?)$}
331
+ $1
332
+ end
333
+
334
+ def node
335
+ self =~ %r{^(.*)/(.*?)$}
336
+ $2
337
+ end
338
+
339
+ def size; self.split( '/' ).size; end
340
+
341
+ def strip; self.gsub( %r{^/+}, '' ).gsub( %r{/+$}, '' ); end
342
+ end
343
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.1
3
+ specification_version: 1
4
+ name: filesystem
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2005-02-16
8
+ summary: FileSystem is a test-obsessed library for mocking out the entire file system.
9
+ require_paths:
10
+ - lib
11
+ author: Francis Hwang
12
+ email: sera@fhwang.net
13
+ homepage: http://filesystem.rubyforge.org/
14
+ rubyforge_project:
15
+ description: "FileSystem is a test-obsessed library for mocking out the entire file system. It
16
+ provides mock objects that clone the functionality of File, FileUtils, Dir, and
17
+ other in-Ruby file-access libraries."
18
+ autorequire: filesystem
19
+ default_executable:
20
+ bindir: bin
21
+ has_rdoc: false
22
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
23
+ requirements:
24
+ -
25
+ - ">"
26
+ - !ruby/object:Gem::Version
27
+ version: 0.0.0
28
+ version:
29
+ platform: ruby
30
+ files:
31
+ - lib/filesystem.rb
32
+ - lib/filesystem.rb~
33
+ test_files: []
34
+ rdoc_options: []
35
+ extra_rdoc_files: []
36
+ executables: []
37
+ extensions: []
38
+ requirements: []
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: extensions
42
+ version_requirement:
43
+ version_requirements: !ruby/object:Gem::Version::Requirement
44
+ requirements:
45
+ -
46
+ - ">"
47
+ - !ruby/object:Gem::Version
48
+ version: 0.0.0
49
+ version: