Module: Capistrano::Configuration::Actions::FileTransferExt
- Defined in:
- lib/capistrano/configuration/actions/file_transfer_ext.rb,
lib/capistrano/configuration/actions/file_transfer_ext/version.rb
Constant Summary collapse
- DIGEST_FILTER_CMD =
since mawk does not recognize /.n/ style quantifier, the regex is very scary.
"awk '%s'" % %q{ { for(n=1;n<=NF;n++){ if(match($n, "^[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]+$" )){ print($n);break } } } }.gsub(/\s+/, "").strip
- VERSION =
"0.1.1"
Instance Method Summary collapse
-
#install(from, to, options = {}, &block) ⇒ Object
(also: #place)
install a file on remote.
-
#install_if_modified(from, to, options = {}, &block) ⇒ Object
(also: #place_if_modified)
install a file on remote, only if the destination is differ from source.
- #safe_put(data, path, options = {}) ⇒ Object
-
#safe_upload(from, to, options = {}, &block) ⇒ Object
upload file from local to remote.
-
#transfer_if_modified(direction, from, to, options = {}, &block) ⇒ Object
transfer file (or IO like object) from local to remote, only if the file checksum is differ.
Instance Method Details
#install(from, to, options = {}, &block) ⇒ Object Also known as: place
install a file on remote.
The options
hash may include any of the following keys:
-
:mode - permission of the file.
-
:via - :run by default.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/capistrano/configuration/actions/file_transfer_ext.rb', line 122 def install(from, to, ={}, &block) = .dup via = .delete(:via) if via == :sudo or .delete(:sudo) # check :sudo for backward compatibility # ignore {:via => :sudo} since `sudo()` cannot handle multiple commands properly. _try_sudo = sudo else _try_sudo = "" [:via] = via if via end # * If :mode is :preserve or :mode is not given, preserve original mode. # * Otherwise, just respect given :mode. mode_given = .key?(:mode) mode = .delete(:mode) if mode_given ? mode == :preserve : true if fetch(:install_preserve_mode, true) begin # respect mode of original file # `stat -c` for GNU, `stat -f` for BSD s = capture("test -f #{to.dump} && ( stat -c '%a' #{to.dump} || stat -f '%p' #{to.dump} )", ) mode = s.to_i(8) & 0777 if /^[0-7]+$/ =~ s logger.debug("preserve original file mode #{mode.to_s(8)}.") rescue mode = nil end else mode = nil end end owner_given = .key?(:owner) owner = .delete(:owner) if owner_given ? owner == :preserve : true if fetch(:install_preserve_owner, true) and via == :sudo begin owner = capture("test -f #{to.dump} && ( stat -c '%u' #{to.dump} || stat -f '%u' #{to.dump} )", ).strip logger.debug("preserve original file owner #{owner.dump}.") rescue owner = nil end else owner = nil end end group_given = .key?(:group) group = .delete(:group) if group_given ? group == :preserve : true if fetch(:install_preserve_group, true) and via == :sudo begin group = capture("test -f #{to.dump} && ( stat -c '%g' #{to.dump} || stat -f '%g' #{to.dump} )", ).strip logger.debug("preserve original file grop #{group.dump}.") rescue group = nil end else group = nil end end execute = [] if block_given? execute << yield(from, to) else execute << "( test -d #{File.dirname(to).dump} || #{_try_sudo} mkdir -p #{File.dirname(to).dump} )" execute << "#{_try_sudo} mv -f #{from.dump} #{to.dump}" end if mode mode = mode.is_a?(Numeric) ? mode.to_s(8) : mode.to_s execute << "#{_try_sudo} chmod #{mode.dump} #{to.dump}" end execute << "#{_try_sudo} chown #{owner.to_s.dump} #{to.dump}" if owner execute << "#{_try_sudo} chgrp #{group.to_s.dump} #{to.dump}" if group invoke_command(execute.join(" && "), ) end |
#install_if_modified(from, to, options = {}, &block) ⇒ Object Also known as: place_if_modified
install a file on remote, only if the destination is differ from source.
The options
hash may include any of the following keys:
-
:mode - permission of the file.
-
:via - :run by default.
-
:digest - digest algorithm. the default is “md5”.
-
:digest_cmd - the digest command. the default is “#digestsum”.
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/capistrano/configuration/actions/file_transfer_ext.rb', line 205 def install_if_modified(from, to, ={}, &block) = .dup if [:via] == :sudo or .delete(:sudo) _try_sudo = sudo [:via] = :sudo else _try_sudo = "" end digest_method = .fetch(:digest, :md5).to_s digest_cmd = .fetch(:digest_cmd, "#{digest_method.downcase}sum") install(from, to, ) do |from, to| execute = [] execute << %{( test -d #{File.dirname(to).dump} || #{_try_sudo} mkdir -p #{File.dirname(to).dump} )} # calculate hexdigest of `from' execute << %{from=$(#{digest_cmd} #{from.dump} 2>/dev/null | #{DIGEST_FILTER_CMD} || true)} execute << %{echo %s} % ["#{digest_method.upcase}(#{from}) = ${from}".dump] # calculate hexdigest of `to' execute << %{to=$(#{digest_cmd} #{to.dump} 2>/dev/null | #{DIGEST_FILTER_CMD} || true)} execute << %{echo %s} % ["#{digest_method.upcase}(#{to}) = ${to}".dump] # check the hexdigests execute << (<<-EOS).gsub(/\s+/, " ").strip if [ -n "${from}" -a "${to}" ] && [ "${from}" = "${to}" ]; then echo "skip installing since no changes."; else #{_try_sudo} mv -f #{from.dump} #{to.dump}; fi EOS execute.join(" && ") end end |
#safe_put(data, path, options = {}) ⇒ Object
27 28 29 30 |
# File 'lib/capistrano/configuration/actions/file_transfer_ext.rb', line 27 def safe_put(data, path, ={}) opts = .dup safe_upload(StringIO.new(data), path, opts) end |
#safe_upload(from, to, options = {}, &block) ⇒ Object
upload file from local to remote. this method uses temporary file to avoid incomplete transmission of files.
The options
hash may include any of the following keys:
-
:transfer - use transfer_if_modified if :if_modified is set
-
:install - use install_if_modified if :if_modified is set
-
:run_method - the default is :run.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/capistrano/configuration/actions/file_transfer_ext.rb', line 40 def safe_upload(from, to, ={}, &block) = .dup transfer_method = .delete(:transfer) == :if_modified ? :transfer_if_modified : :transfer if .has_key?(:install) install_method = .delete(:install) == :if_modified ? :install_if_modified : :install else # for backward compatibility before v0.0.4. install_method = .delete(:place) == :if_modified ? :install_if_modified : :install end run_method = ( .delete(:run_method) || :run ) begin tempname = File.join("/tmp", File.basename(to) + ".XXXXXXXXXX") tempfile = capture("mktemp #{tempname.dump}").strip run("rm -f #{tempfile.dump}", ) send(transfer_method, :up, from, tempfile, , &block) send(install_method, tempfile, to, .merge(:via => run_method), &block) ensure run("rm -f #{tempfile.dump}", ) rescue nil end end |
#transfer_if_modified(direction, from, to, options = {}, &block) ⇒ Object
transfer file (or IO like object) from local to remote, only if the file checksum is differ. do not care if the transfer has been completed or not.
The options
hash may include any of the following keys:
-
:digest - digest algorithm. the default is “md5”.
-
:digest_cmd - the digest command. the default is “#digestsum”.
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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/capistrano/configuration/actions/file_transfer_ext.rb', line 69 def transfer_if_modified(direction, from, to, ={}, &block) = .dup digest_method = .fetch(:digest, :md5).to_s digest_cmd = .fetch(:digest_cmd, "#{digest_method.downcase}sum") target = direction == :up ? from : to remote_target = direction == :up ? to : from require "digest/#{digest_method.downcase}" target_is_io = target.respond_to?(:read) if not(target_is_io) and FileTest.directory?(target) Find.find(target) do |_target| relative_path = Pathname.new(_target).relative_path_from(Pathname.new(target)) _remote_target = File.join(remote_target, relative_path) from = direction == :up ? _target : _remote_target to = direction == :up ? _remote_target : _target transfer_if_modified(direction, from, to, , &block) unless FileTest.directory?(_target) end else if target_is_io pos = target.pos digest = Digest.const_get(digest_method.upcase).hexdigest(target.read) target.pos = pos else begin digest = Digest.const_get(digest_method.upcase).hexdigest(File.read(target)) rescue SystemCallError digest = nil end end logger.debug("#{digest_method.upcase}(#{target}) = #{digest}") if dry_run logger.debug("transfering: #{[direction, from, to] * ', '}") else execute_on_servers() do |servers| targets = servers.map { |server| sessions[server] }.reject { |session| remote_digest = session.exec!("test -f #{remote_target.dump} && #{digest_cmd} #{remote_target.dump} | #{DIGEST_FILTER_CMD}") logger.debug("#{session.xserver.host}: #{digest_method.upcase}(#{remote_target}) = #{remote_digest}") result = !( digest.nil? or remote_digest.nil? ) && digest.strip == remote_digest.strip logger.info("#{session.xserver.host}: skip transfering since no changes: #{[direction, from, to] * ', '}") if result result } Capistrano::Transfer.process(direction, from, to, targets, .merge(:logger => logger), &block) unless targets.empty? end end end end |