rfusefs 1.0.2.RC1 → 1.0.2.RC2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -3,6 +3,7 @@
3
3
  * https://rubygems.org/gems/rfusefs
4
4
  * https://github.com/lwoggardner/rfusefs
5
5
 
6
+ {<img src="https://badge.fury.io/rb/rfusefs.png" alt="Gem Version" />}[http://badge.fury.io/rb/rfusefs]
6
7
  == DESCRIPTION
7
8
 
8
9
  RFuseFS is a port of the FuseFS[http://rubygems.org/gems/fusefs/]
@@ -93,14 +93,14 @@ module FuseFS
93
93
  # Implements RFuseFS
94
94
  # The path supplied to these methods is generally validated by FUSE itself
95
95
  # with a prior "getattr" call so we do not revalidate here.
96
- # http://sourceforge.net/apps/mediawiki/fuse/index.php?title=FuseInvariants
96
+ # http://sourceforge.net/apps/mediawiki/fuse/index.php?title=FuseInvariants
97
97
  class RFuseFS
98
98
  CHECK_FILE="/._rfuse_check_"
99
99
 
100
100
  def initialize(root)
101
101
  @root = root
102
102
  @created_files = { }
103
-
103
+
104
104
  # Keep track of changes to file counts and sizes made via Fuse - for #statfs
105
105
  @adj_nodes = 0
106
106
  @adj_size = 0
@@ -123,7 +123,7 @@ module FuseFS
123
123
  filler.push(".",nil,0)
124
124
  filler.push("..",nil,0)
125
125
 
126
- files = @root.contents(path)
126
+ files = @root.contents(path)
127
127
 
128
128
  files.each do | filename |
129
129
  filler.push(filename,nil,0)
@@ -263,7 +263,7 @@ module FuseFS
263
263
  raise Errno::ENOPERM.new(path)
264
264
  end
265
265
  end
266
-
266
+
267
267
  #If we get this far, save our filehandle in the FUSE structure
268
268
  ffi.fh=fh
269
269
  end
@@ -304,7 +304,7 @@ module FuseFS
304
304
  return fh.write(offset,buf)
305
305
  end
306
306
  end
307
-
307
+
308
308
  def fsync(ctx,path,datasync,ffi)
309
309
  return wrap_context(ctx,__method__,path,datasync,ffi) if ctx
310
310
  fh = ffi.fh
@@ -343,6 +343,8 @@ module FuseFS
343
343
  else
344
344
  @root.raw_close(path)
345
345
  end
346
+ # if was handled as raw, then assume the file has now been created (or not)
347
+ @created_files.delete(path)
346
348
  else
347
349
  # Probably just had flush called, but no harm calling it again
348
350
  flush(nil,path,ffi)
@@ -448,7 +450,7 @@ module FuseFS
448
450
  def statfs(ctx,path)
449
451
  return wrap_context(ctx,__method__,path) if ctx
450
452
  block_size = 1024
451
-
453
+
452
454
  stats = @root.statistics(path)
453
455
  case stats
454
456
  when Array
@@ -1,3 +1,3 @@
1
1
  module RFuseFS
2
- VERSION="1.0.2.RC1"
2
+ VERSION="1.0.2.RC2"
3
3
  end
data/spec/rfusefs_spec.rb CHANGED
@@ -1,17 +1,17 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe FuseFS do
4
-
5
- TEST_FILE = "/aPath/aFile"
4
+
5
+ TEST_FILE = "/aPath/aFile"
6
6
  TEST_DIR = "/aPath"
7
7
  ROOT_PATH = "/"
8
8
  Struct.new("FuseFileInfo",:flags,:fh)
9
-
9
+
10
10
  describe "an empty FuseFS object" do
11
11
  before(:each) do
12
12
  @fuse = FuseFS::RFuseFS.new(Object.new())
13
13
  end
14
-
14
+
15
15
  it "should return an appropriate Stat for the root directory" do
16
16
  stat = @fuse.getattr(nil,ROOT_PATH)
17
17
  stat.should respond_to(:dev)
@@ -19,24 +19,24 @@ describe FuseFS do
19
19
  (stat.mode & RFuse::Stat::S_IFREG).should == 0
20
20
  permissions(stat.mode).should == 0555
21
21
  end
22
-
22
+
23
23
  it "should have an empty root directory" do
24
24
  filler = mock("entries_filler")
25
25
  filler.should_receive(:push).with(".",nil,0)
26
26
  filler.should_receive(:push).with("..",nil,0)
27
27
  @fuse.readdir(nil,"/",filler,nil,nil)
28
28
  end
29
-
29
+
30
30
  it "should raise ENOENT for other paths" do
31
31
  lambda { @fuse.getattr(nil,"/somepath") }.should raise_error(Errno::ENOENT)
32
32
  end
33
-
33
+
34
34
  it "should not allow new files or directories" do
35
35
  lambda { @fuse.mknod(nil,"/afile",0100644,0,0) }.should raise_error(Errno::EACCES)
36
36
  lambda { @fuse.mkdir(nil,"/adir",0040555) }.should raise_error(Errno::EACCES)
37
37
  end
38
38
  end
39
-
39
+
40
40
  describe "a FuseFS filesystem" do
41
41
  before(:each) do
42
42
  @mock_fuse = FuseFS::FuseDir.new()
@@ -47,7 +47,7 @@ describe FuseFS do
47
47
  before(:each) do
48
48
  @mock_fuse.should_receive(:contents).with("/apath").and_return(["afile"])
49
49
  end
50
-
50
+
51
51
  it "should add . and .. to the results of :contents when listing a directory" do
52
52
  filler = mock("entries_filler")
53
53
  filler.should_receive(:push).with(".",nil,0)
@@ -55,22 +55,22 @@ describe FuseFS do
55
55
  filler.should_receive(:push).with("afile",nil,0)
56
56
  @fuse.readdir(nil,"/apath",filler,nil,nil)
57
57
  end
58
-
58
+
59
59
  end
60
-
60
+
61
61
  describe :getattr do
62
-
62
+
63
63
  #Root directory is special (ish) so we need to run these specs twice.
64
64
  [ROOT_PATH,TEST_DIR].each do |dir|
65
-
65
+
66
66
  context "of a directory #{ dir }" do
67
-
67
+
68
68
  before(:each) do
69
69
  @mock_fuse.stub!(:file?).and_return(false)
70
70
  @mock_fuse.should_receive(:directory?).with(dir).at_most(:once).and_return(true)
71
71
  @checkfile = (dir == "/" ? "" : dir ) + FuseFS::RFuseFS::CHECK_FILE
72
72
  end
73
-
73
+
74
74
  it "should return a Stat like object representing a directory" do
75
75
  @mock_fuse.should_receive(:can_write?).with(@checkfile).at_most(:once).and_return(false)
76
76
  @mock_fuse.should_receive(:can_mkdir?).with(@checkfile).at_most(:once).and_return(false)
@@ -80,398 +80,418 @@ describe FuseFS do
80
80
  filetype(stat.mode).should == RFuse::Stat::S_IFDIR
81
81
  permissions(stat.mode).should == 0555
82
82
  end
83
-
84
-
83
+
84
+
85
85
  it "should return writable mode if can_mkdir?" do
86
- @mock_fuse.should_receive(:can_mkdir?).with(@checkfile).at_most(:once).and_return(true)
87
-
86
+ @mock_fuse.should_receive(:can_mkdir?).with(@checkfile).at_most(:once).and_return(true)
87
+
88
88
  stat = @fuse.getattr(nil,dir)
89
89
  permissions(stat.mode).should == 0777
90
90
  end
91
-
91
+
92
92
  it "should return writable mode if can_write?" do
93
93
  @mock_fuse.should_receive(:can_write?).with(@checkfile).at_most(:once).and_return(true)
94
-
94
+
95
95
  stat = @fuse.getattr(nil,dir)
96
96
  permissions(stat.mode).should == 0777
97
-
97
+
98
98
  end
99
-
99
+
100
100
  it "should return times in the result if available" do
101
- @mock_fuse.should_receive(:times).with(dir).and_return([10,20,30])
102
- stat = @fuse.getattr(nil,dir)
103
- stat.atime.should == 10
104
- stat.mtime.should == 20
105
- stat.ctime.should == 30
101
+ @mock_fuse.should_receive(:times).with(dir).and_return([10,20,30])
102
+ stat = @fuse.getattr(nil,dir)
103
+ stat.atime.should == 10
104
+ stat.mtime.should == 20
105
+ stat.ctime.should == 30
106
106
  end
107
107
  end
108
108
  end
109
-
109
+
110
110
  describe "a file" do
111
-
112
- before(:each) do
113
- @file="/aPath/aFile"
114
- @mock_fuse.stub!(:directory?).and_return(false)
115
- @mock_fuse.should_receive(:file?).with(@file).at_most(:once).and_return(true)
111
+
112
+ before(:each) do
113
+ @file="/aPath/aFile"
114
+ @mock_fuse.stub!(:directory?).and_return(false)
115
+ @mock_fuse.should_receive(:file?).with(@file).at_most(:once).and_return(true)
116
+ end
117
+
118
+
119
+ it "should return a Stat like object representing a file" do
120
+ stat = @fuse.getattr(nil,@file)
121
+ (stat.mode & RFuse::Stat::S_IFDIR).should == 0
122
+ (stat.mode & RFuse::Stat::S_IFREG).should_not == 0
123
+ permissions(stat.mode).should == 0444
124
+ end
125
+
126
+ it "should indicate executable mode if executable?" do
127
+ @mock_fuse.should_receive(:executable?).with(@file).and_return(true)
128
+ stat = @fuse.getattr(nil,@file)
129
+ permissions(stat.mode).should == 0555
130
+ end
131
+
132
+ it "should indicate writable mode if can_write?" do
133
+ @mock_fuse.should_receive(:can_write?).with(@file).and_return(true)
134
+ stat = @fuse.getattr(nil,@file)
135
+ permissions(stat.mode).should == 0666
136
+ end
137
+
138
+ it "should by 777 mode if can_write? and exectuable?" do
139
+ @mock_fuse.should_receive(:can_write?).with(@file).and_return(true)
140
+ @mock_fuse.should_receive(:executable?).with(@file).and_return(true)
141
+ stat = @fuse.getattr(nil,@file)
142
+ permissions(stat.mode).should == 0777
143
+ end
144
+
145
+ it "should include size in the result if available" do
146
+ @mock_fuse.should_receive(:size).with(@file).and_return(234)
147
+ stat = @fuse.getattr(nil,@file)
148
+ stat.size.should == 234
149
+ end
150
+
151
+ it "should include times in the result if available" do
152
+ @mock_fuse.should_receive(:times).with(@file).and_return([22,33,44])
153
+ stat = @fuse.getattr(nil,@file)
154
+ stat.atime.should == 22
155
+ stat.mtime.should == 33
156
+ stat.ctime.should == 44
116
157
  end
117
-
118
-
119
- it "should return a Stat like object representing a file" do
120
- stat = @fuse.getattr(nil,@file)
121
- (stat.mode & RFuse::Stat::S_IFDIR).should == 0
122
- (stat.mode & RFuse::Stat::S_IFREG).should_not == 0
123
- permissions(stat.mode).should == 0444
124
- end
125
-
126
- it "should indicate executable mode if executable?" do
127
- @mock_fuse.should_receive(:executable?).with(@file).and_return(true)
128
- stat = @fuse.getattr(nil,@file)
129
- permissions(stat.mode).should == 0555
130
- end
131
-
132
- it "should indicate writable mode if can_write?" do
133
- @mock_fuse.should_receive(:can_write?).with(@file).and_return(true)
134
- stat = @fuse.getattr(nil,@file)
135
- permissions(stat.mode).should == 0666
136
- end
137
-
138
- it "should by 777 mode if can_write? and exectuable?" do
139
- @mock_fuse.should_receive(:can_write?).with(@file).and_return(true)
140
- @mock_fuse.should_receive(:executable?).with(@file).and_return(true)
141
- stat = @fuse.getattr(nil,@file)
142
- permissions(stat.mode).should == 0777
143
- end
144
-
145
- it "should include size in the result if available" do
146
- @mock_fuse.should_receive(:size).with(@file).and_return(234)
147
- stat = @fuse.getattr(nil,@file)
148
- stat.size.should == 234
149
- end
150
-
151
- it "should include times in the result if available" do
152
- @mock_fuse.should_receive(:times).with(@file).and_return([22,33,44])
153
- stat = @fuse.getattr(nil,@file)
154
- stat.atime.should == 22
155
- stat.mtime.should == 33
156
- stat.ctime.should == 44
157
- end
158
158
  end
159
-
159
+
160
160
  it "should raise ENOENT for a path that does not exist" do
161
- @mock_fuse.should_receive(:file?).with(TEST_FILE).and_return(false)
162
- @mock_fuse.should_receive(:directory?).with(TEST_FILE).and_return(false)
163
- lambda{stat = @fuse.getattr(nil,TEST_FILE) }.should raise_error(Errno::ENOENT)
161
+ @mock_fuse.should_receive(:file?).with(TEST_FILE).and_return(false)
162
+ @mock_fuse.should_receive(:directory?).with(TEST_FILE).and_return(false)
163
+ lambda{stat = @fuse.getattr(nil,TEST_FILE) }.should raise_error(Errno::ENOENT)
164
164
  end
165
165
  end
166
-
166
+
167
167
  context "creating files and directories" do
168
-
169
- it ":mknod should raise EACCES unless :can_write?" do
170
- @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
171
- @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
172
- @mock_fuse.should_receive(:can_write?).with(TEST_FILE).and_return(false)
173
- lambda{@fuse.mknod(nil,TEST_FILE,0100644,0,0)}.should raise_error(Errno::EACCES)
174
- end
175
-
176
- it ":mkdir should raise EACCES unless :can_mkdir?" do
177
- @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
178
- @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
179
- @mock_fuse.should_receive(:can_mkdir?).with(TEST_FILE).and_return(false)
180
- lambda{@fuse.mkdir(nil,TEST_FILE,004555)}.should raise_error(Errno::EACCES)
181
- end
182
-
183
- it ":mknod should raise EACCES unless mode requests a regular file" do
184
- @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
185
- @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
186
- @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
187
- lambda{@fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFLNK | 0644,0,0)}.should raise_error(Errno::EACCES)
188
- end
189
-
190
- it ":mknod should result in getattr returning a Stat like object representing an empty file" do
191
- @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
192
- @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
193
- @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
194
- @fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFREG | 0644,0,0)
195
-
196
- stat = @fuse.getattr(nil,TEST_FILE)
197
- filetype(stat.mode).should == RFuse::Stat::S_IFREG
198
- stat.size.should == 0
199
- end
200
-
201
- it "should create zero length files" do
202
- ffi = Struct::FuseFileInfo.new()
203
- ffi.flags = Fcntl::O_WRONLY
204
- @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
205
- @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
206
- @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
207
- @mock_fuse.should_receive(:write_to).once.with(TEST_FILE,"")
208
- @fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFREG | 0644,0,0)
209
- @fuse.open(nil,TEST_FILE,ffi)
210
- @fuse.flush(nil,TEST_FILE,ffi)
211
- @fuse.release(nil,TEST_FILE,ffi)
212
- end
213
168
 
