capistrano 2.8.0 → 3.19.0
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.
- checksums.yaml +7 -0
- data/.docker/Dockerfile +7 -0
- data/.docker/ssh_key_rsa +49 -0
- data/.docker/ssh_key_rsa.pub +1 -0
- data/.docker/ubuntu_setup.sh +23 -0
- data/.github/issue_template.md +19 -0
- data/.github/pull_request_template.md +22 -0
- data/.github/release-drafter.yml +25 -0
- data/.github/workflows/ci.yml +80 -0
- data/.github/workflows/release-drafter.yml +18 -0
- data/.gitignore +23 -8
- data/.rubocop.yml +62 -0
- data/CHANGELOG.md +1 -0
- data/CONTRIBUTING.md +63 -0
- data/DEVELOPMENT.md +112 -0
- data/Gemfile +42 -9
- data/LICENSE.txt +21 -0
- data/README.md +221 -0
- data/RELEASING.md +17 -0
- data/Rakefile +17 -8
- data/UPGRADING-3.7.md +86 -0
- data/bin/cap +2 -3
- data/bin/capify +7 -89
- data/capistrano.gemspec +29 -43
- data/docker-compose.yml +8 -0
- data/features/configuration.feature +28 -0
- data/features/deploy.feature +92 -0
- data/features/deploy_failure.feature +17 -0
- data/features/doctor.feature +11 -0
- data/features/installation.feature +21 -0
- data/features/sshconnect.feature +11 -0
- data/features/stage_failure.feature +9 -0
- data/features/step_definitions/assertions.rb +162 -0
- data/features/step_definitions/cap_commands.rb +21 -0
- data/features/step_definitions/setup.rb +91 -0
- data/features/subdirectory.feature +9 -0
- data/features/support/docker_gateway.rb +53 -0
- data/features/support/env.rb +1 -0
- data/features/support/remote_command_helpers.rb +29 -0
- data/features/support/remote_ssh_helpers.rb +33 -0
- data/lib/Capfile +3 -0
- data/lib/capistrano/all.rb +17 -0
- data/lib/capistrano/application.rb +153 -0
- data/lib/capistrano/configuration/empty_filter.rb +9 -0
- data/lib/capistrano/configuration/filter.rb +26 -0
- data/lib/capistrano/configuration/host_filter.rb +29 -0
- data/lib/capistrano/configuration/null_filter.rb +9 -0
- data/lib/capistrano/configuration/plugin_installer.rb +51 -0
- data/lib/capistrano/configuration/question.rb +76 -0
- data/lib/capistrano/configuration/role_filter.rb +29 -0
- data/lib/capistrano/configuration/scm_resolver.rb +149 -0
- data/lib/capistrano/configuration/server.rb +137 -0
- data/lib/capistrano/configuration/servers.rb +56 -96
- data/lib/capistrano/configuration/validated_variables.rb +110 -0
- data/lib/capistrano/configuration/variables.rb +79 -94
- data/lib/capistrano/configuration.rb +178 -33
- data/lib/capistrano/console.rb +1 -0
- data/lib/capistrano/defaults.rb +36 -0
- data/lib/capistrano/deploy.rb +3 -0
- data/lib/capistrano/doctor/environment_doctor.rb +19 -0
- data/lib/capistrano/doctor/gems_doctor.rb +45 -0
- data/lib/capistrano/doctor/output_helpers.rb +79 -0
- data/lib/capistrano/doctor/servers_doctor.rb +105 -0
- data/lib/capistrano/doctor/variables_doctor.rb +74 -0
- data/lib/capistrano/doctor.rb +6 -0
- data/lib/capistrano/dotfile.rb +2 -0
- data/lib/capistrano/dsl/env.rb +43 -0
- data/lib/capistrano/dsl/paths.rb +89 -0
- data/lib/capistrano/dsl/stages.rb +31 -0
- data/lib/capistrano/dsl/task_enhancements.rb +61 -0
- data/lib/capistrano/dsl.rb +95 -0
- data/lib/capistrano/framework.rb +2 -0
- data/lib/capistrano/i18n.rb +46 -0
- data/lib/capistrano/immutable_task.rb +30 -0
- data/lib/capistrano/install.rb +1 -0
- data/lib/capistrano/plugin.rb +95 -0
- data/lib/capistrano/proc_helpers.rb +13 -0
- data/lib/capistrano/scm/git.rb +105 -0
- data/lib/capistrano/scm/hg.rb +55 -0
- data/lib/capistrano/scm/plugin.rb +13 -0
- data/lib/capistrano/scm/svn.rb +56 -0
- data/lib/capistrano/scm/tasks/git.rake +84 -0
- data/lib/capistrano/scm/tasks/hg.rake +53 -0
- data/lib/capistrano/scm/tasks/svn.rake +53 -0
- data/lib/capistrano/scm.rb +115 -0
- data/lib/capistrano/setup.rb +36 -0
- data/lib/capistrano/tasks/console.rake +25 -0
- data/lib/capistrano/tasks/deploy.rake +280 -0
- data/lib/capistrano/tasks/doctor.rake +24 -0
- data/lib/capistrano/tasks/framework.rake +67 -0
- data/lib/capistrano/tasks/install.rake +41 -0
- data/lib/capistrano/templates/Capfile +38 -0
- data/lib/capistrano/templates/deploy.rb.erb +39 -0
- data/lib/capistrano/templates/stage.rb.erb +61 -0
- data/lib/capistrano/upload_task.rb +9 -0
- data/lib/capistrano/version.rb +1 -14
- data/lib/capistrano/version_validator.rb +32 -0
- data/lib/capistrano.rb +0 -3
- data/spec/integration/dsl_spec.rb +632 -0
- data/spec/integration_spec_helper.rb +5 -0
- data/spec/lib/capistrano/application_spec.rb +60 -0
- data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/filter_spec.rb +109 -0
- data/spec/lib/capistrano/configuration/host_filter_spec.rb +71 -0
- data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
- data/spec/lib/capistrano/configuration/question_spec.rb +92 -0
- data/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
- data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +56 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +309 -0
- data/spec/lib/capistrano/configuration/servers_spec.rb +331 -0
- data/spec/lib/capistrano/configuration_spec.rb +357 -0
- data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
- data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +67 -0
- data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
- data/spec/lib/capistrano/doctor/servers_doctor_spec.rb +86 -0
- data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +89 -0
- data/spec/lib/capistrano/dsl/paths_spec.rb +228 -0
- data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +108 -0
- data/spec/lib/capistrano/dsl_spec.rb +125 -0
- data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
- data/spec/lib/capistrano/plugin_spec.rb +84 -0
- data/spec/lib/capistrano/scm/git_spec.rb +194 -0
- data/spec/lib/capistrano/scm/hg_spec.rb +109 -0
- data/spec/lib/capistrano/scm/svn_spec.rb +137 -0
- data/spec/lib/capistrano/scm_spec.rb +103 -0
- data/spec/lib/capistrano/upload_task_spec.rb +19 -0
- data/spec/lib/capistrano/version_validator_spec.rb +118 -0
- data/spec/lib/capistrano_spec.rb +7 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/matchers.rb +5 -0
- data/spec/support/tasks/database.rake +11 -0
- data/spec/support/tasks/fail.rake +8 -0
- data/spec/support/tasks/failed.rake +5 -0
- data/spec/support/tasks/plugin.rake +6 -0
- data/spec/support/tasks/root.rake +11 -0
- data/spec/support/test_app.rb +205 -0
- metadata +234 -208
- data/.rvmrc +0 -1
- data/CHANGELOG +0 -954
- data/README.mdown +0 -76
- data/lib/capistrano/callback.rb +0 -45
- data/lib/capistrano/cli/execute.rb +0 -85
- data/lib/capistrano/cli/help.rb +0 -125
- data/lib/capistrano/cli/help.txt +0 -81
- data/lib/capistrano/cli/options.rb +0 -243
- data/lib/capistrano/cli/ui.rb +0 -40
- data/lib/capistrano/cli.rb +0 -47
- data/lib/capistrano/command.rb +0 -286
- data/lib/capistrano/configuration/actions/file_transfer.rb +0 -51
- data/lib/capistrano/configuration/actions/inspect.rb +0 -46
- data/lib/capistrano/configuration/actions/invocation.rb +0 -298
- data/lib/capistrano/configuration/callbacks.rb +0 -148
- data/lib/capistrano/configuration/connections.rb +0 -230
- data/lib/capistrano/configuration/execution.rb +0 -143
- data/lib/capistrano/configuration/loading.rb +0 -197
- data/lib/capistrano/configuration/namespaces.rb +0 -197
- data/lib/capistrano/configuration/roles.rb +0 -73
- data/lib/capistrano/errors.rb +0 -19
- data/lib/capistrano/ext/string.rb +0 -5
- data/lib/capistrano/extensions.rb +0 -57
- data/lib/capistrano/logger.rb +0 -59
- data/lib/capistrano/processable.rb +0 -53
- data/lib/capistrano/recipes/compat.rb +0 -32
- data/lib/capistrano/recipes/deploy/assets.rb +0 -57
- data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
- data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -54
- data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -111
- data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
- data/lib/capistrano/recipes/deploy/scm/base.rb +0 -196
- data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
- data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -153
- data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -96
- data/lib/capistrano/recipes/deploy/scm/git.rb +0 -282
- data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -137
- data/lib/capistrano/recipes/deploy/scm/none.rb +0 -44
- data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -138
- data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -121
- data/lib/capistrano/recipes/deploy/scm.rb +0 -19
- data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -88
- data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -224
- data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
- data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
- data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -57
- data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
- data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
- data/lib/capistrano/recipes/deploy.rb +0 -568
- data/lib/capistrano/recipes/standard.rb +0 -37
- data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
- data/lib/capistrano/role.rb +0 -102
- data/lib/capistrano/server_definition.rb +0 -56
- data/lib/capistrano/shell.rb +0 -260
- data/lib/capistrano/ssh.rb +0 -101
- data/lib/capistrano/task_definition.rb +0 -75
- data/lib/capistrano/transfer.rb +0 -216
- data/rvmrc.sample +0 -1
- data/test/cli/execute_test.rb +0 -132
- data/test/cli/help_test.rb +0 -165
- data/test/cli/options_test.rb +0 -329
- data/test/cli/ui_test.rb +0 -28
- data/test/cli_test.rb +0 -17
- data/test/command_test.rb +0 -289
- data/test/configuration/actions/file_transfer_test.rb +0 -61
- data/test/configuration/actions/inspect_test.rb +0 -65
- data/test/configuration/actions/invocation_test.rb +0 -247
- data/test/configuration/callbacks_test.rb +0 -220
- data/test/configuration/connections_test.rb +0 -420
- data/test/configuration/execution_test.rb +0 -175
- data/test/configuration/loading_test.rb +0 -132
- data/test/configuration/namespace_dsl_test.rb +0 -311
- data/test/configuration/roles_test.rb +0 -144
- data/test/configuration/servers_test.rb +0 -183
- data/test/configuration/variables_test.rb +0 -190
- data/test/configuration_test.rb +0 -88
- data/test/deploy/local_dependency_test.rb +0 -76
- data/test/deploy/remote_dependency_test.rb +0 -135
- data/test/deploy/scm/accurev_test.rb +0 -23
- data/test/deploy/scm/base_test.rb +0 -55
- data/test/deploy/scm/bzr_test.rb +0 -51
- data/test/deploy/scm/darcs_test.rb +0 -37
- data/test/deploy/scm/git_test.rb +0 -184
- data/test/deploy/scm/mercurial_test.rb +0 -134
- data/test/deploy/scm/none_test.rb +0 -35
- data/test/deploy/scm/subversion_test.rb +0 -32
- data/test/deploy/strategy/copy_test.rb +0 -321
- data/test/extensions_test.rb +0 -69
- data/test/fixtures/cli_integration.rb +0 -5
- data/test/fixtures/config.rb +0 -5
- data/test/fixtures/custom.rb +0 -3
- data/test/logger_test.rb +0 -123
- data/test/recipes_test.rb +0 -25
- data/test/role_test.rb +0 -11
- data/test/server_definition_test.rb +0 -121
- data/test/shell_test.rb +0 -90
- data/test/ssh_test.rb +0 -113
- data/test/task_definition_test.rb +0 -116
- data/test/transfer_test.rb +0 -160
- data/test/utils.rb +0 -37
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
require "utils"
|
|
2
|
-
require 'capistrano/logger'
|
|
3
|
-
require 'capistrano/recipes/deploy/strategy/copy'
|
|
4
|
-
require 'stringio'
|
|
5
|
-
|
|
6
|
-
class DeployStrategyCopyTest < Test::Unit::TestCase
|
|
7
|
-
def setup
|
|
8
|
-
@config = { :application => "captest",
|
|
9
|
-
:logger => Capistrano::Logger.new(:output => StringIO.new),
|
|
10
|
-
:releases_path => "/u/apps/test/releases",
|
|
11
|
-
:release_path => "/u/apps/test/releases/1234567890",
|
|
12
|
-
:real_revision => "154" }
|
|
13
|
-
@source = mock("source")
|
|
14
|
-
@config.stubs(:source).returns(@source)
|
|
15
|
-
@strategy = Capistrano::Deploy::Strategy::Copy.new(@config)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def test_deploy_with_defaults_should_use_remote_gtar
|
|
19
|
-
@config[:copy_remote_tar] = 'gtar'
|
|
20
|
-
|
|
21
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
22
|
-
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
|
23
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
24
|
-
|
|
25
|
-
Dir.expects(:chdir).with("/temp/dir").yields
|
|
26
|
-
@strategy.expects(:system).with("tar chzf 1234567890.tar.gz 1234567890")
|
|
27
|
-
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.gz", "/tmp/1234567890.tar.gz")
|
|
28
|
-
@strategy.expects(:run).with("cd /u/apps/test/releases && gtar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz")
|
|
29
|
-
|
|
30
|
-
mock_file = mock("file")
|
|
31
|
-
mock_file.expects(:puts).with("154")
|
|
32
|
-
File.expects(:open).with("/temp/dir/1234567890/REVISION", "w").yields(mock_file)
|
|
33
|
-
|
|
34
|
-
FileUtils.expects(:rm).with("/temp/dir/1234567890.tar.gz")
|
|
35
|
-
FileUtils.expects(:rm_rf).with("/temp/dir/1234567890")
|
|
36
|
-
|
|
37
|
-
@strategy.deploy!
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def test_deploy_with_defaults_should_use_local_gtar
|
|
41
|
-
@config[:copy_local_tar] = 'gtar'
|
|
42
|
-
|
|
43
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
44
|
-
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
|
45
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
46
|
-
|
|
47
|
-
Dir.expects(:chdir).with("/temp/dir").yields
|
|
48
|
-
@strategy.expects(:system).with("gtar chzf 1234567890.tar.gz 1234567890")
|
|
49
|
-
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.gz", "/tmp/1234567890.tar.gz")
|
|
50
|
-
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz")
|
|
51
|
-
|
|
52
|
-
mock_file = mock("file")
|
|
53
|
-
mock_file.expects(:puts).with("154")
|
|
54
|
-
File.expects(:open).with("/temp/dir/1234567890/REVISION", "w").yields(mock_file)
|
|
55
|
-
|
|
56
|
-
FileUtils.expects(:rm).with("/temp/dir/1234567890.tar.gz")
|
|
57
|
-
FileUtils.expects(:rm_rf).with("/temp/dir/1234567890")
|
|
58
|
-
|
|
59
|
-
@strategy.deploy!
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def test_deploy_with_defaults_should_use_tar_gz_and_checkout
|
|
63
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
64
|
-
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
|
65
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
66
|
-
|
|
67
|
-
prepare_standard_compress_and_copy!
|
|
68
|
-
@strategy.deploy!
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def test_deploy_with_exclusions_should_remove_patterns_from_destination
|
|
72
|
-
@config[:copy_exclude] = ".git"
|
|
73
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
74
|
-
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
|
75
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
76
|
-
Dir.expects(:glob).with("/temp/dir/1234567890/.git", File::FNM_DOTMATCH).returns(%w(/temp/dir/1234567890/.git))
|
|
77
|
-
|
|
78
|
-
FileUtils.expects(:rm_rf).with(%w(/temp/dir/1234567890/.git))
|
|
79
|
-
prepare_standard_compress_and_copy!
|
|
80
|
-
@strategy.deploy!
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def test_deploy_with_exclusions_should_remove_glob_patterns_from_destination
|
|
84
|
-
@config[:copy_exclude] = ".gi*"
|
|
85
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
86
|
-
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
|
87
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
88
|
-
Dir.expects(:glob).with("/temp/dir/1234567890/.gi*", File::FNM_DOTMATCH).returns(%w(/temp/dir/1234567890/.git))
|
|
89
|
-
|
|
90
|
-
FileUtils.expects(:rm_rf).with(%w(/temp/dir/1234567890/.git))
|
|
91
|
-
prepare_standard_compress_and_copy!
|
|
92
|
-
@strategy.deploy!
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def test_deploy_with_export_should_use_tar_gz_and_export
|
|
96
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
97
|
-
@config[:copy_strategy] = :export
|
|
98
|
-
@source.expects(:export).with("154", "/temp/dir/1234567890").returns(:local_export)
|
|
99
|
-
@strategy.expects(:system).with(:local_export)
|
|
100
|
-
|
|
101
|
-
prepare_standard_compress_and_copy!
|
|
102
|
-
@strategy.deploy!
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def test_deploy_with_zip_should_use_zip_and_checkout
|
|
106
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
107
|
-
Dir.expects(:chdir).with("/temp/dir").yields
|
|
108
|
-
@config[:copy_compression] = :zip
|
|
109
|
-
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
|
110
|
-
|
|
111
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
112
|
-
@strategy.expects(:system).with("zip -qr 1234567890.zip 1234567890")
|
|
113
|
-
@strategy.expects(:upload).with("/temp/dir/1234567890.zip", "/tmp/1234567890.zip")
|
|
114
|
-
@strategy.expects(:run).with("cd /u/apps/test/releases && unzip -q /tmp/1234567890.zip && rm /tmp/1234567890.zip")
|
|
115
|
-
|
|
116
|
-
mock_file = mock("file")
|
|
117
|
-
mock_file.expects(:puts).with("154")
|
|
118
|
-
File.expects(:open).with("/temp/dir/1234567890/REVISION", "w").yields(mock_file)
|
|
119
|
-
|
|
120
|
-
FileUtils.expects(:rm).with("/temp/dir/1234567890.zip")
|
|
121
|
-
FileUtils.expects(:rm_rf).with("/temp/dir/1234567890")
|
|
122
|
-
|
|
123
|
-
@strategy.deploy!
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def test_deploy_with_bzip2_should_use_bz2_and_checkout
|
|
127
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
128
|
-
Dir.expects(:chdir).with("/temp/dir").yields
|
|
129
|
-
@config[:copy_compression] = :bzip2
|
|
130
|
-
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
|
131
|
-
|
|
132
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
133
|
-
@strategy.expects(:system).with("tar chjf 1234567890.tar.bz2 1234567890")
|
|
134
|
-
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.bz2", "/tmp/1234567890.tar.bz2")
|
|
135
|
-
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xjf /tmp/1234567890.tar.bz2 && rm /tmp/1234567890.tar.bz2")
|
|
136
|
-
|
|
137
|
-
mock_file = mock("file")
|
|
138
|
-
mock_file.expects(:puts).with("154")
|
|
139
|
-
File.expects(:open).with("/temp/dir/1234567890/REVISION", "w").yields(mock_file)
|
|
140
|
-
|
|
141
|
-
FileUtils.expects(:rm).with("/temp/dir/1234567890.tar.bz2")
|
|
142
|
-
FileUtils.expects(:rm_rf).with("/temp/dir/1234567890")
|
|
143
|
-
|
|
144
|
-
@strategy.deploy!
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def test_deploy_with_unknown_compression_type_should_error
|
|
148
|
-
@config[:copy_compression] = :bogus
|
|
149
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
150
|
-
@source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
|
|
151
|
-
@strategy.stubs(:system)
|
|
152
|
-
File.stubs(:open)
|
|
153
|
-
|
|
154
|
-
assert_raises(ArgumentError) { @strategy.deploy! }
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def test_deploy_with_custom_copy_dir_should_use_that_as_tmpdir
|
|
158
|
-
Dir.expects(:tmpdir).never
|
|
159
|
-
Dir.expects(:chdir).with("/other/path").yields
|
|
160
|
-
@config[:copy_dir] = "/other/path"
|
|
161
|
-
@source.expects(:checkout).with("154", "/other/path/1234567890").returns(:local_checkout)
|
|
162
|
-
|
|
163
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
164
|
-
@strategy.expects(:system).with("tar chzf 1234567890.tar.gz 1234567890")
|
|
165
|
-
@strategy.expects(:upload).with("/other/path/1234567890.tar.gz", "/tmp/1234567890.tar.gz")
|
|
166
|
-
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz")
|
|
167
|
-
|
|
168
|
-
mock_file = mock("file")
|
|
169
|
-
mock_file.expects(:puts).with("154")
|
|
170
|
-
File.expects(:open).with("/other/path/1234567890/REVISION", "w").yields(mock_file)
|
|
171
|
-
|
|
172
|
-
FileUtils.expects(:rm).with("/other/path/1234567890.tar.gz")
|
|
173
|
-
FileUtils.expects(:rm_rf).with("/other/path/1234567890")
|
|
174
|
-
|
|
175
|
-
@strategy.deploy!
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
def test_deploy_with_copy_remote_dir_should_copy_to_that_dir
|
|
179
|
-
@config[:copy_remote_dir] = "/somewhere/else"
|
|
180
|
-
Dir.expects(:tmpdir).returns("/temp/dir")
|
|
181
|
-
Dir.expects(:chdir).yields
|
|
182
|
-
@source.expects(:checkout).returns(:local_checkout)
|
|
183
|
-
|
|
184
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
185
|
-
@strategy.expects(:system).with("tar chzf 1234567890.tar.gz 1234567890")
|
|
186
|
-
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.gz", "/somewhere/else/1234567890.tar.gz")
|
|
187
|
-
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /somewhere/else/1234567890.tar.gz && rm /somewhere/else/1234567890.tar.gz")
|
|
188
|
-
|
|
189
|
-
mock_file = mock("file")
|
|
190
|
-
mock_file.expects(:puts).with("154")
|
|
191
|
-
File.expects(:open).with("/temp/dir/1234567890/REVISION", "w").yields(mock_file)
|
|
192
|
-
|
|
193
|
-
FileUtils.expects(:rm).with("/temp/dir/1234567890.tar.gz")
|
|
194
|
-
FileUtils.expects(:rm_rf).with("/temp/dir/1234567890")
|
|
195
|
-
|
|
196
|
-
@strategy.deploy!
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
def test_with_copy_cache_should_checkout_to_cache_if_cache_does_not_exist_and_then_copy
|
|
200
|
-
@config[:copy_cache] = true
|
|
201
|
-
|
|
202
|
-
Dir.stubs(:tmpdir).returns("/temp/dir")
|
|
203
|
-
File.expects(:exists?).with("/temp/dir/captest").returns(false)
|
|
204
|
-
Dir.expects(:chdir).with("/temp/dir/captest").yields
|
|
205
|
-
|
|
206
|
-
@source.expects(:checkout).with("154", "/temp/dir/captest").returns(:local_checkout)
|
|
207
|
-
@strategy.expects(:system).with(:local_checkout)
|
|
208
|
-
|
|
209
|
-
FileUtils.expects(:mkdir_p).with("/temp/dir/1234567890")
|
|
210
|
-
|
|
211
|
-
prepare_directory_tree!("/temp/dir/captest")
|
|
212
|
-
|
|
213
|
-
prepare_standard_compress_and_copy!
|
|
214
|
-
@strategy.deploy!
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
def test_with_copy_cache_should_update_cache_if_cache_exists_and_then_copy
|
|
218
|
-
@config[:copy_cache] = true
|
|
219
|
-
|
|
220
|
-
Dir.stubs(:tmpdir).returns("/temp/dir")
|
|
221
|
-
File.expects(:exists?).with("/temp/dir/captest").returns(true)
|
|
222
|
-
Dir.expects(:chdir).with("/temp/dir/captest").yields
|
|
223
|
-
|
|
224
|
-
@source.expects(:sync).with("154", "/temp/dir/captest").returns(:local_sync)
|
|
225
|
-
@strategy.expects(:system).with(:local_sync)
|
|
226
|
-
|
|
227
|
-
FileUtils.expects(:mkdir_p).with("/temp/dir/1234567890")
|
|
228
|
-
|
|
229
|
-
prepare_directory_tree!("/temp/dir/captest")
|
|
230
|
-
|
|
231
|
-
prepare_standard_compress_and_copy!
|
|
232
|
-
@strategy.deploy!
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
def test_with_copy_cache_with_custom_absolute_cache_dir_path_should_use_specified_cache_dir
|
|
236
|
-
@config[:copy_cache] = "/u/caches/captest"
|
|
237
|
-
|
|
238
|
-
Dir.stubs(:tmpdir).returns("/temp/dir")
|
|
239
|
-
File.expects(:exists?).with("/u/caches/captest").returns(true)
|
|
240
|
-
Dir.expects(:chdir).with("/u/caches/captest").yields
|
|
241
|
-
|
|
242
|
-
@source.expects(:sync).with("154", "/u/caches/captest").returns(:local_sync)
|
|
243
|
-
@strategy.expects(:system).with(:local_sync)
|
|
244
|
-
|
|
245
|
-
FileUtils.expects(:mkdir_p).with("/temp/dir/1234567890")
|
|
246
|
-
|
|
247
|
-
prepare_directory_tree!("/u/caches/captest")
|
|
248
|
-
|
|
249
|
-
prepare_standard_compress_and_copy!
|
|
250
|
-
@strategy.deploy!
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
def test_with_copy_cache_with_custom_relative_cache_dir_path_should_use_specified_cache_dir
|
|
254
|
-
@config[:copy_cache] = "caches/captest"
|
|
255
|
-
|
|
256
|
-
Dir.stubs(:pwd).returns("/u")
|
|
257
|
-
Dir.stubs(:tmpdir).returns("/temp/dir")
|
|
258
|
-
File.expects(:exists?).with("/u/caches/captest").returns(true)
|
|
259
|
-
Dir.expects(:chdir).with("/u/caches/captest").yields
|
|
260
|
-
|
|
261
|
-
@source.expects(:sync).with("154", "/u/caches/captest").returns(:local_sync)
|
|
262
|
-
@strategy.expects(:system).with(:local_sync)
|
|
263
|
-
|
|
264
|
-
FileUtils.expects(:mkdir_p).with("/temp/dir/1234567890")
|
|
265
|
-
|
|
266
|
-
prepare_directory_tree!("/u/caches/captest")
|
|
267
|
-
|
|
268
|
-
prepare_standard_compress_and_copy!
|
|
269
|
-
@strategy.deploy!
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
def test_with_copy_cache_with_excludes_should_not_copy_excluded_files
|
|
273
|
-
@config[:copy_cache] = true
|
|
274
|
-
@config[:copy_exclude] = "*/bar.txt"
|
|
275
|
-
|
|
276
|
-
Dir.stubs(:tmpdir).returns("/temp/dir")
|
|
277
|
-
File.expects(:exists?).with("/temp/dir/captest").returns(true)
|
|
278
|
-
Dir.expects(:chdir).with("/temp/dir/captest").yields
|
|
279
|
-
|
|
280
|
-
@source.expects(:sync).with("154", "/temp/dir/captest").returns(:local_sync)
|
|
281
|
-
@strategy.expects(:system).with(:local_sync)
|
|
282
|
-
|
|
283
|
-
FileUtils.expects(:mkdir_p).with("/temp/dir/1234567890")
|
|
284
|
-
|
|
285
|
-
prepare_directory_tree!("/temp/dir/captest", true)
|
|
286
|
-
|
|
287
|
-
prepare_standard_compress_and_copy!
|
|
288
|
-
@strategy.deploy!
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
private
|
|
292
|
-
|
|
293
|
-
def prepare_directory_tree!(cache, exclude=false)
|
|
294
|
-
Dir.expects(:glob).with("*", File::FNM_DOTMATCH).returns([".", "..", "app", "foo.txt"])
|
|
295
|
-
File.expects(:directory?).with("app").returns(true)
|
|
296
|
-
FileUtils.expects(:mkdir).with("/temp/dir/1234567890/app")
|
|
297
|
-
File.expects(:directory?).with("foo.txt").returns(false)
|
|
298
|
-
FileUtils.expects(:ln).with("foo.txt", "/temp/dir/1234567890/foo.txt")
|
|
299
|
-
|
|
300
|
-
Dir.expects(:glob).with("app/*", File::FNM_DOTMATCH).returns(["app/.", "app/..", "app/bar.txt"])
|
|
301
|
-
|
|
302
|
-
unless exclude
|
|
303
|
-
File.expects(:directory?).with("app/bar.txt").returns(false)
|
|
304
|
-
FileUtils.expects(:ln).with("app/bar.txt", "/temp/dir/1234567890/app/bar.txt")
|
|
305
|
-
end
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
def prepare_standard_compress_and_copy!
|
|
309
|
-
Dir.expects(:chdir).with("/temp/dir").yields
|
|
310
|
-
@strategy.expects(:system).with("tar chzf 1234567890.tar.gz 1234567890")
|
|
311
|
-
@strategy.expects(:upload).with("/temp/dir/1234567890.tar.gz", "/tmp/1234567890.tar.gz")
|
|
312
|
-
@strategy.expects(:run).with("cd /u/apps/test/releases && tar xzf /tmp/1234567890.tar.gz && rm /tmp/1234567890.tar.gz")
|
|
313
|
-
|
|
314
|
-
mock_file = mock("file")
|
|
315
|
-
mock_file.expects(:puts).with("154")
|
|
316
|
-
File.expects(:open).with("/temp/dir/1234567890/REVISION", "w").yields(mock_file)
|
|
317
|
-
|
|
318
|
-
FileUtils.expects(:rm).with("/temp/dir/1234567890.tar.gz")
|
|
319
|
-
FileUtils.expects(:rm_rf).with("/temp/dir/1234567890")
|
|
320
|
-
end
|
|
321
|
-
end
|
data/test/extensions_test.rb
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
require "utils"
|
|
2
|
-
require 'capistrano'
|
|
3
|
-
|
|
4
|
-
class ExtensionsTest < Test::Unit::TestCase
|
|
5
|
-
module CustomExtension
|
|
6
|
-
def do_something(command)
|
|
7
|
-
run(command)
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def setup
|
|
12
|
-
@config = Capistrano::Configuration.new
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def teardown
|
|
16
|
-
Capistrano::EXTENSIONS.keys.each { |e| Capistrano.remove_plugin(e) }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def test_register_plugin_should_add_instance_method_on_configuration_and_return_true
|
|
20
|
-
assert !@config.respond_to?(:custom_stuff)
|
|
21
|
-
assert Capistrano.plugin(:custom_stuff, CustomExtension)
|
|
22
|
-
assert @config.respond_to?(:custom_stuff)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def test_register_plugin_that_already_exists_should_return_false
|
|
26
|
-
assert Capistrano.plugin(:custom_stuff, CustomExtension)
|
|
27
|
-
assert !Capistrano.plugin(:custom_stuff, CustomExtension)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def test_register_plugin_with_public_method_name_should_fail
|
|
31
|
-
method = Capistrano::Configuration.public_instance_methods.first
|
|
32
|
-
assert_not_nil method, "need a public instance method for testing"
|
|
33
|
-
assert_raises(Capistrano::Error) { Capistrano.plugin(method, CustomExtension) }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def test_register_plugin_with_protected_method_name_should_fail
|
|
37
|
-
method = Capistrano::Configuration.protected_instance_methods.first
|
|
38
|
-
assert_not_nil method, "need a protected instance method for testing"
|
|
39
|
-
assert_raises(Capistrano::Error) { Capistrano.plugin(method, CustomExtension) }
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def test_register_plugin_with_private_method_name_should_fail
|
|
43
|
-
method = Capistrano::Configuration.private_instance_methods.first
|
|
44
|
-
assert_not_nil method, "need a private instance method for testing"
|
|
45
|
-
assert_raises(Capistrano::Error) { Capistrano.plugin(method, CustomExtension) }
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def test_unregister_plugin_that_does_not_exist_should_return_false
|
|
49
|
-
assert !Capistrano.remove_plugin(:custom_stuff)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def test_unregister_plugin_should_remove_method_and_return_true
|
|
53
|
-
assert Capistrano.plugin(:custom_stuff, CustomExtension)
|
|
54
|
-
assert @config.respond_to?(:custom_stuff)
|
|
55
|
-
assert Capistrano.remove_plugin(:custom_stuff)
|
|
56
|
-
assert !@config.respond_to?(:custom_stuff)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def test_registered_plugin_proxy_should_return_proxy_object
|
|
60
|
-
Capistrano.plugin(:custom_stuff, CustomExtension)
|
|
61
|
-
assert_instance_of Capistrano::ExtensionProxy, @config.custom_stuff
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def test_proxy_object_should_delegate_to_configuration
|
|
65
|
-
Capistrano.plugin(:custom_stuff, CustomExtension)
|
|
66
|
-
@config.expects(:run).with("hello")
|
|
67
|
-
@config.custom_stuff.do_something("hello")
|
|
68
|
-
end
|
|
69
|
-
end
|
data/test/fixtures/config.rb
DELETED
data/test/fixtures/custom.rb
DELETED
data/test/logger_test.rb
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
require "utils"
|
|
2
|
-
require 'capistrano/logger'
|
|
3
|
-
require 'stringio'
|
|
4
|
-
|
|
5
|
-
class LoggerTest < Test::Unit::TestCase
|
|
6
|
-
def setup
|
|
7
|
-
@io = StringIO.new
|
|
8
|
-
@logger = Capistrano::Logger.new(:output => @io)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def test_logger_should_use_STDERR_by_default
|
|
12
|
-
logger = Capistrano::Logger.new
|
|
13
|
-
assert_equal STDERR, logger.device
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def test_logger_should_use_output_option_if_output_responds_to_puts
|
|
17
|
-
logger = Capistrano::Logger.new(:output => STDOUT)
|
|
18
|
-
assert_equal STDOUT, logger.device
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def test_logger_should_open_file_if_output_does_not_respond_to_puts
|
|
22
|
-
File.expects(:open).with("logs/capistrano.log", "a").returns(:mock)
|
|
23
|
-
logger = Capistrano::Logger.new(:output => "logs/capistrano.log")
|
|
24
|
-
assert_equal :mock, logger.device
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def test_close_should_not_close_device_if_device_is_default
|
|
28
|
-
logger = Capistrano::Logger.new
|
|
29
|
-
logger.device.expects(:close).never
|
|
30
|
-
logger.close
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def test_close_should_not_close_device_is_device_is_explicitly_given
|
|
34
|
-
logger = Capistrano::Logger.new(:output => STDOUT)
|
|
35
|
-
STDOUT.expects(:close).never
|
|
36
|
-
logger.close
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def test_close_should_close_device_when_device_was_implicitly_opened
|
|
40
|
-
f = mock("file", :close => nil)
|
|
41
|
-
File.expects(:open).with("logs/capistrano.log", "a").returns(f)
|
|
42
|
-
logger = Capistrano::Logger.new(:output => "logs/capistrano.log")
|
|
43
|
-
logger.close
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def test_log_with_level_greater_than_threshold_should_ignore_message
|
|
47
|
-
@logger.level = 3
|
|
48
|
-
@logger.log(4, "message")
|
|
49
|
-
assert @io.string.empty?
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def test_log_with_level_equal_to_threshold_should_log_message
|
|
53
|
-
@logger.level = 3
|
|
54
|
-
@logger.log(3, "message")
|
|
55
|
-
assert @io.string.include?("message")
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def test_log_with_level_less_than_threshold_should_log_message
|
|
59
|
-
@logger.level = 3
|
|
60
|
-
@logger.log(2, "message")
|
|
61
|
-
assert @io.string.include?("message")
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def test_log_with_multiline_message_should_log_each_line_separately
|
|
65
|
-
@logger.log(0, "first line\nsecond line")
|
|
66
|
-
assert @io.string.include?("*** first line")
|
|
67
|
-
assert @io.string.include?("*** second line")
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def test_log_with_line_prefix_should_insert_line_prefix_before_message
|
|
71
|
-
@logger.log(0, "message", "prefix")
|
|
72
|
-
assert @io.string.include?("*** [prefix] message")
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def test_log_with_level_0_should_have_strong_indent
|
|
76
|
-
@logger.log(0, "message")
|
|
77
|
-
assert @io.string.match(/^\*\*\* message/)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def test_log_with_level_1_should_have_weaker_indent
|
|
81
|
-
@logger.level = 1
|
|
82
|
-
@logger.log(1, "message")
|
|
83
|
-
assert @io.string.match(/^ \*\* message/)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def test_log_with_level_2_should_have_weaker_indent
|
|
87
|
-
@logger.level = 2
|
|
88
|
-
@logger.log(2, "message")
|
|
89
|
-
assert @io.string.match(/^ \* message/)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def test_log_with_level_3_should_have_weakest_indent
|
|
93
|
-
@logger.level = 3
|
|
94
|
-
@logger.log(3, "message")
|
|
95
|
-
assert @io.string.match(/^ message/)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def test_important_should_delegate_to_log_with_level_IMPORTANT
|
|
99
|
-
@logger.expects(:log).with(Capistrano::Logger::IMPORTANT, "message", "prefix")
|
|
100
|
-
@logger.important("message", "prefix")
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def test_info_should_delegate_to_log_with_level_INFO
|
|
104
|
-
@logger.expects(:log).with(Capistrano::Logger::INFO, "message", "prefix")
|
|
105
|
-
@logger.info("message", "prefix")
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def test_debug_should_delegate_to_log_with_level_DEBUG
|
|
109
|
-
@logger.expects(:log).with(Capistrano::Logger::DEBUG, "message", "prefix")
|
|
110
|
-
@logger.debug("message", "prefix")
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def test_trace_should_delegate_to_log_with_level_TRACE
|
|
114
|
-
@logger.expects(:log).with(Capistrano::Logger::TRACE, "message", "prefix")
|
|
115
|
-
@logger.trace("message", "prefix")
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def test_ordering_of_levels
|
|
119
|
-
assert Capistrano::Logger::IMPORTANT < Capistrano::Logger::INFO
|
|
120
|
-
assert Capistrano::Logger::INFO < Capistrano::Logger::DEBUG
|
|
121
|
-
assert Capistrano::Logger::DEBUG < Capistrano::Logger::TRACE
|
|
122
|
-
end
|
|
123
|
-
end
|
data/test/recipes_test.rb
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
require 'utils'
|
|
2
|
-
require 'capistrano/configuration'
|
|
3
|
-
|
|
4
|
-
class RecipesTest < Test::Unit::TestCase
|
|
5
|
-
|
|
6
|
-
def setup
|
|
7
|
-
@config = Capistrano::Configuration.new
|
|
8
|
-
@config.stubs(:logger).returns(stub_everything)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def test_current_releases_does_not_cause_error_on_dry_run
|
|
12
|
-
@config.dry_run = true
|
|
13
|
-
@config.load 'deploy'
|
|
14
|
-
@config.load do
|
|
15
|
-
set :application, "foo"
|
|
16
|
-
task :dry_run_test do
|
|
17
|
-
fetch :current_release
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
assert_nothing_raised do
|
|
22
|
-
@config.dry_run_test
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
data/test/role_test.rb
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
require "utils"
|
|
2
|
-
require 'capistrano/role'
|
|
3
|
-
|
|
4
|
-
class RoleTest < Test::Unit::TestCase
|
|
5
|
-
def test_clearing_a_populated_role_should_yield_no_servers
|
|
6
|
-
role = Capistrano::Role.new("app1.capistrano.test", lambda { |o| "app2.capistrano.test" })
|
|
7
|
-
assert_equal 2, role.servers.size
|
|
8
|
-
role.clear
|
|
9
|
-
assert role.servers.empty?
|
|
10
|
-
end
|
|
11
|
-
end
|