sprockets 2.12.5 → 3.7.2
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 +4 -4
- data/CHANGELOG.md +296 -0
- data/LICENSE +2 -2
- data/README.md +235 -262
- data/bin/sprockets +1 -0
- data/lib/rake/sprocketstask.rb +5 -4
- data/lib/sprockets/asset.rb +143 -212
- data/lib/sprockets/autoload/closure.rb +7 -0
- data/lib/sprockets/autoload/coffee_script.rb +7 -0
- data/lib/sprockets/autoload/eco.rb +7 -0
- data/lib/sprockets/autoload/ejs.rb +7 -0
- data/lib/sprockets/autoload/sass.rb +7 -0
- data/lib/sprockets/autoload/uglifier.rb +7 -0
- data/lib/sprockets/autoload/yui.rb +7 -0
- data/lib/sprockets/autoload.rb +11 -0
- data/lib/sprockets/base.rb +56 -393
- data/lib/sprockets/bower.rb +58 -0
- data/lib/sprockets/bundle.rb +69 -0
- data/lib/sprockets/cache/file_store.rb +168 -14
- data/lib/sprockets/cache/memory_store.rb +66 -0
- data/lib/sprockets/cache/null_store.rb +46 -0
- data/lib/sprockets/cache.rb +236 -0
- data/lib/sprockets/cached_environment.rb +69 -0
- data/lib/sprockets/closure_compressor.rb +35 -10
- data/lib/sprockets/coffee_script_processor.rb +25 -0
- data/lib/sprockets/coffee_script_template.rb +17 -0
- data/lib/sprockets/compressing.rb +44 -23
- data/lib/sprockets/configuration.rb +83 -0
- data/lib/sprockets/context.rb +86 -144
- data/lib/sprockets/dependencies.rb +73 -0
- data/lib/sprockets/deprecation.rb +90 -0
- data/lib/sprockets/digest_utils.rb +180 -0
- data/lib/sprockets/directive_processor.rb +207 -211
- data/lib/sprockets/eco_processor.rb +32 -0
- data/lib/sprockets/eco_template.rb +9 -30
- data/lib/sprockets/ejs_processor.rb +31 -0
- data/lib/sprockets/ejs_template.rb +9 -29
- data/lib/sprockets/encoding_utils.rb +261 -0
- data/lib/sprockets/engines.rb +53 -35
- data/lib/sprockets/environment.rb +17 -64
- data/lib/sprockets/erb_processor.rb +30 -0
- data/lib/sprockets/erb_template.rb +11 -0
- data/lib/sprockets/errors.rb +4 -13
- data/lib/sprockets/file_reader.rb +15 -0
- data/lib/sprockets/http_utils.rb +117 -0
- data/lib/sprockets/jst_processor.rb +35 -15
- data/lib/sprockets/legacy.rb +330 -0
- data/lib/sprockets/legacy_proc_processor.rb +35 -0
- data/lib/sprockets/legacy_tilt_processor.rb +29 -0
- data/lib/sprockets/loader.rb +325 -0
- data/lib/sprockets/manifest.rb +202 -127
- data/lib/sprockets/manifest_utils.rb +45 -0
- data/lib/sprockets/mime.rb +112 -31
- data/lib/sprockets/path_dependency_utils.rb +85 -0
- data/lib/sprockets/path_digest_utils.rb +47 -0
- data/lib/sprockets/path_utils.rb +287 -0
- data/lib/sprockets/paths.rb +42 -19
- data/lib/sprockets/processing.rb +178 -126
- data/lib/sprockets/processor_utils.rb +180 -0
- data/lib/sprockets/resolve.rb +211 -0
- data/lib/sprockets/sass_cache_store.rb +22 -17
- data/lib/sprockets/sass_compressor.rb +39 -15
- data/lib/sprockets/sass_functions.rb +2 -70
- data/lib/sprockets/sass_importer.rb +2 -30
- data/lib/sprockets/sass_processor.rb +292 -0
- data/lib/sprockets/sass_template.rb +12 -59
- data/lib/sprockets/server.rb +129 -84
- data/lib/sprockets/transformers.rb +145 -0
- data/lib/sprockets/uglifier_compressor.rb +39 -12
- data/lib/sprockets/unloaded_asset.rb +137 -0
- data/lib/sprockets/uri_tar.rb +98 -0
- data/lib/sprockets/uri_utils.rb +188 -0
- data/lib/sprockets/utils/gzip.rb +67 -0
- data/lib/sprockets/utils.rb +210 -44
- data/lib/sprockets/version.rb +1 -1
- data/lib/sprockets/yui_compressor.rb +39 -11
- data/lib/sprockets.rb +142 -81
- metadata +96 -90
- data/lib/sprockets/asset_attributes.rb +0 -137
- data/lib/sprockets/bundled_asset.rb +0 -78
- data/lib/sprockets/caching.rb +0 -96
- data/lib/sprockets/charset_normalizer.rb +0 -41
- data/lib/sprockets/index.rb +0 -100
- data/lib/sprockets/processed_asset.rb +0 -152
- data/lib/sprockets/processor.rb +0 -32
- data/lib/sprockets/safety_colons.rb +0 -28
- data/lib/sprockets/scss_template.rb +0 -13
- data/lib/sprockets/static_asset.rb +0 -60
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
require 'tilt'
|
|
2
|
-
|
|
3
|
-
module Sprockets
|
|
4
|
-
# Some browsers have issues with stylesheets that contain multiple
|
|
5
|
-
# `@charset` definitions. The issue surfaces while using Sass since
|
|
6
|
-
# it inserts a `@charset` at the top of each file. Then Sprockets
|
|
7
|
-
# concatenates them together.
|
|
8
|
-
#
|
|
9
|
-
# The `CharsetNormalizer` processor strips out multiple `@charset`
|
|
10
|
-
# definitions.
|
|
11
|
-
#
|
|
12
|
-
# The current implementation is naive. It picks the first `@charset`
|
|
13
|
-
# it sees and strips the others. This works for most people because
|
|
14
|
-
# the other definitions are usually `UTF-8`. A more sophisticated
|
|
15
|
-
# approach would be to re-encode stylesheets with mixed encodings.
|
|
16
|
-
#
|
|
17
|
-
# This behavior can be disabled with:
|
|
18
|
-
#
|
|
19
|
-
# environment.unregister_bundle_processor 'text/css', Sprockets::CharsetNormalizer
|
|
20
|
-
#
|
|
21
|
-
class CharsetNormalizer < Tilt::Template
|
|
22
|
-
def prepare
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def evaluate(context, locals, &block)
|
|
26
|
-
charset = nil
|
|
27
|
-
|
|
28
|
-
# Find and strip out any `@charset` definitions
|
|
29
|
-
filtered_data = data.gsub(/^@charset "([^"]+)";$/) {
|
|
30
|
-
charset ||= $1; ""
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if charset
|
|
34
|
-
# If there was a charset, move it to the top
|
|
35
|
-
"@charset \"#{charset}\";#{filtered_data}"
|
|
36
|
-
else
|
|
37
|
-
data
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
data/lib/sprockets/index.rb
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
require 'sprockets/base'
|
|
2
|
-
|
|
3
|
-
module Sprockets
|
|
4
|
-
# `Index` is a special cached version of `Environment`.
|
|
5
|
-
#
|
|
6
|
-
# The expection is that all of its file system methods are cached
|
|
7
|
-
# for the instances lifetime. This makes `Index` much faster. This
|
|
8
|
-
# behavior is ideal in production environments where the file system
|
|
9
|
-
# is immutable.
|
|
10
|
-
#
|
|
11
|
-
# `Index` should not be initialized directly. Instead use
|
|
12
|
-
# `Environment#index`.
|
|
13
|
-
class Index < Base
|
|
14
|
-
def initialize(environment)
|
|
15
|
-
@environment = environment
|
|
16
|
-
|
|
17
|
-
if environment.respond_to?(:default_external_encoding)
|
|
18
|
-
@default_external_encoding = environment.default_external_encoding
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Copy environment attributes
|
|
22
|
-
@logger = environment.logger
|
|
23
|
-
@context_class = environment.context_class
|
|
24
|
-
@cache = environment.cache
|
|
25
|
-
@trail = environment.trail.index
|
|
26
|
-
@digest = environment.digest
|
|
27
|
-
@digest_class = environment.digest_class
|
|
28
|
-
@version = environment.version
|
|
29
|
-
@mime_types = environment.mime_types
|
|
30
|
-
@engines = environment.engines
|
|
31
|
-
@preprocessors = environment.preprocessors
|
|
32
|
-
@postprocessors = environment.postprocessors
|
|
33
|
-
@bundle_processors = environment.bundle_processors
|
|
34
|
-
@compressors = environment.compressors
|
|
35
|
-
|
|
36
|
-
# Initialize caches
|
|
37
|
-
@assets = {}
|
|
38
|
-
@digests = {}
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# No-op return self as index
|
|
42
|
-
def index
|
|
43
|
-
self
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# Cache calls to `file_digest`
|
|
47
|
-
def file_digest(pathname)
|
|
48
|
-
key = pathname.to_s
|
|
49
|
-
if @digests.key?(key)
|
|
50
|
-
@digests[key]
|
|
51
|
-
else
|
|
52
|
-
@digests[key] = super
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Cache `find_asset` calls
|
|
57
|
-
def find_asset(path, options = {})
|
|
58
|
-
options[:bundle] = true unless options.key?(:bundle)
|
|
59
|
-
if asset = @assets[cache_key_for(path, options)]
|
|
60
|
-
asset
|
|
61
|
-
elsif asset = super
|
|
62
|
-
logical_path_cache_key = cache_key_for(path, options)
|
|
63
|
-
full_path_cache_key = cache_key_for(asset.pathname, options)
|
|
64
|
-
|
|
65
|
-
# Cache on Index
|
|
66
|
-
@assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
|
|
67
|
-
|
|
68
|
-
# Push cache upstream to Environment
|
|
69
|
-
@environment.instance_eval do
|
|
70
|
-
@assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
asset
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
protected
|
|
78
|
-
# Index is immutable, any methods that try to clear the cache
|
|
79
|
-
# should bomb.
|
|
80
|
-
def expire_index!
|
|
81
|
-
raise TypeError, "can't modify immutable index"
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Cache asset building in memory and in persisted cache.
|
|
85
|
-
def build_asset(path, pathname, options)
|
|
86
|
-
# Memory cache
|
|
87
|
-
key = cache_key_for(pathname, options)
|
|
88
|
-
if @assets.key?(key)
|
|
89
|
-
@assets[key]
|
|
90
|
-
else
|
|
91
|
-
@assets[key] = begin
|
|
92
|
-
# Persisted cache
|
|
93
|
-
cache_asset(key) do
|
|
94
|
-
super
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
require 'sprockets/asset'
|
|
2
|
-
require 'sprockets/utils'
|
|
3
|
-
|
|
4
|
-
module Sprockets
|
|
5
|
-
class ProcessedAsset < Asset
|
|
6
|
-
def initialize(environment, logical_path, pathname)
|
|
7
|
-
super
|
|
8
|
-
|
|
9
|
-
start_time = Time.now.to_f
|
|
10
|
-
|
|
11
|
-
context = environment.context_class.new(environment, logical_path, pathname)
|
|
12
|
-
@source = context.evaluate(pathname)
|
|
13
|
-
@length = Rack::Utils.bytesize(source)
|
|
14
|
-
@digest = environment.digest.update(source).hexdigest
|
|
15
|
-
|
|
16
|
-
build_required_assets(environment, context)
|
|
17
|
-
build_dependency_paths(environment, context)
|
|
18
|
-
|
|
19
|
-
@dependency_digest = compute_dependency_digest(environment)
|
|
20
|
-
|
|
21
|
-
elapsed_time = ((Time.now.to_f - start_time) * 1000).to_i
|
|
22
|
-
environment.logger.debug "Compiled #{logical_path} (#{elapsed_time}ms) (pid #{Process.pid})"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Interal: Used to check equality
|
|
26
|
-
attr_reader :dependency_digest
|
|
27
|
-
|
|
28
|
-
attr_reader :source
|
|
29
|
-
|
|
30
|
-
# Initialize `BundledAsset` from serialized `Hash`.
|
|
31
|
-
def init_with(environment, coder)
|
|
32
|
-
super
|
|
33
|
-
|
|
34
|
-
@source = coder['source']
|
|
35
|
-
@dependency_digest = coder['dependency_digest']
|
|
36
|
-
|
|
37
|
-
@required_assets = coder['required_paths'].map { |p|
|
|
38
|
-
p = expand_root_path(p)
|
|
39
|
-
|
|
40
|
-
unless environment.paths.detect { |path| p[path] }
|
|
41
|
-
raise UnserializeError, "#{p} isn't in paths"
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
p == pathname.to_s ? self : environment.find_asset(p, :bundle => false)
|
|
45
|
-
}
|
|
46
|
-
@dependency_paths = coder['dependency_paths'].map { |h|
|
|
47
|
-
DependencyFile.new(expand_root_path(h['path']), h['mtime'], h['digest'])
|
|
48
|
-
}
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Serialize custom attributes in `BundledAsset`.
|
|
52
|
-
def encode_with(coder)
|
|
53
|
-
super
|
|
54
|
-
|
|
55
|
-
coder['source'] = source
|
|
56
|
-
coder['dependency_digest'] = dependency_digest
|
|
57
|
-
|
|
58
|
-
coder['required_paths'] = required_assets.map { |a|
|
|
59
|
-
relativize_root_path(a.pathname).to_s
|
|
60
|
-
}
|
|
61
|
-
coder['dependency_paths'] = dependency_paths.map { |d|
|
|
62
|
-
{ 'path' => relativize_root_path(d.pathname).to_s,
|
|
63
|
-
'mtime' => d.mtime.iso8601,
|
|
64
|
-
'digest' => d.digest }
|
|
65
|
-
}
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# Checks if Asset is stale by comparing the actual mtime and
|
|
69
|
-
# digest to the inmemory model.
|
|
70
|
-
def fresh?(environment)
|
|
71
|
-
# Check freshness of all declared dependencies
|
|
72
|
-
@dependency_paths.all? { |dep| dependency_fresh?(environment, dep) }
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
protected
|
|
76
|
-
class DependencyFile < Struct.new(:pathname, :mtime, :digest)
|
|
77
|
-
def initialize(pathname, mtime, digest)
|
|
78
|
-
pathname = Pathname.new(pathname) unless pathname.is_a?(Pathname)
|
|
79
|
-
mtime = Time.parse(mtime) if mtime.is_a?(String)
|
|
80
|
-
super
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def eql?(other)
|
|
84
|
-
other.is_a?(DependencyFile) &&
|
|
85
|
-
pathname.eql?(other.pathname) &&
|
|
86
|
-
mtime.eql?(other.mtime) &&
|
|
87
|
-
digest.eql?(other.digest)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def hash
|
|
91
|
-
pathname.to_s.hash
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
private
|
|
96
|
-
def build_required_assets(environment, context)
|
|
97
|
-
@required_assets = resolve_dependencies(environment, context._required_paths + [pathname.to_s]) -
|
|
98
|
-
resolve_dependencies(environment, context._stubbed_assets.to_a)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def resolve_dependencies(environment, paths)
|
|
102
|
-
assets = []
|
|
103
|
-
cache = {}
|
|
104
|
-
|
|
105
|
-
paths.each do |path|
|
|
106
|
-
if path == self.pathname.to_s
|
|
107
|
-
unless cache[self]
|
|
108
|
-
cache[self] = true
|
|
109
|
-
assets << self
|
|
110
|
-
end
|
|
111
|
-
elsif asset = environment.find_asset(path, :bundle => false)
|
|
112
|
-
asset.required_assets.each do |asset_dependency|
|
|
113
|
-
unless cache[asset_dependency]
|
|
114
|
-
cache[asset_dependency] = true
|
|
115
|
-
assets << asset_dependency
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
assets
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def build_dependency_paths(environment, context)
|
|
125
|
-
dependency_paths = {}
|
|
126
|
-
|
|
127
|
-
context._dependency_paths.each do |path|
|
|
128
|
-
dep = DependencyFile.new(path, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
|
|
129
|
-
dependency_paths[dep] = true
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
context._dependency_assets.each do |path|
|
|
133
|
-
if path == self.pathname.to_s
|
|
134
|
-
dep = DependencyFile.new(pathname, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
|
|
135
|
-
dependency_paths[dep] = true
|
|
136
|
-
elsif asset = environment.find_asset(path, :bundle => false)
|
|
137
|
-
asset.dependency_paths.each do |d|
|
|
138
|
-
dependency_paths[d] = true
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
@dependency_paths = dependency_paths.keys
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def compute_dependency_digest(environment)
|
|
147
|
-
required_assets.inject(environment.digest) { |digest, asset|
|
|
148
|
-
digest.update asset.digest
|
|
149
|
-
}.hexdigest
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
end
|
data/lib/sprockets/processor.rb
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
require 'tilt'
|
|
2
|
-
|
|
3
|
-
module Sprockets
|
|
4
|
-
# `Processor` creates an anonymous processor class from a block.
|
|
5
|
-
#
|
|
6
|
-
# register_preprocessor 'text/css', :my_processor do |context, data|
|
|
7
|
-
# # ...
|
|
8
|
-
# end
|
|
9
|
-
#
|
|
10
|
-
class Processor < Tilt::Template
|
|
11
|
-
# `processor` is a lambda or block
|
|
12
|
-
def self.processor
|
|
13
|
-
@processor
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def self.name
|
|
17
|
-
"Sprockets::Processor (#{@name})"
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def self.to_s
|
|
21
|
-
name
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def prepare
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Call processor block with `context` and `data`.
|
|
28
|
-
def evaluate(context, locals)
|
|
29
|
-
self.class.processor.call(context, data)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
require 'tilt'
|
|
2
|
-
|
|
3
|
-
module Sprockets
|
|
4
|
-
# For JS developers who are colonfobic, concatenating JS files using
|
|
5
|
-
# the module pattern usually leads to syntax errors.
|
|
6
|
-
#
|
|
7
|
-
# The `SafetyColons` processor will insert missing semicolons to the
|
|
8
|
-
# end of the file.
|
|
9
|
-
#
|
|
10
|
-
# This behavior can be disabled with:
|
|
11
|
-
#
|
|
12
|
-
# environment.unregister_postprocessor 'application/javascript', Sprockets::SafetyColons
|
|
13
|
-
#
|
|
14
|
-
class SafetyColons < Tilt::Template
|
|
15
|
-
def prepare
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def evaluate(context, locals, &block)
|
|
19
|
-
# If the file is blank or ends in a semicolon, leave it as is
|
|
20
|
-
if data =~ /\A\s*\Z/m || data =~ /;\s*\Z/m
|
|
21
|
-
data
|
|
22
|
-
else
|
|
23
|
-
# Otherwise, append a semicolon and newline
|
|
24
|
-
"#{data};\n"
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
require 'sprockets/sass_template'
|
|
2
|
-
|
|
3
|
-
module Sprockets
|
|
4
|
-
# Scss handler to replace Tilt's builtin one. See `SassTemplate` and
|
|
5
|
-
# `SassImporter` for more infomation.
|
|
6
|
-
class ScssTemplate < SassTemplate
|
|
7
|
-
self.default_mime_type = 'text/css'
|
|
8
|
-
|
|
9
|
-
def syntax
|
|
10
|
-
:scss
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
require 'sprockets/asset'
|
|
2
|
-
require 'fileutils'
|
|
3
|
-
require 'zlib'
|
|
4
|
-
|
|
5
|
-
module Sprockets
|
|
6
|
-
# `StaticAsset`s are used for files that are served verbatim without
|
|
7
|
-
# any processing or concatenation. These are typical images and
|
|
8
|
-
# other binary files.
|
|
9
|
-
class StaticAsset < Asset
|
|
10
|
-
# Returns file contents as its `source`.
|
|
11
|
-
def source
|
|
12
|
-
# File is read everytime to avoid memory bloat of large binary files
|
|
13
|
-
pathname.open('rb') { |f| f.read }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Implemented for Rack SendFile support.
|
|
17
|
-
def to_path
|
|
18
|
-
pathname.to_s
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Save asset to disk.
|
|
22
|
-
def write_to(filename, options = {})
|
|
23
|
-
# Gzip contents if filename has '.gz'
|
|
24
|
-
unless options.key?(:compress)
|
|
25
|
-
options[:compress] = File.extname(filename) == '.gz' && File.extname(logical_path) != '.gz'
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
FileUtils.mkdir_p File.dirname(filename)
|
|
29
|
-
|
|
30
|
-
if options[:compress]
|
|
31
|
-
# Open file and run it through `Zlib`
|
|
32
|
-
pathname.open('rb') do |rd|
|
|
33
|
-
File.open("#{filename}+", 'wb') do |wr|
|
|
34
|
-
gz = Zlib::GzipWriter.new(wr, Zlib::BEST_COMPRESSION)
|
|
35
|
-
gz.mtime = mtime.to_i
|
|
36
|
-
buf = ""
|
|
37
|
-
while rd.read(16384, buf)
|
|
38
|
-
gz.write(buf)
|
|
39
|
-
end
|
|
40
|
-
gz.close
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
else
|
|
44
|
-
# If no compression needs to be done, we can just copy it into place.
|
|
45
|
-
FileUtils.cp(pathname, "#{filename}+")
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# Atomic write
|
|
49
|
-
FileUtils.mv("#{filename}+", filename)
|
|
50
|
-
|
|
51
|
-
# Set mtime correctly
|
|
52
|
-
File.utime(mtime, mtime, filename)
|
|
53
|
-
|
|
54
|
-
nil
|
|
55
|
-
ensure
|
|
56
|
-
# Ensure tmp file gets cleaned up
|
|
57
|
-
FileUtils.rm("#{filename}+") if File.exist?("#{filename}+")
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|