214
- it ":mkdir should not raise error if can_mkdir?" do
215
- @mock_fuse.should_receive(:can_mkdir?).with(TEST_FILE).and_return(true)
216
- @fuse.mkdir(nil,TEST_FILE,004555)
217
- end
218
-
169
+ it ":mknod should raise EACCES unless :can_write?" do
170
+ @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
171
+ @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
172
+ @mock_fuse.should_receive(:can_write?).with(TEST_FILE).and_return(false)
173
+ lambda{@fuse.mknod(nil,TEST_FILE,0100644,0,0)}.should raise_error(Errno::EACCES)
174
+ end
175
+
176
+ it ":mkdir should raise EACCES unless :can_mkdir?" do
177
+ @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
178
+ @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
179
+ @mock_fuse.should_receive(:can_mkdir?).with(TEST_FILE).and_return(false)
180
+ lambda{@fuse.mkdir(nil,TEST_FILE,004555)}.should raise_error(Errno::EACCES)
181
+ end
182
+
183
+ it ":mknod should raise EACCES unless mode requests a regular file" do
184
+ @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
185
+ @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
186
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
187
+ lambda{@fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFLNK | 0644,0,0)}.should raise_error(Errno::EACCES)
188
+ end
189
+
190
+ it ":mknod should result in getattr returning a Stat like object representing an empty file" do
191
+ @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
192
+ @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
193
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
194
+ @fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFREG | 0644,0,0)
195
+
196
+ stat = @fuse.getattr(nil,TEST_FILE)
197
+ filetype(stat.mode).should == RFuse::Stat::S_IFREG
198
+ stat.size.should == 0
199
+ end
200
+
201
+ it "should create zero length files" do
202
+ ffi = Struct::FuseFileInfo.new()
203
+ ffi.flags = Fcntl::O_WRONLY
204
+ @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
205
+ @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
206
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
207
+ @mock_fuse.should_receive(:write_to).once.with(TEST_FILE,"")
208
+ @fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFREG | 0644,0,0)
209
+ @fuse.open(nil,TEST_FILE,ffi)
210
+ @fuse.flush(nil,TEST_FILE,ffi)
211
+ @fuse.release(nil,TEST_FILE,ffi)
212
+ end
213
+
214
+ it ":mkdir should not raise error if can_mkdir?" do
215
+ @mock_fuse.should_receive(:can_mkdir?).with(TEST_FILE).and_return(true)
216
+ @fuse.mkdir(nil,TEST_FILE,004555)
217
+ end
218
+
219
219
  end
