rfusefs 1.0.2.RC1 → 1.0.2.RC2

Sign up to get free protection for your applications and to get access to all the features.
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: