dassets 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +42 -10
- data/lib/dassets.rb +16 -28
- data/lib/dassets/asset_file.rb +36 -33
- data/lib/dassets/default_cache.rb +29 -0
- data/lib/dassets/digest_cmd.rb +36 -0
- data/lib/dassets/engine.rb +0 -2
- data/lib/dassets/file_store.rb +36 -0
- data/lib/dassets/runner.rb +2 -9
- data/lib/dassets/server/request.rb +5 -5
- data/lib/dassets/source_cache.rb +39 -0
- data/lib/dassets/source_file.rb +37 -13
- data/lib/dassets/version.rb +1 -1
- data/test/support/config/assets.rb +1 -0
- data/test/system/digest_cmd_run_tests.rb +37 -39
- data/test/system/rack_tests.rb +3 -7
- data/test/unit/asset_file_tests.rb +72 -40
- data/test/unit/config_tests.rb +3 -17
- data/test/unit/dassets_tests.rb +8 -42
- data/test/unit/default_cache_tests.rb +27 -0
- data/test/unit/{cmds/digest_cmd_tests.rb → digest_cmd_tests.rb} +4 -4
- data/test/unit/file_store_tests.rb +30 -0
- data/test/unit/server/request_tests.rb +7 -11
- data/test/unit/server/response_tests.rb +4 -5
- data/test/unit/source_cache_tests.rb +50 -0
- data/test/unit/source_file_tests.rb +28 -29
- metadata +16 -31
- data/lib/dassets/cmds/cache_cmd.rb +0 -33
- data/lib/dassets/cmds/digest_cmd.rb +0 -53
- data/lib/dassets/digests.rb +0 -61
- data/test/support/app/assets/.digests +0 -5
- data/test/support/app/assets/public/file1.txt +0 -1
- data/test/support/app/assets/public/file2.txt +0 -1
- data/test/support/app/assets/public/grumpy_cat.jpg +0 -0
- data/test/support/app/assets/public/nested/a-thing.txt.no-use +0 -4
- data/test/support/app/assets/public/nested/file3.txt +0 -0
- data/test/support/app_public/.gitkeep +0 -0
- data/test/support/example.digests +0 -3
- data/test/system/cache_cmd_run_tests.rb +0 -27
- data/test/unit/cmds/cache_cmd_tests.rb +0 -33
- data/test/unit/digests_tests.rb +0 -79
data/lib/dassets/source_file.rb
CHANGED
@@ -7,6 +7,16 @@ module Dassets
|
|
7
7
|
|
8
8
|
class SourceFile
|
9
9
|
|
10
|
+
def self.find_by_digest_path(path)
|
11
|
+
# always look at the freshest source list to make sure you get all sources
|
12
|
+
# not just the ones Dassets has cached
|
13
|
+
sources = Dassets::SourceList.new(Dassets.config).map{ |p| self.new(p) }
|
14
|
+
|
15
|
+
# get the last matching one in case two sources have the same digest path
|
16
|
+
# the last one *should* be correct since it was last to be digested
|
17
|
+
sources.select{ |s| s.digest_path == path }.last || NullSourceFile.new(path)
|
18
|
+
end
|
19
|
+
|
10
20
|
attr_reader :file_path
|
11
21
|
|
12
22
|
def initialize(file_path)
|
@@ -14,19 +24,8 @@ module Dassets
|
|
14
24
|
@ext_list = File.basename(@file_path).split('.').reverse
|
15
25
|
end
|
16
26
|
|
17
|
-
def
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
def digest
|
22
|
-
return if !self.exists?
|
23
|
-
|
24
|
-
Dassets::AssetFile.new(self.digest_path, self.fingerprint).tap do |asset_file|
|
25
|
-
FileUtils.mkdir_p(File.dirname(asset_file.output_path))
|
26
|
-
File.open(asset_file.output_path, "w"){ |f| f.write(self.compiled) }
|
27
|
-
Dassets.digests[self.digest_path] = self.fingerprint
|
28
|
-
Dassets.digests.save!
|
29
|
-
end
|
27
|
+
def asset_file
|
28
|
+
@asset_file ||= Dassets::AssetFile.new(self.digest_path)
|
30
29
|
end
|
31
30
|
|
32
31
|
def digest_path
|
@@ -52,6 +51,18 @@ module Dassets
|
|
52
51
|
@fingerprint ||= Digest::MD5.new.hexdigest(self.compiled)
|
53
52
|
end
|
54
53
|
|
54
|
+
def exists?
|
55
|
+
File.file?(@file_path)
|
56
|
+
end
|
57
|
+
|
58
|
+
def mtime
|
59
|
+
File.mtime(@file_path).httpdate
|
60
|
+
end
|
61
|
+
|
62
|
+
def ==(other_source_file)
|
63
|
+
self.file_path == other_source_file.file_path
|
64
|
+
end
|
65
|
+
|
55
66
|
private
|
56
67
|
|
57
68
|
def digest_dirname(file_path, source_path)
|
@@ -68,4 +79,17 @@ module Dassets
|
|
68
79
|
|
69
80
|
end
|
70
81
|
|
82
|
+
class NullSourceFile < SourceFile
|
83
|
+
attr_reader :file_path, :digest_path, :compiled, :fingerprint
|
84
|
+
def initialize(digest_path)
|
85
|
+
@file_path = ''
|
86
|
+
@ext_list = []
|
87
|
+
@digest_path = digest_path
|
88
|
+
end
|
89
|
+
def digest; end
|
90
|
+
def ==(other_source_file)
|
91
|
+
self.file_path == other_source_file.file_path
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
71
95
|
end
|
data/lib/dassets/version.rb
CHANGED
@@ -7,62 +7,60 @@ module Dassets
|
|
7
7
|
class DigestCmdRunTests < Assert::Context
|
8
8
|
desc "the DigestCmd"
|
9
9
|
setup do
|
10
|
-
Dassets.
|
11
|
-
Dassets.
|
10
|
+
Dassets.config.file_store = 'public'
|
11
|
+
clear_store_path(Dassets.config.file_store.root)
|
12
12
|
Dassets.digest_source_files
|
13
13
|
|
14
14
|
@addfile = 'addfile.txt'
|
15
|
-
@
|
16
|
-
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
20
|
-
|
21
|
-
|
22
|
-
@
|
23
|
-
|
24
|
-
|
25
|
-
FileUtils.
|
26
|
-
FileUtils.rm @rmfile_path
|
27
|
-
File.open(@updfile_path, "w+"){ |f| f.write('an update') }
|
15
|
+
@addfile_src = source_path(@addfile)
|
16
|
+
|
17
|
+
@rmfile = 'file1.txt'
|
18
|
+
@rmfile_src = source_path(@rmfile)
|
19
|
+
@rmfile_contents = File.read(@rmfile_src)
|
20
|
+
|
21
|
+
FileUtils.touch @addfile_src
|
22
|
+
@addfile_out = store_path(@addfile)
|
23
|
+
|
24
|
+
@rmfile_out = store_path(@rmfile)
|
25
|
+
FileUtils.rm @rmfile_src
|
28
26
|
end
|
29
27
|
teardown do
|
30
|
-
File.open(@
|
31
|
-
|
32
|
-
FileUtils.rm @addfile_path
|
28
|
+
File.open(@rmfile_src, "w"){ |f| f.write @rmfile_contents }
|
29
|
+
FileUtils.rm @addfile_src
|
33
30
|
|
34
|
-
Dassets.reset
|
35
|
-
Dassets.init
|
36
31
|
Dassets.digest_source_files
|
32
|
+
clear_store_path(Dassets.config.file_store.root)
|
33
|
+
Dassets.digest_source_files
|
34
|
+
Dassets.config.file_store = NullFileStore.new
|
37
35
|
end
|
38
36
|
|
39
37
|
should "update the digests on all source files when run with no given paths" do
|
40
|
-
|
41
|
-
assert_equal 5, Dassets.digests.paths.size
|
42
|
-
assert_not_includes @addfile, Dassets.digests.paths
|
43
|
-
assert_includes @rmfile, Dassets.digests.paths
|
44
|
-
assert_equal @orig_updfile_md5, Dassets.digests[@updfile]
|
45
|
-
|
38
|
+
clear_store_path(Dassets.config.file_store.root)
|
46
39
|
Dassets.digest_source_files
|
47
40
|
|
48
|
-
|
49
|
-
|
50
|
-
assert_includes @addfile, Dassets.digests.paths
|
51
|
-
assert_not_includes @rmfile, Dassets.digests.paths
|
52
|
-
assert_not_equal @orig_updfile_md5, Dassets.digests[@updfile]
|
41
|
+
assert_file_exists @addfile_out
|
42
|
+
assert_not_file_exists @rmfile_out
|
53
43
|
end
|
54
44
|
|
55
45
|
should "update the digests on a single source file when given its path" do
|
56
|
-
|
57
|
-
|
46
|
+
clear_store_path(Dassets.config.file_store.root)
|
47
|
+
Dassets.digest_source_files([@addfile_src])
|
58
48
|
|
59
|
-
|
49
|
+
assert_file_exists @addfile_out
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def source_path(file)
|
55
|
+
File.join(File.join(Dassets.config.source_path, file))
|
56
|
+
end
|
57
|
+
|
58
|
+
def store_path(file)
|
59
|
+
Dassets.config.file_store.store_path(Dassets::AssetFile.new(file).url)
|
60
|
+
end
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
assert_includes @addfile, Dassets.digests.paths
|
64
|
-
assert_includes @rmfile, Dassets.digests.paths
|
65
|
-
assert_equal @orig_updfile_md5, Dassets.digests[@updfile]
|
62
|
+
def clear_store_path(path)
|
63
|
+
Dir.glob(File.join(path, '*')).each{ |p| FileUtils.rm_r(p) } if path
|
66
64
|
end
|
67
65
|
|
68
66
|
end
|
data/test/system/rack_tests.rb
CHANGED
@@ -10,12 +10,8 @@ module Dassets
|
|
10
10
|
|
11
11
|
desc "the middleware in a rack app"
|
12
12
|
setup do
|
13
|
-
Dassets.init
|
14
13
|
app.use Dassets::Server
|
15
14
|
end
|
16
|
-
teardown do
|
17
|
-
Dassets.reset
|
18
|
-
end
|
19
15
|
|
20
16
|
def app
|
21
17
|
@app ||= SinatraApp
|
@@ -29,13 +25,13 @@ module Dassets
|
|
29
25
|
should "return a successful response" do
|
30
26
|
resp = get '/file1-daa05c683a4913b268653f7a7e36a5b4.txt'
|
31
27
|
assert_equal 200, resp.status
|
32
|
-
assert_equal Dassets['
|
28
|
+
assert_equal Dassets['file1.txt'].content, resp.body
|
33
29
|
end
|
34
30
|
|
35
31
|
should "return a successful response with no body on HEAD requests" do
|
36
32
|
resp = head '/file2-9bbe1047cffbb590f59e0e5aeff46ae4.txt'
|
37
33
|
assert_equal 200, resp.status
|
38
|
-
assert_equal Dassets['
|
34
|
+
assert_equal Dassets['file2.txt'].size.to_s, resp.headers['Content-Length']
|
39
35
|
assert_empty resp.body
|
40
36
|
end
|
41
37
|
|
@@ -45,7 +41,7 @@ module Dassets
|
|
45
41
|
desc "requesting an existing asset file that has not been modified"
|
46
42
|
setup do
|
47
43
|
@resp = get('/file1-daa05c683a4913b268653f7a7e36a5b4.txt', {}, {
|
48
|
-
'HTTP_IF_MODIFIED_SINCE' => Dassets['
|
44
|
+
'HTTP_IF_MODIFIED_SINCE' => Dassets['file1.txt'].mtime.to_s
|
49
45
|
})
|
50
46
|
end
|
51
47
|
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'assert'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'dassets/file_store'
|
4
|
+
require 'dassets/source_cache'
|
2
5
|
require 'dassets/asset_file'
|
3
6
|
|
4
7
|
class Dassets::AssetFile
|
@@ -6,69 +9,98 @@ class Dassets::AssetFile
|
|
6
9
|
class BaseTests < Assert::Context
|
7
10
|
desc "Dassets::AssetFile"
|
8
11
|
setup do
|
9
|
-
@asset_file = Dassets::AssetFile.new('file1.txt'
|
12
|
+
@asset_file = Dassets::AssetFile.new('file1.txt')
|
10
13
|
end
|
11
14
|
subject{ @asset_file }
|
12
15
|
|
13
|
-
should
|
14
|
-
should
|
15
|
-
should
|
16
|
-
should have_imeth :content, :mtime, :size, :mime_type, :exists?, :==
|
16
|
+
should have_readers :digest_path, :dirname, :extname, :basename, :source_cache
|
17
|
+
should have_imeths :digest!, :url, :fingerprint, :content
|
18
|
+
should have_imeths :href, :mtime, :size, :mime_type, :exists?, :==
|
17
19
|
|
18
|
-
should "know its
|
19
|
-
assert_equal 'file1.txt', subject.
|
20
|
-
assert_equal 'abc123', subject.md5
|
21
|
-
end
|
22
|
-
|
23
|
-
should "know its dirname, extname, and basename" do
|
20
|
+
should "know its digest path, dirname, extname, and basename" do
|
21
|
+
assert_equal 'file1.txt', subject.digest_path
|
24
22
|
assert_equal '.', subject.dirname
|
25
23
|
assert_equal '.txt', subject.extname
|
26
24
|
assert_equal 'file1', subject.basename
|
27
25
|
end
|
28
26
|
|
29
|
-
should "
|
30
|
-
assert_equal
|
27
|
+
should "use its source file attrs as its own" do
|
28
|
+
assert_equal subject.source_cache.mtime, subject.mtime
|
29
|
+
assert_equal Rack::Utils.bytesize(subject.content), subject.size
|
30
|
+
assert_equal "text/plain", subject.mime_type
|
31
|
+
assert subject.exists?
|
32
|
+
|
33
|
+
null_file = Dassets::AssetFile.new('')
|
34
|
+
assert_nil null_file.mtime
|
35
|
+
assert_nil null_file.size
|
36
|
+
assert_nil null_file.mime_type
|
37
|
+
assert_not null_file.exists?
|
38
|
+
end
|
39
|
+
|
40
|
+
should "know its source cache" do
|
41
|
+
assert_not_nil subject.source_cache
|
42
|
+
assert_kind_of Dassets::SourceCache, subject.source_cache
|
43
|
+
assert_equal subject.digest_path, subject.source_cache.digest_path
|
44
|
+
end
|
45
|
+
|
46
|
+
should "have a fingerprint" do
|
47
|
+
assert_not_nil subject.fingerprint
|
48
|
+
end
|
49
|
+
|
50
|
+
should "get its fingerprint from its source cache if none is given" do
|
51
|
+
af = Dassets::AssetFile.new('file1.txt')
|
52
|
+
assert_equal af.source_cache.fingerprint, af.fingerprint
|
53
|
+
end
|
54
|
+
|
55
|
+
should "know it's content" do
|
56
|
+
assert_equal "file1.txt\n", subject.content
|
57
|
+
|
58
|
+
null_file = Dassets::AssetFile.new('')
|
59
|
+
assert_nil null_file.content
|
60
|
+
end
|
61
|
+
|
62
|
+
should "get its content from its source cache if no output file" do
|
63
|
+
digest_path = 'nested/a-thing.txt.no-use'
|
64
|
+
exp_content = "thing\n\nDUMB\nUSELESS"
|
31
65
|
|
32
|
-
|
33
|
-
assert_equal
|
66
|
+
without_output = Dassets::AssetFile.new(digest_path)
|
67
|
+
assert_equal exp_content, without_output.content
|
34
68
|
end
|
35
69
|
|
36
|
-
should "build it's url from the path and the
|
37
|
-
|
70
|
+
should "build it's url from the path and the fingerprint" do
|
71
|
+
assert_match /^file1-[a-f0-9]{32}\.txt$/, subject.url
|
38
72
|
|
39
|
-
nested = Dassets::AssetFile.new('nested/file1.txt'
|
40
|
-
assert_equal "nested/file1
|
73
|
+
nested = Dassets::AssetFile.new('nested/file1.txt')
|
74
|
+
assert_equal "nested/file1-.txt", nested.url
|
41
75
|
end
|
42
76
|
|
43
77
|
should "build it's href from the url" do
|
44
|
-
|
78
|
+
assert_match /^\/file1-[a-f0-9]{32}\.txt$/, subject.href
|
45
79
|
|
46
|
-
nested = Dassets::AssetFile.new('nested/file1.txt'
|
47
|
-
assert_equal "/nested/file1
|
80
|
+
nested = Dassets::AssetFile.new('nested/file1.txt')
|
81
|
+
assert_equal "/nested/file1-.txt", nested.href
|
48
82
|
end
|
49
83
|
|
50
|
-
|
51
|
-
abs_file_path = File.join(Dassets.config.output_path, 'file1.txt')
|
52
|
-
exp_md5 = 'daa05c683a4913b268653f7a7e36a5b4'
|
53
|
-
file = Dassets::AssetFile.from_abs_path(abs_file_path)
|
84
|
+
end
|
54
85
|
|
55
|
-
|
56
|
-
|
86
|
+
class DigestTests < BaseTests
|
87
|
+
desc "being digested with an output path configured"
|
88
|
+
setup do
|
89
|
+
Dassets.config.file_store = 'public'
|
90
|
+
@save_path = @asset_file.digest!
|
91
|
+
@outfile = Dassets.config.file_store.store_path(@asset_file.url)
|
92
|
+
end
|
93
|
+
teardown do
|
94
|
+
Dassets.config.file_store = Dassets::NullFileStore.new
|
57
95
|
end
|
58
96
|
|
59
|
-
should "
|
60
|
-
assert_equal
|
61
|
-
|
62
|
-
assert_equal File.size?(subject.output_path), subject.size
|
63
|
-
assert_equal "text/plain", subject.mime_type
|
64
|
-
assert subject.exists?
|
97
|
+
should "return the asset file url" do
|
98
|
+
assert_equal @outfile, @save_path
|
99
|
+
end
|
65
100
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
assert_nil null_file.size
|
70
|
-
assert_nil null_file.mime_type
|
71
|
-
assert_not null_file.exists?
|
101
|
+
should "compile and write an asset file to the output path" do
|
102
|
+
assert_file_exists @outfile
|
103
|
+
assert_equal subject.content, File.read(@outfile)
|
72
104
|
end
|
73
105
|
|
74
106
|
end
|
data/test/unit/config_tests.rb
CHANGED
@@ -12,9 +12,10 @@ class Dassets::Config
|
|
12
12
|
end
|
13
13
|
subject{ @config }
|
14
14
|
|
15
|
-
should have_option :root_path,
|
15
|
+
should have_option :root_path, Pathname, :required => true
|
16
16
|
should have_option :assets_file, Pathname, :default => ENV['DASSETS_ASSETS_FILE']
|
17
|
-
should have_options :source_path, :
|
17
|
+
should have_options :source_path, :source_filter, :file_store
|
18
|
+
|
18
19
|
should have_reader :engines
|
19
20
|
should have_imeth :source, :engine
|
20
21
|
|
@@ -23,16 +24,6 @@ class Dassets::Config
|
|
23
24
|
assert_equal exp_path, subject.source_path
|
24
25
|
end
|
25
26
|
|
26
|
-
should "should use `apps/assets/public` as the default output path" do
|
27
|
-
exp_path = Dassets.config.root_path.join("app/assets/public").to_s
|
28
|
-
assert_equal exp_path, subject.output_path
|
29
|
-
end
|
30
|
-
|
31
|
-
should "should use `app/assets/.digests` as the default digests file path" do
|
32
|
-
exp_path = Dassets.config.root_path.join("app/assets/.digests").to_s
|
33
|
-
assert_equal exp_path, subject.digests_path.to_s
|
34
|
-
end
|
35
|
-
|
36
27
|
should "set the source path and filter proc with the `sources` method" do
|
37
28
|
path = Dassets::RootPath.new 'app/asset_files'
|
38
29
|
filter = proc{ |paths| [] }
|
@@ -63,11 +54,6 @@ class Dassets::Config
|
|
63
54
|
assert_equal '', subject.engines['empty'].compile('some content')
|
64
55
|
end
|
65
56
|
|
66
|
-
should "should use `apps/assets/public` as the default files path" do
|
67
|
-
exp_path = Dassets.config.root_path.join("app/assets/public").to_s
|
68
|
-
assert_equal exp_path, subject.output_path
|
69
|
-
end
|
70
|
-
|
71
57
|
end
|
72
58
|
|
73
59
|
end
|
data/test/unit/dassets_tests.rb
CHANGED
@@ -8,50 +8,27 @@ module Dassets
|
|
8
8
|
desc "Dassets"
|
9
9
|
subject{ Dassets }
|
10
10
|
|
11
|
-
should have_imeths :config, :
|
12
|
-
should have_imeths :configure, :reset, :init, :[]
|
11
|
+
should have_imeths :config, :configure, :init, :[]
|
13
12
|
should have_imeths :digest_source_files
|
14
13
|
|
15
14
|
should "return a `Config` instance with the `config` method" do
|
16
15
|
assert_kind_of Config, subject.config
|
17
16
|
end
|
18
17
|
|
19
|
-
should "
|
20
|
-
subject.reset
|
21
|
-
assert_empty subject.sources
|
22
|
-
|
23
|
-
subject.init
|
24
|
-
assert_not_empty subject.sources
|
25
|
-
end
|
26
|
-
|
27
|
-
should "read/parse the digests on init" do
|
28
|
-
subject.reset
|
29
|
-
assert_empty subject.digests.paths
|
30
|
-
|
31
|
-
subject.init
|
32
|
-
assert_not_empty subject.digests.paths
|
33
|
-
end
|
34
|
-
|
35
|
-
should "return asset files given a their path using the index operator" do
|
36
|
-
subject.init
|
18
|
+
should "return asset files given a their digest path using the index operator" do
|
37
19
|
file = subject['nested/file3.txt']
|
38
20
|
|
39
21
|
assert_kind_of Dassets::AssetFile, file
|
40
|
-
assert_equal 'nested/file3.txt', file.
|
41
|
-
assert_equal 'd41d8cd98f00b204e9800998ecf8427e', file.
|
42
|
-
|
43
|
-
subject.reset
|
22
|
+
assert_equal 'nested/file3.txt', file.digest_path
|
23
|
+
assert_equal 'd41d8cd98f00b204e9800998ecf8427e', file.fingerprint
|
44
24
|
end
|
45
25
|
|
46
|
-
should "return an asset file with
|
47
|
-
file = subject['path/not/found.txt']
|
48
|
-
assert_equal '', file.md5
|
49
|
-
|
50
|
-
subject.init
|
26
|
+
should "return an asset file with unknown source if digest path not found" do
|
51
27
|
file = subject['path/not/found.txt']
|
52
|
-
assert_equal '', file.md5
|
53
28
|
|
54
|
-
|
29
|
+
assert_kind_of Dassets::SourceCache, file.source_cache
|
30
|
+
assert_kind_of Dassets::NullSourceFile, file.source_cache.source_file
|
31
|
+
assert_not file.source_cache.exists?
|
55
32
|
end
|
56
33
|
|
57
34
|
end
|
@@ -69,17 +46,6 @@ module Dassets
|
|
69
46
|
assert_equal exp_list, Dassets::SourceList.new(config)
|
70
47
|
end
|
71
48
|
|
72
|
-
should "filter out any paths in the output path" do
|
73
|
-
config = Dassets::Config.new
|
74
|
-
config.source_path = "source_files" # test/support/source_files
|
75
|
-
config.output_path = "source_files/nested"
|
76
|
-
exp_list = [
|
77
|
-
'test1.txt', '_ignored.txt'
|
78
|
-
].map{ |p| File.expand_path(p, config.source_path) }.sort
|
79
|
-
|
80
|
-
assert_equal exp_list, Dassets::SourceList.new(config)
|
81
|
-
end
|
82
|
-
|
83
49
|
should "run the supplied source filter on the paths" do
|
84
50
|
config = Dassets::Config.new
|
85
51
|
config.source_path = "source_files" # test/support/source_files
|