220
-
220
+
221
221
  context "reading files" do
222
- it "should read the contents of a file" do
223
- ffi = Struct::FuseFileInfo.new()
224
- ffi.flags = Fcntl::O_RDONLY
225
- @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(true)
226
- @mock_fuse.stub!(:read_file).with(TEST_FILE).and_return("Hello World\n")
227
- @fuse.open(nil,TEST_FILE,ffi)
228
- #to me fuse is backwards -- size, offset!
229
- @fuse.read(nil,TEST_FILE,5,0,ffi).should == "Hello"
230
- @fuse.read(nil,TEST_FILE,4,6,ffi).should == "Worl"
231
- @fuse.read(nil,TEST_FILE,10,8,ffi).should == "rld\n"
232
- @fuse.flush(nil,TEST_FILE,ffi)
233
- @fuse.release(nil,TEST_FILE,ffi)
234
- end
222
+ it "should read the contents of a file" do
223
+ ffi = Struct::FuseFileInfo.new()
224
+ ffi.flags = Fcntl::O_RDONLY
225
+ @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(true)
226
+ @mock_fuse.stub!(:read_file).with(TEST_FILE).and_return("Hello World\n")
227
+ @fuse.open(nil,TEST_FILE,ffi)
228
+ #to me fuse is backwards -- size, offset!
229
+ @fuse.read(nil,TEST_FILE,5,0,ffi).should == "Hello"
230
+ @fuse.read(nil,TEST_FILE,4,6,ffi).should == "Worl"
231
+ @fuse.read(nil,TEST_FILE,10,8,ffi).should == "rld\n"
232
+ @fuse.flush(nil,TEST_FILE,ffi)
233
+ @fuse.release(nil,TEST_FILE,ffi)
234
+ end
235
235
  end
