rfuse 1.0.0
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/.gitignore +5 -0
- data/CHANGES.md +40 -0
- data/Gemfile +4 -0
- data/LICENSE +340 -0
- data/README.md +61 -0
- data/Rakefile +12 -0
- data/ext/.gitignore +2 -0
- data/ext/rfuse/bufferwrapper.c +48 -0
- data/ext/rfuse/bufferwrapper.h +10 -0
- data/ext/rfuse/context.c +70 -0
- data/ext/rfuse/context.h +5 -0
- data/ext/rfuse/extconf.rb +12 -0
- data/ext/rfuse/file_info.c +140 -0
- data/ext/rfuse/file_info.h +13 -0
- data/ext/rfuse/filler.c +60 -0
- data/ext/rfuse/filler.h +15 -0
- data/ext/rfuse/helper.c +93 -0
- data/ext/rfuse/helper.h +22 -0
- data/ext/rfuse/intern_rfuse.c +84 -0
- data/ext/rfuse/intern_rfuse.h +22 -0
- data/ext/rfuse/pollhandle.c +54 -0
- data/ext/rfuse/pollhandle.h +10 -0
- data/ext/rfuse/rfuse.c +2045 -0
- data/ext/rfuse/rfuse.h +3 -0
- data/ext/rfuse/rfuse_mod.c +12 -0
- data/lib/rfuse/version.rb +3 -0
- data/lib/rfuse-ng.rb +1 -0
- data/lib/rfuse.rb +211 -0
- data/lib/rfuse_ng.rb +3 -0
- data/rfuse.gemspec +26 -0
- data/sample/test-ruby.rb +339 -0
- data/spec/basic_spec.rb +176 -0
- data/spec/fuse_file_info_spec.rb +46 -0
- data/spec/ruby_loop_spec.rb +65 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/xattr_spec.rb +39 -0
- metadata +164 -0
data/spec/basic_spec.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
describe RFuse::Fuse do
|
5
|
+
|
6
|
+
let(:dir_stat) { RFuse::Stat.directory(0444) }
|
7
|
+
let(:file_stat) { RFuse::Stat.file(0444) }
|
8
|
+
let!(:mockfs) { m = mock("fuse"); m.stub(:getattr).and_return(nil); m }
|
9
|
+
let(:mountpoint) { tempmount() }
|
10
|
+
|
11
|
+
context "mount options" do
|
12
|
+
it "should handle -h" do
|
13
|
+
fuse = RFuse::FuseDelegator.new(mockfs,mountpoint,"-h")
|
14
|
+
fuse.mounted?.should be_false
|
15
|
+
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should behave sensibly for bad mountpoint" do
|
19
|
+
fuse = RFuse::FuseDelegator.new(mockfs,"bad/mount/point")
|
20
|
+
fuse.mounted?.should be_false
|
21
|
+
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should behave sensibly for bad options" do
|
25
|
+
fuse = RFuse::FuseDelegator.new(mockfs,mountpoint,"-eviloption")
|
26
|
+
fuse.mounted?.should be_false
|
27
|
+
lambda { fuse.loop }.should raise_error(RFuse::Error)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should handle a Pathname as a mountpoint" do
|
31
|
+
fuse = RFuse::FuseDelegator.new(mockfs,Pathname.new(mountpoint))
|
32
|
+
fuse.mounted?.should be_true
|
33
|
+
fuse.unmount()
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "links" do
|
38
|
+
it "should create and resolve symbolic links"
|
39
|
+
|
40
|
+
it "should create and resolve hard links"
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
context "directories" do
|
45
|
+
it "should make directories" do
|
46
|
+
|
47
|
+
mockfs.stub(:getattr).and_return(nil)
|
48
|
+
mockfs.stub(:getattr).with(anything(),"/aDirectory").and_return(nil,dir_stat)
|
49
|
+
mockfs.should_receive(:mkdir).with(anything(),"/aDirectory",anything())
|
50
|
+
|
51
|
+
with_fuse(mountpoint,mockfs) do
|
52
|
+
Dir.mkdir("#{mountpoint}/aDirectory")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should list directories" do
|
57
|
+
|
58
|
+
mockfs.should_receive(:readdir) do | ctx, path, filler,offset,ffi |
|
59
|
+
filler.push("hello",nil,0)
|
60
|
+
filler.push("world",nil,0)
|
61
|
+
end
|
62
|
+
|
63
|
+
with_fuse(mountpoint,mockfs) do
|
64
|
+
entries = Dir.entries(mountpoint)
|
65
|
+
entries.size.should == 2
|
66
|
+
entries.should include("hello")
|
67
|
+
entries.should include("world")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "permissions" do
|
73
|
+
it "should process chmod" do
|
74
|
+
mockfs.stub(:getattr).with(anything(),"/myPerms").and_return(file_stat)
|
75
|
+
|
76
|
+
mockfs.should_receive(:chmod).with(anything(),"/myPerms",file_mode(0644))
|
77
|
+
|
78
|
+
with_fuse(mountpoint,mockfs) do
|
79
|
+
File.chmod(0644,"#{mountpoint}/myPerms").should == 1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "timestamps" do
|
85
|
+
|
86
|
+
it "should support stat with subsecond resolution" do
|
87
|
+
begin
|
88
|
+
atime = Time.now() + 60
|
89
|
+
sleep(0.001)
|
90
|
+
end until atime.usec != 0
|
91
|
+
|
92
|
+
begin
|
93
|
+
mtime = Time.now() + 600
|
94
|
+
sleep(0.001)
|
95
|
+
end until mtime.usec != 0
|
96
|
+
|
97
|
+
begin
|
98
|
+
ctime = Time.now() + 3600
|
99
|
+
sleep(0.001)
|
100
|
+
end until ctime.usec != 0
|
101
|
+
|
102
|
+
file_stat.atime = atime
|
103
|
+
file_stat.mtime = mtime
|
104
|
+
file_stat.ctime = ctime
|
105
|
+
|
106
|
+
|
107
|
+
# ruby can't set file times with ns res, o we are limited to usecs
|
108
|
+
mockfs.stub(:getattr).with(anything(),"/nanos").and_return(file_stat)
|
109
|
+
|
110
|
+
with_fuse(mountpoint,mockfs) do
|
111
|
+
stat = File.stat("#{mountpoint}/nanos")
|
112
|
+
stat.atime.should == atime
|
113
|
+
stat.ctime.should == ctime
|
114
|
+
stat.mtime.should == mtime
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should set file access and modification times" do
|
119
|
+
|
120
|
+
atime = Time.now()
|
121
|
+
mtime = atime + 1
|
122
|
+
|
123
|
+
mockfs.stub(:getattr).with(anything(),"/times").and_return(file_stat)
|
124
|
+
mockfs.should_receive(:utime).with(anything(),"/times",atime.to_i,mtime.to_i)
|
125
|
+
|
126
|
+
with_fuse(mountpoint,mockfs) do
|
127
|
+
File.utime(atime,mtime,"#{mountpoint}/times").should == 1
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
context "file io" do
|
134
|
+
|
135
|
+
it "should create files" do
|
136
|
+
|
137
|
+
mockfs.stub(:getattr).with(anything(),"/newfile").and_return(nil,file_stat)
|
138
|
+
mockfs.should_receive(:mknod).with(anything(),"/newfile",file_mode(0644),0,0)
|
139
|
+
|
140
|
+
with_fuse(mountpoint,mockfs) do
|
141
|
+
File.open("#{mountpoint}/newfile","w",0644) { |f| }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# ruby doesn't seem to have a native method to create these
|
146
|
+
# maybe try ruby-mkfifo
|
147
|
+
it "should create special device files"
|
148
|
+
|
149
|
+
it "should read files" do
|
150
|
+
|
151
|
+
file_stat.size = 11
|
152
|
+
mockfs.stub(:getattr) { | ctx, path|
|
153
|
+
case path
|
154
|
+
when "/test"
|
155
|
+
file_stat
|
156
|
+
else
|
157
|
+
raise Errno::ENOENT
|
158
|
+
end
|
159
|
+
|
160
|
+
}
|
161
|
+
|
162
|
+
reads = 0
|
163
|
+
mockfs.stub(:read) { |ctx,path,size,offset,ffi|
|
164
|
+
reads += 2
|
165
|
+
"hello world"[offset,reads]
|
166
|
+
}
|
167
|
+
|
168
|
+
with_fuse(mountpoint,mockfs) do
|
169
|
+
File.open("#{mountpoint}/test") do |f|
|
170
|
+
val = f.gets
|
171
|
+
val.should == "hello world"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RFuse::Fuse do
|
4
|
+
context "file handles" do
|
5
|
+
it "should retain file handles over GC" do
|
6
|
+
mockfs = mock("fuse")
|
7
|
+
|
8
|
+
file_stat = RFuse::Stat.file(0444,:size => 11)
|
9
|
+
|
10
|
+
mockfs.stub(:getattr) { | ctx, path|
|
11
|
+
case path
|
12
|
+
when "/one","/two"
|
13
|
+
file_stat
|
14
|
+
else
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
}
|
19
|
+
|
20
|
+
open_files = {}
|
21
|
+
mockfs.stub(:open) { |ctx,path,ffi|
|
22
|
+
ffi.fh = Object.new()
|
23
|
+
open_files[path] = ffi.fh.object_id
|
24
|
+
}
|
25
|
+
|
26
|
+
mockfs.stub(:read) { |ctx,path,size,offset,ffi|
|
27
|
+
GC.start()
|
28
|
+
open_files[path].should == ffi.fh.object_id
|
29
|
+
"hello world"
|
30
|
+
}
|
31
|
+
|
32
|
+
mountpoint = tempmount()
|
33
|
+
with_fuse(mountpoint,mockfs) do
|
34
|
+
f1 = File.new("#{mountpoint}/one")
|
35
|
+
f2 = File.new("#{mountpoint}/two")
|
36
|
+
|
37
|
+
val = f1.gets
|
38
|
+
val.should == "hello world"
|
39
|
+
f2.gets.should == "hello world"
|
40
|
+
|
41
|
+
f1.close()
|
42
|
+
f2.close()
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RFuse do
|
4
|
+
|
5
|
+
let(:mockfs) { m = mock("fuse"); m.stub(:getattr).and_return(nil) ; m }
|
6
|
+
let(:mountpoint) { tempmount() }
|
7
|
+
|
8
|
+
context "ruby loop" do
|
9
|
+
it "should exit from another thread and allow multiple loops" do
|
10
|
+
|
11
|
+
fuse = RFuse::FuseDelegator.new(mockfs,mountpoint)
|
12
|
+
t = Thread.new { sleep 0.5; fuse.exit }
|
13
|
+
fuse.loop()
|
14
|
+
t.join
|
15
|
+
t = Thread.new { sleep 0.5; fuse.exit }
|
16
|
+
fuse.loop
|
17
|
+
t.join
|
18
|
+
fuse.unmount
|
19
|
+
fuse.mounted?.should be_false
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# This will never work!
|
24
|
+
#it "should allow threads to operate on the filesystem" do
|
25
|
+
#
|
26
|
+
# mockfs = mock("fuse")
|
27
|
+
# mockfs.stub(:getattr).and_return(nil)
|
28
|
+
|
29
|
+
# fuse = RFuse::FuseDelegator.new(mockfs,"/tmp/rfuse-spec")
|
30
|
+
|
31
|
+
# t = Thread.new { sleep 0.5 ; File.stat("/tmp/rfuse-spec/thread") ; fuse.exit }
|
32
|
+
|
33
|
+
# fuse.loop()
|
34
|
+
# fuse.unmount()
|
35
|
+
#end
|
36
|
+
|
37
|
+
it "should allow other threads to be scheduled" do
|
38
|
+
|
39
|
+
file_stat = RFuse::Stat.file(0444)
|
40
|
+
|
41
|
+
thread_ran = false
|
42
|
+
|
43
|
+
mockfs.stub(:getattr).with(anything(),"/before") {
|
44
|
+
puts "before"
|
45
|
+
thread_ran.should be_false
|
46
|
+
file_stat
|
47
|
+
}
|
48
|
+
|
49
|
+
mockfs.stub(:getattr).with(anything(),"/missing") {
|
50
|
+
puts "missing"
|
51
|
+
GC.start()
|
52
|
+
thread_ran.should be_true
|
53
|
+
file_stat
|
54
|
+
}
|
55
|
+
|
56
|
+
t = Thread.new() { sleep 1.5 ; thread_ran = true }
|
57
|
+
with_fuse(mountpoint,mockfs) do
|
58
|
+
File.stat("#{mountpoint}/before");
|
59
|
+
sleep 2;
|
60
|
+
File.stat("#{mountpoint}/missing");
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rfuse'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
class FileModeMatcher
|
5
|
+
def initialize(expected)
|
6
|
+
@expected = expected
|
7
|
+
end
|
8
|
+
|
9
|
+
def description
|
10
|
+
"file mode #{@expected}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(actual)
|
14
|
+
(actual | RFuse::Stat::S_IFMT) == (@expected | RFuse::Stat::S_IFMT)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module RFuseHelper
|
19
|
+
# Runs the single threaded fuse loop
|
20
|
+
# on a pre configured mock fuse filesystem
|
21
|
+
# Executes fork block in a separate process
|
22
|
+
# that is expected to return success
|
23
|
+
def with_fuse(mnt,mockfs,*options,&fork_block)
|
24
|
+
|
25
|
+
fpid = Kernel.fork() {
|
26
|
+
sleep 0.5
|
27
|
+
begin
|
28
|
+
fork_block.call() if fork_block
|
29
|
+
ensure
|
30
|
+
sleep 0.3
|
31
|
+
system("fusermount -u #{mnt}")
|
32
|
+
end
|
33
|
+
}
|
34
|
+
|
35
|
+
fuse = RFuse::FuseDelegator.new(mockfs,mnt,*options)
|
36
|
+
fuse.loop
|
37
|
+
pid,result = Process.waitpid2(fpid)
|
38
|
+
result.should be_success
|
39
|
+
fuse.open_files.should be_empty()
|
40
|
+
fuse.mounted?.should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
def file_mode(mode)
|
44
|
+
FileModeMatcher.new(mode)
|
45
|
+
end
|
46
|
+
|
47
|
+
def tempmount()
|
48
|
+
Dir.mktmpdir("rfuse-spec")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
include RFuseHelper
|
data/spec/xattr_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ffi-xattr'
|
3
|
+
|
4
|
+
describe RFuse::Fuse do
|
5
|
+
it "should handle extended attributes" do
|
6
|
+
mockfs = mock("fuse")
|
7
|
+
|
8
|
+
file_stat = RFuse::Stat.file(0444,:size => 11)
|
9
|
+
|
10
|
+
mockfs.stub(:getattr).and_return(file_stat)
|
11
|
+
mockfs.stub(:getxattr) { |ctx,path,name|
|
12
|
+
case name
|
13
|
+
when "user.one"
|
14
|
+
"1"
|
15
|
+
when "user.two"
|
16
|
+
"2"
|
17
|
+
end
|
18
|
+
}
|
19
|
+
|
20
|
+
mockfs.stub(:listxattr).with(anything(),"/myfile").and_return([ "user.one","user.two" ])
|
21
|
+
mockfs.should_receive(:setxattr).with(anything(),"/myfile","user.three","updated",anything())
|
22
|
+
mockfs.should_receive(:removexattr).with(anything(),"/myfile","user.one")
|
23
|
+
|
24
|
+
mountpoint = tempmount()
|
25
|
+
|
26
|
+
with_fuse(mountpoint,mockfs) do
|
27
|
+
xattr = Xattr.new("#{mountpoint}/myfile")
|
28
|
+
xattr.list.should include("user.one")
|
29
|
+
xattr.list.should include("user.two")
|
30
|
+
xattr.list.size.should == 2
|
31
|
+
|
32
|
+
xattr['user.one'].should == "1"
|
33
|
+
xattr['user.two'].should == "2"
|
34
|
+
xattr['user.three']= "updated"
|
35
|
+
xattr.remove('user.one')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rfuse
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Grant Gardner
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: yard
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: redcarpet
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: ffi-xattr
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Ruby language binding for FUSE. It was forked from rfuse and modified
|
95
|
+
for Ruby 1.9.2.
|
96
|
+
email:
|
97
|
+
- grant@lastweekend.com.au
|
98
|
+
executables: []
|
99
|
+
extensions:
|
100
|
+
- ext/rfuse/extconf.rb
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- .gitignore
|
104
|
+
- CHANGES.md
|
105
|
+
- Gemfile
|
106
|
+
- LICENSE
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- ext/.gitignore
|
110
|
+
- ext/rfuse/bufferwrapper.c
|
111
|
+
- ext/rfuse/bufferwrapper.h
|
112
|
+
- ext/rfuse/context.c
|
113
|
+
- ext/rfuse/context.h
|
114
|
+
- ext/rfuse/extconf.rb
|
115
|
+
- ext/rfuse/file_info.c
|
116
|
+
- ext/rfuse/file_info.h
|
117
|
+
- ext/rfuse/filler.c
|
118
|
+
- ext/rfuse/filler.h
|
119
|
+
- ext/rfuse/helper.c
|
120
|
+
- ext/rfuse/helper.h
|
121
|
+
- ext/rfuse/intern_rfuse.c
|
122
|
+
- ext/rfuse/intern_rfuse.h
|
123
|
+
- ext/rfuse/pollhandle.c
|
124
|
+
- ext/rfuse/pollhandle.h
|
125
|
+
- ext/rfuse/rfuse.c
|
126
|
+
- ext/rfuse/rfuse.h
|
127
|
+
- ext/rfuse/rfuse_mod.c
|
128
|
+
- lib/rfuse-ng.rb
|
129
|
+
- lib/rfuse.rb
|
130
|
+
- lib/rfuse/version.rb
|
131
|
+
- lib/rfuse_ng.rb
|
132
|
+
- rfuse.gemspec
|
133
|
+
- sample/test-ruby.rb
|
134
|
+
- spec/basic_spec.rb
|
135
|
+
- spec/fuse_file_info_spec.rb
|
136
|
+
- spec/ruby_loop_spec.rb
|
137
|
+
- spec/spec_helper.rb
|
138
|
+
- spec/xattr_spec.rb
|
139
|
+
homepage: http://rubygems.org/gems/rfuse
|
140
|
+
licenses: []
|
141
|
+
post_install_message:
|
142
|
+
rdoc_options: []
|
143
|
+
require_paths:
|
144
|
+
- lib
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
none: false
|
147
|
+
requirements:
|
148
|
+
- - ! '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
153
|
+
requirements:
|
154
|
+
- - ! '>='
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 1.8.24
|
160
|
+
signing_key:
|
161
|
+
specification_version: 3
|
162
|
+
summary: Ruby language binding for FUSE
|
163
|
+
test_files: []
|
164
|
+
has_rdoc:
|