capistrano-improved-rsync-with-remote-cache 0.0.9

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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in capistrano-scm-passthrough.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,96 @@
1
+ = Capistrano rsync_with_remote_cache Deployment Strategy
2
+
3
+ == Description
4
+
5
+ This gem provides a deployment strategy for Capistrano which combines the
6
+ <tt>rsync</tt> command with a remote cache, allowing fast deployments from SCM
7
+ repositories behind firewalls.
8
+
9
+ == Requirements
10
+
11
+ This gem supports Subversion, Git, Mercurial and Bazaar. Only Subversion and
12
+ Git have been extensively tested. This gem is unlikely to be supported for
13
+ other SCM systems.
14
+
15
+ This gem requires the <tt>rsync</tt> command-line utilities on the local and
16
+ remote hosts. It also requires either <tt>svn</tt>, <tt>git</tt>, <tt>hg</tt>
17
+ or <tt>bzr</tt> on the local host, but not the remote host.
18
+
19
+ This gem is tested on Mac OS X and Linux. Windows is neither tested nor supported.
20
+
21
+ == Installation
22
+
23
+ gem install capistrano_rsync_with_remote_cache
24
+
25
+ == Usage
26
+
27
+ To use this deployment strategy, add this line to your <tt>deploy.rb</tt> file:
28
+
29
+ set :deploy_via, :rsync_with_remote_cache
30
+
31
+ == Under the Hood
32
+
33
+ This strategy maintains two cache directories:
34
+
35
+ * The local cache directory is a checkout from the SCM repository. The local
36
+ cache directory is specified with the <tt>:local_cache</tt> variable in the
37
+ configuration. If not specified, it will default to <tt>.rsync_cache</tt>
38
+ in the same directory as the Capfile.
39
+
40
+ * The remote cache directory is an <tt>rsync</tt> copy of the local cache directory.
41
+ The remote cache directory is specified with the <tt>:repository_cache</tt> variable
42
+ in the configuration (this name comes from the <tt>:remote_cache</tt> strategy that
43
+ ships with Capistrano, and has been maintained for compatibility.) If not
44
+ specified, it will default to <tt>shared/cached-copy</tt> (again, for compatibility
45
+ with remote_cache.)
46
+
47
+ Deployment happens in three major steps. First, the local cache directory is
48
+ processed. There are three possibilities:
49
+
50
+ * If the local cache does not exist, it is created with a checkout of the
51
+ revision to be deployed.
52
+ * If the local cache exists and matches the <tt>:repository</tt> variable, it is
53
+ updated to the revision to be deployed.
54
+ * If the local cache exists and does not match the <p>:repository</p> variable,
55
+ the local cache is purged and recreated with a checkout of the revision
56
+ to be deployed.
57
+ * If the local cache exists but is not a directory, an exception is raised
58
+
59
+ Second, <tt>rsync</tt> runs on the local side to sync the remote cache to the local
60
+ cache. When the <tt>rsync</tt> is complete, the remote cache should be an exact
61
+ replica of the local cache.
62
+
63
+ Finally, a copy of the remote cache is made in the appropriate release
64
+ directory. The end result is the same as if the code had been checked out
65
+ directly on the remote server, as in the default strategy.
66
+
67
+ == Contributors
68
+
69
+ Thanks to the people who submitted patches:
70
+
71
+ * {S. Brent Faulkner}[http://github.com/sbfaulkner]
72
+
73
+ == License
74
+
75
+ Copyright (c) 2007 - 2010 Patrick Reagan (patrick.reagan@viget.com) & Mark Cornick
76
+
77
+ Permission is hereby granted, free of charge, to any person
78
+ obtaining a copy of this software and associated documentation
79
+ files (the "Software"), to deal in the Software without
80
+ restriction, including without limitation the rights to use,
81
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
82
+ copies of the Software, and to permit persons to whom the
83
+ Software is furnished to do so, subject to the following
84
+ conditions:
85
+
86
+ The above copyright notice and this permission notice shall be
87
+ included in all copies or substantial portions of the Software.
88
+
89
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
90
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
91
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
92
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
93
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
94
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
95
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
96
+ OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "capistrano-improved-rsync-with-remote-cache"
5
+ gem.version = "0.0.9"
6
+ gem.authors = ["Carlos Buenosvinos"]
7
+ gem.email = ["hi@carlos.io"]
8
+ gem.homepage = "https://github.com/carlosbuenosvinos/capistrano-improved-rsync-with-remote-cache"
9
+ gem.summary = %q{Improved version of rsync-with-remote-cache deployment strategy.}
10
+ gem.description = %q{Improved version of rsync-with-remote-cache deployment strategy.}
11
+
12
+ gem.files = `git ls-files`.split($/)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.require_paths = ["lib"]
16
+
17
+ gem.add_dependency('capistrano', '>=2.4.1')
18
+ end
@@ -0,0 +1,129 @@
1
+ require 'capistrano/recipes/deploy/strategy/remote'
2
+ require 'fileutils'
3
+
4
+ module Capistrano
5
+ module Deploy
6
+ module Strategy
7
+ class RsyncWithRemoteCache < Remote
8
+
9
+ class InvalidCacheError < Exception; end
10
+
11
+ def self.default_attribute(attribute, default_value)
12
+ define_method(attribute) { configuration[attribute] || default_value }
13
+ end
14
+
15
+ INFO_COMMANDS = {
16
+ :subversion => "svn info . | sed -n \'s/URL: //p\'",
17
+ :git => "git config remote.origin.url",
18
+ :mercurial => "hg showconfig paths.default",
19
+ :bzr => "bzr info | grep parent | sed \'s/^.*parent branch: //\'"
20
+ }
21
+
22
+ default_attribute :rsync_options, '-az --delete'
23
+ default_attribute :local_cache, '.rsync_cache'
24
+ default_attribute :repository_cache, 'cached-copy'
25
+
26
+ def deploy!
27
+ update_local_cache
28
+ update_remote_cache
29
+ copy_remote_cache
30
+ end
31
+
32
+ def update_local_cache
33
+ system(command)
34
+ mark_local_cache
35
+ end
36
+
37
+ def update_remote_cache
38
+ finder_options = {:except => { :no_release => true }}
39
+ find_servers(finder_options).each {|s| system(rsync_command_for(s)) }
40
+ end
41
+
42
+ def copy_remote_cache
43
+ run("rsync -a --delete #{repository_cache_path}/ #{configuration[:release_path]}/")
44
+ end
45
+
46
+ def rsync_command_for(server)
47
+ # We should respect any keys speficied
48
+ ssh_options_string = "-p #{ssh_port(server)}"
49
+ ssh_options_string << " -i #{ssh_options[:keys]}" if ssh_options[:keys]
50
+ "rsync #{rsync_options} --rsh='ssh #{ssh_options_string}' #{local_cache_path}/ #{rsync_host(server)}:#{repository_cache_path}/"
51
+ end
52
+
53
+ def mark_local_cache
54
+ File.open(File.join(local_cache_path, 'REVISION'), 'w') {|f| f << revision }
55
+ end
56
+
57
+ def ssh_port(server)
58
+ server.port || ssh_options[:port] || 22
59
+ end
60
+
61
+ def local_cache_path
62
+ File.expand_path(local_cache)
63
+ end
64
+
65
+ def repository_cache_path
66
+ File.join(shared_path, repository_cache)
67
+ end
68
+
69
+ def repository_url
70
+ `cd #{local_cache_path} && #{INFO_COMMANDS[configuration[:scm]]}`.strip
71
+ end
72
+
73
+ def repository_url_changed?
74
+ repository_url != configuration[:repository]
75
+ end
76
+
77
+ def remove_local_cache
78
+ logger.trace "repository has changed; removing old local cache from #{local_cache_path}"
79
+ FileUtils.rm_rf(local_cache_path)
80
+ end
81
+
82
+ def remove_cache_if_repository_url_changed
83
+ remove_local_cache if repository_url_changed?
84
+ end
85
+
86
+ def rsync_host(server)
87
+ configuration[:user] ? "#{configuration[:user]}@#{server.host}" : server.host
88
+ end
89
+
90
+ def local_cache_exists?
91
+ File.exist?(local_cache_path)
92
+ end
93
+
94
+ def local_cache_valid?
95
+ local_cache_exists? && File.directory?(local_cache_path)
96
+ end
97
+
98
+ # Defines commands that should be checked for by deploy:check. These include the SCM command
99
+ # on the local end, and rsync on both ends. Note that the SCM command is not needed on the
100
+ # remote end.
101
+ def check!
102
+ super.check do |check|
103
+ check.local.command(source.command)
104
+ check.local.command('rsync')
105
+ check.remote.command('rsync')
106
+ end
107
+ end
108
+
109
+ private
110
+
111
+ def command
112
+ if local_cache_valid?
113
+ # if SCM if none
114
+ if configuration[:scm] == :none
115
+ "true"
116
+ else
117
+ source.sync(revision, local_cache_path)
118
+ end
119
+ elsif !local_cache_exists?
120
+ "mkdir -p #{local_cache_path} && #{source.checkout(revision, local_cache_path)}"
121
+ else
122
+ raise InvalidCacheError, "The local cache exists but is not valid (#{local_cache_path})"
123
+ end
124
+ end
125
+ end
126
+
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,288 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'mocha'
4
+ require 'shoulda'
5
+ require 'matchy'
6
+ require 'tmpdir'
7
+
8
+ require 'capistrano/recipes/deploy/strategy/rsync_with_remote_cache'
9
+
10
+ class CapistranoRsyncWithRemoteCacheTest < Test::Unit::TestCase
11
+
12
+ context "An instance of the CapistranoRsyncWithRemoteCache class" do
13
+ setup { @strategy = Capistrano::Deploy::Strategy::RsyncWithRemoteCache.new }
14
+
15
+ should "know the default rsync options" do
16
+ @strategy.rsync_options.should == '-az --delete'
17
+ end
18
+
19
+ should "allow overriding of the rsync options" do
20
+ @strategy.stubs(:configuration).with().returns(:rsync_options => 'new_opts')
21
+ @strategy.rsync_options.should == 'new_opts'
22
+ end
23
+
24
+ should "know the default local cache name" do
25
+ @strategy.local_cache.should == '.rsync_cache'
26
+ end
27
+
28
+ should "know the local cache name if it has been configured" do
29
+ @strategy.stubs(:configuration).with().returns(:local_cache => 'cache')
30
+ @strategy.local_cache.should == 'cache'
31
+ end
32
+
33
+ should "know the cache path" do
34
+ @strategy.stubs(:local_cache).with().returns('cache_dir')
35
+ File.expects(:expand_path).with('cache_dir').returns('local_cache_path')
36
+
37
+ @strategy.local_cache_path.should == 'local_cache_path'
38
+ end
39
+
40
+ should "know the repository URL for a subversion repository" do
41
+ @strategy.stubs(:local_cache_path).with().returns('cache_path')
42
+ @strategy.stubs(:configuration).with().returns(:scm => :subversion)
43
+ @strategy.expects(:`).with("cd cache_path && svn info . | sed -n \'s/URL: //p\'").returns("svn_url\n")
44
+ @strategy.repository_url.should == 'svn_url'
45
+ end
46
+
47
+ should "know the repository URL for a git repository" do
48
+ @strategy.stubs(:local_cache_path).with().returns('cache_path')
49
+ @strategy.stubs(:configuration).with().returns(:scm => :git)
50
+ @strategy.expects(:`).with("cd cache_path && git config remote.origin.url").returns("git_url\n")
51
+ @strategy.repository_url.should == 'git_url'
52
+ end
53
+
54
+ should "know the repository URL for a mercurial repository" do
55
+ @strategy.stubs(:local_cache_path).with().returns('cache_path')
56
+ @strategy.stubs(:configuration).with().returns(:scm => :mercurial)
57
+ @strategy.expects(:`).with("cd cache_path && hg showconfig paths.default").returns("hg_url\n")
58
+ @strategy.repository_url.should == 'hg_url'
59
+ end
60
+
61
+ should "know the repository URL for a bzr repository" do
62
+ @strategy.stubs(:local_cache_path).with().returns('cache_path')
63
+ @strategy.stubs(:configuration).with().returns(:scm => :bzr)
64
+ @strategy.expects(:`).with("cd cache_path && bzr info | grep parent | sed \'s/^.*parent branch: //\'").returns("bzr_url\n")
65
+ @strategy.repository_url.should == 'bzr_url'
66
+ end
67
+
68
+ should "know that the repository URL has not changed" do
69
+ @strategy.stubs(:repository_url).with().returns('repo_url')
70
+ @strategy.stubs(:configuration).with().returns(:repository => 'repo_url')
71
+
72
+ @strategy.repository_url_changed?.should be(false)
73
+ end
74
+
75
+ should "know that the repository URL has changed" do
76
+ @strategy.stubs(:repository_url).with().returns('new_repo_url')
77
+ @strategy.stubs(:configuration).with().returns(:repository => 'old_repo_url')
78
+
79
+ @strategy.repository_url_changed?.should be(true)
80
+ end
81
+
82
+ should "be able to remove the local cache" do
83
+ @strategy.stubs(:logger).with().returns(stub(:trace))
84
+ @strategy.stubs(:local_cache_path).with().returns('local_cache_path')
85
+ FileUtils.expects(:rm_rf).with('local_cache_path')
86
+
87
+ @strategy.remove_local_cache
88
+ end
89
+
90
+ should "remove the local cache if the repository URL has changed" do
91
+ @strategy.stubs(:repository_url_changed?).with().returns(true)
92
+ @strategy.expects(:remove_local_cache).with()
93
+
94
+ @strategy.remove_cache_if_repository_url_changed
95
+ end
96
+
97
+ should "not remove the local cache if the repository URL has not changed" do
98
+ @strategy.stubs(:repository_url_changed?).with().returns(false)
99
+ @strategy.expects(:remove_local_cache).with().never
100
+
101
+ @strategy.remove_cache_if_repository_url_changed
102
+ end
103
+
104
+ should "know the default SSH port" do
105
+ @strategy.stubs(:ssh_options).with().returns({})
106
+ server = stub(:port => nil)
107
+ @strategy.ssh_port(server).should == 22
108
+ end
109
+
110
+ should "be able to override the default SSH port" do
111
+ @strategy.stubs(:ssh_options).with().returns({:port => 95})
112
+ server = stub(:port => nil)
113
+ @strategy.ssh_port(server).should == 95
114
+ end
115
+
116
+ should "be able to override the default SSH port for each server" do
117
+ @strategy.stubs(:ssh_options).with().returns({:port => 95})
118
+ server = stub(:port => 123)
119
+ @strategy.ssh_port(server).should == 123
120
+ end
121
+
122
+ should "know the default repository cache" do
123
+ @strategy.repository_cache.should == 'cached-copy'
124
+ end
125
+
126
+ should "be able to override the default repository cache" do
127
+ @strategy.stubs(:configuration).with().returns(:repository_cache => 'other_cache')
128
+ @strategy.repository_cache.should == 'other_cache'
129
+ end
130
+
131
+ should "know the repository cache path" do
132
+ @strategy.stubs(:shared_path).with().returns('shared_path')
133
+ @strategy.stubs(:repository_cache).with().returns('cache_path')
134
+
135
+ File.expects(:join).with('shared_path', 'cache_path').returns('path')
136
+ @strategy.repository_cache_path.should == 'path'
137
+ end
138
+
139
+ should "be able to determine the hostname for the rsync command" do
140
+ server = stub(:host => 'host.com')
141
+ @strategy.rsync_host(server).should == 'host.com'
142
+ end
143
+
144
+ should "be able to determine the hostname for the rsync command when a user is configured" do
145
+ @strategy.stubs(:configuration).with().returns(:user => 'foobar')
146
+ server = stub(:host => 'host.com')
147
+
148
+ @strategy.rsync_host(server).should == 'foobar@host.com'
149
+ end
150
+
151
+ should "know that the local cache exists" do
152
+ @strategy.stubs(:local_cache_path).with().returns('path')
153
+ File.stubs(:exist?).with('path').returns(true)
154
+
155
+ @strategy.local_cache_exists?.should be(true)
156
+ end
157
+
158
+ should "know that the local cache does not exist" do
159
+ @strategy.stubs(:local_cache_path).with().returns('path')
160
+ File.stubs(:exist?).with('path').returns(false)
161
+
162
+ @strategy.local_cache_exists?.should be(false)
163
+ end
164
+
165
+ should "know that the local cache is not valid if it does not exist" do
166
+ @strategy.stubs(:local_cache_exists?).with().returns(false)
167
+ @strategy.local_cache_valid?.should be(false)
168
+ end
169
+
170
+ should "know that the local cache is not valid if it's not a directory" do
171
+ @strategy.stubs(:local_cache_path).with().returns('path')
172
+ @strategy.stubs(:local_cache_exists?).with().returns(true)
173
+
174
+ File.stubs(:directory?).with('path').returns(false)
175
+ @strategy.local_cache_valid?.should be(false)
176
+ end
177
+
178
+ should "know that the local cache is valid" do
179
+ @strategy.stubs(:local_cache_path).with().returns('path')
180
+ @strategy.stubs(:local_cache_exists?).with().returns(true)
181
+
182
+ File.stubs(:directory?).with('path').returns(true)
183
+ @strategy.local_cache_valid?.should be(true)
184
+ end
185
+
186
+ should "know the SCM command when the local cache is valid" do
187
+ source = mock() {|s| s.expects(:sync).with('revision', 'path').returns('scm_command') }
188
+
189
+ @strategy.stubs(:local_cache_valid?).with().returns(true)
190
+ @strategy.stubs(:local_cache_path).with().returns('path')
191
+ @strategy.stubs(:revision).with().returns('revision')
192
+ @strategy.stubs(:source).with().returns(source)
193
+
194
+ @strategy.send(:command).should == 'scm_command'
195
+ end
196
+
197
+ should "know the SCM command when the local cache does not exist" do
198
+ source = mock() {|s| s.expects(:checkout).with('revision', 'path').returns('scm_command') }
199
+
200
+ @strategy.stubs(:local_cache_valid?).with().returns(false)
201
+ @strategy.stubs(:local_cache_exists?).with().returns(false)
202
+ @strategy.stubs(:local_cache_path).with().returns('path')
203
+ @strategy.stubs(:revision).with().returns('revision')
204
+ @strategy.stubs(:source).with().returns(source)
205
+
206
+ @strategy.send(:command).should == 'mkdir -p path && scm_command'
207
+ end
208
+
209
+ should "raise an exception when the local cache is invalid" do
210
+ @strategy.stubs(:local_cache_valid?).with().returns(false)
211
+ @strategy.stubs(:local_cache_exists?).with().returns(true)
212
+
213
+ lambda {
214
+ @strategy.send(:command)
215
+ }.should raise_error(Capistrano::Deploy::Strategy::RsyncWithRemoteCache::InvalidCacheError)
216
+ end
217
+
218
+ should "be able to tag the local cache" do
219
+ local_cache_path = Dir.tmpdir
220
+ @strategy.stubs(:revision).with().returns('1')
221
+ @strategy.stubs(:local_cache_path).with().returns(local_cache_path)
222
+
223
+ @strategy.mark_local_cache
224
+
225
+ File.read(File.join(local_cache_path, 'REVISION')).should == '1'
226
+ end
227
+
228
+ should "be able to update the local cache" do
229
+ @strategy.stubs(:command).with().returns('scm_command')
230
+ @strategy.expects(:system).with('scm_command')
231
+ @strategy.expects(:mark_local_cache).with()
232
+
233
+ @strategy.update_local_cache
234
+ end
235
+
236
+ should "be able to run the rsync command on a server" do
237
+ server = stub()
238
+
239
+ @strategy.stubs(:rsync_host).with(server).returns('rsync_host')
240
+
241
+ @strategy.stubs(
242
+ :rsync_options => 'rsync_options',
243
+ :ssh_port => 'ssh_port',
244
+ :local_cache_path => 'local_cache_path',
245
+ :repository_cache_path => 'repository_cache_path'
246
+ )
247
+
248
+ expected = "rsync rsync_options --rsh='ssh -p ssh_port' local_cache_path/ rsync_host:repository_cache_path/"
249
+
250
+ @strategy.rsync_command_for(server).should == expected
251
+ end
252
+
253
+ should "be able to update the remote cache" do
254
+ server_1, server_2 = [stub(), stub()]
255
+ @strategy.stubs(:find_servers).with(:except => {:no_release => true}).returns([server_1, server_2])
256
+
257
+ @strategy.stubs(:rsync_command_for).with(server_1).returns('server_1_rsync_command')
258
+ @strategy.stubs(:rsync_command_for).with(server_2).returns('server_2_rsync_command')
259
+
260
+ @strategy.expects(:system).with('server_1_rsync_command')
261
+ @strategy.expects(:system).with('server_2_rsync_command')
262
+
263
+ @strategy.update_remote_cache
264
+ end
265
+
266
+ should "be able copy the remote cache into place" do
267
+ @strategy.stubs(
268
+ :repository_cache_path => 'repository_cache_path',
269
+ :configuration => {:release_path => 'release_path'}
270
+ )
271
+
272
+ command = "rsync -a --delete repository_cache_path/ release_path/"
273
+ @strategy.expects(:run).with(command)
274
+
275
+ @strategy.copy_remote_cache
276
+ end
277
+
278
+ should "be able to deploy" do
279
+ @strategy.expects(:update_local_cache).with()
280
+ @strategy.expects(:update_remote_cache).with()
281
+ @strategy.expects(:copy_remote_cache).with()
282
+
283
+ @strategy.deploy!
284
+ end
285
+
286
+ end
287
+
288
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-improved-rsync-with-remote-cache
3
+ version: !ruby/object:Gem::Version
4
+ hash: 13
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 9
10
+ version: 0.0.9
11
+ platform: ruby
12
+ authors:
13
+ - Carlos Buenosvinos
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-02-20 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: capistrano
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 29
29
+ segments:
30
+ - 2
31
+ - 4
32
+ - 1
33
+ version: 2.4.1
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: Improved version of rsync-with-remote-cache deployment strategy.
37
+ email:
38
+ - hi@carlos.io
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - .gitignore
47
+ - Gemfile
48
+ - README.rdoc
49
+ - Rakefile
50
+ - capistrano-improved-rsync-with-remote-cache.gemspec
51
+ - lib/capistrano/recipes/deploy/strategy/improved_rsync_with_remote_cache.rb
52
+ - test/capistrano_rsync_with_remote_cache_test.rb
53
+ homepage: https://github.com/carlosbuenosvinos/capistrano-improved-rsync-with-remote-cache
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options: []
58
+
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ hash: 3
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.8.25
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Improved version of rsync-with-remote-cache deployment strategy.
86
+ test_files:
87
+ - test/capistrano_rsync_with_remote_cache_test.rb