chef 0.9.8 → 0.9.10.rc.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.rdoc +1 -1
- data/distro/common/man/man8/knife.8 +89 -79
- data/distro/common/markdown/knife.mkd +7 -0
- data/distro/debian/etc/default/chef-server +3 -0
- data/distro/debian/etc/default/chef-server-webui +3 -0
- data/distro/debian/etc/default/chef-solr +3 -0
- data/distro/debian/etc/default/chef-solr-indexer +3 -0
- data/distro/debian/etc/init.d/chef-server +3 -1
- data/distro/debian/etc/init.d/chef-server-webui +3 -1
- data/distro/redhat/etc/init.d/chef-client +1 -1
- data/lib/chef/application.rb +2 -0
- data/lib/chef/application/client.rb +5 -3
- data/lib/chef/application/knife.rb +16 -5
- data/lib/chef/application/solo.rb +0 -1
- data/lib/chef/checksum.rb +65 -1
- data/lib/chef/checksum_cache.rb +173 -0
- data/lib/chef/client.rb +84 -121
- data/lib/chef/cookbook/remote_file_vendor.rb +10 -3
- data/lib/chef/cookbook/syntax_check.rb +2 -2
- data/lib/chef/cookbook_loader.rb +2 -0
- data/lib/chef/cookbook_site_streaming_uploader.rb +29 -0
- data/lib/chef/cookbook_uploader.rb +8 -7
- data/lib/chef/cookbook_version.rb +155 -114
- data/lib/chef/exceptions.rb +5 -0
- data/lib/chef/handler.rb +43 -0
- data/lib/chef/index_queue/consumer.rb +1 -1
- data/lib/chef/index_queue/indexable.rb +1 -1
- data/lib/chef/knife.rb +18 -5
- data/lib/chef/knife/bootstrap.rb +2 -2
- data/lib/chef/knife/bootstrap/archlinux-gems.erb +44 -0
- data/lib/chef/knife/bootstrap/client-install.vbs +80 -0
- data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
- data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +6 -7
- data/lib/chef/knife/bootstrap/windows-gems.erb +34 -0
- data/lib/chef/knife/configure_client.rb +4 -2
- data/lib/chef/knife/cookbook_metadata.rb +1 -1
- data/lib/chef/knife/cookbook_site_share.rb +2 -1
- data/lib/chef/knife/cookbook_site_vendor.rb +6 -0
- data/lib/chef/knife/cookbook_test.rb +1 -1
- data/lib/chef/knife/ec2_server_create.rb +51 -26
- data/lib/chef/knife/exec.rb +52 -0
- data/lib/chef/knife/ssh.rb +27 -15
- data/lib/chef/knife/status.rb +27 -10
- data/lib/chef/knife/windows_bootstrap.rb +154 -0
- data/lib/chef/mixin/checksum.rb +2 -2
- data/lib/chef/mixin/xml_escape.rb +75 -49
- data/lib/chef/node.rb +54 -58
- data/lib/chef/node/attribute.rb +61 -53
- data/lib/chef/platform.rb +19 -2
- data/lib/chef/provider/breakpoint.rb +1 -1
- data/lib/chef/provider/cookbook_file.rb +3 -3
- data/lib/chef/provider/cron.rb +3 -3
- data/lib/chef/provider/cron/solaris.rb +195 -0
- data/lib/chef/provider/deploy.rb +3 -3
- data/lib/chef/provider/directory.rb +2 -2
- data/lib/chef/provider/env.rb +5 -5
- data/lib/chef/provider/execute.rb +1 -1
- data/lib/chef/provider/file.rb +10 -9
- data/lib/chef/provider/git.rb +12 -4
- data/lib/chef/provider/group.rb +5 -5
- data/lib/chef/provider/http_request.rb +25 -9
- data/lib/chef/provider/ifconfig.rb +2 -2
- data/lib/chef/provider/link.rb +11 -6
- data/lib/chef/provider/log.rb +1 -0
- data/lib/chef/provider/mdadm.rb +3 -3
- data/lib/chef/provider/mount.rb +5 -5
- data/lib/chef/provider/mount/mount.rb +1 -1
- data/lib/chef/provider/ohai.rb +41 -0
- data/lib/chef/provider/package.rb +5 -5
- data/lib/chef/provider/package/yum-dump.py +5 -2
- data/lib/chef/provider/remote_directory.rb +11 -5
- data/lib/chef/provider/remote_file.rb +2 -2
- data/lib/chef/provider/route.rb +154 -133
- data/lib/chef/provider/ruby_block.rb +1 -1
- data/lib/chef/provider/service.rb +6 -6
- data/lib/chef/provider/subversion.rb +12 -9
- data/lib/chef/provider/template.rb +2 -2
- data/lib/chef/provider/user.rb +7 -7
- data/lib/chef/provider/user/useradd.rb +15 -1
- data/lib/chef/providers.rb +2 -0
- data/lib/chef/resource.rb +164 -58
- data/lib/chef/resource/http_request.rb +9 -0
- data/lib/chef/resource/ohai.rb +40 -0
- data/lib/chef/resource/remote_directory.rb +10 -1
- data/lib/chef/resource/rpm_package.rb +34 -0
- data/lib/chef/resource_collection.rb +3 -2
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/rest.rb +13 -7
- data/lib/chef/rest/auth_credentials.rb +1 -1
- data/lib/chef/rest/rest_request.rb +3 -1
- data/lib/chef/runner.rb +31 -55
- data/lib/chef/shef/shef_session.rb +1 -1
- data/lib/chef/util/windows/net_use.rb +1 -1
- data/lib/chef/version.rb +1 -1
- data/lib/chef/webui_user.rb +0 -1
- metadata +38 -19
- data/lib/chef/cache.rb +0 -61
- data/lib/chef/cache/checksum.rb +0 -91
@@ -115,6 +115,13 @@ __ssh QUERY COMMAND__ _(options)_
|
|
115
115
|
|
116
116
|
The _ssh_ sub-command opens an ssh session to each of the nodes in the search results of the _QUERY_. This sub-command requires that the net-ssh-multi and highline Ruby libraries are installed. On Debian systems, these are the libnet-ssh-multi-ruby and libhighline-ruby packages. They can also be installed as RubyGems (net-ssh-multi and highline, respectively).
|
117
117
|
|
118
|
+
__status__ _(options)_
|
119
|
+
|
120
|
+
* `-r`, `--run-list RUN_LIST`:
|
121
|
+
Show the run list
|
122
|
+
|
123
|
+
The _status_ sub-command searches the Chef Server for all nodes and displays information about the last time the node checked into the server and executed a `node.save`. The fields displayed are the relative checkin time, the node name, it's operating system platform and version, the fully-qualified domain name and the default IP address. If the `-r` option is given, the node's run list will also be displayed. Note that depending on the configuration of the nodes, the FQDN and IP displayed may not be publicly reachable.
|
124
|
+
|
118
125
|
## BOOTSTRAP SUB-COMMANDS
|
119
126
|
|
120
127
|
__bootstrap FQDN__ _(options)_
|
@@ -57,7 +57,9 @@ stop_server() {
|
|
57
57
|
|
58
58
|
reload_server() {
|
59
59
|
stop_server
|
60
|
+
[ -n "$DIETIME" ] && sleep $DIETIME
|
60
61
|
start_server
|
62
|
+
[ -n "$STARTTIME" ] && sleep $STARTTIME
|
61
63
|
}
|
62
64
|
|
63
65
|
case "$1" in
|
@@ -69,7 +71,7 @@ case "$1" in
|
|
69
71
|
exit 0
|
70
72
|
fi
|
71
73
|
if start_server ; then
|
72
|
-
sleep
|
74
|
+
[ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time
|
73
75
|
if running ; then
|
74
76
|
log_end_msg 0
|
75
77
|
else
|
@@ -58,7 +58,9 @@ stop_server() {
|
|
58
58
|
|
59
59
|
reload_server() {
|
60
60
|
stop_server
|
61
|
+
[ -n "$DIETIME" ] && sleep $DIETIME
|
61
62
|
start_server
|
63
|
+
[ -n "$STARTTIME" ] && sleep $STARTTIME
|
62
64
|
}
|
63
65
|
|
64
66
|
case "$1" in
|
@@ -70,7 +72,7 @@ case "$1" in
|
|
70
72
|
exit 0
|
71
73
|
fi
|
72
74
|
if start_server ; then
|
73
|
-
sleep
|
75
|
+
[ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time
|
74
76
|
if running ; then
|
75
77
|
log_end_msg 0
|
76
78
|
else
|
@@ -35,7 +35,7 @@ start() {
|
|
35
35
|
[ -x $exec ] || exit 5
|
36
36
|
[ -f $config ] || exit 6
|
37
37
|
echo -n $"Starting $prog: "
|
38
|
-
daemon chef-client -d -c "$config" -L "$logfile" -i "$interval" -s "$splay" "$options"
|
38
|
+
daemon chef-client -d -c "$config" -L "$logfile" -p "$pidfile" -i "$interval" -s "$splay" "$options"
|
39
39
|
retval=$?
|
40
40
|
echo
|
41
41
|
[ $retval -eq 0 ] && touch $lockfile
|
data/lib/chef/application.rb
CHANGED
@@ -80,6 +80,8 @@ class Chef::Application
|
|
80
80
|
Chef::Log.warn("Can not find config file: #{config[:config_file]}, using defaults.")
|
81
81
|
Chef::Log.warn("#{error.message}")
|
82
82
|
Chef::Log.warn("*****************************************")
|
83
|
+
|
84
|
+
Chef::Config.merge!(config)
|
83
85
|
end
|
84
86
|
|
85
87
|
end
|
@@ -149,6 +149,9 @@ class Chef::Application::Client < Chef::Application
|
|
149
149
|
|
150
150
|
if Chef::Config[:daemonize]
|
151
151
|
Chef::Config[:interval] ||= 1800
|
152
|
+
else
|
153
|
+
Chef::Config[:interval] = nil
|
154
|
+
Chef::Config[:splay] = nil
|
152
155
|
end
|
153
156
|
|
154
157
|
if Chef::Config[:json_attribs]
|
@@ -221,9 +224,8 @@ class Chef::Application::Client < Chef::Application
|
|
221
224
|
raise
|
222
225
|
rescue Exception => e
|
223
226
|
if Chef::Config[:interval]
|
224
|
-
Chef::Log.error("#{e.class}")
|
225
|
-
Chef::Log.
|
226
|
-
Chef::Log.fatal("Sleeping for #{Chef::Config[:interval]} seconds before trying again")
|
227
|
+
Chef::Log.error("#{e.class}:#{e}\n#{e.backtrace.join("\n")}")
|
228
|
+
Chef::Log.error("Sleeping for #{Chef::Config[:interval]} seconds before trying again")
|
227
229
|
sleep Chef::Config[:interval]
|
228
230
|
retry
|
229
231
|
else
|
@@ -31,6 +31,8 @@ require 'uri'
|
|
31
31
|
|
32
32
|
class Chef::Application::Knife < Chef::Application
|
33
33
|
|
34
|
+
NO_COMMAND_GIVEN = "You need to pass a sub-command (e.g., knife SUB-COMMAND)\n"
|
35
|
+
|
34
36
|
banner "Usage: #{$0} sub-command (options)"
|
35
37
|
|
36
38
|
option :config_file,
|
@@ -114,6 +116,7 @@ class Chef::Application::Knife < Chef::Application
|
|
114
116
|
|
115
117
|
# Run knife
|
116
118
|
def run
|
119
|
+
Mixlib::Log::Formatter.show_time = false
|
117
120
|
validate_and_parse_options
|
118
121
|
Chef::Knife.run(ARGV, options)
|
119
122
|
exit 0
|
@@ -124,11 +127,15 @@ class Chef::Application::Knife < Chef::Application
|
|
124
127
|
def validate_and_parse_options
|
125
128
|
# Checking ARGV validity *before* parse_options because parse_options
|
126
129
|
# mangles ARGV in some situations
|
127
|
-
if
|
128
|
-
print_help_and_exit
|
129
|
-
|
130
|
+
if no_command_given?
|
131
|
+
print_help_and_exit(1, NO_COMMAND_GIVEN)
|
132
|
+
elsif no_subcommand_given?
|
133
|
+
if (want_help? || want_version?)
|
134
|
+
print_help_and_exit
|
135
|
+
else
|
136
|
+
print_help_and_exit(2, NO_COMMAND_GIVEN)
|
137
|
+
end
|
130
138
|
end
|
131
|
-
print_help_and_exit if no_command_given?
|
132
139
|
end
|
133
140
|
|
134
141
|
def no_subcommand_given?
|
@@ -142,9 +149,13 @@ class Chef::Application::Knife < Chef::Application
|
|
142
149
|
def want_help?
|
143
150
|
ARGV[0] =~ /^(--help|-h)$/
|
144
151
|
end
|
152
|
+
|
153
|
+
def want_version?
|
154
|
+
ARGV[0] =~ /^(--version|-v)$/
|
155
|
+
end
|
145
156
|
|
146
157
|
def print_help_and_exit(exitcode=1, fatal_message=nil)
|
147
|
-
Chef::Log.
|
158
|
+
Chef::Log.error(fatal_message) if fatal_message
|
148
159
|
|
149
160
|
begin
|
150
161
|
self.parse_options
|
data/lib/chef/checksum.rb
CHANGED
@@ -25,7 +25,13 @@ class Chef
|
|
25
25
|
class Checksum
|
26
26
|
attr_accessor :checksum, :create_time
|
27
27
|
attr_accessor :couchdb_id, :couchdb_rev
|
28
|
-
|
28
|
+
|
29
|
+
# When a Checksum commits a sandboxed file to its final home in the checksum
|
30
|
+
# repo, this attribute will have the original on-disk path where the file
|
31
|
+
# was stored; it will be used if the commit is reverted to restore the sandbox
|
32
|
+
# to the pre-commit state.
|
33
|
+
attr_reader :original_committed_file_location
|
34
|
+
|
29
35
|
DESIGN_DOCUMENT = {
|
30
36
|
"version" => 1,
|
31
37
|
"language" => "javascript",
|
@@ -52,6 +58,7 @@ class Chef
|
|
52
58
|
def initialize(checksum=nil, couchdb=nil)
|
53
59
|
@create_time = Time.now.iso8601
|
54
60
|
@checksum = checksum
|
61
|
+
@original_committed_file_location = nil
|
55
62
|
end
|
56
63
|
|
57
64
|
def to_json(*a)
|
@@ -82,6 +89,51 @@ class Chef
|
|
82
89
|
checksum
|
83
90
|
end
|
84
91
|
|
92
|
+
|
93
|
+
##
|
94
|
+
# On-Disk Checksum File Repo (Chef Server API)
|
95
|
+
##
|
96
|
+
|
97
|
+
def file_location
|
98
|
+
File.join(checksum_repo_directory, checksum)
|
99
|
+
end
|
100
|
+
|
101
|
+
def checksum_repo_directory
|
102
|
+
File.join(Chef::Config.checksum_path, checksum[0..1])
|
103
|
+
end
|
104
|
+
|
105
|
+
# Moves the given +sandbox_file+ into the checksum repo using the path
|
106
|
+
# given by +file_location+ and saves the Checksum to the database
|
107
|
+
def commit_sandbox_file(sandbox_file)
|
108
|
+
@original_committed_file_location = sandbox_file
|
109
|
+
Chef::Log.info("commiting sandbox file: move #{sandbox_file} to #{file_location}")
|
110
|
+
FileUtils.mkdir_p(checksum_repo_directory)
|
111
|
+
File.rename(sandbox_file, file_location)
|
112
|
+
cdb_save
|
113
|
+
end
|
114
|
+
|
115
|
+
# Moves the checksum file back to its pre-commit location and deletes
|
116
|
+
# the checksum object from the database, effectively undoing +commit_sandbox_file+.
|
117
|
+
# Raises Chef::Exceptions::IllegalChecksumRevert if the original file location
|
118
|
+
# is unknown, which is will be the case if commit_sandbox_file was not
|
119
|
+
# previously called
|
120
|
+
def revert_sandbox_file_commit
|
121
|
+
unless original_committed_file_location
|
122
|
+
raise Chef::Exceptions::IllegalChecksumRevert, "Checksum #{self.inspect} cannot be reverted because the original sandbox file location is not known"
|
123
|
+
end
|
124
|
+
|
125
|
+
Chef::Log.warn("reverting sandbox file commit: moving #{file_location} back to #{original_committed_file_location}")
|
126
|
+
File.rename(file_location, original_committed_file_location)
|
127
|
+
cdb_destroy
|
128
|
+
end
|
129
|
+
|
130
|
+
# Removes the on-disk file backing this checksum object, then removes it
|
131
|
+
# from the database
|
132
|
+
def purge
|
133
|
+
purge_file
|
134
|
+
cdb_destroy
|
135
|
+
end
|
136
|
+
|
85
137
|
##
|
86
138
|
# Couchdb
|
87
139
|
##
|
@@ -114,5 +166,17 @@ class Chef
|
|
114
166
|
@couchdb_rev = (couchdb || Chef::CouchDB.new).store("checksum", checksum, self)["rev"]
|
115
167
|
end
|
116
168
|
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
# Deletes the file backing this checksum from the on-disk repo.
|
173
|
+
# Purging the checksums is how users can get back to a valid state if
|
174
|
+
# they've deleted files, so we silently swallow Errno::ENOENT here.
|
175
|
+
def purge_file
|
176
|
+
FileUtils.rm(file_location)
|
177
|
+
rescue Errno::ENOENT
|
178
|
+
true
|
179
|
+
end
|
180
|
+
|
117
181
|
end
|
118
182
|
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Author:: Daniel DeLeo (<dan@kallistec.com>)
|
4
|
+
# Copyright:: Copyright (c) 2009 Opscode, Inc.
|
5
|
+
# Copyright:: Copyright (c) 2009 Daniel DeLeo
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'set'
|
22
|
+
require 'fileutils'
|
23
|
+
require 'chef/log'
|
24
|
+
require 'chef/config'
|
25
|
+
require 'chef/client'
|
26
|
+
require 'chef/mixin/convert_to_class_name'
|
27
|
+
require 'singleton'
|
28
|
+
require 'moneta'
|
29
|
+
|
30
|
+
class Chef
|
31
|
+
class ChecksumCache
|
32
|
+
include Chef::Mixin::ConvertToClassName
|
33
|
+
include ::Singleton
|
34
|
+
|
35
|
+
attr_reader :moneta
|
36
|
+
|
37
|
+
def initialize(*args)
|
38
|
+
self.reset!(*args)
|
39
|
+
end
|
40
|
+
|
41
|
+
def reset!(backend=nil, options=nil)
|
42
|
+
backend ||= Chef::Config[:cache_type]
|
43
|
+
options ||= Chef::Config[:cache_options]
|
44
|
+
|
45
|
+
begin
|
46
|
+
require "moneta/#{convert_to_snake_case(backend, 'Moneta')}"
|
47
|
+
rescue LoadError => e
|
48
|
+
Chef::Log.fatal("Could not load Moneta back end #{backend.inspect}")
|
49
|
+
raise e
|
50
|
+
end
|
51
|
+
|
52
|
+
@moneta = Moneta.const_get(backend).new(options)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.reset_cache_validity
|
56
|
+
@valid_cached_checksums = nil
|
57
|
+
end
|
58
|
+
|
59
|
+
Chef::Client.when_run_starts do |run_status|
|
60
|
+
reset_cache_validity
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.valid_cached_checksums
|
64
|
+
@valid_cached_checksums ||= Set.new
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.validate_checksum(checksum_key)
|
68
|
+
valid_cached_checksums << checksum_key
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.all_cached_checksums
|
72
|
+
all_checksums_with_filenames = {}
|
73
|
+
|
74
|
+
Dir[File.join(Chef::Config[:cache_options][:path], '*')].each do |cksum_file|
|
75
|
+
all_checksums_with_filenames[File.basename(cksum_file)] = cksum_file
|
76
|
+
end
|
77
|
+
all_checksums_with_filenames
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.cleanup_checksum_cache
|
81
|
+
Chef::Log.info("cleaning the checksum cache")
|
82
|
+
if (Chef::Config[:cache_type].to_s == "BasicFile")
|
83
|
+
all_cached_checksums.each do |cache_key, cksum_cache_file|
|
84
|
+
unless valid_cached_checksums.include?(cache_key)
|
85
|
+
remove_unused_checksum(cksum_cache_file)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
Chef::Client.when_run_completes_successfully do |run_status|
|
92
|
+
cleanup_checksum_cache
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.remove_unused_checksum(checksum_file)
|
96
|
+
Chef::Log.debug("removing unused checksum cache file #{checksum_file}")
|
97
|
+
FileUtils.rm(checksum_file)
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.checksum_for_file(*args)
|
101
|
+
instance.checksum_for_file(*args)
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate_checksum(*args)
|
105
|
+
self.class.validate_checksum(*args)
|
106
|
+
end
|
107
|
+
|
108
|
+
def checksum_for_file(file, key=nil)
|
109
|
+
key ||= generate_key(file)
|
110
|
+
fstat = File.stat(file)
|
111
|
+
lookup_checksum(key, fstat) || generate_checksum(key, file, fstat)
|
112
|
+
end
|
113
|
+
|
114
|
+
def lookup_checksum(key, fstat)
|
115
|
+
cached = @moneta.fetch(key)
|
116
|
+
if cached && file_unchanged?(cached, fstat)
|
117
|
+
validate_checksum(key)
|
118
|
+
cached["checksum"]
|
119
|
+
else
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def generate_checksum(key, file, fstat)
|
125
|
+
checksum = checksum_file(file, Digest::SHA256.new)
|
126
|
+
moneta.store(key, {"mtime" => fstat.mtime.to_f, "checksum" => checksum})
|
127
|
+
validate_checksum(key)
|
128
|
+
checksum
|
129
|
+
end
|
130
|
+
|
131
|
+
def generate_key(file, group="chef")
|
132
|
+
"#{group}-file-#{file.gsub(/(#{File::SEPARATOR}|\.)/, '-')}"
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.generate_md5_checksum_for_file(*args)
|
136
|
+
instance.generate_md5_checksum_for_file(*args)
|
137
|
+
end
|
138
|
+
|
139
|
+
def generate_md5_checksum_for_file(file)
|
140
|
+
checksum_file(file, Digest::MD5.new)
|
141
|
+
end
|
142
|
+
|
143
|
+
def generate_md5_checksum(io)
|
144
|
+
checksum_io(io, Digest::MD5.new)
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def file_unchanged?(cached, fstat)
|
150
|
+
cached["mtime"].to_f == fstat.mtime.to_f
|
151
|
+
end
|
152
|
+
|
153
|
+
def checksum_file(file, digest)
|
154
|
+
File.open(file) { |f| checksum_io(f, digest) }
|
155
|
+
end
|
156
|
+
|
157
|
+
def checksum_io(io, digest)
|
158
|
+
while chunk = io.read(1024 * 8)
|
159
|
+
digest.update(chunk)
|
160
|
+
end
|
161
|
+
digest.hexdigest
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
module Moneta
|
168
|
+
module Defaults
|
169
|
+
def default
|
170
|
+
nil
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|