236
-
236
+
237
237
  context "writing files" do
238
- it "should overwrite a file opened WR_ONLY" do
239
- ffi = Struct::FuseFileInfo.new()
240
- ffi.flags = Fcntl::O_WRONLY
241
- @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
242
- @mock_fuse.stub!(:read_file).with(TEST_FILE).and_return("I'm writing a file\n")
243
- @mock_fuse.should_receive(:write_to).once().with(TEST_FILE,"My new contents\n")
244
- @fuse.open(nil,TEST_FILE,ffi)
245
- @fuse.ftruncate(nil,TEST_FILE,0,ffi)
246
- @fuse.write(nil,TEST_FILE,"My new c",0,ffi)
247
- @fuse.write(nil,TEST_FILE,"ontents\n",8,ffi)
248
- @fuse.flush(nil,TEST_FILE,ffi)
249
- #that's right flush can be called more than once.
250
- @fuse.flush(nil,TEST_FILE,ffi)
251
- #but then we can write some more and flush again
252
- @fuse.release(nil,TEST_FILE,ffi)
253
- end
254
-
255
- it "should append to a file opened WR_ONLY | APPEND" do
256
- ffi = Struct::FuseFileInfo.new()
257
- ffi.flags = Fcntl::O_WRONLY | Fcntl::O_APPEND
258
- @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
259
- @mock_fuse.stub!(:read_file).with(TEST_FILE).and_return("I'm writing a file\n")
260
- @mock_fuse.should_receive(:write_to).once().with(TEST_FILE,"I'm writing a file\nMy new contents\n")
261
- @fuse.open(nil,TEST_FILE,ffi)
262
- @fuse.write(nil,TEST_FILE,"My new c",0,ffi)
263
- @fuse.write(nil,TEST_FILE,"ontents\n",8,ffi)
264
- @fuse.flush(nil,TEST_FILE,ffi)
265
- #that's right flush can be called more than once. But we should only write-to the first time
266
- @fuse.flush(nil,TEST_FILE,ffi)
267
- @fuse.release(nil,TEST_FILE,ffi)
268
-
269
- end
270
-
271
- it "should do sensible things for files opened RDWR"
272
-
273
- it "should pass on buffered data when requested (fsync)"
238
+ it "should overwrite a file opened WR_ONLY" do
239
+ ffi = Struct::FuseFileInfo.new()
240
+ ffi.flags = Fcntl::O_WRONLY
241
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
242
+ @mock_fuse.stub!(:read_file).with(TEST_FILE).and_return("I'm writing a file\n")
243
+ @mock_fuse.should_receive(:write_to).once().with(TEST_FILE,"My new contents\n")
244
+ @fuse.open(nil,TEST_FILE,ffi)
245
+ @fuse.ftruncate(nil,TEST_FILE,0,ffi)
246
+ @fuse.write(nil,TEST_FILE,"My new c",0,ffi)
247
+ @fuse.write(nil,TEST_FILE,"ontents\n",8,ffi)
248
+ @fuse.flush(nil,TEST_FILE,ffi)
249
+ #that's right flush can be called more than once.
250
+ @fuse.flush(nil,TEST_FILE,ffi)
251
+ #but then we can write some more and flush again
252
+ @fuse.release(nil,TEST_FILE,ffi)
253
+ end
254
+
255
+ it "should append to a file opened WR_ONLY | APPEND" do
256
+ ffi = Struct::FuseFileInfo.new()
257
+ ffi.flags = Fcntl::O_WRONLY | Fcntl::O_APPEND
258
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
259
+ @mock_fuse.stub!(:read_file).with(TEST_FILE).and_return("I'm writing a file\n")
260
+ @mock_fuse.should_receive(:write_to).once().with(TEST_FILE,"I'm writing a file\nMy new contents\n")
261
+ @fuse.open(nil,TEST_FILE,ffi)
262
+ @fuse.write(nil,TEST_FILE,"My new c",0,ffi)
263
+ @fuse.write(nil,TEST_FILE,"ontents\n",8,ffi)
264
+ @fuse.flush(nil,TEST_FILE,ffi)
265
+ #that's right flush can be called more than once. But we should only write-to the first time
266
+ @fuse.flush(nil,TEST_FILE,ffi)
267
+ @fuse.release(nil,TEST_FILE,ffi)
268
+
269
+ end
270
+
271
+ it "should do sensible things for files opened RDWR"
272
+
273
+ it "should pass on buffered data when requested (fsync)"
274
274
 
