/
files.rb
94 lines (75 loc) · 1.89 KB
/
files.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
require "files/version"
module Files
# class methods
def self.default_options level = 2
{:remove => true, :name => called_from(level)}
end
def self.called_from level = 1
File.basename caller[level].split(':').first, ".rb"
end
def self.create options = default_options, &block
require 'tmpdir'
require 'fileutils'
name = options[:name]
path = File.join(Dir::tmpdir, "#{name}_#{Time.now.to_i}_#{rand(1000)}")
Files.new path, block, options
end
# mixin methods
def files options = ::Files.default_options # todo: block
@files ||= ::Files.create(options)
end
def file *args, &block
files.file *args, &block
end
def dir *args, &block
files.dir *args, &block
end
# concrete class for creating files and dirs under a temporary directory
class Files
attr_reader :root
def initialize path, block, options
@root = path
@dirs = []
dir path, &block
@dirs = [path]
at_exit {remove} if options[:remove]
end
def dir name, &block
path = "#{current}/#{name}"
Dir.mkdir path
@dirs << name
Dir.chdir(path) do
instance_eval &block if block
end
@dirs.pop
path
end
def file name, contents = "contents of #{name}"
if name.is_a? File
FileUtils.cp name.path, current
# todo: return path
else
path = "#{current}/#{name}"
if contents.is_a? File
FileUtils.cp contents.path, path
else
file_path = File.open(path, "w") do |f|
f.write contents
end
end
path
end
end
def remove
FileUtils.rm_rf(@root) if File.exists?(@root)
end
private
def current
@dirs.join('/')
end
end
end
def Files options = Files.default_options, &block
files = Files.create options, &block
files.root
end