Changeset 8993
- Timestamp:
- 03/08/08 19:07:46 (5 months ago)
- Files:
-
- tools/capistrano/CHANGELOG (modified) (1 diff)
- tools/capistrano/lib/capistrano/recipes/deploy/strategy/base.rb (modified) (1 diff)
- tools/capistrano/lib/capistrano/recipes/deploy/strategy/copy.rb (modified) (3 diffs)
- tools/capistrano/test/deploy/strategy/copy_test.rb (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
tools/capistrano/CHANGELOG
r8939 r8993 1 *SVN* 2 3 * Improved "copy" strategy supports local caching and pattern exclusion (via :copy_cache and :copy_exclude variables) [Jamis Buck] 4 5 1 6 *2.2.0* February 27, 2008 2 7 tools/capistrano/lib/capistrano/recipes/deploy/strategy/base.rb
r7136 r8993 47 47 end 48 48 49 # A wrapper for Kernel#system that logs the command being executed. 50 def system(*args) 51 logger.trace "executing locally: #{args.join(' ')}" 52 super 53 end 54 49 55 private 50 56 tools/capistrano/lib/capistrano/recipes/deploy/strategy/copy.rb
r7376 r8993 16 16 # you can set the :copy_strategy variable to :export. 17 17 # 18 # This deployment strategy supports a special variable, 18 # set :copy_strategy, :export 19 # 20 # For even faster deployments, you can set the :copy_cache variable to 21 # true. This will cause deployments to do a new checkout of your 22 # repository to a new directory, and then copy that checkout. Subsequent 23 # deploys will just resync that copy, rather than doing an entirely new 24 # checkout. Additionally, you can specify file patterns to exclude from 25 # the copy when using :copy_cache; just set the :copy_exclude variable 26 # to an array of file globs or regexps. 27 # 28 # set :copy_cache, true 29 # set :copy_exclude, ".git/*" 30 # 31 # Note that :copy_strategy is ignored when :copy_cache is set. Also, if 32 # you want the copy cache put somewhere specific, you can set the variable 33 # to the path you want, instead of merely 'true': 34 # 35 # set :copy_cache, "/tmp/caches/myapp" 36 # 37 # This deployment strategy also supports a special variable, 19 38 # :copy_compression, which must be one of :gzip, :bz2, or 20 39 # :zip, and which specifies how the source should be compressed for … … 26 45 # directory. 27 46 def deploy! 28 logger.debug "getting (via #{copy_strategy}) revision #{revision} to #{destination}" 29 system(command) 47 if copy_cache 48 if File.exists?(copy_cache) 49 logger.debug "refreshing local cache to revision #{revision} at #{copy_cache}" 50 system(source.sync(revision, copy_cache)) 51 else 52 logger.debug "preparing local cache at #{copy_cache}" 53 system(source.checkout(revision, copy_cache)) 54 end 55 56 logger.debug "copying cache to deployment staging area #{destination}" 57 Dir.chdir(copy_cache) do 58 FileUtils.mkdir_p(destination) 59 queue = Dir.glob("*", File::FNM_DOTMATCH) 60 while queue.any? 61 item = queue.shift 62 name = File.basename(item) 63 next if name == "." || name == ".." 64 next if copy_exclude.any? { |pattern| pattern.is_a?(Regexp) ? item =~ pattern : File.fnmatch?(pattern, item, File::FNM_DOTMATCH) } 65 if File.directory?(item) 66 queue += Dir.glob("#{item}/*", File::FNM_DOTMATCH) 67 FileUtils.mkdir(File.join(destination, item)) 68 else 69 FileUtils.ln(File.join(copy_cache, item), File.join(destination, item)) 70 end 71 end 72 end 73 else 74 logger.debug "getting (via #{copy_strategy}) revision #{revision} to #{destination}" 75 system(command) 76 end 77 30 78 File.open(File.join(destination, "REVISION"), "w") { |f| f.puts(revision) } 31 79 … … 49 97 end 50 98 99 # Returns the location of the local copy cache, if the strategy should 100 # use a local cache + copy instead of a new checkout/export every 101 # time. Returns +nil+ unless :copy_cache has been set. If :copy_cache 102 # is +true+, a default cache location will be returned. 103 def copy_cache 104 @copy_cache ||= configuration[:copy_cache] == true ? 105 File.join(Dir.tmpdir, configuration[:application]) : 106 configuration[:copy_cache] 107 end 108 51 109 private 110 111 # Specify patterns to exclude from the copy. This is only valid 112 # when using a local cache. 113 def copy_exclude 114 @copy_exclude ||= Array(configuration.fetch(:copy_exclude, [])) 115 end 52 116 53 117 # Returns the basename of the release_path, which will be used to tools/capistrano/test/deploy/strategy/copy_test.rb
r7859 r8993 6 6 class DeployStrategyCopyTest < Test::Unit::TestCase 7 7 def setup 8 @config = { :logger => Capistrano::Logger.new(:output => StringIO.new), 8 @config = { :application => "captest", 9 :logger => Capistrano::Logger.new(:output => StringIO.new), 9 10 :releases_path => "/u/apps/test/releases", 10 11 :release_path => "/u/apps/test/releases/1234567890", … … 17 18 def test_deploy_with_defaults_should_use_tar_gz_and_checkout 18 19 Dir.expects(:tmpdir).returns("/temp/dir") 19 Dir.expects(:chdir).with("/temp/dir").yields20 20 @source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout) 21 22 @strategy.expects(:system).with(:local_checkout) 23 @strategy.expects(:system).with("tar czf 1234567890.tar.gz 1234567890") 24 @strategy.expects(:put).with(:mock_file_contents, "/tmp/1234567890.tar.gz") 25 @strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz") 26 27 mock_file = mock("file") 28 mock_file.expects(:puts).with("154") 29 File.expects(:open).with("/temp/dir/1234567890/REVISION", "w").yields(mock_file) 30 File.expects(:open).with("/temp/dir/1234567890.tar.gz", "rb").yields(StringIO.new).returns(:mock_file_contents) 31 32 FileUtils.expects(:rm).with("/temp/dir/1234567890.tar.gz") 33 FileUtils.expects(:rm_rf).with("/temp/dir/1234567890") 34 21 @strategy.expects(:system).with(:local_checkout) 22 23 prepare_standard_compress_and_copy! 35 24 @strategy.deploy! 36 25 end … … 38 27 def test_deploy_with_export_should_use_tar_gz_and_export 39 28 Dir.expects(:tmpdir).returns("/temp/dir") 40 Dir.expects(:chdir).with("/temp/dir").yields41 29 @config[:copy_strategy] = :export 42 30 @source.expects(:export).with("154", "/temp/dir/1234567890").returns(:local_export) 43 44 31 @strategy.expects(:system).with(:local_export) 45 @strategy.expects(:system).with("tar czf 1234567890.tar.gz 1234567890") 46 @strategy.expects(:put).with(:mock_file_contents, "/tmp/1234567890.tar.gz") 47 @strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz") 48 49 mock_file = mock("file") 50 mock_file.expects(:puts).with("154") 51 File.expects(:open).with("/temp/dir/1234567890/REVISION", "w").yields(mock_file) 52 File.expects(:open).with("/temp/dir/1234567890.tar.gz", "rb").yields(StringIO.new).returns(:mock_file_contents) 53 54 FileUtils.expects(:rm).with("/temp/dir/1234567890.tar.gz") 55 FileUtils.expects(:rm_rf).with("/temp/dir/1234567890") 56 32 33 prepare_standard_compress_and_copy! 57 34 @strategy.deploy! 58 35 end … … 80 57 end 81 58 82 def test_deploy_with_bzip2_should_use_ zip_and_checkout59 def test_deploy_with_bzip2_should_use_bz2_and_checkout 83 60 Dir.expects(:tmpdir).returns("/temp/dir") 84 61 Dir.expects(:chdir).with("/temp/dir").yields … … 145 122 @strategy.deploy! 146 123 end 124 125 def test_with_copy_cache_should_checkout_to_cache_if_cache_does_not_exist_and_then_copy 126 @config[:copy_cache] = true 127 128 Dir.stubs(:tmpdir).returns("/temp/dir") 129 File.expects(:exists?).with("/temp/dir/captest").returns(false) 130 Dir.expects(:chdir).with("/temp/dir/captest").yields 131 132 @source.expects(:checkout).with("154", "/temp/dir/captest").returns(:local_checkout) 133 @strategy.expects(:system).with(:local_checkout) 134 135 FileUtils.expects(:mkdir_p).with("/temp/dir/1234567890") 136 137 prepare_directory_tree!("/temp/dir/captest") 138 139 prepare_standard_compress_and_copy! 140 @strategy.deploy! 141 end 142 143 def test_with_copy_cache_should_update_cache_if_cache_exists_and_then_copy 144 @config[:copy_cache] = true 145 146 Dir.stubs(:tmpdir).returns("/temp/dir") 147 File.expects(:exists?).with("/temp/dir/captest").returns(true) 148 Dir.expects(:chdir).with("/temp/dir/captest").yields 149 150 @source.expects(:sync).with("154", "/temp/dir/captest").returns(:local_sync) 151 @strategy.expects(:system).with(:local_sync) 152 153 FileUtils.expects(:mkdir_p).with("/temp/dir/1234567890") 154 155 prepare_directory_tree!("/temp/dir/captest") 156 157 prepare_standard_compress_and_copy! 158 @strategy.deploy! 159 end 160 161 def test_with_copy_cache_with_custom_cache_dir_should_use_specified_cache_dir 162 @config[:copy_cache] = "/u/caches/captest" 163 164 Dir.stubs(:tmpdir).returns("/temp/dir") 165 File.expects(:exists?).with("/u/caches/captest").returns(true) 166 Dir.expects(:chdir).with("/u/caches/captest").yields 167 168 @source.expects(:sync).with("154", "/u/caches/captest").returns(:local_sync) 169 @strategy.expects(:system).with(:local_sync) 170 171 FileUtils.expects(:mkdir_p).with("/temp/dir/1234567890") 172 173 prepare_directory_tree!("/u/caches/captest") 174 175 prepare_standard_compress_and_copy! 176 @strategy.deploy! 177 end 178 179 def test_with_copy_cache_with_excludes_should_not_copy_excluded_files 180 @config[:copy_cache] = true 181 @config[:copy_exclude] = "*/bar.txt" 182 183 Dir.stubs(:tmpdir).returns("/temp/dir") 184 File.expects(:exists?).with("/temp/dir/captest").returns(true) 185 Dir.expects(:chdir).with("/temp/dir/captest").yields 186 187 @source.expects(:sync).with("154", "/temp/dir/captest").returns(:local_sync) 188 @strategy.expects(:system).with(:local_sync) 189 190 FileUtils.expects(:mkdir_p).with("/temp/dir/1234567890") 191 192 prepare_directory_tree!("/temp/dir/captest", true) 193 194 prepare_standard_compress_and_copy! 195 @strategy.deploy! 196 end 197 198 private 199 200 def prepare_directory_tree!(cache, exclude=false) 201 Dir.expects(:glob).with("*", File::FNM_DOTMATCH).returns([".", "..", "app", "foo.txt"]) 202 File.expects(:directory?).with("app").returns(true) 203 FileUtils.expects(:mkdir).with("/temp/dir/1234567890/app") 204 File.expects(:directory?).with("foo.txt").returns(false) 205 FileUtils.expects(:ln).with("#{cache}/foo.txt", "/temp/dir/1234567890/foo.txt") 206 207 Dir.expects(:glob).with("app/*", File::FNM_DOTMATCH).returns(["app/.", "app/..", "app/bar.txt"]) 208 unless exclude 209 File.expects(:directory?).with("app/bar.txt").returns(false) 210 FileUtils.expects(:ln).with("#{cache}/app/bar.txt", "/temp/dir/1234567890/app/bar.txt") 211 end 212 end 213 214 def prepare_standard_compress_and_copy! 215 Dir.expects(:chdir).with("/temp/dir").yields 216 @strategy.expects(:system).with("tar czf 1234567890.tar.gz 1234567890") 217 @strategy.expects(:put).with(:mock_file_contents, "/tmp/1234567890.tar.gz") 218 @strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz") 219 220 mock_file = mock("file") 221 mock_file.expects(:puts).with("154") 222 File.expects(:open).with("/temp/dir/1234567890/REVISION", "w").yields(mock_file) 223 File.expects(:open).with("/temp/dir/1234567890.tar.gz", "rb").yields(StringIO.new).returns(:mock_file_contents) 224 225 FileUtils.expects(:rm).with("/temp/dir/1234567890.tar.gz") 226 FileUtils.expects(:rm_rf).with("/temp/dir/1234567890") 227 end 147 228 end