capistrano-file-transfer-ext 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
@@ -7,36 +7,121 @@ module Capistrano
|
|
7
7
|
class Configuration
|
8
8
|
module Actions
|
9
9
|
module FileTransferExt
|
10
|
+
DIGEST_FILTER_CMD = %{awk '{for(n=1;n<=NF;n++){if(match($n,"^[0-9a-z]{16,}$")){print($n);break}}}'}
|
11
|
+
|
10
12
|
def safe_put(data, path, options={})
|
11
13
|
opts = options.dup
|
12
14
|
safe_upload(StringIO.new(data), path, opts)
|
13
15
|
end
|
14
16
|
|
17
|
+
# upload file from local to remote.
|
18
|
+
# this method uses temporary file to avoid incomplete transmission of files.
|
19
|
+
#
|
20
|
+
# The +options+ hash may include any of the following keys:
|
21
|
+
#
|
22
|
+
# * :transfer - use transfer_if_modified if :if_modified is set
|
23
|
+
# * :place - use place_if_modified if :if_modified is set
|
24
|
+
# * :run_method - the default is :run.
|
15
25
|
def safe_upload(from, to, options={}, &block)
|
16
|
-
|
17
|
-
|
18
|
-
|
26
|
+
transfer_method = options.delete(:transfer) == :if_modified ? :transfer_if_modified : :transfer
|
27
|
+
place_method = options.delete(:place) == :if_modified ? :place_if_modified : :place
|
28
|
+
run_method = ( options.delete(:run_method) || :run )
|
19
29
|
begin
|
20
30
|
tempname = File.join("/tmp", File.basename(to) + ".XXXXXXXXXX")
|
21
31
|
tempfile = capture("mktemp #{tempname.dump}").strip
|
22
32
|
run("rm -f #{tempfile.dump}", options)
|
23
|
-
|
24
|
-
|
25
|
-
case compare_method
|
26
|
-
when :diff
|
27
|
-
execute << "( diff -u #{to.dump} #{tempfile.dump} || mv -f #{tempfile.dump} #{to.dump} )"
|
28
|
-
else
|
29
|
-
execute << "( cmp #{to.dump} #{tempfile.dump} || mv -f #{tempfile.dump} #{to.dump} )"
|
30
|
-
end
|
31
|
-
if mode
|
32
|
-
mode = mode.is_a?(Numeric) ? mode.to_s(8) : mode.to_s
|
33
|
-
execute << "chmod #{mode} #{to}"
|
34
|
-
end
|
35
|
-
invoke_command(execute.join(" && "), options.merge(:via => via))
|
33
|
+
send(transfer_method, :up, from, tempfile, options, &block)
|
34
|
+
send(place_method, tempfile, to, options.merge(:via => run_method), &block)
|
36
35
|
ensure
|
37
36
|
run("rm -f #{tempfile.dump}", options) rescue nil
|
38
37
|
end
|
39
38
|
end
|
39
|
+
|
40
|
+
# transfer file (or IO like object) from local to remote, only if the file checksum is differ.
|
41
|
+
# do not care if the transfer has been completed or not.
|
42
|
+
#
|
43
|
+
# The +options+ hash may include any of the following keys:
|
44
|
+
#
|
45
|
+
# * :digest - digest algorithm. the default is "md5".
|
46
|
+
# * :digest_cmd - the digest command. the default is "#{digest}sum".
|
47
|
+
#
|
48
|
+
def transfer_if_modified(direction, from, to, options={}, &block)
|
49
|
+
digest_method = options.fetch(:digest, "md5")
|
50
|
+
digest_cmd = options.fetch(:digest_cmd, "#{digest_method.downcase}sum")
|
51
|
+
require "digest/#{digest_method.downcase}"
|
52
|
+
target = direction == :up ? from : to
|
53
|
+
remote_target = direction == :up ? to : from
|
54
|
+
if target.respond_to?(:read)
|
55
|
+
pos = target.pos
|
56
|
+
digest = Digest.const_get(digest_method.upcase).hexdigest(target.read)
|
57
|
+
target.pos = pos
|
58
|
+
else
|
59
|
+
begin
|
60
|
+
digest = Digest::const_get(digest_method.upcase).hexdigest(File.read(target))
|
61
|
+
rescue SystemCallError
|
62
|
+
digest = nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
if dry_run
|
66
|
+
logger.debug("transfering: #{[direction, from, to] * ', '}")
|
67
|
+
else
|
68
|
+
execute_on_servers(options) do |servers|
|
69
|
+
targets = servers.map { |server| sessions[server] }.reject { |session|
|
70
|
+
remote_digest = session.exec!("test -f #{remote_target.dump} && #{digest_cmd} #{remote_target.dump} | #{DIGEST_FILTER_CMD}")
|
71
|
+
result = !( digest.nil? or remote_digest.nil? ) && digest == remote_digest.strip
|
72
|
+
logger.info("#{session.xserver.host}: skip transfering since no changes: #{[direction, from, to] * ', '}") if result
|
73
|
+
result
|
74
|
+
}
|
75
|
+
Capistrano::Transfer.process(direction, from, to, targets, options.merge(:logger => logger), &block) unless targets.empty?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# place a file on remote.
|
81
|
+
#
|
82
|
+
# The +options+ hash may include any of the following keys:
|
83
|
+
#
|
84
|
+
# * :mode - permission of the file.
|
85
|
+
# * :sudo - use sudo if set true. the default is false.
|
86
|
+
#
|
87
|
+
def place(from, to, options={}, &block)
|
88
|
+
mode = options.delete(:mode)
|
89
|
+
try_sudo = options.delete(:sudo) ? sudo : ""
|
90
|
+
execute = []
|
91
|
+
execute << "( test -d #{File.dirname(to).dump} || #{try_sudo} mkdir -p #{File.dirname(to).dump} )"
|
92
|
+
execute << "#{try_sudo} mv -f #{from.dump} #{to.dump}"
|
93
|
+
if mode
|
94
|
+
mode = mode.is_a?(Numeric) ? mode.to_s(8) : mode.to_s
|
95
|
+
execute << "#{try_sudo} chmod #{mode} #{to.dump}"
|
96
|
+
end
|
97
|
+
invoke_command(execute.join(" && "), options)
|
98
|
+
end
|
99
|
+
|
100
|
+
# place a file on remote, only if the destination is differ from source.
|
101
|
+
#
|
102
|
+
# The +options+ hash may include any of the following keys:
|
103
|
+
#
|
104
|
+
# * :mode - permission of the file.
|
105
|
+
# * :sudo - use sudo if set true. the default is false.
|
106
|
+
# * :digest - digest algorithm. the default is "md5".
|
107
|
+
# * :digest_cmd - the digest command. the default is "#{digest}sum".
|
108
|
+
#
|
109
|
+
def place_if_modified(from, to, options={}, &block)
|
110
|
+
mode = options.delete(:mode)
|
111
|
+
try_sudo = options.delete(:sudo) ? sudo : ""
|
112
|
+
digest_method = options.fetch(:digest, "md5")
|
113
|
+
digest_cmd = options.fetch(:digest_cmd, "#{digest_method.downcase}sum")
|
114
|
+
execute = []
|
115
|
+
execute << %{( test -d #{File.dirname(to).dump} || #{try_sudo} mkdir -p #{File.dirname(to).dump} )}
|
116
|
+
execute << %{from=$(#{digest_cmd} #{from.dump} | #{DIGEST_FILTER_CMD})}
|
117
|
+
execute << %{to=$(#{digest_cmd} #{to.dump} | #{DIGEST_FILTER_CMD})}
|
118
|
+
execute << %{( test "x${from}" = "x${to}" || ( echo #{from.dump} '->' #{to.dump}; #{try_sudo} mv -f #{from.dump} #{to.dump} ) )}
|
119
|
+
if mode
|
120
|
+
mode = mode.is_a?(Numeric) ? mode.to_s(8) : mode.to_s
|
121
|
+
execute << "#{try_sudo} chmod #{mode} #{to.dump}"
|
122
|
+
end
|
123
|
+
invoke_command(execute.join(" && "), options)
|
124
|
+
end
|
40
125
|
end
|
41
126
|
end
|
42
127
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano-file-transfer-ext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: capistrano
|