275
275
  end
276
-
276
+
277
277
  context "raw reading" do
278
- it "should call the raw_read/raw_close if raw_open returns true" do
279
- ffi = Struct::FuseFileInfo.new()
280
- ffi.flags = Fcntl::O_RDONLY
281
- @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
282
- @mock_fuse.should_receive(:raw_open).with(TEST_FILE,"r",true).and_return("raw")
283
- @mock_fuse.should_receive(:raw_read).with(TEST_FILE,5,0,"raw").and_return("12345")
284
- @mock_fuse.should_receive(:raw_read).with(TEST_FILE,5,5,"raw").and_return("67890")
285
- @mock_fuse.should_receive(:raw_close).with(TEST_FILE,"raw")
286
- @fuse.open(nil,TEST_FILE,ffi)
287
- @fuse.read(nil,TEST_FILE,0,5,ffi).should == "12345"
288
- @fuse.read(nil,TEST_FILE,5,5,ffi).should == "67890"
289
- @fuse.flush(nil,TEST_FILE,ffi)
290
- @fuse.release(nil,TEST_FILE,ffi)
291
- end
292
-
278
+
279
+ it "should call the raw_read/raw_close if raw_open returns true" do
280
+ ffi = Struct::FuseFileInfo.new()
281
+ ffi.flags = Fcntl::O_RDONLY
282
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
283
+ @mock_fuse.should_receive(:raw_open).with(TEST_FILE,"r",true).and_return("raw")
284
+ @mock_fuse.should_receive(:raw_read).with(TEST_FILE,5,0,"raw").and_return("12345")
285
+ @mock_fuse.should_receive(:raw_read).with(TEST_FILE,5,5,"raw").and_return("67890")
286
+ @mock_fuse.should_receive(:raw_close).with(TEST_FILE,"raw")
287
+ @fuse.open(nil,TEST_FILE,ffi)
288
+ @fuse.read(nil,TEST_FILE,0,5,ffi).should == "12345"
289
+ @fuse.read(nil,TEST_FILE,5,5,ffi).should == "67890"
290
+ @fuse.flush(nil,TEST_FILE,ffi)
291
+ @fuse.release(nil,TEST_FILE,ffi)
292
+ end
293
+
293
294
  end
294
-
295
+
295
296
  context "raw writing" do
