oz_capistrano_rsync_with_remote_cache 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,96 @@
1
+ = Öz Capistrano oz_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,30 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+
5
+ spec = Gem::Specification.new do |s|
6
+ s.name = 'oz_capistrano_rsync_with_remote_cache'
7
+ s.version = '2.5.0'
8
+ s.has_rdoc = true
9
+ s.extra_rdoc_files = %w(README.rdoc)
10
+ s.rdoc_options = %w(--main README.rdoc)
11
+ s.summary = "A deployment strategy for Capistrano 2.0 which combines rsync with a remote cache, allowing fast deployments from SCM servers behind firewalls. Forked from capistrano_rsync_with_remote_cache and fixed couple of errors"
12
+ s.authors = ['Patrick Reagan', 'Mark Cornick', 'Levent Yalcin']
13
+ s.email = 'leventyalcin@gmail.com'
14
+ s.homepage = 'https://github.com/leventyalcin/capistrano_rsync_with_remote_cache'
15
+ s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib,test}/**/*")
16
+
17
+ s.add_dependency('capistrano', '>=2.1.0')
18
+ end
19
+
20
+ Rake::GemPackageTask.new(spec) do |pkg|
21
+ pkg.gem_spec = spec
22
+ end
23
+
24
+ Rake::TestTask.new do |t|
25
+ t.libs << 'test'
26
+ t.test_files = FileList["test/**/*_test.rb"]
27
+ t.verbose = true
28
+ end
29
+
30
+ task :default => :test
@@ -0,0 +1,134 @@
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
+ "rsync #{rsync_options} --rsh='ssh -p #{ssh_port(server)} #{ssh_key} #{ssh_config_file}' #{local_cache_path}/ #{rsync_host(server)}:#{repository_cache_path}/"
48
+ end
49
+
50
+ def mark_local_cache
51
+ File.open(File.join(local_cache_path, 'REVISION'), 'w') {|f| f << revision }
52
+ end
53
+
54
+ def ssh_port(server)
55
+ server.port || ssh_options[:port] || 22
56
+ end
57
+
58
+ def ssh_key
59
+ ssh_options[:keys] ? "-i #{ssh_options[:keys]}" : ""
60
+ end
61
+
62
+ def ssh_config_file
63
+ ssh_options[:config] ? "-F #{ssh_options[:config]}" : ""
64
+ end
65
+
66
+ def local_cache_path
67
+ File.expand_path(local_cache)
68
+ end
69
+
70
+ def repository_cache_path
71
+ File.join(shared_path, repository_cache)
72
+ end
73
+
74
+ def repository_url
75
+ `cd #{local_cache_path} && #{INFO_COMMANDS[configuration[:scm]]}`.strip
76
+ end
77
+
78
+ def repository_url_changed?
79
+ repository_url != configuration[:repository]
80
+ end
81
+
82
+ def remove_local_cache
83
+ logger.trace "repository has changed; removing old local cache from #{local_cache_path}"
84
+ FileUtils.rm_rf(local_cache_path)
85
+ end
86
+
87
+ def remove_cache_if_repository_url_changed
88
+ remove_local_cache if repository_url_changed?
89
+ end
90
+
91
+ def rsync_host(server)
92
+ configuration[:user] ? "#{configuration[:user]}@#{server.host}" : server.host
93
+ end
94
+
95
+ def local_cache_exists?
96
+ File.exist?(local_cache_path)
97
+ end
98
+
99
+ def local_cache_valid?
100
+ local_cache_exists? && File.directory?(local_cache_path)
101
+ end
102
+
103
+ # Defines commands that should be checked for by deploy:check. These include the SCM command
104
+ # on the local end, and rsync on both ends. Note that the SCM command is not needed on the
105
+ # remote end.
106
+ def check!
107
+ super.check do |check|
108
+ check.local.command(source.command)
109
+ check.local.command('rsync')
110
+ check.remote.command('rsync')
111
+ end
112
+ end
113
+
114
+ private
115
+
116
+ def command
117
+ if configuration[:scm] == :none
118
+ #If scm is NONE, we don't need to sync
119
+ logger.info ":scm is none and we dont need to sync"
120
+ else
121
+ if local_cache_valid?
122
+ source.sync(revision, local_cache_path)
123
+ elsif !local_cache_exists?
124
+ "mkdir -p #{local_cache_path} && #{source.checkout(revision, local_cache_path)}"
125
+ else
126
+ raise InvalidCacheError, "The local cache exists but is not valid (#{local_cache_path})"
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ end
133
+ end
134
+ 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,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oz_capistrano_rsync_with_remote_cache
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 2
7
+ - 5
8
+ - 0
9
+ version: 2.5.0
10
+ platform: ruby
11
+ authors:
12
+ - Patrick Reagan
13
+ - Mark Cornick
14
+ - Levent Yalcin
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2013-03-29 00:00:00 +02:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: capistrano
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 2
31
+ - 1
32
+ - 0
33
+ version: 2.1.0
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description:
37
+ email: leventyalcin@gmail.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - README.rdoc
44
+ files:
45
+ - README.rdoc
46
+ - Rakefile
47
+ - lib/capistrano/recipes/deploy/strategy/rsync_with_remote_cache.rb
48
+ - test/capistrano_rsync_with_remote_cache_test.rb
49
+ has_rdoc: true
50
+ homepage: https://github.com/leventyalcin/capistrano_rsync_with_remote_cache
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --main
56
+ - README.rdoc
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.3.6
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: A deployment strategy for Capistrano 2.0 which combines rsync with a remote cache, allowing fast deployments from SCM servers behind firewalls. Forked from capistrano_rsync_with_remote_cache and fixed couple of errors
80
+ test_files: []
81
+