memfs 0.0.1
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.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +128 -0
- data/Rakefile +6 -0
- data/lib/fileutils.rb +1738 -0
- data/lib/memfs/dir.rb +33 -0
- data/lib/memfs/fake/directory.rb +51 -0
- data/lib/memfs/fake/entry.rb +73 -0
- data/lib/memfs/fake/file/content.rb +47 -0
- data/lib/memfs/fake/file.rb +36 -0
- data/lib/memfs/fake/symlink.rb +32 -0
- data/lib/memfs/file/stat.rb +48 -0
- data/lib/memfs/file.rb +284 -0
- data/lib/memfs/file_system.rb +157 -0
- data/lib/memfs/filesystem_access.rb +7 -0
- data/lib/memfs/version.rb +3 -0
- data/lib/memfs.rb +100 -0
- data/memfs.gemspec +29 -0
- data/spec/fileutils_spec.rb +961 -0
- data/spec/memfs/dir_spec.rb +104 -0
- data/spec/memfs/fake/directory_spec.rb +115 -0
- data/spec/memfs/fake/entry_spec.rb +140 -0
- data/spec/memfs/fake/file/content_spec.rb +154 -0
- data/spec/memfs/fake/file_spec.rb +37 -0
- data/spec/memfs/fake/symlink_spec.rb +43 -0
- data/spec/memfs/file/stat_spec.rb +209 -0
- data/spec/memfs/file_spec.rb +928 -0
- data/spec/memfs/file_system_spec.rb +393 -0
- data/spec/memfs_spec.rb +54 -0
- data/spec/spec_helper.rb +20 -0
- metadata +203 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'memfs/fake/directory'
|
3
|
+
require 'memfs/fake/file'
|
4
|
+
require 'memfs/fake/symlink'
|
5
|
+
|
6
|
+
module MemFs
|
7
|
+
class FileSystem
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
attr_accessor :working_directory
|
11
|
+
attr_accessor :registred_entries
|
12
|
+
attr_accessor :root
|
13
|
+
|
14
|
+
def basename(path)
|
15
|
+
File.basename(path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def chdir(path, &block)
|
19
|
+
destination = find_directory!(path)
|
20
|
+
|
21
|
+
previous_directory = working_directory
|
22
|
+
self.working_directory = destination
|
23
|
+
|
24
|
+
block.call if block
|
25
|
+
ensure
|
26
|
+
if block
|
27
|
+
self.working_directory = previous_directory
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def clear!
|
32
|
+
self.root = Fake::Directory.new('/')
|
33
|
+
self.chdir('/')
|
34
|
+
end
|
35
|
+
|
36
|
+
def chmod(mode_int, file_name)
|
37
|
+
find!(file_name).mode = mode_int
|
38
|
+
end
|
39
|
+
|
40
|
+
def chown(uid, gid, path)
|
41
|
+
entry = find!(path).dereferenced
|
42
|
+
entry.uid = uid if uid && uid != -1
|
43
|
+
entry.gid = gid if gid && gid != -1
|
44
|
+
end
|
45
|
+
|
46
|
+
def directory?(path)
|
47
|
+
find(path).is_a?(Fake::Directory)
|
48
|
+
end
|
49
|
+
|
50
|
+
def dirname(path)
|
51
|
+
File.dirname(path)
|
52
|
+
end
|
53
|
+
|
54
|
+
def entries(path)
|
55
|
+
find_directory!(path).entry_names
|
56
|
+
end
|
57
|
+
|
58
|
+
def find(path)
|
59
|
+
if path == '/'
|
60
|
+
root
|
61
|
+
elsif dirname(path) == '.'
|
62
|
+
working_directory.find(path)
|
63
|
+
else
|
64
|
+
root.find(path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def find!(path)
|
69
|
+
find(path) || raise(Errno::ENOENT, path)
|
70
|
+
end
|
71
|
+
|
72
|
+
def find_directory!(path)
|
73
|
+
entry = find!(path).dereferenced
|
74
|
+
|
75
|
+
raise Errno::ENOTDIR, path unless entry.is_a?(Fake::Directory)
|
76
|
+
|
77
|
+
entry
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_parent!(path)
|
81
|
+
parent_path = dirname(path)
|
82
|
+
find_directory!(parent_path)
|
83
|
+
end
|
84
|
+
|
85
|
+
def getwd
|
86
|
+
working_directory.path
|
87
|
+
end
|
88
|
+
alias :pwd :getwd
|
89
|
+
|
90
|
+
def initialize
|
91
|
+
clear!
|
92
|
+
end
|
93
|
+
|
94
|
+
def link(old_name, new_name)
|
95
|
+
file = find!(old_name)
|
96
|
+
|
97
|
+
raise Errno::EEXIST, "(#{old_name}, #{new_name})" if find(new_name)
|
98
|
+
|
99
|
+
link = file.dup
|
100
|
+
link.name = basename(new_name)
|
101
|
+
find_parent!(new_name).add_entry link
|
102
|
+
end
|
103
|
+
|
104
|
+
def mkdir(path)
|
105
|
+
raise Errno::EEXIST, path if find(path)
|
106
|
+
find_parent!(path).add_entry Fake::Directory.new(path)
|
107
|
+
end
|
108
|
+
|
109
|
+
def rename(old_name, new_name)
|
110
|
+
file = find!(old_name)
|
111
|
+
file.delete
|
112
|
+
|
113
|
+
file.name = basename(new_name)
|
114
|
+
find_parent!(new_name).add_entry(file)
|
115
|
+
end
|
116
|
+
|
117
|
+
def rmdir(path)
|
118
|
+
directory = find!(path)
|
119
|
+
|
120
|
+
raise Errno::ENOTEMPTY, path unless directory.empty?
|
121
|
+
|
122
|
+
directory.delete
|
123
|
+
end
|
124
|
+
|
125
|
+
def symlink(old_name, new_name)
|
126
|
+
raise Errno::EEXIST, new_name if find(new_name)
|
127
|
+
|
128
|
+
find_parent!(new_name).add_entry Fake::Symlink.new(new_name, old_name)
|
129
|
+
end
|
130
|
+
|
131
|
+
def symlink?(path)
|
132
|
+
find(path).is_a?(Fake::Symlink)
|
133
|
+
end
|
134
|
+
|
135
|
+
def touch(*paths)
|
136
|
+
paths.each do |path|
|
137
|
+
entry = find(path)
|
138
|
+
|
139
|
+
unless entry
|
140
|
+
entry = Fake::File.new(path)
|
141
|
+
parent_dir = find_parent!(path)
|
142
|
+
parent_dir.add_entry entry
|
143
|
+
end
|
144
|
+
|
145
|
+
entry.touch
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def unlink(path)
|
150
|
+
entry = find!(path)
|
151
|
+
|
152
|
+
raise Errno::EPERM, path if entry.is_a?(Fake::Directory)
|
153
|
+
|
154
|
+
entry.delete
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
data/lib/memfs.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'memfs/version'
|
2
|
+
|
3
|
+
# Provides a clean way to interact with a fake file system.
|
4
|
+
#
|
5
|
+
# @example Calling activate with a block.
|
6
|
+
# MemFs.activate do
|
7
|
+
# Dir.mkdir '/hello_world'
|
8
|
+
# # /hello_world exists here, in memory
|
9
|
+
# end
|
10
|
+
# # /hello_world doesn't exist and has never been on the real FS
|
11
|
+
#
|
12
|
+
# @example Calling activate! and deactivate!.
|
13
|
+
# MemFs.activate!
|
14
|
+
# # The fake file system is running here
|
15
|
+
# MemFs.deactivate!
|
16
|
+
# # Everything back to normal
|
17
|
+
module MemFs
|
18
|
+
extend self
|
19
|
+
|
20
|
+
# Keeps track of the original Ruby Dir class.
|
21
|
+
OriginalDir = ::Dir
|
22
|
+
|
23
|
+
# Keeps track of the original Ruby File class.
|
24
|
+
OriginalFile = ::File
|
25
|
+
|
26
|
+
require 'memfs/file_system'
|
27
|
+
require 'memfs/dir'
|
28
|
+
require 'memfs/file'
|
29
|
+
require 'memfs/file/stat'
|
30
|
+
|
31
|
+
# Calls the given block with MemFs activated.
|
32
|
+
#
|
33
|
+
# The advantage of using {#activate} against {#activate!} is that, in case an
|
34
|
+
# exception occurs, MemFs is deactivated.
|
35
|
+
#
|
36
|
+
# @yield with no argument.
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# MemFs.activate do
|
40
|
+
# Dir.mkdir '/hello_world'
|
41
|
+
# # /hello_world exists here, in memory
|
42
|
+
# end
|
43
|
+
# # /hello_world doesn't exist and has never been on the real FS
|
44
|
+
#
|
45
|
+
# @example Exception in activate block.
|
46
|
+
# MemFs.activate do
|
47
|
+
# raise "Some Error"
|
48
|
+
# end
|
49
|
+
# # Still back to the original Ruby classes
|
50
|
+
#
|
51
|
+
# @return nothing.
|
52
|
+
def activate
|
53
|
+
activate!
|
54
|
+
yield
|
55
|
+
ensure
|
56
|
+
deactivate!
|
57
|
+
end
|
58
|
+
|
59
|
+
# Activates the fake file system.
|
60
|
+
#
|
61
|
+
# @note Don't forget to call {#deactivate!} to disable the fake file system,
|
62
|
+
# you may have some issues in your scripts or tests otherwise.
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# MemFs.activate!
|
66
|
+
# Dir.mkdir '/hello_world'
|
67
|
+
# # /hello_world exists here, in memory
|
68
|
+
# MemFs.deactivate!
|
69
|
+
# # /hello_world doesn't exist and has never been on the real FS
|
70
|
+
#
|
71
|
+
# @see #deactivate!
|
72
|
+
# @return nothing.
|
73
|
+
def activate!
|
74
|
+
Object.class_eval do
|
75
|
+
remove_const :Dir
|
76
|
+
remove_const :File
|
77
|
+
|
78
|
+
const_set :Dir, MemFs::Dir
|
79
|
+
const_set :File, MemFs::File
|
80
|
+
end
|
81
|
+
|
82
|
+
MemFs::FileSystem.instance.clear!
|
83
|
+
end
|
84
|
+
|
85
|
+
# Deactivates the fake file system.
|
86
|
+
#
|
87
|
+
# @note This method should always be called when using activate!
|
88
|
+
#
|
89
|
+
# @see #activate!
|
90
|
+
# @return nothing.
|
91
|
+
def deactivate!
|
92
|
+
Object.class_eval do
|
93
|
+
remove_const :Dir
|
94
|
+
remove_const :File
|
95
|
+
|
96
|
+
const_set :Dir, MemFs::OriginalDir
|
97
|
+
const_set :File, MemFs::OriginalFile
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/memfs.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'memfs/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "memfs"
|
8
|
+
gem.version = MemFs::VERSION
|
9
|
+
gem.authors = ["Simon COURTOIS"]
|
10
|
+
gem.email = ["scourtois@cubyx.fr"]
|
11
|
+
gem.description = "MemFs provides a fake file system that can be used " \
|
12
|
+
"for tests. Strongly inspired by FakeFS."
|
13
|
+
gem.summary = "memfs-#{MemFs::VERSION}"
|
14
|
+
gem.homepage = "http://github.com/simonc/memfs"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_development_dependency "coveralls", "~> 0.6"
|
22
|
+
gem.add_development_dependency "rake", "~> 10.0"
|
23
|
+
gem.add_development_dependency "rspec", "~> 2.12"
|
24
|
+
gem.add_development_dependency "guard", "~> 1.5"
|
25
|
+
gem.add_development_dependency "guard-rspec", "~> 2.1"
|
26
|
+
gem.add_development_dependency "rb-inotify", "~> 0.8"
|
27
|
+
gem.add_development_dependency "rb-fsevent", "~> 0.9"
|
28
|
+
gem.add_development_dependency "rb-fchange", "~> 0.0"
|
29
|
+
end
|