296
- it "should call other raw_* methods if raw_open returns true" do
297
- ffi = Struct::FuseFileInfo.new()
298
- ffi.flags = Fcntl::O_WRONLY
299
- raw = Object.new()
300
- @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
301
- @mock_fuse.should_receive(:raw_open).with(TEST_FILE,"w",true).and_return(raw)
302
- @mock_fuse.should_receive(:raw_truncate).with(TEST_FILE,0,raw)
303
- @mock_fuse.should_receive(:raw_write).with(TEST_FILE,0,5,"12345",raw).once().and_return(5)
304
- @mock_fuse.should_receive(:raw_write).with(TEST_FILE,5,5,"67890",raw).once().and_return(5)
305
- @mock_fuse.should_receive(:raw_sync).with(TEST_FILE, false, raw)
306
- @mock_fuse.should_receive(:raw_close).with(TEST_FILE,raw)
307
- @fuse.open(nil,TEST_FILE,ffi)
308
- @fuse.ftruncate(nil,TEST_FILE,0,ffi)
309
- @fuse.write(nil,TEST_FILE,"12345",0,ffi).should == 5
310
- @fuse.fsync(nil,TEST_FILE,0,ffi)
311
- @fuse.write(nil,TEST_FILE,"67890",5,ffi).should == 5
312
- @fuse.flush(nil,TEST_FILE,ffi)
313
- @fuse.release(nil,TEST_FILE,ffi)
314
- end
315
-
316
- it "should pass 'wa' to raw_open if fuse sends WRONLY | APPEND" do
317
- ffi = Struct::FuseFileInfo.new()
318
- ffi.flags = Fcntl::O_WRONLY | Fcntl::O_APPEND
319
- raw = Object.new()
320
- @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
321
- @mock_fuse.should_receive(:raw_open).with(TEST_FILE,"wa",true).and_return(raw)
322
- @fuse.open(nil,TEST_FILE,ffi)
323
- end
324
- end
325
-
326
- context "deleting files" do
327
- it "should raise EACCES unless :can_delete?" do
328
- @mock_fuse.should_receive(:can_delete?).with(TEST_FILE).and_return(false)
329
- lambda {@fuse.unlink(nil,TEST_FILE)}.should raise_error(Errno::EACCES)
330
- end
331
-
332
- it "should :delete without error if :can_delete?" do
333
- @mock_fuse.stub!(:can_delete?).with(TEST_FILE).and_return(true)
334
- @mock_fuse.should_receive(:delete).with(TEST_FILE)
335
- @fuse.unlink(nil,TEST_FILE)
336
- end
337
-
338
- it "should remove entries created with mknod that have never been opened" do
339
- @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
340
- @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
341
- @mock_fuse.stub!(:can_delete?).with(TEST_FILE).and_return(true)
342
- @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
343
- @fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFREG | 0644,0,0)
344
-
345
- @fuse.unlink(nil,TEST_FILE)
346
- lambda {@fuse.getattr(nil,TEST_FILE)}.should raise_error(Errno::ENOENT)
347
- end
348
- end
349
-
350
- context "deleting directories" do
351
- it "should raise EACCES unless :can_rmdir?" do
352
- @mock_fuse.should_receive(:can_rmdir?).with(TEST_DIR).and_return(false)
353
- lambda{@fuse.rmdir(nil,TEST_DIR)}.should raise_error(Errno::EACCES)
354
- end
355
-
356
- it "should :rmdir without error if :can_rmdir?" do
357
- @mock_fuse.stub!(:can_rmdir?).with(TEST_DIR).and_return(true)
358
- @fuse.rmdir(nil,TEST_DIR)
359
- end
360
- end
361
-
362
- context "touching files" do
363
- it "should call :touch in response to utime" do
364
- @mock_fuse.should_receive(:touch).with(TEST_FILE,220)
365
- @fuse.utime(nil,TEST_FILE,100,220)
366
- end
297
+ it "should call other raw_* methods if raw_open returns true" do
298
+ ffi = Struct::FuseFileInfo.new()
299
+ ffi.flags = Fcntl::O_WRONLY
300
+ raw = Object.new()
301
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
302
+ @mock_fuse.should_receive(:raw_open).with(TEST_FILE,"w",true).and_return(raw)
303
+ @mock_fuse.should_receive(:raw_truncate).with(TEST_FILE,0,raw)
304
+ @mock_fuse.should_receive(:raw_write).with(TEST_FILE,0,5,"12345",raw).once().and_return(5)
305
+ @mock_fuse.should_receive(:raw_write).with(TEST_FILE,5,5,"67890",raw).once().and_return(5)
306
+ @mock_fuse.should_receive(:raw_sync).with(TEST_FILE, false, raw)
307
+ @mock_fuse.should_receive(:raw_close).with(TEST_FILE,raw)
308
+ @fuse.open(nil,TEST_FILE,ffi)
309
+ @fuse.ftruncate(nil,TEST_FILE,0,ffi)
310
+ @fuse.write(nil,TEST_FILE,"12345",0,ffi).should == 5
311
+ @fuse.fsync(nil,TEST_FILE,0,ffi)
312
+ @fuse.write(nil,TEST_FILE,"67890",5,ffi).should == 5
313
+ @fuse.flush(nil,TEST_FILE,ffi)
314
+ @fuse.release(nil,TEST_FILE,ffi)
315
+ end
316
+
317
+ it "should clean up created files" do
318
+ ffi = Struct::FuseFileInfo.new()
319
+ ffi.flags = Fcntl::O_WRONLY
320
+ raw = Object.new()
321
+ @mock_fuse.stub!(:directory?).and_return(false)
322
+ @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false,true)
323
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
324
+ @mock_fuse.should_receive(:raw_open).with(TEST_FILE,"w",true).and_return(raw)
325
+ @mock_fuse.should_receive(:raw_close).with(TEST_FILE,raw)
326
+ @mock_fuse.should_receive(:size).with(TEST_FILE).and_return(25)
327
+
328
+ lambda { @fuse.getattr(nil,TEST_FILE) }.should raise_error(Errno::ENOENT)
329
+ @fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFREG | 0644,0,0)
330
+ @fuse.open(nil,TEST_FILE,ffi)
331
+ @fuse.flush(nil,TEST_FILE,ffi)
332
+ @fuse.release(nil,TEST_FILE,ffi)
333
+ stat = @fuse.getattr(nil,TEST_FILE)
334
+ stat.size = 25
335
+ end
336
+
337
+ it "should pass 'wa' to raw_open if fuse sends WRONLY | APPEND" do
338
+ ffi = Struct::FuseFileInfo.new()
339
+ ffi.flags = Fcntl::O_WRONLY | Fcntl::O_APPEND
340
+ raw = Object.new()
341
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
342
+ @mock_fuse.should_receive(:raw_open).with(TEST_FILE,"wa",true).and_return(raw)
343
+ @fuse.open(nil,TEST_FILE,ffi)
344
+ end
345
+ end
346
+
347
+ context "deleting files" do
348
+ it "should raise EACCES unless :can_delete?" do
349
+ @mock_fuse.should_receive(:can_delete?).with(TEST_FILE).and_return(false)
350
+ lambda {@fuse.unlink(nil,TEST_FILE)}.should raise_error(Errno::EACCES)
351
+ end
352
+
353
+ it "should :delete without error if :can_delete?" do
354
+ @mock_fuse.stub!(:can_delete?).with(TEST_FILE).and_return(true)
355
+ @mock_fuse.should_receive(:delete).with(TEST_FILE)
356
+ @fuse.unlink(nil,TEST_FILE)
357
+ end
358
+
359
+ it "should remove entries created with mknod that have never been opened" do
360
+ @mock_fuse.stub!(:file?).with(TEST_FILE).and_return(false)
361
+ @mock_fuse.stub!(:directory?).with(TEST_FILE).and_return(false)
362
+ @mock_fuse.stub!(:can_delete?).with(TEST_FILE).and_return(true)
363
+ @mock_fuse.stub!(:can_write?).with(TEST_FILE).and_return(true)
364
+ @fuse.mknod(nil,TEST_FILE,RFuse::Stat::S_IFREG | 0644,0,0)
365
+
366
+ @fuse.unlink(nil,TEST_FILE)
367
+ lambda {@fuse.getattr(nil,TEST_FILE)}.should raise_error(Errno::ENOENT)
368
+ end
369
+ end
370
+
371
+ context "deleting directories" do
372
+ it "should raise EACCES unless :can_rmdir?" do
373
+ @mock_fuse.should_receive(:can_rmdir?).with(TEST_DIR).and_return(false)
374
+ lambda{@fuse.rmdir(nil,TEST_DIR)}.should raise_error(Errno::EACCES)
375
+ end
376
+
377
+ it "should :rmdir without error if :can_rmdir?" do
378
+ @mock_fuse.stub!(:can_rmdir?).with(TEST_DIR).and_return(true)
379
+ @fuse.rmdir(nil,TEST_DIR)
380
+ end
381
+ end
382
+
383
+ context "touching files" do
384
+ it "should call :touch in response to utime" do
385
+ @mock_fuse.should_receive(:touch).with(TEST_FILE,220)
386
+ @fuse.utime(nil,TEST_FILE,100,220)
387
+ end
367
388
  end
