files 0.1.0 → 0.2.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/README.md +64 -10
- data/files.gemspec +1 -1
- data/lib/files.rb +25 -6
- data/lib/files/version.rb +1 -1
- data/test/files_test.rb +68 -15
- metadata +9 -9
data/README.md
CHANGED
@@ -2,11 +2,35 @@
|
|
2
2
|
|
3
3
|
*a simple DSL for creating temporary files and directories*
|
4
4
|
|
5
|
-
|
5
|
+
Ever want to create a whole bunch of files at once? Like when you're writing tests for a tool that processes files? The Files gem lets you cleanly specify those files and their contents inside your test code, instead of forcing you to create a fixture directory and check it in to your repo. It puts them in a temporary directory and cleans up when your test is done.
|
6
|
+
|
7
|
+
## Usage (mixin mode)
|
8
|
+
|
9
|
+
The mixin mode is a fairly clean API, suitable for use in unit tests. After `include Files` you can call `file` or `dir` to make a temporary file or directory; it'll put them into a new temp dir that is removed on process exit. It also saves a reference to this directory inside an instance variable named `@files` so you can't use that name for your own instance variables.
|
10
|
+
|
11
|
+
require "files"
|
12
|
+
include Files
|
13
|
+
|
14
|
+
file "hello.txt" # creates file "hello.txt" containing "contents of hello.txt"
|
15
|
+
|
16
|
+
dir "web" do # creates directory "web"
|
17
|
+
file "snippet.html", # creates file "web/snippet.html"...
|
18
|
+
"<h1>Fix this!</h1>" # ...containing "<h1>Fix this!</h1>"
|
19
|
+
dir "img" do # creates directory "web/img"
|
20
|
+
file File.new("data/hello.png") # containing a copy of hello.png
|
21
|
+
file "hi.png", File.new("data/hello.png") # and a copy of hello.png named hi.png
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
files.root # creates (or returns) the temporary directory
|
26
|
+
|
27
|
+
## Usage (bare function mode)
|
28
|
+
|
29
|
+
In bare function mode, you call the `Files` method, which doesn't pollute the current object with a `@files` instance variable. It returns a string with the path to the root temp dir that you can use later.
|
6
30
|
|
7
31
|
require "files"
|
8
32
|
|
9
|
-
|
33
|
+
temp_dir = Files do # creates a temporary directory inside Dir.tmpdir
|
10
34
|
file "hello.txt" # creates file "hello.txt" containing "contents of hello.txt"
|
11
35
|
dir "web" do # creates directory "web"
|
12
36
|
file "snippet.html", # creates file "web/snippet.html"...
|
@@ -16,24 +40,54 @@
|
|
16
40
|
file "hi.png", File.new("data/hello.png") # and a copy of hello.png named hi.png
|
17
41
|
end
|
18
42
|
end
|
19
|
-
end # returns a string with the path to the directory
|
43
|
+
end # "Files" returns a string with the path to the directory
|
20
44
|
|
21
|
-
|
45
|
+
|
46
|
+
see `test/files_test.rb` for more usage examples
|
22
47
|
|
23
48
|
## Details
|
24
49
|
|
25
50
|
* the directory will be removed at exit
|
26
51
|
* unless you pass `:remove => false`
|
27
52
|
* the directory name is based on the name of the source file you called Files from
|
53
|
+
* if the first argument to `file` is a String, then a new file is made
|
54
|
+
* the content of the new file is either a short, descriptive message, or whatever you passed as the second argument
|
55
|
+
* if the argument to `file` is a Ruby `File` object, then it copies the contents of the named file into the temporary location
|
28
56
|
|
29
57
|
## TODO
|
30
58
|
|
59
|
+
* test under Windows
|
31
60
|
* :path option -- specifying the parent of the temporary dir (default: Dir.tmpdir)
|
32
|
-
* take a hash
|
33
|
-
*
|
34
|
-
* emit a hash
|
35
|
-
* emit a YAML file or string
|
36
|
-
* support symlinks (?)
|
37
|
-
* specify file mode
|
61
|
+
* take a hash or a YAML file or YAML string to specify the directory layout and contents
|
62
|
+
* emit a hash or a YAML file or string to serialize the directory layout and contents for later
|
38
63
|
* copy an entire data dir
|
64
|
+
* support symlinks (?)
|
65
|
+
* specify file write mode (?)
|
39
66
|
* play nice with FakeFS (possibly with a :fake option)
|
67
|
+
* global/default :remove option
|
68
|
+
|
69
|
+
## Credits
|
70
|
+
|
71
|
+
Written by Alex Chaffee <http://alexchaffee.com> <mailto:alex@stinky.com> <http://github.com/alexch> [@alexch](http://twitter.com/alexch)
|
72
|
+
|
73
|
+
## License
|
74
|
+
|
75
|
+
Copyright (C) 2012 Alex Chaffee
|
76
|
+
|
77
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
78
|
+
this software and associated documentation files (the "Software"), to deal in
|
79
|
+
the Software without restriction, including without limitation the rights to
|
80
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
81
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
82
|
+
so, subject to the following conditions:
|
83
|
+
|
84
|
+
The above copyright notice and this permission notice shall be included in all
|
85
|
+
copies or substantial portions of the Software.
|
86
|
+
|
87
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
88
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
89
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
90
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
91
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
92
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
93
|
+
SOFTWARE.
|
data/files.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = ["alex@stinky.com"]
|
10
10
|
s.homepage = ""
|
11
11
|
s.summary = %q{a simple DSL for creating temporary files and directories}
|
12
|
-
s.description = %q{
|
12
|
+
s.description = %q{Ever want to create a whole bunch of files at once? Like when you're writing tests for a tool that processes files? The Files gem lets you cleanly specify those files and their contents inside your test code, instead of forcing you to create a fixture directory and check it in to your repo. It puts them in a temporary directory and cleans up when your test is done.}
|
13
13
|
|
14
14
|
s.rubyforge_project = "files"
|
15
15
|
|
data/lib/files.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require "files/version"
|
2
2
|
|
3
|
-
|
4
3
|
module Files
|
4
|
+
|
5
|
+
# class methods
|
5
6
|
|
6
7
|
def self.default_options level = 2
|
7
8
|
{:remove => true, :name => called_from(level)}
|
@@ -18,11 +19,23 @@ module Files
|
|
18
19
|
name = options[:name]
|
19
20
|
path = File.join(Dir::tmpdir, "#{name}_#{Time.now.to_i}_#{rand(1000)}")
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
files.root
|
22
|
+
Files.new path, block, options
|
24
23
|
end
|
25
24
|
|
25
|
+
# mixin methods
|
26
|
+
def files options = ::Files.default_options # todo: block
|
27
|
+
@files ||= ::Files.create(options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def file *args, &block
|
31
|
+
files.file *args, &block
|
32
|
+
end
|
33
|
+
|
34
|
+
def dir *args, &block
|
35
|
+
files.dir *args, &block
|
36
|
+
end
|
37
|
+
|
38
|
+
# concrete class for creating files and dirs under a temporary directory
|
26
39
|
class Files
|
27
40
|
|
28
41
|
attr_reader :root
|
@@ -31,7 +44,8 @@ module Files
|
|
31
44
|
@root = path
|
32
45
|
@dirs = []
|
33
46
|
dir path, &block
|
34
|
-
|
47
|
+
@dirs = [path]
|
48
|
+
at_exit {remove} if options[:remove]
|
35
49
|
end
|
36
50
|
|
37
51
|
def dir name, &block
|
@@ -62,6 +76,10 @@ module Files
|
|
62
76
|
end
|
63
77
|
end
|
64
78
|
|
79
|
+
def remove
|
80
|
+
FileUtils.rm_rf(@root) if File.exists?(@root)
|
81
|
+
end
|
82
|
+
|
65
83
|
private
|
66
84
|
def current
|
67
85
|
@dirs.join('/')
|
@@ -71,5 +89,6 @@ module Files
|
|
71
89
|
end
|
72
90
|
|
73
91
|
def Files options = Files.default_options, &block
|
74
|
-
Files.create options, &block
|
92
|
+
files = Files.create options, &block
|
93
|
+
files.root
|
75
94
|
end
|
data/lib/files/version.rb
CHANGED
data/test/files_test.rb
CHANGED
@@ -5,21 +5,28 @@ here = File.dirname __FILE__
|
|
5
5
|
$LOAD_PATH.unshift File.join(here, '..', 'lib')
|
6
6
|
require "files"
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
8
|
+
## Testing the Files object
|
9
|
+
|
10
|
+
files = Files.create # creates a temporary directory inside Dir.tmpdir
|
11
|
+
|
12
|
+
assert { files.root }
|
13
|
+
|
14
|
+
files.file "hello.txt" # creates file "hello.txt" containing "contents of hello.txt"
|
15
|
+
files.dir "web" do # creates directory "web"
|
16
|
+
file "snippet.html", # creates file "web/snippet.html", with content
|
17
|
+
"<h1>File under F for fantastic!</h1>"
|
18
|
+
dir "img" do # creates directory "web/img"
|
19
|
+
file File.new("#{here}/data/cheez_doing_it_wrong.jpg") # containing a copy of cheez_doing_it_wrong.jpg
|
20
|
+
file "other.jpg", # and a different named file...
|
21
|
+
File.new("#{here}/data/cheez_doing_it_wrong.jpg") # containing the content of cheez_doing_it_wrong.jpg
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
25
|
+
dir = files.root
|
21
26
|
assert { dir.split('/').last =~ /^files_test/ }
|
22
27
|
|
28
|
+
assert { dir =~ /^#{Dir::tmpdir}/}
|
29
|
+
|
23
30
|
assert { File.read("#{dir}/hello.txt") == "contents of hello.txt" }
|
24
31
|
assert { File.read("#{dir}/web/snippet.html") == "<h1>File under F for fantastic!</h1>" }
|
25
32
|
assert {
|
@@ -31,10 +38,19 @@ assert {
|
|
31
38
|
File.read("#{here}/data/cheez_doing_it_wrong.jpg")
|
32
39
|
}
|
33
40
|
|
41
|
+
files.remove
|
42
|
+
assert("remove removes the root dir and all contents") { !File.exist?(dir) }
|
43
|
+
assert("after remove, the object is bogus") do
|
44
|
+
rescuing { (files.file "uhoh.txt") }.is_a? Errno::ENOENT
|
45
|
+
end
|
46
|
+
|
47
|
+
## Testing the Files method (which is the recommended public API)
|
48
|
+
|
34
49
|
dir = Files do
|
35
50
|
file "hello.txt"
|
36
51
|
dir("web") { file "hello.html" }
|
37
52
|
end
|
53
|
+
assert { dir }
|
38
54
|
assert { File.read("#{dir}/hello.txt") == "contents of hello.txt" }
|
39
55
|
assert { File.read("#{dir}/web/hello.html") == "contents of hello.html" }
|
40
56
|
assert { dir.split('/').last =~ /^files_test/ }
|
@@ -72,18 +88,17 @@ dir = Files do
|
|
72
88
|
end
|
73
89
|
assert { File.exist? "#{dir}/a" and File.directory? "#{dir}/a"}
|
74
90
|
|
75
|
-
|
76
|
-
# the file and dir methods return the path, suitable for saving into a predeclared local var
|
91
|
+
# the file and dir methods return the path, suitable for storing in a predeclared local var
|
77
92
|
stuff = nil
|
78
93
|
hello = nil
|
79
|
-
|
94
|
+
files_dir = Files do
|
80
95
|
stuff = dir "stuff" do
|
81
96
|
hello = file "hello.txt"
|
82
97
|
end
|
83
98
|
end
|
84
99
|
|
85
|
-
assert { stuff == "#{
|
86
|
-
assert { hello == "#{
|
100
|
+
assert { stuff == "#{files_dir}/stuff" }
|
101
|
+
assert { hello == "#{files_dir}/stuff/hello.txt" }
|
87
102
|
|
88
103
|
dir_inside_do_block = nil
|
89
104
|
dir = Files do
|
@@ -95,3 +110,41 @@ end
|
|
95
110
|
assert("sets the current directory inside the Files block") { File.basename(dir_inside_do_block) == File.basename(dir) }
|
96
111
|
# note that we can't just compare the full paths because some OS's hard link their temp dir to different base paths
|
97
112
|
|
113
|
+
## Testing the Mixin interface (which is the alternate public API)
|
114
|
+
class FilesMixinTest
|
115
|
+
include Files
|
116
|
+
def go
|
117
|
+
assert {@files.nil?}
|
118
|
+
file "foo.txt"
|
119
|
+
assert("calling file creates an instance var") { @files and @files.root }
|
120
|
+
assert("the method 'files' returns the instance var") { @files.object_id == files.object_id }
|
121
|
+
|
122
|
+
assert("calling file creates a file") { File.exist?("#{@files.root}/foo.txt") }
|
123
|
+
assert("the created file contains a nice message") { File.read("#{@files.root}/foo.txt") == "contents of foo.txt" }
|
124
|
+
|
125
|
+
dir "bar" do
|
126
|
+
file "bar.txt"
|
127
|
+
assert("the current directory is set inside a dir block") { File.read("bar.txt") == "contents of bar.txt" }
|
128
|
+
dir "sub" do
|
129
|
+
file "sub.txt"
|
130
|
+
assert("the current directory is set inside a nested dir block") { File.read("sub.txt") == "contents of sub.txt" }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
assert("a file created inside the dir block exists under the root dir") {
|
134
|
+
File.read("#{@files.root}/bar/bar.txt") == "contents of bar.txt"
|
135
|
+
}
|
136
|
+
|
137
|
+
subdir = dir "baz"
|
138
|
+
assert("the dir method creates the dir") { File.exist?("#{@files.root}/baz")}
|
139
|
+
assert("the dir method returns the created dir") { subdir == "#{@files.root}/baz"}
|
140
|
+
assert { File.directory?("#{@files.root}/baz")}
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
FilesMixinTest.new.go
|
145
|
+
|
146
|
+
# TODO: allow options to be set in mixin mode
|
147
|
+
# TODO: test options from function mode and mixin mode
|
148
|
+
# files = Files.create :dummy => true
|
149
|
+
# assert { files.options[:dummy] == true }
|
150
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: files
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,13 +9,13 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-01-
|
12
|
+
date: 2012-01-24 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
|
-
description:
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
description: Ever want to create a whole bunch of files at once? Like when you're
|
15
|
+
writing tests for a tool that processes files? The Files gem lets you cleanly specify
|
16
|
+
those files and their contents inside your test code, instead of forcing you to
|
17
|
+
create a fixture directory and check it in to your repo. It puts them in a temporary
|
18
|
+
directory and cleans up when your test is done.
|
19
19
|
email:
|
20
20
|
- alex@stinky.com
|
21
21
|
executables: []
|
@@ -45,7 +45,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
45
45
|
version: '0'
|
46
46
|
segments:
|
47
47
|
- 0
|
48
|
-
hash: -
|
48
|
+
hash: -1401824793539482884
|
49
49
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
@@ -54,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
54
|
version: '0'
|
55
55
|
segments:
|
56
56
|
- 0
|
57
|
-
hash: -
|
57
|
+
hash: -1401824793539482884
|
58
58
|
requirements: []
|
59
59
|
rubyforge_project: files
|
60
60
|
rubygems_version: 1.8.6
|