368
-
389
+
369
390
  context "renaming files" do
370
- before(:each) do
371
- @oldfile = "/aPath/oldFile"
372
- @newfile = "/aNewFile"
373
- @mock_fuse.stub!(:file?).with(@oldfile).and_return(true)
374
- @mock_fuse.stub!(:directory?).with(@oldfile).and_return(false)
375
- end
376
- it "should raise EACCES unless :can_write? the new file" do
377
- @mock_fuse.stub!(:can_delete?).with(@oldfile).and_return(true)
378
- @mock_fuse.should_receive(:can_write?).with(@newfile).and_return(false)
379
- lambda {@fuse.rename(nil,@oldfile,@newfile)}.should raise_error(Errno::EACCES)
380
- end
391
+ before(:each) do
392
+ @oldfile = "/aPath/oldFile"
393
+ @newfile = "/aNewFile"
394
+ @mock_fuse.stub!(:file?).with(@oldfile).and_return(true)
395
+ @mock_fuse.stub!(:directory?).with(@oldfile).and_return(false)
396
+ end
397
+ it "should raise EACCES unless :can_write? the new file" do
398
+ @mock_fuse.stub!(:can_delete?).with(@oldfile).and_return(true)
399
+ @mock_fuse.should_receive(:can_write?).with(@newfile).and_return(false)
400
+ lambda {@fuse.rename(nil,@oldfile,@newfile)}.should raise_error(Errno::EACCES)
401
+ end
381
402
 
382
- it "should raise EACCES unless :can_delete the old file" do
383
- @mock_fuse.stub!(:can_write?).with(@newfile).and_return(true)
384
- @mock_fuse.should_receive(:can_delete?).with(@oldfile).and_return(false)
385
- lambda {@fuse.rename(nil,@oldfile,@newfile)}.should raise_error(Errno::EACCES)
386
- end
403
+ it "should raise EACCES unless :can_delete the old file" do
404
+ @mock_fuse.stub!(:can_write?).with(@newfile).and_return(true)
405
+ @mock_fuse.should_receive(:can_delete?).with(@oldfile).and_return(false)
406
+ lambda {@fuse.rename(nil,@oldfile,@newfile)}.should raise_error(Errno::EACCES)
407
+ end
387
408
 
388
- it "should copy and delete files" do
389
- @mock_fuse.stub!(:can_write?).with(@newfile).and_return(true)
390
- @mock_fuse.stub!(:can_delete?).with(@oldfile).and_return(true)
391
- @mock_fuse.should_receive(:read_file).with(@oldfile).and_return("some contents\n")
392
- @mock_fuse.should_receive(:write_to).with(@newfile,"some contents\n")
393
- @mock_fuse.should_receive(:delete).with(@oldfile)
394
- @fuse.rename(nil,@oldfile,@newfile)
395
- end
409
+ it "should copy and delete files" do
410
+ @mock_fuse.stub!(:can_write?).with(@newfile).and_return(true)
411
+ @mock_fuse.stub!(:can_delete?).with(@oldfile).and_return(true)
412
+ @mock_fuse.should_receive(:read_file).with(@oldfile).and_return("some contents\n")
413
+ @mock_fuse.should_receive(:write_to).with(@newfile,"some contents\n")
414
+ @mock_fuse.should_receive(:delete).with(@oldfile)
415
+ @fuse.rename(nil,@oldfile,@newfile)
416
+ end
396
417
 
397
- it "should not copy and delete files if fs responds_to? :rename" do
398
- @mock_fuse.should_receive(:rename).with(@oldfile,@newfile).and_return(true)
399
- @fuse.rename(nil,@oldfile,@newfile)
400
- end
418
+ it "should not copy and delete files if fs responds_to? :rename" do
419
+ @mock_fuse.should_receive(:rename).with(@oldfile,@newfile).and_return(true)
420
+ @fuse.rename(nil,@oldfile,@newfile)
421
+ end
401
422
 
402
- it "should raise EACCES if moving a directory and rename not supported" do
403
- @mock_fuse.stub!(:file?).with(@oldfile).and_return(false)
404
- @mock_fuse.stub!(:directory?).with(@oldfile).and_return(true)
405
- @mock_fuse.stub!(:can_write?).with(@newfile).and_return(true)
406
- @mock_fuse.stub!(:can_delete?).with(@oldfile).and_return(true)
407
- lambda{@fuse.rename(nil,@oldfile,@newfile)}.should raise_error(Errno::EACCES)
408
- end
423
+ it "should raise EACCES if moving a directory and rename not supported" do
424
+ @mock_fuse.stub!(:file?).with(@oldfile).and_return(false)
425
+ @mock_fuse.stub!(:directory?).with(@oldfile).and_return(true)
426
+ @mock_fuse.stub!(:can_write?).with(@newfile).and_return(true)
427
+ @mock_fuse.stub!(:can_delete?).with(@oldfile).and_return(true)
428
+ lambda{@fuse.rename(nil,@oldfile,@newfile)}.should raise_error(Errno::EACCES)
429
+ end
409
430
 
410
431
  end
411
432
  context "extended attributes" do
412
433
 
413
- let(:xattr) { mock(:xattr) }
414
- before(:each) { @mock_fuse.stub!(:xattr).with(TEST_FILE).and_return(xattr) }
434
+ let(:xattr) { mock(:xattr) }
435
+ before(:each) { @mock_fuse.stub!(:xattr).with(TEST_FILE).and_return(xattr) }
415
436
 
416
- it "should list attributes via #keys on result of #xattr" do
417
- xattr.should_receive(:keys).and_return(["one","two"])
418
- @fuse.listxattr(nil,TEST_FILE).should == [ "one","two" ]
419
- end
437
+ it "should list attributes via #keys on result of #xattr" do
438
+ xattr.should_receive(:keys).and_return(["one","two"])
439
+ @fuse.listxattr(nil,TEST_FILE).should == [ "one","two" ]
440
+ end
420
441
 
421
- it "should get attributes via #xattr.[]" do
422
- xattr.should_receive(:[]).with("user.one").and_return("one")
442
+ it "should get attributes via #xattr.[]" do
443
+ xattr.should_receive(:[]).with("user.one").and_return("one")
423
444
 
424
- @fuse.getxattr(nil,TEST_FILE,"user.one").should == "one"
425
- end
445
+ @fuse.getxattr(nil,TEST_FILE,"user.one").should == "one"
446
+ end
426
447
 
427
- it "should set attributes via #xattr.[]=" do
428
- xattr.should_receive(:[]=).with("user.two","two")
448
+ it "should set attributes via #xattr.[]=" do
449
+ xattr.should_receive(:[]=).with("user.two","two")
429
450
 
430
- @fuse.setxattr(nil,TEST_FILE,"user.two","two",0)
431
- end
451
+ @fuse.setxattr(nil,TEST_FILE,"user.two","two",0)
452
+ end
432
453
 
433
- it "should remove attributes via #xattr.delete" do
434
- xattr.should_receive(:delete).with("user.three")
454
+ it "should remove attributes via #xattr.delete" do
455
+ xattr.should_receive(:delete).with("user.three")
435
456
 
436
- @fuse.removexattr(nil,TEST_FILE,"user.three")
437
- end
457
+ @fuse.removexattr(nil,TEST_FILE,"user.three")
458
+ end
438
459
 
439
- it "should raise ENODATA when #xattr.[] returns nil" do
460
+ it "should raise ENODATA when #xattr.[] returns nil" do
440
461
 
441
- xattr.should_receive(:[]).with("user.xxxx").and_return(nil)
442
- lambda{@fuse.getxattr(nil,TEST_FILE,"user.xxxx") }.should raise_error(Errno::ENODATA)
443
- end
462
+ xattr.should_receive(:[]).with("user.xxxx").and_return(nil)
463
+ lambda{@fuse.getxattr(nil,TEST_FILE,"user.xxxx") }.should raise_error(Errno::ENODATA)
464
+ end
444
465
  end
445
466
 
446
467
  context "#statfs" do
447
- # used space, used files, total_space, total_files
448
- let(:stats) { [ 1000 * 1024, 5, 1200 * 1024, 12 ] }
449
- it "should convert simple array into StatVfs" do
450
-
451
- @mock_fuse.should_receive(:statistics).with(TEST_FILE).and_return(stats)
452
-
453
- result = @fuse.statfs(nil,TEST_FILE)
454
- result.should be_kind_of(RFuse::StatVfs)
455
- result.f_bsize.should == 1024
456
- result.f_blocks.should == 1200
457
- result.f_bavail.should == 200
458
- result.f_files.should == 12
459
- result.f_ffree.should == 7
460
- end
468
+ # used space, used files, total_space, total_files
469
+ let(:stats) { [ 1000 * 1024, 5, 1200 * 1024, 12 ] }
470
+ it "should convert simple array into StatVfs" do
461
471
 
462
- it "passes on raw statistics" do
463
- statvfs = Object.new()
464
- @mock_fuse.should_receive(:statistics).with(TEST_FILE).and_return(statvfs)
472
+ @mock_fuse.should_receive(:statistics).with(TEST_FILE).and_return(stats)
465
473
 
466
- @fuse.statfs(nil,TEST_FILE).should equal(statvfs)
467
- end
474
+ result = @fuse.statfs(nil,TEST_FILE)
475
+ result.should be_kind_of(RFuse::StatVfs)
476
+ result.f_bsize.should == 1024
477
+ result.f_blocks.should == 1200
478
+ result.f_bavail.should == 200
479
+ result.f_files.should == 12
480
+ result.f_ffree.should == 7
481
+ end
482
+
483
+ it "passes on raw statistics" do
484
+ statvfs = Object.new()
485
+ @mock_fuse.should_receive(:statistics).with(TEST_FILE).and_return(statvfs)
486
+
487
+ @fuse.statfs(nil,TEST_FILE).should equal(statvfs)
488
+ end
468
489
 
469
490
  end
470
491
  end
471
-
492
+
472
493
  describe "a FuseFS filesystem with gid/uid specific behaviour" do
473
494
  it "should provide context uid and gid for all API methods"
474
495
  end
475
- end
476
-
477
496
 
497
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rfusefs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2.RC1
4
+ version: 1.0.2.RC2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-12 00:00:00.000000000 Z
12
+ date: 2014-02-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rfuse
@@ -191,6 +191,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
191
191
  - - ! '>='
192
192
  - !ruby/object:Gem::Version
193
193
  version: '0'
194
+ segments:
195
+ - 0
196
+ hash: -1145013380842573975
194
197
  required_rubygems_version: !ruby/object:Gem::Requirement
195
198
  none: false
196
199
  requirements: